blob: ef61f85e364ee385a8e913f9bf4baad3a6a8d22c [file] [log] [blame]
Gregory P. Smithe54dff52009-05-01 22:13:48 +00001# Copyright 2007 Google Inc.
2# Licensed to PSF under a Contributor Agreement.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied. See the License for the specific language governing
14# permissions and limitations under the License.
15#
16# See also: http://code.google.com/p/ipaddr-py/
17
18"""An IPv4/IPv6 manipulation library in Python.
19
20This library is used to create/poke/manipulate IPv4 and IPv6 addresses
21and prefixes.
22
23"""
24
25__version__ = '1.0.2'
26
27import struct
28
Gregory P. Smith75930f82009-05-03 19:38:29 +000029
Gregory P. Smithe54dff52009-05-01 22:13:48 +000030class Error(Exception):
31
32 """Base class for exceptions."""
33
34
35class IPTypeError(Error):
36
37 """Tried to perform a v4 action on v6 object or vice versa."""
38
39
40class IPAddressExclusionError(Error):
41
42 """An Error we should never see occurred in address exclusion."""
43
44
45class IPv4IpValidationError(Error):
46
47 """Raised when an IPv4 address is invalid."""
48
49 def __init__(self, ip):
50 Error.__init__(self)
51 self.ip = ip
52
53 def __str__(self):
54 return repr(self.ip) + ' is not a valid IPv4 address'
55
56
57class IPv4NetmaskValidationError(Error):
58
59 """Raised when a netmask is invalid."""
60
61 def __init__(self, netmask):
62 Error.__init__(self)
63 self.netmask = netmask
64
65 def __str__(self):
66 return repr(self.netmask) + ' is not a valid IPv4 netmask'
67
68
69class IPv6IpValidationError(Error):
70
71 """Raised when an IPv6 address is invalid."""
72
73 def __init__(self, ip):
74 Error.__init__(self)
75 self.ip = ip
76
77 def __str__(self):
78 return repr(self.ip) + ' is not a valid IPv6 address'
79
80
81class IPv6NetmaskValidationError(Error):
82
83 """Raised when an IPv6 netmask is invalid."""
84
85 def __init__(self, netmask):
86 Error.__init__(self)
87 self.netmask = netmask
88
89 def __str__(self):
90 return repr(self.netmask) + ' is not a valid IPv6 netmask'
91
92
93class PrefixlenDiffInvalidError(Error):
94
95 """Raised when Sub/Supernets is called with a bad prefixlen_diff."""
96
97 def __init__(self, error_str):
98 Error.__init__(self)
99 self.error_str = error_str
100
101
102def IP(ipaddr):
103 """Take an IP string/int and return an object of the correct type.
104
105 Args:
106 ipaddr: A string or integer, the IP address. Either IPv4 or
107 IPv6 addresses may be supplied; integers less than 2**32 will
108 be considered to be IPv4.
109
110 Returns:
111 An IPv4 or IPv6 object.
112
113 Raises:
114 ValueError: if the string passed isn't either a v4 or a v6
115 address.
116
117 """
118
119 try:
120 return IPv4(ipaddr)
121 except (IPv4IpValidationError, IPv4NetmaskValidationError):
122 pass
123
124 try:
125 return IPv6(ipaddr)
126 except (IPv6IpValidationError, IPv6NetmaskValidationError):
127 pass
128
129 raise ValueError('%r does not appear to be an IPv4 or IPv6 address' %
130 ipaddr)
131
132
133def _collapse_address_list_recursive(addresses):
134 """Loops through the addresses, collapsing concurrent netblocks.
135
136 Example:
137
138 ip1 = IPv4('1.1.0.0/24')
139 ip2 = IPv4('1.1.1.0/24')
140 ip3 = IPv4('1.1.2.0/24')
141 ip4 = IPv4('1.1.3.0/24')
142 ip5 = IPv4('1.1.4.0/24')
143 ip6 = IPv4('1.1.0.1/22')
144
145 _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) ->
146 [IPv4('1.1.0.0/22'), IPv4('1.1.4.0/24')]
147
148 This shouldn't be called directly; it is called via
149 collapse_address_list([]).
150
151 Args:
152 addresses: A list of IPv4 or IPv6 objects.
153
154 Returns:
155 A list of IPv4 or IPv6 objects depending on what we were passed.
156
157 """
158 ret_array = []
159 optimized = False
160
161 for cur_addr in addresses:
162 if not ret_array:
163 ret_array.append(cur_addr)
164 continue
165 if cur_addr in ret_array[-1]:
166 optimized = True
167 elif cur_addr == ret_array[-1].supernet().subnet()[1]:
168 ret_array.append(ret_array.pop().supernet())
169 optimized = True
170 else:
171 ret_array.append(cur_addr)
172
173 if optimized:
174 return _collapse_address_list_recursive(ret_array)
175
176 return ret_array
177
178
179def collapse_address_list(addresses):
180 """Collapse a list of IP objects.
181
182 Example:
183 collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) ->
184 [IPv4('1.1.0.0/23')]
185
186 Args:
187 addresses: A list of IPv4 or IPv6 objects.
188
189 Returns:
190 A list of IPv4 or IPv6 objects depending on what we were passed.
191
192 """
193 return _collapse_address_list_recursive(
194 sorted(addresses, key=BaseIP._get_networks_key))
195
196
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000197class BaseIP(object):
198
199 """A generic IP object.
200
201 This IP class contains most of the methods which are used by
202 the IPv4 and IPv6 classes.
203
204 """
205
206 def __getitem__(self, n):
207 if n >= 0:
208 if self.network + n > self.broadcast:
209 raise IndexError
210 return self._string_from_ip_int(self.network + n)
211 else:
Gregory P. Smith2fcd73d2009-05-08 23:19:47 +0000212 n += 1
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000213 if self.broadcast + n < self.network:
214 raise IndexError
215 return self._string_from_ip_int(self.broadcast + n)
216
217 def __lt__(self, other):
218 try:
219 return (self.version < other.version
220 or self.ip < other.ip
221 or self.netmask < other.netmask)
222 except AttributeError:
223 return NotImplemented
224
225 def __gt__(self, other):
226 try:
227 return (self.version > other.version
228 or self.ip > other.ip
229 or self.netmask > other.netmask)
230 except AttributeError:
231 return NotImplemented
232
233 def __eq__(self, other):
234 try:
235 return (self.version == other.version
236 and self.ip == other.ip
237 and self.netmask == other.netmask)
238 except AttributeError:
239 return NotImplemented
240
241 def __ne__(self, other):
242 eq = self.__eq__(other)
243 if eq is NotImplemented:
244 return NotImplemented
245 return not eq
246
247 def __le__(self, other):
248 gt = self.__gt__(other)
249 if gt is NotImplemented:
250 return NotImplemented
251 return not gt
252
253 def __ge__(self, other):
254 lt = self.__lt__(other)
255 if lt is NotImplemented:
256 return NotImplemented
257 return not lt
258
259 def __repr__(self):
260 return '%s(%r)' % (self.__class__.__name__, str(self))
261
262 def __index__(self):
263 return self.ip
264
265 def __int__(self):
266 return self.ip
267
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000268 def address_exclude(self, other):
269 """Remove an address from a larger block.
270
271 For example:
272
273 addr1 = IP('10.1.1.0/24')
274 addr2 = IP('10.1.1.0/26')
275 addr1.address_exclude(addr2) =
276 [IP('10.1.1.64/26'), IP('10.1.1.128/25')]
277
278 or IPv6:
279
280 addr1 = IP('::1/32')
281 addr2 = IP('::1/128')
282 addr1.address_exclude(addr2) = [IP('::0/128'),
283 IP('::2/127'),
284 IP('::4/126'),
285 IP('::8/125'),
286 ...
287 IP('0:0:8000::/33')]
288
289 Args:
290 other: An IP object of the same type.
291
292 Returns:
293 A sorted list of IP objects addresses which is self minus
294 other.
295
296 Raises:
297 IPTypeError: If self and other are of difffering address
298 versions.
299 IPAddressExclusionError: There was some unknown error in the
300 address exclusion process. This likely points to a bug
301 elsewhere in this code.
302 ValueError: If other is not completely contained by self.
303
304 """
305 if not self.version == other.version:
306 raise IPTypeError("%s and %s aren't of the same version" % (
307 str(self), str(other)))
308
309 if other not in self:
310 raise ValueError('%s not contained in %s' % (str(other),
311 str(self)))
312
313 ret_addrs = []
314
315 # Make sure we're comparing the network of other.
316 other = IP(other.network_ext + '/' + str(other.prefixlen))
317
318 s1, s2 = self.subnet()
319 while s1 != other and s2 != other:
320 if other in s1:
321 ret_addrs.append(s2)
322 s1, s2 = s1.subnet()
323 elif other in s2:
324 ret_addrs.append(s1)
325 s1, s2 = s2.subnet()
326 else:
327 # If we got here, there's a bug somewhere.
328 raise IPAddressExclusionError('Error performing exclusion: '
329 's1: %s s2: %s other: %s' %
330 (str(s1), str(s2), str(other)))
331 if s1 == other:
332 ret_addrs.append(s2)
333 elif s2 == other:
334 ret_addrs.append(s1)
335 else:
336 # If we got here, there's a bug somewhere.
337 raise IPAddressExclusionError('Error performing exclusion: '
338 's1: %s s2: %s other: %s' %
339 (str(s1), str(s2), str(other)))
340
341 return sorted(ret_addrs, key=BaseIP._get_networks_key)
342
343 def compare_networks(self, other):
344 """Compare two IP objects.
345
346 This is only concerned about the comparison of the integer
347 representation of the network addresses. This means that the
348 host bits aren't considered at all in this method. If you want
349 to compare host bits, you can easily enough do a
350 'HostA.ip < HostB.ip'
351
352 Args:
353 other: An IP object.
354
355 Returns:
356 If the IP versions of self and other are the same, returns:
357
358 -1 if self < other:
359 eg: IPv4('1.1.1.0/24') < IPv4('1.1.2.0/24')
360 IPv6('1080::200C:417A') < IPv6('1080::200B:417B')
361 0 if self == other
362 eg: IPv4('1.1.1.1/24') == IPv4('1.1.1.2/24')
363 IPv6('1080::200C:417A/96') == IPv6('1080::200C:417B/96')
364 1 if self > other
365 eg: IPv4('1.1.1.0/24') > IPv4('1.1.0.0/24')
366 IPv6('1080::1:200C:417A/112') >
367 IPv6('1080::0:200C:417A/112')
368
369 If the IP versions of self and other are different, returns:
370
371 -1 if self.version < other.version
372 eg: IPv4('10.0.0.1/24') < IPv6('::1/128')
373 1 if self.version > other.version
374 eg: IPv6('::1/128') > IPv4('255.255.255.0/24')
375
376 """
377 if self.version < other.version:
378 return -1
379 if self.version > other.version:
380 return 1
381 # self.version == other.version below here:
382 if self.network < other.network:
383 return -1
384 if self.network > other.network:
385 return 1
386 # self.network == other.network below here:
387 if self.netmask < other.netmask:
388 return -1
389 if self.netmask > other.netmask:
390 return 1
391 # self.network == other.network and self.netmask == other.netmask
392 return 0
393
394 def _get_networks_key(self):
395 """Network-only key function.
396
397 Returns an object that identifies this address' network and
398 netmask. This function is a suitable "key" argument for sorted()
399 and list.sort().
400
401 """
402 return (self.version, self.network, self.netmask)
403
404 prefixlen = property(
405 fget=lambda self: self._prefixlen,
406 fset=lambda self, prefixlen: self._set_prefix(prefixlen))
407
408 def __str__(self):
409 return '%s/%s' % (self._string_from_ip_int(self.ip),
410 str(self.prefixlen))
411
412 def __hash__(self):
413 return hash(self.ip ^ self.netmask)
414
415 def __contains__(self, other):
416 return self.network <= other.ip and self.broadcast >= other.broadcast
417
418 @property
419 def ip_ext(self):
420 """Dotted decimal or colon string version of the IP address."""
421 return self._string_from_ip_int(self.ip)
422
423 @property
424 def ip_ext_full(self):
425 """Canonical string version of the IP address."""
426 return self.ip_ext
427
428 @property
429 def broadcast(self):
430 """Integer representation of the broadcast address."""
431 return self.ip | self.hostmask
432
433 @property
434 def broadcast_ext(self):
435 """Dotted decimal or colon string version of the broadcast."""
436 return self._string_from_ip_int(self.broadcast)
437
438 @property
439 def hostmask(self):
440 """Integer representation of the hostmask."""
441 return self.netmask ^ self._ALL_ONES
442
443 @property
444 def hostmask_ext(self):
445 """Dotted decimal or colon string version of the hostmask."""
446 return self._string_from_ip_int(self.hostmask)
447
448 @property
449 def network(self):
450 """Integer representation of the network."""
451 return self.ip & self.netmask
452
453 @property
454 def network_ext(self):
455 """Dotted decimal or colon string version of the network."""
456 return self._string_from_ip_int(self.network)
457
458 @property
459 def netmask_ext(self):
460 """Dotted decimal or colon string version of the netmask."""
461 return self._string_from_ip_int(self.netmask)
462
463 @property
464 def numhosts(self):
465 """Number of hosts in the current subnet."""
466 return self.broadcast - self.network + 1
467
468 @property
469 def version(self):
470 raise NotImplementedError('BaseIP has no version')
471
472 def _ip_int_from_prefix(self, prefixlen=None):
473 """Turn the prefix length netmask into a int for comparison.
474
475 Args:
476 prefixlen: An integer, the prefix length.
477
478 Returns:
479 An integer.
480
481 """
482 if not prefixlen and prefixlen != 0:
483 prefixlen = self.prefixlen
484 return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen)
485
486 def _prefix_from_ip_int(self, ip_int, mask=32):
487 """Return prefix length from the decimal netmask.
488
489 Args:
490 ip_int: An integer, the IP address.
491 mask: The netmask. Defaults to 32.
492
493 Returns:
494 An integer, the prefix length.
495
496 """
497 while mask:
498 if ip_int & 1 == 1:
499 break
500 ip_int >>= 1
501 mask -= 1
502
503 return mask
504
505 def _ip_string_from_prefix(self, prefixlen=None):
506 """Turn a prefix length into a dotted decimal string.
507
508 Args:
509 prefixlen: An integer, the netmask prefix length.
510
511 Returns:
512 A string, the dotted decimal netmask string.
513
514 """
515 if not prefixlen:
516 prefixlen = self.prefixlen
517 return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen))
518
519
520class IPv4(BaseIP):
521
522 """This class represents and manipulates 32-bit IPv4 addresses.
523
524 Attributes: [examples for IPv4('1.2.3.4/27')]
525 .ip: 16909060
526 .ip_ext: '1.2.3.4'
527 .ip_ext_full: '1.2.3.4'
528 .network: 16909056L
529 .network_ext: '1.2.3.0'
530 .hostmask: 31L (0x1F)
531 .hostmask_ext: '0.0.0.31'
532 .broadcast: 16909087L (0x102031F)
533 .broadcast_ext: '1.2.3.31'
534 .netmask: 4294967040L (0xFFFFFFE0)
535 .netmask_ext: '255.255.255.224'
536 .prefixlen: 27
537
538 """
539
540 # Equivalent to 255.255.255.255 or 32 bits of 1's.
541 _ALL_ONES = 0xffffffff
Gregory P. Smith75930f82009-05-03 19:38:29 +0000542 _version = 4
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000543
544 def __init__(self, ipaddr):
545 """Instantiate a new IPv4 object.
546
547 Args:
548 ipaddr: A string or integer representing the IP [& network].
549 '192.168.1.1/32'
550 '192.168.1.1/255.255.255.255'
551 '192.168.1.1/0.0.0.255'
552 '192.168.1.1'
553 are all functionally the same in IPv4. That is to say,
554 failing to provide a subnetmask will create an object with
555 a mask of /32. A netmask of '255.255.255.255' is assumed
556 to be /32 and '0.0.0.0' is assumed to be /0, even though
557 other netmasks can be expressed both as host- and
558 net-masks. (255.0.0.0 == 0.255.255.255)
559
560 Additionally, an integer can be passed, so
561 IPv4('192.168.1.1') == IPv4(3232235777).
562 or, more generally
563 IPv4(IPv4('192.168.1.1').ip) == IPv4('192.168.1.1')
564
565 Raises:
566 IPv4IpValidationError: If ipaddr isn't a valid IPv4 address.
567 IPv4NetmaskValidationError: If the netmask isn't valid for
568 an IPv4 address.
569
570 """
571 BaseIP.__init__(self)
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000572
573 # Efficient constructor from integer.
Gregory P. Smith02953d22009-05-02 18:35:58 +0000574 if isinstance(ipaddr, int):
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000575 self.ip = ipaddr
576 self._prefixlen = 32
577 self.netmask = self._ALL_ONES
578 if ipaddr < 0 or ipaddr > self._ALL_ONES:
579 raise IPv4IpValidationError(ipaddr)
580 return
581
Gregory P. Smith02953d22009-05-02 18:35:58 +0000582 # Constructing from a packed address
583 if isinstance(ipaddr, (bytes, bytearray)) and len(ipaddr) == 4:
Benjamin Petersonb83819f2009-05-02 18:10:37 +0000584 self.ip = struct.unpack('!I', ipaddr)[0]
585 self._prefixlen = 32
586 self.netmask = self._ALL_ONES
587 return
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000588
589 # Assume input argument to be string or any object representation
590 # which converts into a formatted IP prefix string.
591 addr = str(ipaddr).split('/')
592
593 if len(addr) > 2:
594 raise IPv4IpValidationError(ipaddr)
595
596 if not self._is_valid_ip(addr[0]):
597 raise IPv4IpValidationError(addr[0])
598
599 self.ip = self._ip_int_from_string(addr[0])
600
601 if len(addr) == 2:
602 mask = addr[1].split('.')
603 if len(mask) == 4:
604 # We have dotted decimal netmask.
605 if not self._is_valid_netmask(addr[1]):
606 raise IPv4NetmaskValidationError(addr[1])
607 if self._is_hostmask(addr[1]):
608 self.netmask = (
609 self._ip_int_from_string(addr[1]) ^ self._ALL_ONES)
610 else:
611 self.netmask = self._ip_int_from_string(addr[1])
612 self._prefixlen = self._prefix_from_ip_int(self.netmask)
613 else:
614 # We have a netmask in prefix length form.
615 if not self._is_valid_netmask(addr[1]):
616 raise IPv4NetmaskValidationError(addr[1])
617 self._prefixlen = int(addr[1])
618 self.netmask = self._ip_int_from_prefix(self._prefixlen)
619 else:
620 self._prefixlen = 32
621 self.netmask = self._ip_int_from_prefix(self._prefixlen)
622
623 def _set_prefix(self, prefixlen):
624 """Change the prefix length.
625
626 Args:
627 prefixlen: An integer, the new prefix length.
628
629 Raises:
630 IPv4NetmaskValidationError: If prefixlen is out of bounds.
631
632 """
633 if not 0 <= prefixlen <= 32:
634 raise IPv4NetmaskValidationError(prefixlen)
635 self._prefixlen = prefixlen
636 self.netmask = self._ip_int_from_prefix(self._prefixlen)
637
638 def subnet(self, prefixlen_diff=1):
639 """The subnets which join to make the current subnet.
640
641 In the case that self contains only one IP
642 (self._prefixlen == 32), return a list with just ourself.
643
644 Args:
645 prefixlen_diff: An integer, the amount the prefix length
646 should be increased by. Given a /24 network and a
647 prefixlen_diff of 3, for example, 8 subnets of size /27
648 will be returned. The default value of 1 splits the
649 current network into two halves.
650
651 Returns:
652 A list of IPv4 objects.
653
654 Raises:
655 PrefixlenDiffInvalidError: The prefixlen_diff is too small
656 or too large.
657
658 """
659 if self._prefixlen == 32:
660 return [self]
661
662 if prefixlen_diff < 0:
663 raise PrefixlenDiffInvalidError('prefix length diff must be > 0')
664 new_prefixlen = self.prefixlen + prefixlen_diff
665
666 if not self._is_valid_netmask(str(new_prefixlen)):
667 raise PrefixlenDiffInvalidError(
668 'prefix length diff %d is invalid for netblock %s' % (
669 new_prefixlen, str(self)))
670
671 first = IPv4(
672 self._string_from_ip_int(self.network) + '/' +
673 str(self._prefixlen + prefixlen_diff))
674 subnets = [first]
675 current = first
676 while True:
677 broadcast = current.broadcast
678 if broadcast == self.broadcast:
679 break
680 current = IPv4(self._string_from_ip_int(broadcast + 1) + '/' +
681 str(new_prefixlen))
682 subnets.append(current)
683
684 return subnets
685
686 def supernet(self, prefixlen_diff=1):
687 """The supernet containing the current network.
688
689 Args:
690 prefixlen_diff: An integer, the amount the prefix length of
691 the network should be decreased by. For example, given a
692 /24 network and a prefixlen_diff of 3, a supernet with a
693 /21 netmask is returned.
694
695 Returns:
696 An IPv4 object.
697
698 Raises:
699 PrefixlenDiffInvalidError: If
700 self.prefixlen - prefixlen_diff < 0. I.e., you have a
701 negative prefix length.
702
703 """
704 if self.prefixlen == 0:
705 return self
706 if self.prefixlen - prefixlen_diff < 0:
707 raise PrefixlenDiffInvalidError(
708 'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
709 (self.prefixlen, prefixlen_diff))
710 return IPv4(self.ip_ext + '/' + str(self.prefixlen - prefixlen_diff))
711
712 @property
713 def is_private(self):
714 """Test if this address is allocated for private networks.
715
716 Returns:
717 A boolean, True if the address is reserved per RFC 1918.
718
719 """
Gregory P. Smith75930f82009-05-03 19:38:29 +0000720 for network in _IPV4_RFC1918_NETWORKS:
721 if self in network:
722 return True
723 return False
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000724
725 @property
726 def is_multicast(self):
727 """Test if the address is reserved for multicast use.
728
729 Returns:
730 A boolean, True if the address is multicast.
731 See RFC 3171 for details.
732
733 """
Gregory P. Smith75930f82009-05-03 19:38:29 +0000734 return self in _IPV4_RFC3171_MULTICAST
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000735
736 @property
737 def is_loopback(self):
738 """Test if the address is a loopback adddress.
739
740 Returns:
741 A boolean, True if the address is a loopback per RFC 3330.
742
743 """
Gregory P. Smith75930f82009-05-03 19:38:29 +0000744 return self in _IPV4_RFC3330_LOOPBACK
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000745
746 @property
747 def is_link_local(self):
748 """Test if the address is reserved for link-local.
749
750 Returns:
751 A boolean, True if the address is link-local per RFC 3927.
752
753 """
Gregory P. Smith75930f82009-05-03 19:38:29 +0000754 return self in _IPV4_RFC3927_LINK_LOCAL
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000755
756 @property
757 def version(self):
758 return self._version
759
760 @property
761 def packed(self):
762 """The binary representation of this address."""
763 return struct.pack('!I', self.ip)
764
765 def _is_hostmask(self, ip_str):
766 """Test if the IP string is a hostmask (rather than a netmask).
767
768 Args:
769 ip_str: A string, the potential hostmask.
770
771 Returns:
772 A boolean, True if the IP string is a hostmask.
773
774 """
775 parts = [int(x) for x in ip_str.split('.')]
776 if parts[0] < parts[-1]:
777 return True
778 return False
779
780 def _ip_int_from_string(self, ip_str):
781 """Turn the given IP string into an integer for comparison.
782
783 Args:
784 ip_str: A string, the IP address.
785
786 Returns:
787 The IP address as an integer.
788
789 """
790 packed_ip = 0
791 for oc in ip_str.split('.'):
792 packed_ip = (packed_ip << 8) | int(oc)
793 return packed_ip
794
795 def _string_from_ip_int(self, ip_int):
796 """Turns a 32-bit integer into dotted decimal notation.
797
798 Args:
799 ip_int: An integer, the IP address.
800
801 Returns:
802 The IP address as a string in dotted decimal notation.
803
804 """
805 octets = []
806 for _ in range(4):
807 octets.insert(0, str(ip_int & 0xFF))
808 ip_int >>= 8
809 return '.'.join(octets)
810
811 def _is_valid_ip(self, ip_str):
812 """Validate the dotted decimal notation IP/netmask string.
813
814 Args:
815 ip_str: A string, the IP address.
816
817 Returns:
818 A boolean, True if the string is a valid dotted decimal IP
819 string.
820
821 """
822 octets = ip_str.split('.')
823 if len(octets) == 1:
824 # We have an integer rather than a dotted decimal IP.
825 try:
826 return int(ip_str) >= 0 and int(ip_str) <= self._ALL_ONES
827 except ValueError:
828 return False
829
830 if len(octets) != 4:
831 return False
832
833 for octet in octets:
834 try:
835 if not 0 <= int(octet) <= 255:
836 return False
837 except ValueError:
838 return False
839 return True
840
841 def _is_valid_netmask(self, netmask):
842 """Verify that the netmask is valid.
843
844 Args:
845 netmask: A string, either a prefix or dotted decimal
846 netmask.
847
848 Returns:
849 A boolean, True if the prefix represents a valid IPv4
850 netmask.
851
852 """
853 if len(netmask.split('.')) == 4:
854 return self._is_valid_ip(netmask)
855 try:
856 netmask = int(netmask)
857 except ValueError:
858 return False
859 return 0 <= netmask <= 32
860
861
862class IPv6(BaseIP):
863
864 """This class respresents and manipulates 128-bit IPv6 addresses.
865
866 Attributes: [examples for IPv6('2001:658:22A:CAFE:200::1/64')]
867 .ip: 42540616829182469433547762482097946625L
868 .ip_ext: '2001:658:22a:cafe:200::1'
869 .ip_ext_full: '2001:0658:022a:cafe:0200:0000:0000:0001'
870 .network: 42540616829182469433403647294022090752L
871 .network_ext: '2001:658:22a:cafe::'
872 .hostmask: 18446744073709551615L
873 .hostmask_ext: '::ffff:ffff:ffff:ffff'
874 .broadcast: 42540616829182469451850391367731642367L
875 .broadcast_ext: '2001:658:22a:cafe:ffff:ffff:ffff:ffff'
876 .netmask: 340282366920938463444927863358058659840L
877 .netmask_ext: 64
878 .prefixlen: 64
879
880 """
881
882 _ALL_ONES = (2**128) - 1
Gregory P. Smith75930f82009-05-03 19:38:29 +0000883 _version = 6
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000884
885 def __init__(self, ipaddr):
886 """Instantiate a new IPv6 object.
887
888 Args:
889 ipaddr: A string or integer representing the IP or the IP
890 and prefix/netmask.
891 '2001:4860::/128'
892 '2001:4860:0000:0000:0000:0000:0000:0000/128'
893 '2001:4860::'
894 are all functionally the same in IPv6. That is to say,
895 failing to provide a subnetmask will create an object with
896 a mask of /128.
897
898 Additionally, an integer can be passed, so
899 IPv6('2001:4860::') ==
900 IPv6(42541956101370907050197289607612071936L).
901 or, more generally
902 IPv6(IPv6('2001:4860::').ip) == IPv6('2001:4860::')
903
904 Raises:
905 IPv6IpValidationError: If ipaddr isn't a valid IPv6 address.
906 IPv6NetmaskValidationError: If the netmask isn't valid for
907 an IPv6 address.
908
909 """
910 BaseIP.__init__(self)
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000911
912 # Efficient constructor from integer.
Gregory P. Smith02953d22009-05-02 18:35:58 +0000913 if isinstance(ipaddr, int):
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000914 self.ip = ipaddr
915 self._prefixlen = 128
916 self.netmask = self._ALL_ONES
917 if ipaddr < 0 or ipaddr > self._ALL_ONES:
918 raise IPv6IpValidationError(ipaddr)
919 return
920
Gregory P. Smith02953d22009-05-02 18:35:58 +0000921 # Constructing from a packed address
922 if isinstance(ipaddr, (bytes, bytearray)) and len(ipaddr) == 16:
Benjamin Petersonb83819f2009-05-02 18:10:37 +0000923 tmp = struct.unpack('!QQ', ipaddr)
924 self.ip = (tmp[0] << 64) | tmp[1]
925 self._prefixlen = 128
926 self.netmask = self._ALL_ONES
927 return
Gregory P. Smithe54dff52009-05-01 22:13:48 +0000928
929 # Assume input argument to be string or any object representation
930 # which converts into a formatted IP prefix string.
931 addr_str = str(ipaddr)
932 if not addr_str:
933 raise IPv6IpValidationError('')
934 addr = addr_str.split('/')
935 if len(addr) > 1:
936 if self._is_valid_netmask(addr[1]):
937 self._prefixlen = int(addr[1])
938 else:
939 raise IPv6NetmaskValidationError(addr[1])
940 else:
941 self._prefixlen = 128
942
943 self.netmask = self._ip_int_from_prefix(self._prefixlen)
944
945 if not self._is_valid_ip(addr[0]):
946 raise IPv6IpValidationError(addr[0])
947
948 self.ip = self._ip_int_from_string(addr[0])
949
950 @property
951 def ip_ext_full(self):
952 """Returns the expanded version of the IPv6 string."""
953 return self._explode_shorthand_ip_string(self.ip_ext)
954
955 def _set_prefix(self, prefixlen):
956 """Change the prefix length.
957
958 Args:
959 prefixlen: An integer, the new prefix length.
960
961 Raises:
962 IPv6NetmaskValidationError: If prefixlen is out of bounds.
963
964 """
965 if not 0 <= prefixlen <= 128:
966 raise IPv6NetmaskValidationError(prefixlen)
967 self._prefixlen = prefixlen
968 self.netmask = self._ip_int_from_prefix(self.prefixlen)
969
970 def subnet(self, prefixlen_diff=1):
971 """The subnets which join to make the current subnet.
972
973 In the case that self contains only one IP
974 (self._prefixlen == 128), return a list with just ourself.
975
976 Args:
977 prefixlen_diff: An integer, the amount the prefix length
978 should be increased by.
979
980 Returns:
981 A list of IPv6 objects.
982
983 Raises:
984 PrefixlenDiffInvalidError: The prefixlen_diff is too small
985 or too large.
986
987 """
988 # Preserve original functionality (return [self] if
989 # self.prefixlen == 128).
990 if self.prefixlen == 128:
991 return [self]
992
993 if prefixlen_diff < 0:
994 raise PrefixlenDiffInvalidError('Prefix length diff must be > 0')
995 new_prefixlen = self.prefixlen + prefixlen_diff
996 if not self._is_valid_netmask(str(new_prefixlen)):
997 raise PrefixlenDiffInvalidError(
998 'Prefix length diff %d is invalid for netblock %s' % (
999 new_prefixlen, str(self)))
1000 first = IPv6(
1001 self._string_from_ip_int(self.network) + '/' +
1002 str(self._prefixlen + prefixlen_diff))
1003 subnets = [first]
1004 current = first
1005 while True:
1006 broadcast = current.broadcast
1007 if current.broadcast == self.broadcast:
1008 break
1009 current = IPv6(self._string_from_ip_int(broadcast + 1) + '/' +
1010 str(new_prefixlen))
1011 subnets.append(current)
1012
1013 return subnets
1014
1015 def supernet(self, prefixlen_diff=1):
1016 """The supernet containing the current network.
1017
1018 Args:
1019 prefixlen_diff: An integer, the amount the prefix length of the
1020 network should be decreased by. For example, given a /96
1021 network and a prefixlen_diff of 3, a supernet with a /93
1022 netmask is returned.
1023
1024 Returns:
1025 An IPv6 object.
1026
1027 Raises:
1028 PrefixlenDiffInvalidError: If
1029 self._prefixlen - prefixlen_diff < 0. I.e., you have a
1030 negative prefix length.
1031
1032 """
1033 if self.prefixlen == 0:
1034 return self
1035 if self.prefixlen - prefixlen_diff < 0:
1036 raise PrefixlenDiffInvalidError(
1037 'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
1038 (self.prefixlen, prefixlen_diff))
1039 return IPv6(self.ip_ext + '/' + str(self.prefixlen - prefixlen_diff))
1040
1041 @property
1042 def is_multicast(self):
1043 """Test if the address is reserved for multicast use.
1044
1045 Returns:
1046 A boolean, True if the address is a multicast address.
1047 See RFC 2373 2.7 for details.
1048
1049 """
Gregory P. Smith75930f82009-05-03 19:38:29 +00001050 return self in _IPV6_RFC2373_MULTICAST
Gregory P. Smithe54dff52009-05-01 22:13:48 +00001051
1052 @property
1053 def is_unspecified(self):
1054 """Test if the address is unspecified.
1055
1056 Returns:
1057 A boolean, True if this is the unspecified address as defined in
1058 RFC 2373 2.5.2.
1059
1060 """
Gregory P. Smith75930f82009-05-03 19:38:29 +00001061 return self == _IPV6_RFC2373_UNSPECIFIED
Gregory P. Smithe54dff52009-05-01 22:13:48 +00001062
1063 @property
1064 def is_loopback(self):
1065 """Test if the address is a loopback adddress.
1066
1067 Returns:
1068 A boolean, True if the address is a loopback address as defined in
1069 RFC 2373 2.5.3.
1070
1071 """
Gregory P. Smith75930f82009-05-03 19:38:29 +00001072 return self == _IPV6_RFC2373_LOOPBACK
Gregory P. Smithe54dff52009-05-01 22:13:48 +00001073
1074 @property
1075 def is_link_local(self):
1076 """Test if the address is reserved for link-local.
1077
1078 Returns:
1079 A boolean, True if the address is reserved per RFC 4291.
1080
1081 """
Gregory P. Smith75930f82009-05-03 19:38:29 +00001082 return self in _IPV6_RFC4291_LINK_LOCAL
Gregory P. Smithe54dff52009-05-01 22:13:48 +00001083
1084 @property
1085 def is_site_local(self):
1086 """Test if the address is reserved for site-local.
1087
1088 Note that the site-local address space has been deprecated by RFC 3879.
1089 Use is_private to test if this address is in the space of unique local
1090 addresses as defined by RFC 4193.
1091
1092 Returns:
1093 A boolean, True if the address is reserved per RFC 3513 2.5.6.
1094
1095 """
Gregory P. Smith75930f82009-05-03 19:38:29 +00001096 return self in _IPV6_RFC3513_SITE_LOCAL
Gregory P. Smithe54dff52009-05-01 22:13:48 +00001097
1098 @property
1099 def is_private(self):
1100 """Test if this address is allocated for private networks.
1101
1102 Returns:
1103 A boolean, True if the address is reserved per RFC 4193.
1104
1105 """
Gregory P. Smith75930f82009-05-03 19:38:29 +00001106 return self in _IPV6_RFC4193_PRIVATE
Gregory P. Smithe54dff52009-05-01 22:13:48 +00001107
1108 @property
1109 def version(self):
1110 return self._version
1111
1112 @property
1113 def packed(self):
1114 """The binary representation of this address."""
1115 return struct.pack('!QQ', self.ip >> 64, self.ip & (2**64 - 1))
1116
1117 def _is_shorthand_ip(self, ip_str=None):
1118 """Determine if the address is shortened.
1119
1120 Args:
1121 ip_str: A string, the IPv6 address.
1122
1123 Returns:
1124 A boolean, True if the address is shortened.
1125
1126 """
1127 if ip_str.count('::') == 1:
1128 return True
1129 return False
1130
1131 def _explode_shorthand_ip_string(self, ip_str):
1132 """Expand a shortened IPv6 address.
1133
1134 Args:
1135 ip_str: A string, the IPv6 address.
1136
1137 Returns:
1138 A string, the expanded IPv6 address.
1139
1140 """
1141 if self._is_shorthand_ip(ip_str):
1142 new_ip = []
1143 hextet = ip_str.split('::')
1144 sep = len(hextet[0].split(':')) + len(hextet[1].split(':'))
1145 new_ip = hextet[0].split(':')
1146
1147 for _ in range(8 - sep):
1148 new_ip.append('0000')
1149 new_ip += hextet[1].split(':')
1150
1151 # Now need to make sure every hextet is 4 lower case characters.
1152 # If a hextet is < 4 characters, we've got missing leading 0's.
1153 ret_ip = []
1154 for hextet in new_ip:
1155 ret_ip.append(('0' * (4 - len(hextet)) + hextet).lower())
1156 return ':'.join(ret_ip)
1157 # We've already got a longhand ip_str.
1158 return ip_str
1159
1160 def _is_valid_ip(self, ip_str=None):
1161 """Ensure we have a valid IPv6 address.
1162
1163 Probably not as exhaustive as it should be.
1164
1165 Args:
1166 ip_str: A string, the IPv6 address.
1167
1168 Returns:
1169 A boolean, True if this is a valid IPv6 address.
1170
1171 """
1172 if not ip_str:
1173 ip_str = self.ip_ext
1174
1175 # We need to have at least one ':'.
1176 if ':' not in ip_str:
1177 return False
1178
1179 # We can only have one '::' shortener.
1180 if ip_str.count('::') > 1:
1181 return False
1182
1183 # '::' should be encompassed by start, digits or end.
1184 if ':::' in ip_str:
1185 return False
1186
1187 # A single colon can neither start nor end an address.
1188 if ((ip_str.startswith(':') and not ip_str.startswith('::')) or
1189 (ip_str.endswith(':') and not ip_str.endswith('::'))):
1190 return False
1191
1192 # If we have no concatenation, we need to have 8 fields with 7 ':'.
1193 if '::' not in ip_str and ip_str.count(':') != 7:
1194 # We might have an IPv4 mapped address.
1195 if ip_str.count('.') != 3:
1196 return False
1197
1198 ip_str = self._explode_shorthand_ip_string(ip_str)
1199
1200 # Now that we have that all squared away, let's check that each of the
1201 # hextets are between 0x0 and 0xFFFF.
1202 for hextet in ip_str.split(':'):
1203 if hextet.count('.') == 3:
1204 # If we have an IPv4 mapped address, the IPv4 portion has to be
1205 # at the end of the IPv6 portion.
1206 if not ip_str.split(':')[-1] == hextet:
1207 return False
1208 try:
1209 IPv4(hextet)
1210 except IPv4IpValidationError:
1211 return False
1212 elif int(hextet, 16) < 0x0 or int(hextet, 16) > 0xFFFF:
1213 return False
1214 return True
1215
1216 def _is_valid_netmask(self, prefixlen):
1217 """Verify that the netmask/prefixlen is valid.
1218
1219 Args:
1220 prefixlen: A string, the netmask in prefix length format.
1221
1222 Returns:
1223 A boolean, True if the prefix represents a valid IPv6
1224 netmask.
1225
1226 """
1227 try:
1228 prefixlen = int(prefixlen)
1229 except ValueError:
1230 return False
1231 return 0 <= prefixlen <= 128
1232
1233 def _ip_int_from_string(self, ip_str=None):
1234 """Turn an IPv6 address into an integer.
1235
1236 Args:
1237 ip_str: A string, the IPv6 address.
1238
1239 Returns:
1240 A long, the IPv6 address.
1241
1242 """
1243 if not ip_str:
1244 ip_str = self.ip_ext
1245
1246 ip_int = 0
1247
1248 fields = self._explode_shorthand_ip_string(ip_str).split(':')
1249
1250 # Do we have an IPv4 mapped (::ffff:a.b.c.d) or compact (::a.b.c.d)
1251 # address?
1252 if fields[-1].count('.') == 3:
1253 ipv4_string = fields.pop()
1254 ipv4_int = IPv4(ipv4_string).ip
1255 octets = []
1256 for _ in range(2):
1257 octets.append(hex(ipv4_int & 0xFFFF).lstrip('0x').rstrip('L'))
1258 ipv4_int >>= 16
1259 fields.extend(reversed(octets))
1260
1261 for field in fields:
1262 ip_int = (ip_int << 16) + int(field, 16)
1263
1264 return ip_int
1265
1266 def _compress_hextets(self, hextets):
1267 """Compresses a list of hextets.
1268
1269 Compresses a list of strings, replacing the longest continuous
1270 sequence of "0" in the list with "" and adding empty strings at
1271 the beginning or at the end of the string such that subsequently
1272 calling ":".join(hextets) will produce the compressed version of
1273 the IPv6 address.
1274
1275 Args:
1276 hextets: A list of strings, the hextets to compress.
1277
1278 Returns:
1279 A list of strings.
1280
1281 """
1282 best_doublecolon_start = -1
1283 best_doublecolon_len = 0
1284 doublecolon_start = -1
1285 doublecolon_len = 0
1286 for index in range(len(hextets)):
1287 if hextets[index] == '0':
1288 doublecolon_len += 1
1289 if doublecolon_start == -1:
1290 # Start of a sequence of zeros.
1291 doublecolon_start = index
1292 if doublecolon_len > best_doublecolon_len:
1293 # This is the longest sequence of zeros so far.
1294 best_doublecolon_len = doublecolon_len
1295 best_doublecolon_start = doublecolon_start
1296 else:
1297 doublecolon_len = 0
1298 doublecolon_start = -1
1299
1300 if best_doublecolon_len > 1:
1301 best_doublecolon_end = (best_doublecolon_start +
1302 best_doublecolon_len)
1303 # For zeros at the end of the address.
1304 if best_doublecolon_end == len(hextets):
1305 hextets += ['']
1306 hextets[best_doublecolon_start:best_doublecolon_end] = ['']
1307 # For zeros at the beginning of the address.
1308 if best_doublecolon_start == 0:
1309 hextets = [''] + hextets
1310
1311 return hextets
1312
1313 def _string_from_ip_int(self, ip_int=None):
1314 """Turns a 128-bit integer into hexadecimal notation.
1315
1316 Args:
1317 ip_int: An integer, the IP address.
1318
1319 Returns:
1320 A string, the hexadecimal representation of the address.
1321
1322 Raises:
1323 ValueError: The address is bigger than 128 bits of all ones.
1324
1325 """
1326 if not ip_int and ip_int != 0:
1327 ip_int = self.ip
1328
1329 if ip_int > self._ALL_ONES:
1330 raise ValueError('IPv6 address is too large')
1331
1332 hex_str = '%032x' % ip_int
1333 hextets = []
1334 for x in range(0, 32, 4):
1335 hextets.append('%x' % int(hex_str[x:x+4], 16))
1336
1337 hextets = self._compress_hextets(hextets)
1338 return ':'.join(hextets)
1339
1340 @property
1341 def netmask_ext(self):
1342 """IPv6 extended netmask.
1343
1344 We don't deal with netmasks in IPv6 like we do in IPv4. This is
1345 here strictly for IPv4 compatibility. We simply return the
1346 prefix length.
1347
1348 Returns:
1349 An integer.
1350
1351 """
1352 return self.prefixlen
Gregory P. Smith75930f82009-05-03 19:38:29 +00001353
1354
1355# IPv4 constants.
1356_IPV4_RFC1918_NETWORKS = (IPv4('10.0.0.0/8'),
1357 IPv4('172.16.0.0/12'),
1358 IPv4('192.168.0.0/16'))
1359_IPV4_RFC3171_MULTICAST = IPv4('224.0.0.0/4')
1360_IPV4_RFC3330_LOOPBACK = IPv4('127.0.0.0/8')
1361_IPV4_RFC3927_LINK_LOCAL = IPv4('169.254.0.0/16')
1362
1363# IPv6 constants.
1364_IPV6_RFC2373_MULTICAST = IPv6('ff00::/8')
1365_IPV6_RFC2373_UNSPECIFIED = IPv6('::')
1366_IPV6_RFC2373_LOOPBACK = IPv6('::1')
1367_IPV6_RFC4291_LINK_LOCAL = IPv6('fe80::/10')
1368_IPV6_RFC3513_SITE_LOCAL = IPv6('fec0::/10') # Deprecated by RFC3879.
1369_IPV6_RFC4193_PRIVATE = IPv6('fc00::/7')