1 # Copyright 2007 Google Inc.
2 # Licensed to PSF under a Contributor Agreement.
4 # See also: http://code.google.com/p/ipaddr-py/
6 """An IPv4/IPv6 manipulation library in Python.
8 This library is used to create/poke/manipulate IPv4 and IPv6 addresses
18 class Error(Exception):
20 """Base class for exceptions."""
23 class IPTypeError(Error
):
25 """Tried to perform a v4 action on v6 object or vice versa."""
28 class IPAddressExclusionError(Error
):
30 """An Error we should never see occurred in address exclusion."""
33 class IPv4IpValidationError(Error
):
35 """Raised when an IPv4 address is invalid."""
37 def __init__(self
, ip
):
42 return repr(self
.ip
) + ' is not a valid IPv4 address'
45 class IPv4NetmaskValidationError(Error
):
47 """Raised when a netmask is invalid."""
49 def __init__(self
, netmask
):
51 self
.netmask
= netmask
54 return repr(self
.netmask
) + ' is not a valid IPv4 netmask'
57 class IPv6IpValidationError(Error
):
59 """Raised when an IPv6 address is invalid."""
61 def __init__(self
, ip
):
66 return repr(self
.ip
) + ' is not a valid IPv6 address'
69 class IPv6NetmaskValidationError(Error
):
71 """Raised when an IPv6 netmask is invalid."""
73 def __init__(self
, netmask
):
75 self
.netmask
= netmask
78 return repr(self
.netmask
) + ' is not a valid IPv6 netmask'
81 class PrefixlenDiffInvalidError(Error
):
83 """Raised when Sub/Supernets is called with a bad prefixlen_diff."""
85 def __init__(self
, error_str
):
87 self
.error_str
= error_str
91 """Take an IP string/int and return an object of the correct type.
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.
99 An IPv4 or IPv6 object.
102 ValueError: if the string passed isn't either a v4 or a v6
109 except (IPv4IpValidationError
, IPv4NetmaskValidationError
):
114 except (IPv6IpValidationError
, IPv6NetmaskValidationError
):
117 raise ValueError('%r does not appear to be an IPv4 or IPv6 address' %
121 def _collapse_address_list_recursive(addresses
):
122 """Loops through the addresses, collapsing concurrent netblocks.
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')
133 _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) ->
134 [IPv4('1.1.0.0/22'), IPv4('1.1.4.0/24')]
136 This shouldn't be called directly; it is called via
137 collapse_address_list([]).
140 addresses: A list of IPv4 or IPv6 objects.
143 A list of IPv4 or IPv6 objects depending on what we were passed.
149 for cur_addr
in addresses
:
151 ret_array
.append(cur_addr
)
153 if cur_addr
in ret_array
[-1]:
155 elif cur_addr
== ret_array
[-1].supernet().subnet()[1]:
156 ret_array
.append(ret_array
.pop().supernet())
159 ret_array
.append(cur_addr
)
162 return _collapse_address_list_recursive(ret_array
)
167 def collapse_address_list(addresses
):
168 """Collapse a list of IP objects.
171 collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) ->
175 addresses: A list of IPv4 or IPv6 objects.
178 A list of IPv4 or IPv6 objects depending on what we were passed.
181 return _collapse_address_list_recursive(
182 sorted(addresses
, key
=BaseIP
._get
_networks
_key
))
185 class BaseIP(object):
187 """A generic IP object.
189 This IP class contains most of the methods which are used by
190 the IPv4 and IPv6 classes.
194 def __getitem__(self
, n
):
196 if self
.network
+ n
> self
.broadcast
:
198 return self
._string
_from
_ip
_int
(self
.network
+ n
)
201 if self
.broadcast
+ n
< self
.network
:
203 return self
._string
_from
_ip
_int
(self
.broadcast
+ n
)
205 def __lt__(self
, other
):
207 if self
.version
!= other
.version
:
208 return self
.version
< other
.version
209 if self
.ip
!= other
.ip
:
210 return self
.ip
< other
.ip
211 if self
.netmask
!= other
.netmask
:
212 return self
.netmask
< other
.netmask
214 except AttributeError:
215 return NotImplemented
217 def __gt__(self
, other
):
219 if self
.version
!= other
.version
:
220 return self
.version
> other
.version
221 if self
.ip
!= other
.ip
:
222 return self
.ip
> other
.ip
223 if self
.netmask
!= other
.netmask
:
224 return self
.netmask
> other
.netmask
226 except AttributeError:
227 return NotImplemented
229 def __eq__(self
, other
):
231 return (self
.version
== other
.version
232 and self
.ip
== other
.ip
233 and self
.netmask
== other
.netmask
)
234 except AttributeError:
235 return NotImplemented
237 def __ne__(self
, other
):
238 eq
= self
.__eq
__(other
)
239 if eq
is NotImplemented:
240 return NotImplemented
243 def __le__(self
, other
):
244 gt
= self
.__gt
__(other
)
245 if gt
is NotImplemented:
246 return NotImplemented
249 def __ge__(self
, other
):
250 lt
= self
.__lt
__(other
)
251 if lt
is NotImplemented:
252 return NotImplemented
256 return '%s(%r)' % (self
.__class
__.__name
__, str(self
))
265 return hex(int(self
))
267 def address_exclude(self
, other
):
268 """Remove an address from a larger block.
272 addr1 = IP('10.1.1.0/24')
273 addr2 = IP('10.1.1.0/26')
274 addr1.address_exclude(addr2) =
275 [IP('10.1.1.64/26'), IP('10.1.1.128/25')]
280 addr2 = IP('::1/128')
281 addr1.address_exclude(addr2) = [IP('::0/128'),
289 other: An IP object of the same type.
292 A sorted list of IP objects addresses which is self minus
296 IPTypeError: If self and other are of difffering address
298 IPAddressExclusionError: There was some unknown error in the
299 address exclusion process. This likely points to a bug
300 elsewhere in this code.
301 ValueError: If other is not completely contained by self.
304 if not self
.version
== other
.version
:
305 raise IPTypeError("%s and %s aren't of the same version" % (
306 str(self
), str(other
)))
308 if other
not in self
:
309 raise ValueError('%s not contained in %s' % (str(other
),
314 # Make sure we're comparing the network of other.
315 other
= IP(other
.network_ext
+ '/' + str(other
.prefixlen
))
317 s1
, s2
= self
.subnet()
318 while s1
!= other
and s2
!= other
:
326 # If we got here, there's a bug somewhere.
327 raise IPAddressExclusionError('Error performing exclusion: '
328 's1: %s s2: %s other: %s' %
329 (str(s1
), str(s2
), str(other
)))
335 # If we got here, there's a bug somewhere.
336 raise IPAddressExclusionError('Error performing exclusion: '
337 's1: %s s2: %s other: %s' %
338 (str(s1
), str(s2
), str(other
)))
340 return sorted(ret_addrs
, key
=BaseIP
._get
_networks
_key
)
342 def compare_networks(self
, other
):
343 """Compare two IP objects.
345 This is only concerned about the comparison of the integer
346 representation of the network addresses. This means that the
347 host bits aren't considered at all in this method. If you want
348 to compare host bits, you can easily enough do a
349 'HostA.ip < HostB.ip'
355 If the IP versions of self and other are the same, returns:
358 eg: IPv4('1.1.1.0/24') < IPv4('1.1.2.0/24')
359 IPv6('1080::200C:417A') < IPv6('1080::200B:417B')
361 eg: IPv4('1.1.1.1/24') == IPv4('1.1.1.2/24')
362 IPv6('1080::200C:417A/96') == IPv6('1080::200C:417B/96')
364 eg: IPv4('1.1.1.0/24') > IPv4('1.1.0.0/24')
365 IPv6('1080::1:200C:417A/112') >
366 IPv6('1080::0:200C:417A/112')
368 If the IP versions of self and other are different, returns:
370 -1 if self.version < other.version
371 eg: IPv4('10.0.0.1/24') < IPv6('::1/128')
372 1 if self.version > other.version
373 eg: IPv6('::1/128') > IPv4('255.255.255.0/24')
376 if self
.version
< other
.version
:
378 if self
.version
> other
.version
:
380 # self.version == other.version below here:
381 if self
.network
< other
.network
:
383 if self
.network
> other
.network
:
385 # self.network == other.network below here:
386 if self
.netmask
< other
.netmask
:
388 if self
.netmask
> other
.netmask
:
390 # self.network == other.network and self.netmask == other.netmask
393 def _get_networks_key(self
):
394 """Network-only key function.
396 Returns an object that identifies this address' network and
397 netmask. This function is a suitable "key" argument for sorted()
401 return (self
.version
, self
.network
, self
.netmask
)
403 prefixlen
= property(
404 fget
=lambda self
: self
._prefixlen
,
405 fset
=lambda self
, prefixlen
: self
._set
_prefix
(prefixlen
))
408 return '%s/%s' % (self
._string
_from
_ip
_int
(self
.ip
),
412 return hash(self
.ip ^ self
.netmask
)
414 def __contains__(self
, other
):
415 return self
.network
<= other
.ip
and self
.broadcast
>= other
.broadcast
419 """Dotted decimal or colon string version of the IP address."""
420 return self
._string
_from
_ip
_int
(self
.ip
)
423 def ip_ext_full(self
):
424 """Canonical string version of the IP address."""
429 """Integer representation of the broadcast address."""
430 return self
.ip | self
.hostmask
433 def broadcast_ext(self
):
434 """Dotted decimal or colon string version of the broadcast."""
435 return self
._string
_from
_ip
_int
(self
.broadcast
)
439 """Integer representation of the hostmask."""
440 return self
.netmask ^ self
._ALL
_ONES
443 def hostmask_ext(self
):
444 """Dotted decimal or colon string version of the hostmask."""
445 return self
._string
_from
_ip
_int
(self
.hostmask
)
449 """Integer representation of the network."""
450 return self
.ip
& self
.netmask
453 def network_ext(self
):
454 """Dotted decimal or colon string version of the network."""
455 return self
._string
_from
_ip
_int
(self
.network
)
458 def netmask_ext(self
):
459 """Dotted decimal or colon string version of the netmask."""
460 return self
._string
_from
_ip
_int
(self
.netmask
)
464 """Number of hosts in the current subnet."""
465 return self
.broadcast
- self
.network
+ 1
469 raise NotImplementedError('BaseIP has no version')
471 def _ip_int_from_prefix(self
, prefixlen
=None):
472 """Turn the prefix length netmask into a int for comparison.
475 prefixlen: An integer, the prefix length.
481 if not prefixlen
and prefixlen
!= 0:
482 prefixlen
= self
.prefixlen
483 return self
._ALL
_ONES ^
(self
._ALL
_ONES
>> prefixlen
)
485 def _prefix_from_ip_int(self
, ip_int
, mask
=32):
486 """Return prefix length from the decimal netmask.
489 ip_int: An integer, the IP address.
490 mask: The netmask. Defaults to 32.
493 An integer, the prefix length.
504 def _ip_string_from_prefix(self
, prefixlen
=None):
505 """Turn a prefix length into a dotted decimal string.
508 prefixlen: An integer, the netmask prefix length.
511 A string, the dotted decimal netmask string.
515 prefixlen
= self
.prefixlen
516 return self
._string
_from
_ip
_int
(self
._ip
_int
_from
_prefix
(prefixlen
))
521 """This class represents and manipulates 32-bit IPv4 addresses.
523 Attributes: [examples for IPv4('1.2.3.4/27')]
526 .ip_ext_full: '1.2.3.4'
528 .network_ext: '1.2.3.0'
529 .hostmask: 31L (0x1F)
530 .hostmask_ext: '0.0.0.31'
531 .broadcast: 16909087L (0x102031F)
532 .broadcast_ext: '1.2.3.31'
533 .netmask: 4294967040L (0xFFFFFFE0)
534 .netmask_ext: '255.255.255.224'
539 # Equivalent to 255.255.255.255 or 32 bits of 1's.
540 _ALL_ONES
= 0xffffffff
543 def __init__(self
, ipaddr
):
544 """Instantiate a new IPv4 object.
547 ipaddr: A string or integer representing the IP [& network].
549 '192.168.1.1/255.255.255.255'
550 '192.168.1.1/0.0.0.255'
552 are all functionally the same in IPv4. That is to say,
553 failing to provide a subnetmask will create an object with
554 a mask of /32. A netmask of '255.255.255.255' is assumed
555 to be /32 and '0.0.0.0' is assumed to be /0, even though
556 other netmasks can be expressed both as host- and
557 net-masks. (255.0.0.0 == 0.255.255.255)
559 Additionally, an integer can be passed, so
560 IPv4('192.168.1.1') == IPv4(3232235777).
562 IPv4(IPv4('192.168.1.1').ip) == IPv4('192.168.1.1')
565 IPv4IpValidationError: If ipaddr isn't a valid IPv4 address.
566 IPv4NetmaskValidationError: If the netmask isn't valid for
570 BaseIP
.__init
__(self
)
572 # Efficient constructor from integer.
573 if isinstance(ipaddr
, int) or isinstance(ipaddr
, long):
576 self
.netmask
= self
._ALL
_ONES
577 if ipaddr
< 0 or ipaddr
> self
._ALL
_ONES
:
578 raise IPv4IpValidationError(ipaddr
)
581 # Assume input argument to be string or any object representation
582 # which converts into a formatted IP prefix string.
583 addr
= str(ipaddr
).split('/')
586 raise IPv4IpValidationError(ipaddr
)
588 if not self
._is
_valid
_ip
(addr
[0]):
589 raise IPv4IpValidationError(addr
[0])
591 self
.ip
= self
._ip
_int
_from
_string
(addr
[0])
594 mask
= addr
[1].split('.')
596 # We have dotted decimal netmask.
597 if not self
._is
_valid
_netmask
(addr
[1]):
598 raise IPv4NetmaskValidationError(addr
[1])
599 if self
._is
_hostmask
(addr
[1]):
601 self
._ip
_int
_from
_string
(addr
[1]) ^ self
._ALL
_ONES
)
603 self
.netmask
= self
._ip
_int
_from
_string
(addr
[1])
604 self
._prefixlen
= self
._prefix
_from
_ip
_int
(self
.netmask
)
606 # We have a netmask in prefix length form.
607 if not self
._is
_valid
_netmask
(addr
[1]):
608 raise IPv4NetmaskValidationError(addr
[1])
609 self
._prefixlen
= int(addr
[1])
610 self
.netmask
= self
._ip
_int
_from
_prefix
(self
._prefixlen
)
613 self
.netmask
= self
._ip
_int
_from
_prefix
(self
._prefixlen
)
615 def _set_prefix(self
, prefixlen
):
616 """Change the prefix length.
619 prefixlen: An integer, the new prefix length.
622 IPv4NetmaskValidationError: If prefixlen is out of bounds.
625 if not 0 <= prefixlen
<= 32:
626 raise IPv4NetmaskValidationError(prefixlen
)
627 self
._prefixlen
= prefixlen
628 self
.netmask
= self
._ip
_int
_from
_prefix
(self
._prefixlen
)
630 def subnet(self
, prefixlen_diff
=1):
631 """The subnets which join to make the current subnet.
633 In the case that self contains only one IP
634 (self._prefixlen == 32), return a list with just ourself.
637 prefixlen_diff: An integer, the amount the prefix length
638 should be increased by. Given a /24 network and a
639 prefixlen_diff of 3, for example, 8 subnets of size /27
640 will be returned. The default value of 1 splits the
641 current network into two halves.
644 A list of IPv4 objects.
647 PrefixlenDiffInvalidError: The prefixlen_diff is too small
651 if self
._prefixlen
== 32:
654 if prefixlen_diff
< 0:
655 raise PrefixlenDiffInvalidError('prefix length diff must be > 0')
656 new_prefixlen
= self
.prefixlen
+ prefixlen_diff
658 if not self
._is
_valid
_netmask
(str(new_prefixlen
)):
659 raise PrefixlenDiffInvalidError(
660 'prefix length diff %d is invalid for netblock %s' % (
661 new_prefixlen
, str(self
)))
664 self
._string
_from
_ip
_int
(self
.network
) + '/' +
665 str(self
._prefixlen
+ prefixlen_diff
))
669 broadcast
= current
.broadcast
670 if broadcast
== self
.broadcast
:
672 current
= IPv4(self
._string
_from
_ip
_int
(broadcast
+ 1) + '/' +
674 subnets
.append(current
)
678 def supernet(self
, prefixlen_diff
=1):
679 """The supernet containing the current network.
682 prefixlen_diff: An integer, the amount the prefix length of
683 the network should be decreased by. For example, given a
684 /24 network and a prefixlen_diff of 3, a supernet with a
685 /21 netmask is returned.
691 PrefixlenDiffInvalidError: If
692 self.prefixlen - prefixlen_diff < 0. I.e., you have a
693 negative prefix length.
696 if self
.prefixlen
== 0:
698 if self
.prefixlen
- prefixlen_diff
< 0:
699 raise PrefixlenDiffInvalidError(
700 'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
701 (self
.prefixlen
, prefixlen_diff
))
702 return IPv4(self
.ip_ext
+ '/' + str(self
.prefixlen
- prefixlen_diff
))
705 def is_private(self
):
706 """Test if this address is allocated for private networks.
709 A boolean, True if the address is reserved per RFC 1918.
712 for network
in _IPV4_RFC1918_NETWORKS
:
718 def is_multicast(self
):
719 """Test if the address is reserved for multicast use.
722 A boolean, True if the address is multicast.
723 See RFC 3171 for details.
726 return self
in _IPV4_RFC3171_MULTICAST
729 def is_loopback(self
):
730 """Test if the address is a loopback adddress.
733 A boolean, True if the address is a loopback per RFC 3330.
736 return self
in _IPV4_RFC3330_LOOPBACK
739 def is_link_local(self
):
740 """Test if the address is reserved for link-local.
743 A boolean, True if the address is link-local per RFC 3927.
746 return self
in _IPV4_RFC3927_LINK_LOCAL
754 """The binary representation of this address."""
755 return struct
.pack('!I', self
.ip
)
757 def _is_hostmask(self
, ip_str
):
758 """Test if the IP string is a hostmask (rather than a netmask).
761 ip_str: A string, the potential hostmask.
764 A boolean, True if the IP string is a hostmask.
767 parts
= [int(x
) for x
in ip_str
.split('.')]
768 if parts
[0] < parts
[-1]:
772 def _ip_int_from_string(self
, ip_str
):
773 """Turn the given IP string into an integer for comparison.
776 ip_str: A string, the IP address.
779 The IP address as an integer.
783 for oc
in ip_str
.split('.'):
784 packed_ip
= (packed_ip
<< 8) |
int(oc
)
787 def _string_from_ip_int(self
, ip_int
):
788 """Turns a 32-bit integer into dotted decimal notation.
791 ip_int: An integer, the IP address.
794 The IP address as a string in dotted decimal notation.
799 octets
.insert(0, str(ip_int
& 0xFF))
801 return '.'.join(octets
)
803 def _is_valid_ip(self
, ip_str
):
804 """Validate the dotted decimal notation IP/netmask string.
807 ip_str: A string, the IP address.
810 A boolean, True if the string is a valid dotted decimal IP
814 octets
= ip_str
.split('.')
816 # We have an integer rather than a dotted decimal IP.
818 return int(ip_str
) >= 0 and int(ip_str
) <= self
._ALL
_ONES
827 if not 0 <= int(octet
) <= 255:
833 def _is_valid_netmask(self
, netmask
):
834 """Verify that the netmask is valid.
837 netmask: A string, either a prefix or dotted decimal
841 A boolean, True if the prefix represents a valid IPv4
845 if len(netmask
.split('.')) == 4:
846 return self
._is
_valid
_ip
(netmask
)
848 netmask
= int(netmask
)
851 return 0 <= netmask
<= 32
856 """This class respresents and manipulates 128-bit IPv6 addresses.
858 Attributes: [examples for IPv6('2001:658:22A:CAFE:200::1/64')]
859 .ip: 42540616829182469433547762482097946625L
860 .ip_ext: '2001:658:22a:cafe:200::1'
861 .ip_ext_full: '2001:0658:022a:cafe:0200:0000:0000:0001'
862 .network: 42540616829182469433403647294022090752L
863 .network_ext: '2001:658:22a:cafe::'
864 .hostmask: 18446744073709551615L
865 .hostmask_ext: '::ffff:ffff:ffff:ffff'
866 .broadcast: 42540616829182469451850391367731642367L
867 .broadcast_ext: '2001:658:22a:cafe:ffff:ffff:ffff:ffff'
868 .netmask: 340282366920938463444927863358058659840L
874 _ALL_ONES
= (2**128) - 1
877 def __init__(self
, ipaddr
):
878 """Instantiate a new IPv6 object.
881 ipaddr: A string or integer representing the IP or the IP
884 '2001:4860:0000:0000:0000:0000:0000:0000/128'
886 are all functionally the same in IPv6. That is to say,
887 failing to provide a subnetmask will create an object with
890 Additionally, an integer can be passed, so
891 IPv6('2001:4860::') ==
892 IPv6(42541956101370907050197289607612071936L).
894 IPv6(IPv6('2001:4860::').ip) == IPv6('2001:4860::')
897 IPv6IpValidationError: If ipaddr isn't a valid IPv6 address.
898 IPv6NetmaskValidationError: If the netmask isn't valid for
902 BaseIP
.__init
__(self
)
904 # Efficient constructor from integer.
905 if isinstance(ipaddr
, long) or isinstance(ipaddr
, int):
907 self
._prefixlen
= 128
908 self
.netmask
= self
._ALL
_ONES
909 if ipaddr
< 0 or ipaddr
> self
._ALL
_ONES
:
910 raise IPv6IpValidationError(ipaddr
)
913 # Assume input argument to be string or any object representation
914 # which converts into a formatted IP prefix string.
915 addr_str
= str(ipaddr
)
917 raise IPv6IpValidationError('')
918 addr
= addr_str
.split('/')
920 if self
._is
_valid
_netmask
(addr
[1]):
921 self
._prefixlen
= int(addr
[1])
923 raise IPv6NetmaskValidationError(addr
[1])
925 self
._prefixlen
= 128
927 self
.netmask
= self
._ip
_int
_from
_prefix
(self
._prefixlen
)
929 if not self
._is
_valid
_ip
(addr
[0]):
930 raise IPv6IpValidationError(addr
[0])
932 self
.ip
= self
._ip
_int
_from
_string
(addr
[0])
935 def ip_ext_full(self
):
936 """Returns the expanded version of the IPv6 string."""
937 return self
._explode
_shorthand
_ip
_string
(self
.ip_ext
)
939 def _set_prefix(self
, prefixlen
):
940 """Change the prefix length.
943 prefixlen: An integer, the new prefix length.
946 IPv6NetmaskValidationError: If prefixlen is out of bounds.
949 if not 0 <= prefixlen
<= 128:
950 raise IPv6NetmaskValidationError(prefixlen
)
951 self
._prefixlen
= prefixlen
952 self
.netmask
= self
._ip
_int
_from
_prefix
(self
.prefixlen
)
954 def subnet(self
, prefixlen_diff
=1):
955 """The subnets which join to make the current subnet.
957 In the case that self contains only one IP
958 (self._prefixlen == 128), return a list with just ourself.
961 prefixlen_diff: An integer, the amount the prefix length
962 should be increased by.
965 A list of IPv6 objects.
968 PrefixlenDiffInvalidError: The prefixlen_diff is too small
972 # Preserve original functionality (return [self] if
973 # self.prefixlen == 128).
974 if self
.prefixlen
== 128:
977 if prefixlen_diff
< 0:
978 raise PrefixlenDiffInvalidError('Prefix length diff must be > 0')
979 new_prefixlen
= self
.prefixlen
+ prefixlen_diff
980 if not self
._is
_valid
_netmask
(str(new_prefixlen
)):
981 raise PrefixlenDiffInvalidError(
982 'Prefix length diff %d is invalid for netblock %s' % (
983 new_prefixlen
, str(self
)))
985 self
._string
_from
_ip
_int
(self
.network
) + '/' +
986 str(self
._prefixlen
+ prefixlen_diff
))
990 broadcast
= current
.broadcast
991 if current
.broadcast
== self
.broadcast
:
993 current
= IPv6(self
._string
_from
_ip
_int
(broadcast
+ 1) + '/' +
995 subnets
.append(current
)
999 def supernet(self
, prefixlen_diff
=1):
1000 """The supernet containing the current network.
1003 prefixlen_diff: An integer, the amount the prefix length of the
1004 network should be decreased by. For example, given a /96
1005 network and a prefixlen_diff of 3, a supernet with a /93
1006 netmask is returned.
1012 PrefixlenDiffInvalidError: If
1013 self._prefixlen - prefixlen_diff < 0. I.e., you have a
1014 negative prefix length.
1017 if self
.prefixlen
== 0:
1019 if self
.prefixlen
- prefixlen_diff
< 0:
1020 raise PrefixlenDiffInvalidError(
1021 'current prefixlen is %d, cannot have a prefixlen_diff of %d' %
1022 (self
.prefixlen
, prefixlen_diff
))
1023 return IPv6(self
.ip_ext
+ '/' + str(self
.prefixlen
- prefixlen_diff
))
1026 def is_multicast(self
):
1027 """Test if the address is reserved for multicast use.
1030 A boolean, True if the address is a multicast address.
1031 See RFC 2373 2.7 for details.
1034 return self
in _IPV6_RFC2373_MULTICAST
1037 def is_unspecified(self
):
1038 """Test if the address is unspecified.
1041 A boolean, True if this is the unspecified address as defined in
1045 return self
== _IPV6_RFC2373_UNSPECIFIED
1048 def is_loopback(self
):
1049 """Test if the address is a loopback adddress.
1052 A boolean, True if the address is a loopback address as defined in
1056 return self
== _IPV6_RFC2373_LOOPBACK
1059 def is_link_local(self
):
1060 """Test if the address is reserved for link-local.
1063 A boolean, True if the address is reserved per RFC 4291.
1066 return self
in _IPV6_RFC4291_LINK_LOCAL
1069 def is_site_local(self
):
1070 """Test if the address is reserved for site-local.
1072 Note that the site-local address space has been deprecated by RFC 3879.
1073 Use is_private to test if this address is in the space of unique local
1074 addresses as defined by RFC 4193.
1077 A boolean, True if the address is reserved per RFC 3513 2.5.6.
1080 return self
in _IPV6_RFC3513_SITE_LOCAL
1083 def is_private(self
):
1084 """Test if this address is allocated for private networks.
1087 A boolean, True if the address is reserved per RFC 4193.
1090 return self
in _IPV6_RFC4193_PRIVATE
1094 return self
._version
1098 """The binary representation of this address."""
1099 return struct
.pack('!QQ', self
.ip
>> 64, self
.ip
& (2**64 - 1))
1101 def _is_shorthand_ip(self
, ip_str
=None):
1102 """Determine if the address is shortened.
1105 ip_str: A string, the IPv6 address.
1108 A boolean, True if the address is shortened.
1111 if ip_str
.count('::') == 1:
1115 def _explode_shorthand_ip_string(self
, ip_str
):
1116 """Expand a shortened IPv6 address.
1119 ip_str: A string, the IPv6 address.
1122 A string, the expanded IPv6 address.
1125 if self
._is
_shorthand
_ip
(ip_str
):
1127 hextet
= ip_str
.split('::')
1128 sep
= len(hextet
[0].split(':')) + len(hextet
[1].split(':'))
1129 new_ip
= hextet
[0].split(':')
1131 for _
in xrange(8 - sep
):
1132 new_ip
.append('0000')
1133 new_ip
+= hextet
[1].split(':')
1135 # Now need to make sure every hextet is 4 lower case characters.
1136 # If a hextet is < 4 characters, we've got missing leading 0's.
1138 for hextet
in new_ip
:
1139 ret_ip
.append(('0' * (4 - len(hextet
)) + hextet
).lower())
1140 return ':'.join(ret_ip
)
1141 # We've already got a longhand ip_str.
1144 def _is_valid_ip(self
, ip_str
=None):
1145 """Ensure we have a valid IPv6 address.
1147 Probably not as exhaustive as it should be.
1150 ip_str: A string, the IPv6 address.
1153 A boolean, True if this is a valid IPv6 address.
1157 ip_str
= self
.ip_ext
1159 # We need to have at least one ':'.
1160 if ':' not in ip_str
:
1163 # We can only have one '::' shortener.
1164 if ip_str
.count('::') > 1:
1167 # '::' should be encompassed by start, digits or end.
1171 # A single colon can neither start nor end an address.
1172 if ((ip_str
.startswith(':') and not ip_str
.startswith('::')) or
1173 (ip_str
.endswith(':') and not ip_str
.endswith('::'))):
1176 # If we have no concatenation, we need to have 8 fields with 7 ':'.
1177 if '::' not in ip_str
and ip_str
.count(':') != 7:
1178 # We might have an IPv4 mapped address.
1179 if ip_str
.count('.') != 3:
1182 ip_str
= self
._explode
_shorthand
_ip
_string
(ip_str
)
1184 # Now that we have that all squared away, let's check that each of the
1185 # hextets are between 0x0 and 0xFFFF.
1186 for hextet
in ip_str
.split(':'):
1187 if hextet
.count('.') == 3:
1188 # If we have an IPv4 mapped address, the IPv4 portion has to be
1189 # at the end of the IPv6 portion.
1190 if not ip_str
.split(':')[-1] == hextet
:
1194 except IPv4IpValidationError
:
1196 elif int(hextet
, 16) < 0x0 or int(hextet
, 16) > 0xFFFF:
1200 def _is_valid_netmask(self
, prefixlen
):
1201 """Verify that the netmask/prefixlen is valid.
1204 prefixlen: A string, the netmask in prefix length format.
1207 A boolean, True if the prefix represents a valid IPv6
1212 prefixlen
= int(prefixlen
)
1215 return 0 <= prefixlen
<= 128
1217 def _ip_int_from_string(self
, ip_str
=None):
1218 """Turn an IPv6 address into an integer.
1221 ip_str: A string, the IPv6 address.
1224 A long, the IPv6 address.
1228 ip_str
= self
.ip_ext
1232 fields
= self
._explode
_shorthand
_ip
_string
(ip_str
).split(':')
1234 # Do we have an IPv4 mapped (::ffff:a.b.c.d) or compact (::a.b.c.d)
1236 if fields
[-1].count('.') == 3:
1237 ipv4_string
= fields
.pop()
1238 ipv4_int
= IPv4(ipv4_string
).ip
1241 octets
.append(hex(ipv4_int
& 0xFFFF).lstrip('0x').rstrip('L'))
1243 fields
.extend(reversed(octets
))
1245 for field
in fields
:
1246 ip_int
= (ip_int
<< 16) + int(field
, 16)
1250 def _compress_hextets(self
, hextets
):
1251 """Compresses a list of hextets.
1253 Compresses a list of strings, replacing the longest continuous
1254 sequence of "0" in the list with "" and adding empty strings at
1255 the beginning or at the end of the string such that subsequently
1256 calling ":".join(hextets) will produce the compressed version of
1260 hextets: A list of strings, the hextets to compress.
1266 best_doublecolon_start
= -1
1267 best_doublecolon_len
= 0
1268 doublecolon_start
= -1
1270 for index
in range(len(hextets
)):
1271 if hextets
[index
] == '0':
1272 doublecolon_len
+= 1
1273 if doublecolon_start
== -1:
1274 # Start of a sequence of zeros.
1275 doublecolon_start
= index
1276 if doublecolon_len
> best_doublecolon_len
:
1277 # This is the longest sequence of zeros so far.
1278 best_doublecolon_len
= doublecolon_len
1279 best_doublecolon_start
= doublecolon_start
1282 doublecolon_start
= -1
1284 if best_doublecolon_len
> 1:
1285 best_doublecolon_end
= (best_doublecolon_start
+
1286 best_doublecolon_len
)
1287 # For zeros at the end of the address.
1288 if best_doublecolon_end
== len(hextets
):
1290 hextets
[best_doublecolon_start
:best_doublecolon_end
] = ['']
1291 # For zeros at the beginning of the address.
1292 if best_doublecolon_start
== 0:
1293 hextets
= [''] + hextets
1297 def _string_from_ip_int(self
, ip_int
=None):
1298 """Turns a 128-bit integer into hexadecimal notation.
1301 ip_int: An integer, the IP address.
1304 A string, the hexadecimal representation of the address.
1307 ValueError: The address is bigger than 128 bits of all ones.
1310 if not ip_int
and ip_int
!= 0:
1313 if ip_int
> self
._ALL
_ONES
:
1314 raise ValueError('IPv6 address is too large')
1316 hex_str
= '%032x' % ip_int
1318 for x
in range(0, 32, 4):
1319 hextets
.append('%x' % int(hex_str
[x
:x
+4], 16))
1321 hextets
= self
._compress
_hextets
(hextets
)
1322 return ':'.join(hextets
)
1325 def netmask_ext(self
):
1326 """IPv6 extended netmask.
1328 We don't deal with netmasks in IPv6 like we do in IPv4. This is
1329 here strictly for IPv4 compatibility. We simply return the
1336 return self
.prefixlen
1340 _IPV4_RFC1918_NETWORKS
= (IPv4('10.0.0.0/8'),
1341 IPv4('172.16.0.0/12'),
1342 IPv4('192.168.0.0/16'))
1343 _IPV4_RFC3171_MULTICAST
= IPv4('224.0.0.0/4')
1344 _IPV4_RFC3330_LOOPBACK
= IPv4('127.0.0.0/8')
1345 _IPV4_RFC3927_LINK_LOCAL
= IPv4('169.254.0.0/16')
1348 _IPV6_RFC2373_MULTICAST
= IPv6('ff00::/8')
1349 _IPV6_RFC2373_UNSPECIFIED
= IPv6('::')
1350 _IPV6_RFC2373_LOOPBACK
= IPv6('::1')
1351 _IPV6_RFC4291_LINK_LOCAL
= IPv6('fe80::/10')
1352 _IPV6_RFC3513_SITE_LOCAL
= IPv6('fec0::/10') # Deprecated by RFC3879.
1353 _IPV6_RFC4193_PRIVATE
= IPv6('fc00::/7')