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