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