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