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