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