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