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