| OLD | NEW |
| (Empty) | |
| 1 #!/usr/bin/python |
| 2 # |
| 3 # Copyright 2007 Google Inc. |
| 4 # Licensed to PSF under a Contributor Agreement. |
| 5 # |
| 6 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 # you may not use this file except in compliance with the License. |
| 8 # You may obtain a copy of the License at |
| 9 # |
| 10 # http://www.apache.org/licenses/LICENSE-2.0 |
| 11 # |
| 12 # Unless required by applicable law or agreed to in writing, software |
| 13 # distributed under the License is distributed on an "AS IS" BASIS, |
| 14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| 15 # implied. See the License for the specific language governing |
| 16 # permissions and limitations under the License. |
| 17 |
| 18 """A fast, lightweight IPv4/IPv6 manipulation library in Python. |
| 19 |
| 20 This library is used to create/poke/manipulate IPv4 and IPv6 addresses |
| 21 and networks. |
| 22 |
| 23 """ |
| 24 |
| 25 __version__ = '2.1.10' |
| 26 |
| 27 import struct |
| 28 |
| 29 IPV4LENGTH = 32 |
| 30 IPV6LENGTH = 128 |
| 31 |
| 32 |
| 33 class AddressValueError(ValueError): |
| 34 """A Value Error related to the address.""" |
| 35 |
| 36 |
| 37 class NetmaskValueError(ValueError): |
| 38 """A Value Error related to the netmask.""" |
| 39 |
| 40 |
| 41 def IPAddress(address, version=None): |
| 42 """Take an IP string/int and return an object of the correct type. |
| 43 |
| 44 Args: |
| 45 address: A string or integer, the IP address. Either IPv4 or |
| 46 IPv6 addresses may be supplied; integers less than 2**32 will |
| 47 be considered to be IPv4 by default. |
| 48 version: An Integer, 4 or 6. If set, don't try to automatically |
| 49 determine what the IP address type is. important for things |
| 50 like IPAddress(1), which could be IPv4, '0.0.0.1', or IPv6, |
| 51 '::1'. |
| 52 |
| 53 Returns: |
| 54 An IPv4Address or IPv6Address object. |
| 55 |
| 56 Raises: |
| 57 ValueError: if the string passed isn't either a v4 or a v6 |
| 58 address. |
| 59 |
| 60 """ |
| 61 if version: |
| 62 if version == 4: |
| 63 return IPv4Address(address) |
| 64 elif version == 6: |
| 65 return IPv6Address(address) |
| 66 |
| 67 try: |
| 68 return IPv4Address(address) |
| 69 except (AddressValueError, NetmaskValueError): |
| 70 pass |
| 71 |
| 72 try: |
| 73 return IPv6Address(address) |
| 74 except (AddressValueError, NetmaskValueError): |
| 75 pass |
| 76 |
| 77 raise ValueError('%r does not appear to be an IPv4 or IPv6 address' % |
| 78 address) |
| 79 |
| 80 |
| 81 def IPNetwork(address, version=None, strict=False): |
| 82 """Take an IP string/int and return an object of the correct type. |
| 83 |
| 84 Args: |
| 85 address: A string or integer, the IP address. Either IPv4 or |
| 86 IPv6 addresses may be supplied; integers less than 2**32 will |
| 87 be considered to be IPv4 by default. |
| 88 version: An Integer, if set, don't try to automatically |
| 89 determine what the IP address type is. important for things |
| 90 like IPNetwork(1), which could be IPv4, '0.0.0.1/32', or IPv6, |
| 91 '::1/128'. |
| 92 |
| 93 Returns: |
| 94 An IPv4Network or IPv6Network object. |
| 95 |
| 96 Raises: |
| 97 ValueError: if the string passed isn't either a v4 or a v6 |
| 98 address. Or if a strict network was requested and a strict |
| 99 network wasn't given. |
| 100 |
| 101 """ |
| 102 if version: |
| 103 if version == 4: |
| 104 return IPv4Network(address, strict) |
| 105 elif version == 6: |
| 106 return IPv6Network(address, strict) |
| 107 |
| 108 try: |
| 109 return IPv4Network(address, strict) |
| 110 except (AddressValueError, NetmaskValueError): |
| 111 pass |
| 112 |
| 113 try: |
| 114 return IPv6Network(address, strict) |
| 115 except (AddressValueError, NetmaskValueError): |
| 116 pass |
| 117 |
| 118 raise ValueError('%r does not appear to be an IPv4 or IPv6 network' % |
| 119 address) |
| 120 |
| 121 |
| 122 def v4_int_to_packed(address): |
| 123 """The binary representation of this address. |
| 124 |
| 125 Args: |
| 126 address: An integer representation of an IPv4 IP address. |
| 127 |
| 128 Returns: |
| 129 The binary representation of this address. |
| 130 |
| 131 Raises: |
| 132 ValueError: If the integer is too large to be an IPv4 IP |
| 133 address. |
| 134 """ |
| 135 if address > _BaseV4._ALL_ONES: |
| 136 raise ValueError('Address too large for IPv4') |
| 137 return Bytes(struct.pack('!I', address)) |
| 138 |
| 139 |
| 140 def v6_int_to_packed(address): |
| 141 """The binary representation of this address. |
| 142 |
| 143 Args: |
| 144 address: An integer representation of an IPv4 IP address. |
| 145 |
| 146 Returns: |
| 147 The binary representation of this address. |
| 148 """ |
| 149 return Bytes(struct.pack('!QQ', address >> 64, address & (2**64 - 1))) |
| 150 |
| 151 |
| 152 def _find_address_range(addresses): |
| 153 """Find a sequence of addresses. |
| 154 |
| 155 Args: |
| 156 addresses: a list of IPv4 or IPv6 addresses. |
| 157 |
| 158 Returns: |
| 159 A tuple containing the first and last IP addresses in the sequence. |
| 160 |
| 161 """ |
| 162 first = last = addresses[0] |
| 163 for ip in addresses[1:]: |
| 164 if ip._ip == last._ip + 1: |
| 165 last = ip |
| 166 else: |
| 167 break |
| 168 return (first, last) |
| 169 |
| 170 def _get_prefix_length(number1, number2, bits): |
| 171 """Get the number of leading bits that are same for two numbers. |
| 172 |
| 173 Args: |
| 174 number1: an integer. |
| 175 number2: another integer. |
| 176 bits: the maximum number of bits to compare. |
| 177 |
| 178 Returns: |
| 179 The number of leading bits that are the same for two numbers. |
| 180 |
| 181 """ |
| 182 for i in range(bits): |
| 183 if number1 >> i == number2 >> i: |
| 184 return bits - i |
| 185 return 0 |
| 186 |
| 187 def _count_righthand_zero_bits(number, bits): |
| 188 """Count the number of zero bits on the right hand side. |
| 189 |
| 190 Args: |
| 191 number: an integer. |
| 192 bits: maximum number of bits to count. |
| 193 |
| 194 Returns: |
| 195 The number of zero bits on the right hand side of the number. |
| 196 |
| 197 """ |
| 198 if number == 0: |
| 199 return bits |
| 200 for i in range(bits): |
| 201 if (number >> i) % 2: |
| 202 return i |
| 203 |
| 204 def summarize_address_range(first, last): |
| 205 """Summarize a network range given the first and last IP addresses. |
| 206 |
| 207 Example: |
| 208 >>> summarize_address_range(IPv4Address('1.1.1.0'), |
| 209 IPv4Address('1.1.1.130')) |
| 210 [IPv4Network('1.1.1.0/25'), IPv4Network('1.1.1.128/31'), |
| 211 IPv4Network('1.1.1.130/32')] |
| 212 |
| 213 Args: |
| 214 first: the first IPv4Address or IPv6Address in the range. |
| 215 last: the last IPv4Address or IPv6Address in the range. |
| 216 |
| 217 Returns: |
| 218 The address range collapsed to a list of IPv4Network's or |
| 219 IPv6Network's. |
| 220 |
| 221 Raise: |
| 222 TypeError: |
| 223 If the first and last objects are not IP addresses. |
| 224 If the first and last objects are not the same version. |
| 225 ValueError: |
| 226 If the last object is not greater than the first. |
| 227 If the version is not 4 or 6. |
| 228 |
| 229 """ |
| 230 if not (isinstance(first, _BaseIP) and isinstance(last, _BaseIP)): |
| 231 raise TypeError('first and last must be IP addresses, not networks') |
| 232 if first.version != last.version: |
| 233 raise TypeError("%s and %s are not of the same version" % ( |
| 234 str(first), str(last))) |
| 235 if first > last: |
| 236 raise ValueError('last IP address must be greater than first') |
| 237 |
| 238 networks = [] |
| 239 |
| 240 if first.version == 4: |
| 241 ip = IPv4Network |
| 242 elif first.version == 6: |
| 243 ip = IPv6Network |
| 244 else: |
| 245 raise ValueError('unknown IP version') |
| 246 |
| 247 ip_bits = first._max_prefixlen |
| 248 first_int = first._ip |
| 249 last_int = last._ip |
| 250 while first_int <= last_int: |
| 251 nbits = _count_righthand_zero_bits(first_int, ip_bits) |
| 252 current = None |
| 253 while nbits >= 0: |
| 254 addend = 2**nbits - 1 |
| 255 current = first_int + addend |
| 256 nbits -= 1 |
| 257 if current <= last_int: |
| 258 break |
| 259 prefix = _get_prefix_length(first_int, current, ip_bits) |
| 260 net = ip('%s/%d' % (str(first), prefix)) |
| 261 networks.append(net) |
| 262 if current == ip._ALL_ONES: |
| 263 break |
| 264 first_int = current + 1 |
| 265 first = IPAddress(first_int, version=first._version) |
| 266 return networks |
| 267 |
| 268 def _collapse_address_list_recursive(addresses): |
| 269 """Loops through the addresses, collapsing concurrent netblocks. |
| 270 |
| 271 Example: |
| 272 |
| 273 ip1 = IPv4Network('1.1.0.0/24') |
| 274 ip2 = IPv4Network('1.1.1.0/24') |
| 275 ip3 = IPv4Network('1.1.2.0/24') |
| 276 ip4 = IPv4Network('1.1.3.0/24') |
| 277 ip5 = IPv4Network('1.1.4.0/24') |
| 278 ip6 = IPv4Network('1.1.0.1/22') |
| 279 |
| 280 _collapse_address_list_recursive([ip1, ip2, ip3, ip4, ip5, ip6]) -> |
| 281 [IPv4Network('1.1.0.0/22'), IPv4Network('1.1.4.0/24')] |
| 282 |
| 283 This shouldn't be called directly; it is called via |
| 284 collapse_address_list([]). |
| 285 |
| 286 Args: |
| 287 addresses: A list of IPv4Network's or IPv6Network's |
| 288 |
| 289 Returns: |
| 290 A list of IPv4Network's or IPv6Network's depending on what we were |
| 291 passed. |
| 292 |
| 293 """ |
| 294 ret_array = [] |
| 295 optimized = False |
| 296 |
| 297 for cur_addr in addresses: |
| 298 if not ret_array: |
| 299 ret_array.append(cur_addr) |
| 300 continue |
| 301 if cur_addr in ret_array[-1]: |
| 302 optimized = True |
| 303 elif cur_addr == ret_array[-1].supernet().subnet()[1]: |
| 304 ret_array.append(ret_array.pop().supernet()) |
| 305 optimized = True |
| 306 else: |
| 307 ret_array.append(cur_addr) |
| 308 |
| 309 if optimized: |
| 310 return _collapse_address_list_recursive(ret_array) |
| 311 |
| 312 return ret_array |
| 313 |
| 314 |
| 315 def collapse_address_list(addresses): |
| 316 """Collapse a list of IP objects. |
| 317 |
| 318 Example: |
| 319 collapse_address_list([IPv4('1.1.0.0/24'), IPv4('1.1.1.0/24')]) -> |
| 320 [IPv4('1.1.0.0/23')] |
| 321 |
| 322 Args: |
| 323 addresses: A list of IPv4Network or IPv6Network objects. |
| 324 |
| 325 Returns: |
| 326 A list of IPv4Network or IPv6Network objects depending on what we |
| 327 were passed. |
| 328 |
| 329 Raises: |
| 330 TypeError: If passed a list of mixed version objects. |
| 331 |
| 332 """ |
| 333 i = 0 |
| 334 addrs = [] |
| 335 ips = [] |
| 336 nets = [] |
| 337 |
| 338 # split IP addresses and networks |
| 339 for ip in addresses: |
| 340 if isinstance(ip, _BaseIP): |
| 341 if ips and ips[-1]._version != ip._version: |
| 342 raise TypeError("%s and %s are not of the same version" % ( |
| 343 str(ip), str(ips[-1]))) |
| 344 ips.append(ip) |
| 345 elif ip._prefixlen == ip._max_prefixlen: |
| 346 if ips and ips[-1]._version != ip._version: |
| 347 raise TypeError("%s and %s are not of the same version" % ( |
| 348 str(ip), str(ips[-1]))) |
| 349 ips.append(ip.ip) |
| 350 else: |
| 351 if nets and nets[-1]._version != ip._version: |
| 352 raise TypeError("%s and %s are not of the same version" % ( |
| 353 str(ip), str(ips[-1]))) |
| 354 nets.append(ip) |
| 355 |
| 356 # sort and dedup |
| 357 ips = sorted(set(ips)) |
| 358 nets = sorted(set(nets)) |
| 359 |
| 360 while i < len(ips): |
| 361 (first, last) = _find_address_range(ips[i:]) |
| 362 i = ips.index(last) + 1 |
| 363 addrs.extend(summarize_address_range(first, last)) |
| 364 |
| 365 return _collapse_address_list_recursive(sorted( |
| 366 addrs + nets, key=_BaseNet._get_networks_key)) |
| 367 |
| 368 # backwards compatibility |
| 369 CollapseAddrList = collapse_address_list |
| 370 |
| 371 # We need to distinguish between the string and packed-bytes representations |
| 372 # of an IP address. For example, b'0::1' is the IPv4 address 48.58.58.49, |
| 373 # while '0::1' is an IPv6 address. |
| 374 # |
| 375 # In Python 3, the native 'bytes' type already provides this functionality, |
| 376 # so we use it directly. For earlier implementations where bytes is not a |
| 377 # distinct type, we create a subclass of str to serve as a tag. |
| 378 # |
| 379 # Usage example (Python 2): |
| 380 # ip = ipaddr.IPAddress(ipaddr.Bytes('xxxx')) |
| 381 # |
| 382 # Usage example (Python 3): |
| 383 # ip = ipaddr.IPAddress(b'xxxx') |
| 384 try: |
| 385 if bytes is str: |
| 386 raise TypeError("bytes is not a distinct type") |
| 387 Bytes = bytes |
| 388 except (NameError, TypeError): |
| 389 class Bytes(str): |
| 390 def __repr__(self): |
| 391 return 'Bytes(%s)' % str.__repr__(self) |
| 392 |
| 393 def get_mixed_type_key(obj): |
| 394 """Return a key suitable for sorting between networks and addresses. |
| 395 |
| 396 Address and Network objects are not sortable by default; they're |
| 397 fundamentally different so the expression |
| 398 |
| 399 IPv4Address('1.1.1.1') <= IPv4Network('1.1.1.1/24') |
| 400 |
| 401 doesn't make any sense. There are some times however, where you may wish |
| 402 to have ipaddr sort these for you anyway. If you need to do this, you |
| 403 can use this function as the key= argument to sorted(). |
| 404 |
| 405 Args: |
| 406 obj: either a Network or Address object. |
| 407 Returns: |
| 408 appropriate key. |
| 409 |
| 410 """ |
| 411 if isinstance(obj, _BaseNet): |
| 412 return obj._get_networks_key() |
| 413 elif isinstance(obj, _BaseIP): |
| 414 return obj._get_address_key() |
| 415 return NotImplemented |
| 416 |
| 417 class _IPAddrBase(object): |
| 418 |
| 419 """The mother class.""" |
| 420 |
| 421 def __index__(self): |
| 422 return self._ip |
| 423 |
| 424 def __int__(self): |
| 425 return self._ip |
| 426 |
| 427 def __hex__(self): |
| 428 return hex(self._ip) |
| 429 |
| 430 @property |
| 431 def exploded(self): |
| 432 """Return the longhand version of the IP address as a string.""" |
| 433 return self._explode_shorthand_ip_string() |
| 434 |
| 435 @property |
| 436 def compressed(self): |
| 437 """Return the shorthand version of the IP address as a string.""" |
| 438 return str(self) |
| 439 |
| 440 |
| 441 class _BaseIP(_IPAddrBase): |
| 442 |
| 443 """A generic IP object. |
| 444 |
| 445 This IP class contains the version independent methods which are |
| 446 used by single IP addresses. |
| 447 |
| 448 """ |
| 449 |
| 450 def __eq__(self, other): |
| 451 try: |
| 452 return (self._ip == other._ip |
| 453 and self._version == other._version) |
| 454 except AttributeError: |
| 455 return NotImplemented |
| 456 |
| 457 def __ne__(self, other): |
| 458 eq = self.__eq__(other) |
| 459 if eq is NotImplemented: |
| 460 return NotImplemented |
| 461 return not eq |
| 462 |
| 463 def __le__(self, other): |
| 464 gt = self.__gt__(other) |
| 465 if gt is NotImplemented: |
| 466 return NotImplemented |
| 467 return not gt |
| 468 |
| 469 def __ge__(self, other): |
| 470 lt = self.__lt__(other) |
| 471 if lt is NotImplemented: |
| 472 return NotImplemented |
| 473 return not lt |
| 474 |
| 475 def __lt__(self, other): |
| 476 if self._version != other._version: |
| 477 raise TypeError('%s and %s are not of the same version' % ( |
| 478 str(self), str(other))) |
| 479 if not isinstance(other, _BaseIP): |
| 480 raise TypeError('%s and %s are not of the same type' % ( |
| 481 str(self), str(other))) |
| 482 if self._ip != other._ip: |
| 483 return self._ip < other._ip |
| 484 return False |
| 485 |
| 486 def __gt__(self, other): |
| 487 if self._version != other._version: |
| 488 raise TypeError('%s and %s are not of the same version' % ( |
| 489 str(self), str(other))) |
| 490 if not isinstance(other, _BaseIP): |
| 491 raise TypeError('%s and %s are not of the same type' % ( |
| 492 str(self), str(other))) |
| 493 if self._ip != other._ip: |
| 494 return self._ip > other._ip |
| 495 return False |
| 496 |
| 497 # Shorthand for Integer addition and subtraction. This is not |
| 498 # meant to ever support addition/subtraction of addresses. |
| 499 def __add__(self, other): |
| 500 if not isinstance(other, int): |
| 501 return NotImplemented |
| 502 return IPAddress(int(self) + other, version=self._version) |
| 503 |
| 504 def __sub__(self, other): |
| 505 if not isinstance(other, int): |
| 506 return NotImplemented |
| 507 return IPAddress(int(self) - other, version=self._version) |
| 508 |
| 509 def __repr__(self): |
| 510 return '%s(%r)' % (self.__class__.__name__, str(self)) |
| 511 |
| 512 def __str__(self): |
| 513 return '%s' % self._string_from_ip_int(self._ip) |
| 514 |
| 515 def __hash__(self): |
| 516 return hash(hex(long(self._ip))) |
| 517 |
| 518 def _get_address_key(self): |
| 519 return (self._version, self) |
| 520 |
| 521 @property |
| 522 def version(self): |
| 523 raise NotImplementedError('BaseIP has no version') |
| 524 |
| 525 |
| 526 class _BaseNet(_IPAddrBase): |
| 527 |
| 528 """A generic IP object. |
| 529 |
| 530 This IP class contains the version independent methods which are |
| 531 used by networks. |
| 532 |
| 533 """ |
| 534 |
| 535 def __init__(self, address): |
| 536 self._cache = {} |
| 537 |
| 538 def __repr__(self): |
| 539 return '%s(%r)' % (self.__class__.__name__, str(self)) |
| 540 |
| 541 def iterhosts(self): |
| 542 """Generate Iterator over usable hosts in a network. |
| 543 |
| 544 This is like __iter__ except it doesn't return the network |
| 545 or broadcast addresses. |
| 546 |
| 547 """ |
| 548 cur = int(self.network) + 1 |
| 549 bcast = int(self.broadcast) - 1 |
| 550 while cur <= bcast: |
| 551 cur += 1 |
| 552 yield IPAddress(cur - 1, version=self._version) |
| 553 |
| 554 def __iter__(self): |
| 555 cur = int(self.network) |
| 556 bcast = int(self.broadcast) |
| 557 while cur <= bcast: |
| 558 cur += 1 |
| 559 yield IPAddress(cur - 1, version=self._version) |
| 560 |
| 561 def __getitem__(self, n): |
| 562 network = int(self.network) |
| 563 broadcast = int(self.broadcast) |
| 564 if n >= 0: |
| 565 if network + n > broadcast: |
| 566 raise IndexError |
| 567 return IPAddress(network + n, version=self._version) |
| 568 else: |
| 569 n += 1 |
| 570 if broadcast + n < network: |
| 571 raise IndexError |
| 572 return IPAddress(broadcast + n, version=self._version) |
| 573 |
| 574 def __lt__(self, other): |
| 575 if self._version != other._version: |
| 576 raise TypeError('%s and %s are not of the same version' % ( |
| 577 str(self), str(other))) |
| 578 if not isinstance(other, _BaseNet): |
| 579 raise TypeError('%s and %s are not of the same type' % ( |
| 580 str(self), str(other))) |
| 581 if self.network != other.network: |
| 582 return self.network < other.network |
| 583 if self.netmask != other.netmask: |
| 584 return self.netmask < other.netmask |
| 585 return False |
| 586 |
| 587 def __gt__(self, other): |
| 588 if self._version != other._version: |
| 589 raise TypeError('%s and %s are not of the same version' % ( |
| 590 str(self), str(other))) |
| 591 if not isinstance(other, _BaseNet): |
| 592 raise TypeError('%s and %s are not of the same type' % ( |
| 593 str(self), str(other))) |
| 594 if self.network != other.network: |
| 595 return self.network > other.network |
| 596 if self.netmask != other.netmask: |
| 597 return self.netmask > other.netmask |
| 598 return False |
| 599 |
| 600 def __le__(self, other): |
| 601 gt = self.__gt__(other) |
| 602 if gt is NotImplemented: |
| 603 return NotImplemented |
| 604 return not gt |
| 605 |
| 606 def __ge__(self, other): |
| 607 lt = self.__lt__(other) |
| 608 if lt is NotImplemented: |
| 609 return NotImplemented |
| 610 return not lt |
| 611 |
| 612 def __eq__(self, other): |
| 613 try: |
| 614 return (self._version == other._version |
| 615 and self.network == other.network |
| 616 and int(self.netmask) == int(other.netmask)) |
| 617 except AttributeError: |
| 618 if isinstance(other, _BaseIP): |
| 619 return (self._version == other._version |
| 620 and self._ip == other._ip) |
| 621 |
| 622 def __ne__(self, other): |
| 623 eq = self.__eq__(other) |
| 624 if eq is NotImplemented: |
| 625 return NotImplemented |
| 626 return not eq |
| 627 |
| 628 def __str__(self): |
| 629 return '%s/%s' % (str(self.ip), |
| 630 str(self._prefixlen)) |
| 631 |
| 632 def __hash__(self): |
| 633 return hash(int(self.network) ^ int(self.netmask)) |
| 634 |
| 635 def __contains__(self, other): |
| 636 # always false if one is v4 and the other is v6. |
| 637 if self._version != other._version: |
| 638 return False |
| 639 # dealing with another network. |
| 640 if isinstance(other, _BaseNet): |
| 641 return (self.network <= other.network and |
| 642 self.broadcast >= other.broadcast) |
| 643 # dealing with another address |
| 644 else: |
| 645 return (int(self.network) <= int(other._ip) <= |
| 646 int(self.broadcast)) |
| 647 |
| 648 def overlaps(self, other): |
| 649 """Tell if self is partly contained in other.""" |
| 650 return self.network in other or self.broadcast in other or ( |
| 651 other.network in self or other.broadcast in self) |
| 652 |
| 653 @property |
| 654 def network(self): |
| 655 x = self._cache.get('network') |
| 656 if x is None: |
| 657 x = IPAddress(self._ip & int(self.netmask), version=self._version) |
| 658 self._cache['network'] = x |
| 659 return x |
| 660 |
| 661 @property |
| 662 def broadcast(self): |
| 663 x = self._cache.get('broadcast') |
| 664 if x is None: |
| 665 x = IPAddress(self._ip | int(self.hostmask), version=self._version) |
| 666 self._cache['broadcast'] = x |
| 667 return x |
| 668 |
| 669 @property |
| 670 def hostmask(self): |
| 671 x = self._cache.get('hostmask') |
| 672 if x is None: |
| 673 x = IPAddress(int(self.netmask) ^ self._ALL_ONES, |
| 674 version=self._version) |
| 675 self._cache['hostmask'] = x |
| 676 return x |
| 677 |
| 678 @property |
| 679 def with_prefixlen(self): |
| 680 return '%s/%d' % (str(self.ip), self._prefixlen) |
| 681 |
| 682 @property |
| 683 def with_netmask(self): |
| 684 return '%s/%s' % (str(self.ip), str(self.netmask)) |
| 685 |
| 686 @property |
| 687 def with_hostmask(self): |
| 688 return '%s/%s' % (str(self.ip), str(self.hostmask)) |
| 689 |
| 690 @property |
| 691 def numhosts(self): |
| 692 """Number of hosts in the current subnet.""" |
| 693 return int(self.broadcast) - int(self.network) + 1 |
| 694 |
| 695 @property |
| 696 def version(self): |
| 697 raise NotImplementedError('BaseNet has no version') |
| 698 |
| 699 @property |
| 700 def prefixlen(self): |
| 701 return self._prefixlen |
| 702 |
| 703 def address_exclude(self, other): |
| 704 """Remove an address from a larger block. |
| 705 |
| 706 For example: |
| 707 |
| 708 addr1 = IPNetwork('10.1.1.0/24') |
| 709 addr2 = IPNetwork('10.1.1.0/26') |
| 710 addr1.address_exclude(addr2) = |
| 711 [IPNetwork('10.1.1.64/26'), IPNetwork('10.1.1.128/25')] |
| 712 |
| 713 or IPv6: |
| 714 |
| 715 addr1 = IPNetwork('::1/32') |
| 716 addr2 = IPNetwork('::1/128') |
| 717 addr1.address_exclude(addr2) = [IPNetwork('::0/128'), |
| 718 IPNetwork('::2/127'), |
| 719 IPNetwork('::4/126'), |
| 720 IPNetwork('::8/125'), |
| 721 ... |
| 722 IPNetwork('0:0:8000::/33')] |
| 723 |
| 724 Args: |
| 725 other: An IPvXNetwork object of the same type. |
| 726 |
| 727 Returns: |
| 728 A sorted list of IPvXNetwork objects addresses which is self |
| 729 minus other. |
| 730 |
| 731 Raises: |
| 732 TypeError: If self and other are of difffering address |
| 733 versions, or if other is not a network object. |
| 734 ValueError: If other is not completely contained by self. |
| 735 |
| 736 """ |
| 737 if not self._version == other._version: |
| 738 raise TypeError("%s and %s are not of the same version" % ( |
| 739 str(self), str(other))) |
| 740 |
| 741 if not isinstance(other, _BaseNet): |
| 742 raise TypeError("%s is not a network object" % str(other)) |
| 743 |
| 744 if other not in self: |
| 745 raise ValueError('%s not contained in %s' % (str(other), |
| 746 str(self))) |
| 747 if other == self: |
| 748 return [] |
| 749 |
| 750 ret_addrs = [] |
| 751 |
| 752 # Make sure we're comparing the network of other. |
| 753 other = IPNetwork('%s/%s' % (str(other.network), str(other.prefixlen)), |
| 754 version=other._version) |
| 755 |
| 756 s1, s2 = self.subnet() |
| 757 while s1 != other and s2 != other: |
| 758 if other in s1: |
| 759 ret_addrs.append(s2) |
| 760 s1, s2 = s1.subnet() |
| 761 elif other in s2: |
| 762 ret_addrs.append(s1) |
| 763 s1, s2 = s2.subnet() |
| 764 else: |
| 765 # If we got here, there's a bug somewhere. |
| 766 assert True == False, ('Error performing exclusion: ' |
| 767 's1: %s s2: %s other: %s' % |
| 768 (str(s1), str(s2), str(other))) |
| 769 if s1 == other: |
| 770 ret_addrs.append(s2) |
| 771 elif s2 == other: |
| 772 ret_addrs.append(s1) |
| 773 else: |
| 774 # If we got here, there's a bug somewhere. |
| 775 assert True == False, ('Error performing exclusion: ' |
| 776 's1: %s s2: %s other: %s' % |
| 777 (str(s1), str(s2), str(other))) |
| 778 |
| 779 return sorted(ret_addrs, key=_BaseNet._get_networks_key) |
| 780 |
| 781 def compare_networks(self, other): |
| 782 """Compare two IP objects. |
| 783 |
| 784 This is only concerned about the comparison of the integer |
| 785 representation of the network addresses. This means that the |
| 786 host bits aren't considered at all in this method. If you want |
| 787 to compare host bits, you can easily enough do a |
| 788 'HostA._ip < HostB._ip' |
| 789 |
| 790 Args: |
| 791 other: An IP object. |
| 792 |
| 793 Returns: |
| 794 If the IP versions of self and other are the same, returns: |
| 795 |
| 796 -1 if self < other: |
| 797 eg: IPv4('1.1.1.0/24') < IPv4('1.1.2.0/24') |
| 798 IPv6('1080::200C:417A') < IPv6('1080::200B:417B') |
| 799 0 if self == other |
| 800 eg: IPv4('1.1.1.1/24') == IPv4('1.1.1.2/24') |
| 801 IPv6('1080::200C:417A/96') == IPv6('1080::200C:417B/96') |
| 802 1 if self > other |
| 803 eg: IPv4('1.1.1.0/24') > IPv4('1.1.0.0/24') |
| 804 IPv6('1080::1:200C:417A/112') > |
| 805 IPv6('1080::0:200C:417A/112') |
| 806 |
| 807 If the IP versions of self and other are different, returns: |
| 808 |
| 809 -1 if self._version < other._version |
| 810 eg: IPv4('10.0.0.1/24') < IPv6('::1/128') |
| 811 1 if self._version > other._version |
| 812 eg: IPv6('::1/128') > IPv4('255.255.255.0/24') |
| 813 |
| 814 """ |
| 815 if self._version < other._version: |
| 816 return -1 |
| 817 if self._version > other._version: |
| 818 return 1 |
| 819 # self._version == other._version below here: |
| 820 if self.network < other.network: |
| 821 return -1 |
| 822 if self.network > other.network: |
| 823 return 1 |
| 824 # self.network == other.network below here: |
| 825 if self.netmask < other.netmask: |
| 826 return -1 |
| 827 if self.netmask > other.netmask: |
| 828 return 1 |
| 829 # self.network == other.network and self.netmask == other.netmask |
| 830 return 0 |
| 831 |
| 832 def _get_networks_key(self): |
| 833 """Network-only key function. |
| 834 |
| 835 Returns an object that identifies this address' network and |
| 836 netmask. This function is a suitable "key" argument for sorted() |
| 837 and list.sort(). |
| 838 |
| 839 """ |
| 840 return (self._version, self.network, self.netmask) |
| 841 |
| 842 def _ip_int_from_prefix(self, prefixlen=None): |
| 843 """Turn the prefix length netmask into a int for comparison. |
| 844 |
| 845 Args: |
| 846 prefixlen: An integer, the prefix length. |
| 847 |
| 848 Returns: |
| 849 An integer. |
| 850 |
| 851 """ |
| 852 if not prefixlen and prefixlen != 0: |
| 853 prefixlen = self._prefixlen |
| 854 return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen) |
| 855 |
| 856 def _prefix_from_ip_int(self, ip_int, mask=32): |
| 857 """Return prefix length from the decimal netmask. |
| 858 |
| 859 Args: |
| 860 ip_int: An integer, the IP address. |
| 861 mask: The netmask. Defaults to 32. |
| 862 |
| 863 Returns: |
| 864 An integer, the prefix length. |
| 865 |
| 866 """ |
| 867 while mask: |
| 868 if ip_int & 1 == 1: |
| 869 break |
| 870 ip_int >>= 1 |
| 871 mask -= 1 |
| 872 |
| 873 return mask |
| 874 |
| 875 def _ip_string_from_prefix(self, prefixlen=None): |
| 876 """Turn a prefix length into a dotted decimal string. |
| 877 |
| 878 Args: |
| 879 prefixlen: An integer, the netmask prefix length. |
| 880 |
| 881 Returns: |
| 882 A string, the dotted decimal netmask string. |
| 883 |
| 884 """ |
| 885 if not prefixlen: |
| 886 prefixlen = self._prefixlen |
| 887 return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen)) |
| 888 |
| 889 def iter_subnets(self, prefixlen_diff=1, new_prefix=None): |
| 890 """The subnets which join to make the current subnet. |
| 891 |
| 892 In the case that self contains only one IP |
| 893 (self._prefixlen == 32 for IPv4 or self._prefixlen == 128 |
| 894 for IPv6), return a list with just ourself. |
| 895 |
| 896 Args: |
| 897 prefixlen_diff: An integer, the amount the prefix length |
| 898 should be increased by. This should not be set if |
| 899 new_prefix is also set. |
| 900 new_prefix: The desired new prefix length. This must be a |
| 901 larger number (smaller prefix) than the existing prefix. |
| 902 This should not be set if prefixlen_diff is also set. |
| 903 |
| 904 Returns: |
| 905 An iterator of IPv(4|6) objects. |
| 906 |
| 907 Raises: |
| 908 ValueError: The prefixlen_diff is too small or too large. |
| 909 OR |
| 910 prefixlen_diff and new_prefix are both set or new_prefix |
| 911 is a smaller number than the current prefix (smaller |
| 912 number means a larger network) |
| 913 |
| 914 """ |
| 915 if self._prefixlen == self._max_prefixlen: |
| 916 yield self |
| 917 return |
| 918 |
| 919 if new_prefix is not None: |
| 920 if new_prefix < self._prefixlen: |
| 921 raise ValueError('new prefix must be longer') |
| 922 if prefixlen_diff != 1: |
| 923 raise ValueError('cannot set prefixlen_diff and new_prefix') |
| 924 prefixlen_diff = new_prefix - self._prefixlen |
| 925 |
| 926 if prefixlen_diff < 0: |
| 927 raise ValueError('prefix length diff must be > 0') |
| 928 new_prefixlen = self._prefixlen + prefixlen_diff |
| 929 |
| 930 if not self._is_valid_netmask(str(new_prefixlen)): |
| 931 raise ValueError( |
| 932 'prefix length diff %d is invalid for netblock %s' % ( |
| 933 new_prefixlen, str(self))) |
| 934 |
| 935 first = IPNetwork('%s/%s' % (str(self.network), |
| 936 str(self._prefixlen + prefixlen_diff)), |
| 937 version=self._version) |
| 938 |
| 939 yield first |
| 940 current = first |
| 941 while True: |
| 942 broadcast = current.broadcast |
| 943 if broadcast == self.broadcast: |
| 944 return |
| 945 new_addr = IPAddress(int(broadcast) + 1, version=self._version) |
| 946 current = IPNetwork('%s/%s' % (str(new_addr), str(new_prefixlen)), |
| 947 version=self._version) |
| 948 |
| 949 yield current |
| 950 |
| 951 def masked(self): |
| 952 """Return the network object with the host bits masked out.""" |
| 953 return IPNetwork('%s/%d' % (self.network, self._prefixlen), |
| 954 version=self._version) |
| 955 |
| 956 def subnet(self, prefixlen_diff=1, new_prefix=None): |
| 957 """Return a list of subnets, rather than an iterator.""" |
| 958 return list(self.iter_subnets(prefixlen_diff, new_prefix)) |
| 959 |
| 960 def supernet(self, prefixlen_diff=1, new_prefix=None): |
| 961 """The supernet containing the current network. |
| 962 |
| 963 Args: |
| 964 prefixlen_diff: An integer, the amount the prefix length of |
| 965 the network should be decreased by. For example, given a |
| 966 /24 network and a prefixlen_diff of 3, a supernet with a |
| 967 /21 netmask is returned. |
| 968 |
| 969 Returns: |
| 970 An IPv4 network object. |
| 971 |
| 972 Raises: |
| 973 ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have a |
| 974 negative prefix length. |
| 975 OR |
| 976 If prefixlen_diff and new_prefix are both set or new_prefix is a |
| 977 larger number than the current prefix (larger number means a |
| 978 smaller network) |
| 979 |
| 980 """ |
| 981 if self._prefixlen == 0: |
| 982 return self |
| 983 |
| 984 if new_prefix is not None: |
| 985 if new_prefix > self._prefixlen: |
| 986 raise ValueError('new prefix must be shorter') |
| 987 if prefixlen_diff != 1: |
| 988 raise ValueError('cannot set prefixlen_diff and new_prefix') |
| 989 prefixlen_diff = self._prefixlen - new_prefix |
| 990 |
| 991 |
| 992 if self.prefixlen - prefixlen_diff < 0: |
| 993 raise ValueError( |
| 994 'current prefixlen is %d, cannot have a prefixlen_diff of %d' % |
| 995 (self.prefixlen, prefixlen_diff)) |
| 996 return IPNetwork('%s/%s' % (str(self.network), |
| 997 str(self.prefixlen - prefixlen_diff)), |
| 998 version=self._version) |
| 999 |
| 1000 # backwards compatibility |
| 1001 Subnet = subnet |
| 1002 Supernet = supernet |
| 1003 AddressExclude = address_exclude |
| 1004 CompareNetworks = compare_networks |
| 1005 Contains = __contains__ |
| 1006 |
| 1007 |
| 1008 class _BaseV4(object): |
| 1009 |
| 1010 """Base IPv4 object. |
| 1011 |
| 1012 The following methods are used by IPv4 objects in both single IP |
| 1013 addresses and networks. |
| 1014 |
| 1015 """ |
| 1016 |
| 1017 # Equivalent to 255.255.255.255 or 32 bits of 1's. |
| 1018 _ALL_ONES = (2**IPV4LENGTH) - 1 |
| 1019 _DECIMAL_DIGITS = frozenset('0123456789') |
| 1020 |
| 1021 def __init__(self, address): |
| 1022 self._version = 4 |
| 1023 self._max_prefixlen = IPV4LENGTH |
| 1024 |
| 1025 def _explode_shorthand_ip_string(self): |
| 1026 return str(self) |
| 1027 |
| 1028 def _ip_int_from_string(self, ip_str): |
| 1029 """Turn the given IP string into an integer for comparison. |
| 1030 |
| 1031 Args: |
| 1032 ip_str: A string, the IP ip_str. |
| 1033 |
| 1034 Returns: |
| 1035 The IP ip_str as an integer. |
| 1036 |
| 1037 Raises: |
| 1038 AddressValueError: if ip_str isn't a valid IPv4 Address. |
| 1039 |
| 1040 """ |
| 1041 octets = ip_str.split('.') |
| 1042 if len(octets) != 4: |
| 1043 raise AddressValueError(ip_str) |
| 1044 |
| 1045 packed_ip = 0 |
| 1046 for oc in octets: |
| 1047 try: |
| 1048 packed_ip = (packed_ip << 8) | self._parse_octet(oc) |
| 1049 except ValueError: |
| 1050 raise AddressValueError(ip_str) |
| 1051 return packed_ip |
| 1052 |
| 1053 def _parse_octet(self, octet_str): |
| 1054 """Convert a decimal octet into an integer. |
| 1055 |
| 1056 Args: |
| 1057 octet_str: A string, the number to parse. |
| 1058 |
| 1059 Returns: |
| 1060 The octet as an integer. |
| 1061 |
| 1062 Raises: |
| 1063 ValueError: if the octet isn't strictly a decimal from [0..255]. |
| 1064 |
| 1065 """ |
| 1066 # Whitelist the characters, since int() allows a lot of bizarre stuff. |
| 1067 if not self._DECIMAL_DIGITS.issuperset(octet_str): |
| 1068 raise ValueError |
| 1069 octet_int = int(octet_str, 10) |
| 1070 # Disallow leading zeroes, because no clear standard exists on |
| 1071 # whether these should be interpreted as decimal or octal. |
| 1072 if octet_int > 255 or (octet_str[0] == '0' and len(octet_str) > 1): |
| 1073 raise ValueError |
| 1074 return octet_int |
| 1075 |
| 1076 def _string_from_ip_int(self, ip_int): |
| 1077 """Turns a 32-bit integer into dotted decimal notation. |
| 1078 |
| 1079 Args: |
| 1080 ip_int: An integer, the IP address. |
| 1081 |
| 1082 Returns: |
| 1083 The IP address as a string in dotted decimal notation. |
| 1084 |
| 1085 """ |
| 1086 octets = [] |
| 1087 for _ in xrange(4): |
| 1088 octets.insert(0, str(ip_int & 0xFF)) |
| 1089 ip_int >>= 8 |
| 1090 return '.'.join(octets) |
| 1091 |
| 1092 @property |
| 1093 def max_prefixlen(self): |
| 1094 return self._max_prefixlen |
| 1095 |
| 1096 @property |
| 1097 def packed(self): |
| 1098 """The binary representation of this address.""" |
| 1099 return v4_int_to_packed(self._ip) |
| 1100 |
| 1101 @property |
| 1102 def version(self): |
| 1103 return self._version |
| 1104 |
| 1105 @property |
| 1106 def is_reserved(self): |
| 1107 """Test if the address is otherwise IETF reserved. |
| 1108 |
| 1109 Returns: |
| 1110 A boolean, True if the address is within the |
| 1111 reserved IPv4 Network range. |
| 1112 |
| 1113 """ |
| 1114 return self in IPv4Network('240.0.0.0/4') |
| 1115 |
| 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 1918. |
| 1122 |
| 1123 """ |
| 1124 return (self in IPv4Network('10.0.0.0/8') or |
| 1125 self in IPv4Network('172.16.0.0/12') or |
| 1126 self in IPv4Network('192.168.0.0/16')) |
| 1127 |
| 1128 @property |
| 1129 def is_multicast(self): |
| 1130 """Test if the address is reserved for multicast use. |
| 1131 |
| 1132 Returns: |
| 1133 A boolean, True if the address is multicast. |
| 1134 See RFC 3171 for details. |
| 1135 |
| 1136 """ |
| 1137 return self in IPv4Network('224.0.0.0/4') |
| 1138 |
| 1139 @property |
| 1140 def is_unspecified(self): |
| 1141 """Test if the address is unspecified. |
| 1142 |
| 1143 Returns: |
| 1144 A boolean, True if this is the unspecified address as defined in |
| 1145 RFC 5735 3. |
| 1146 |
| 1147 """ |
| 1148 return self in IPv4Network('0.0.0.0') |
| 1149 |
| 1150 @property |
| 1151 def is_loopback(self): |
| 1152 """Test if the address is a loopback address. |
| 1153 |
| 1154 Returns: |
| 1155 A boolean, True if the address is a loopback per RFC 3330. |
| 1156 |
| 1157 """ |
| 1158 return self in IPv4Network('127.0.0.0/8') |
| 1159 |
| 1160 @property |
| 1161 def is_link_local(self): |
| 1162 """Test if the address is reserved for link-local. |
| 1163 |
| 1164 Returns: |
| 1165 A boolean, True if the address is link-local per RFC 3927. |
| 1166 |
| 1167 """ |
| 1168 return self in IPv4Network('169.254.0.0/16') |
| 1169 |
| 1170 |
| 1171 class IPv4Address(_BaseV4, _BaseIP): |
| 1172 |
| 1173 """Represent and manipulate single IPv4 Addresses.""" |
| 1174 |
| 1175 def __init__(self, address): |
| 1176 |
| 1177 """ |
| 1178 Args: |
| 1179 address: A string or integer representing the IP |
| 1180 '192.168.1.1' |
| 1181 |
| 1182 Additionally, an integer can be passed, so |
| 1183 IPv4Address('192.168.1.1') == IPv4Address(3232235777). |
| 1184 or, more generally |
| 1185 IPv4Address(int(IPv4Address('192.168.1.1'))) == |
| 1186 IPv4Address('192.168.1.1') |
| 1187 |
| 1188 Raises: |
| 1189 AddressValueError: If ipaddr isn't a valid IPv4 address. |
| 1190 |
| 1191 """ |
| 1192 _BaseV4.__init__(self, address) |
| 1193 |
| 1194 # Efficient constructor from integer. |
| 1195 if isinstance(address, (int, long)): |
| 1196 self._ip = address |
| 1197 if address < 0 or address > self._ALL_ONES: |
| 1198 raise AddressValueError(address) |
| 1199 return |
| 1200 |
| 1201 # Constructing from a packed address |
| 1202 if isinstance(address, Bytes): |
| 1203 try: |
| 1204 self._ip, = struct.unpack('!I', address) |
| 1205 except struct.error: |
| 1206 raise AddressValueError(address) # Wrong length. |
| 1207 return |
| 1208 |
| 1209 # Assume input argument to be string or any object representation |
| 1210 # which converts into a formatted IP string. |
| 1211 addr_str = str(address) |
| 1212 self._ip = self._ip_int_from_string(addr_str) |
| 1213 |
| 1214 |
| 1215 class IPv4Network(_BaseV4, _BaseNet): |
| 1216 |
| 1217 """This class represents and manipulates 32-bit IPv4 networks. |
| 1218 |
| 1219 Attributes: [examples for IPv4Network('1.2.3.4/27')] |
| 1220 ._ip: 16909060 |
| 1221 .ip: IPv4Address('1.2.3.4') |
| 1222 .network: IPv4Address('1.2.3.0') |
| 1223 .hostmask: IPv4Address('0.0.0.31') |
| 1224 .broadcast: IPv4Address('1.2.3.31') |
| 1225 .netmask: IPv4Address('255.255.255.224') |
| 1226 .prefixlen: 27 |
| 1227 |
| 1228 """ |
| 1229 |
| 1230 # the valid octets for host and netmasks. only useful for IPv4. |
| 1231 _valid_mask_octets = set((255, 254, 252, 248, 240, 224, 192, 128, 0)) |
| 1232 |
| 1233 def __init__(self, address, strict=False): |
| 1234 """Instantiate a new IPv4 network object. |
| 1235 |
| 1236 Args: |
| 1237 address: A string or integer representing the IP [& network]. |
| 1238 '192.168.1.1/24' |
| 1239 '192.168.1.1/255.255.255.0' |
| 1240 '192.168.1.1/0.0.0.255' |
| 1241 are all functionally the same in IPv4. Similarly, |
| 1242 '192.168.1.1' |
| 1243 '192.168.1.1/255.255.255.255' |
| 1244 '192.168.1.1/32' |
| 1245 are also functionaly equivalent. That is to say, failing to |
| 1246 provide a subnetmask will create an object with a mask of /32. |
| 1247 |
| 1248 If the mask (portion after the / in the argument) is given in |
| 1249 dotted quad form, it is treated as a netmask if it starts with a |
| 1250 non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it |
| 1251 starts with a zero field (e.g. 0.255.255.255 == /8), with the |
| 1252 single exception of an all-zero mask which is treated as a |
| 1253 netmask == /0. If no mask is given, a default of /32 is used. |
| 1254 |
| 1255 Additionally, an integer can be passed, so |
| 1256 IPv4Network('192.168.1.1') == IPv4Network(3232235777). |
| 1257 or, more generally |
| 1258 IPv4Network(int(IPv4Network('192.168.1.1'))) == |
| 1259 IPv4Network('192.168.1.1') |
| 1260 |
| 1261 strict: A boolean. If true, ensure that we have been passed |
| 1262 A true network address, eg, 192.168.1.0/24 and not an |
| 1263 IP address on a network, eg, 192.168.1.1/24. |
| 1264 |
| 1265 Raises: |
| 1266 AddressValueError: If ipaddr isn't a valid IPv4 address. |
| 1267 NetmaskValueError: If the netmask isn't valid for |
| 1268 an IPv4 address. |
| 1269 ValueError: If strict was True and a network address was not |
| 1270 supplied. |
| 1271 |
| 1272 """ |
| 1273 _BaseNet.__init__(self, address) |
| 1274 _BaseV4.__init__(self, address) |
| 1275 |
| 1276 # Constructing from an integer or packed bytes. |
| 1277 if isinstance(address, (int, long, Bytes)): |
| 1278 self.ip = IPv4Address(address) |
| 1279 self._ip = self.ip._ip |
| 1280 self._prefixlen = self._max_prefixlen |
| 1281 self.netmask = IPv4Address(self._ALL_ONES) |
| 1282 return |
| 1283 |
| 1284 # Assume input argument to be string or any object representation |
| 1285 # which converts into a formatted IP prefix string. |
| 1286 addr = str(address).split('/') |
| 1287 |
| 1288 if len(addr) > 2: |
| 1289 raise AddressValueError(address) |
| 1290 |
| 1291 self._ip = self._ip_int_from_string(addr[0]) |
| 1292 self.ip = IPv4Address(self._ip) |
| 1293 |
| 1294 if len(addr) == 2: |
| 1295 mask = addr[1].split('.') |
| 1296 if len(mask) == 4: |
| 1297 # We have dotted decimal netmask. |
| 1298 if self._is_valid_netmask(addr[1]): |
| 1299 self.netmask = IPv4Address(self._ip_int_from_string( |
| 1300 addr[1])) |
| 1301 elif self._is_hostmask(addr[1]): |
| 1302 self.netmask = IPv4Address( |
| 1303 self._ip_int_from_string(addr[1]) ^ self._ALL_ONES) |
| 1304 else: |
| 1305 raise NetmaskValueError('%s is not a valid netmask' |
| 1306 % addr[1]) |
| 1307 |
| 1308 self._prefixlen = self._prefix_from_ip_int(int(self.netmask)) |
| 1309 else: |
| 1310 # We have a netmask in prefix length form. |
| 1311 if not self._is_valid_netmask(addr[1]): |
| 1312 raise NetmaskValueError(addr[1]) |
| 1313 self._prefixlen = int(addr[1]) |
| 1314 self.netmask = IPv4Address(self._ip_int_from_prefix( |
| 1315 self._prefixlen)) |
| 1316 else: |
| 1317 self._prefixlen = self._max_prefixlen |
| 1318 self.netmask = IPv4Address(self._ip_int_from_prefix( |
| 1319 self._prefixlen)) |
| 1320 if strict: |
| 1321 if self.ip != self.network: |
| 1322 raise ValueError('%s has host bits set' % |
| 1323 self.ip) |
| 1324 if self._prefixlen == (self._max_prefixlen - 1): |
| 1325 self.iterhosts = self.__iter__ |
| 1326 |
| 1327 def _is_hostmask(self, ip_str): |
| 1328 """Test if the IP string is a hostmask (rather than a netmask). |
| 1329 |
| 1330 Args: |
| 1331 ip_str: A string, the potential hostmask. |
| 1332 |
| 1333 Returns: |
| 1334 A boolean, True if the IP string is a hostmask. |
| 1335 |
| 1336 """ |
| 1337 bits = ip_str.split('.') |
| 1338 try: |
| 1339 parts = [int(x) for x in bits if int(x) in self._valid_mask_octets] |
| 1340 except ValueError: |
| 1341 return False |
| 1342 if len(parts) != len(bits): |
| 1343 return False |
| 1344 if parts[0] < parts[-1]: |
| 1345 return True |
| 1346 return False |
| 1347 |
| 1348 def _is_valid_netmask(self, netmask): |
| 1349 """Verify that the netmask is valid. |
| 1350 |
| 1351 Args: |
| 1352 netmask: A string, either a prefix or dotted decimal |
| 1353 netmask. |
| 1354 |
| 1355 Returns: |
| 1356 A boolean, True if the prefix represents a valid IPv4 |
| 1357 netmask. |
| 1358 |
| 1359 """ |
| 1360 mask = netmask.split('.') |
| 1361 if len(mask) == 4: |
| 1362 if [x for x in mask if int(x) not in self._valid_mask_octets]: |
| 1363 return False |
| 1364 if [y for idx, y in enumerate(mask) if idx > 0 and |
| 1365 y > mask[idx - 1]]: |
| 1366 return False |
| 1367 return True |
| 1368 try: |
| 1369 netmask = int(netmask) |
| 1370 except ValueError: |
| 1371 return False |
| 1372 return 0 <= netmask <= self._max_prefixlen |
| 1373 |
| 1374 # backwards compatibility |
| 1375 IsRFC1918 = lambda self: self.is_private |
| 1376 IsMulticast = lambda self: self.is_multicast |
| 1377 IsLoopback = lambda self: self.is_loopback |
| 1378 IsLinkLocal = lambda self: self.is_link_local |
| 1379 |
| 1380 |
| 1381 class _BaseV6(object): |
| 1382 |
| 1383 """Base IPv6 object. |
| 1384 |
| 1385 The following methods are used by IPv6 objects in both single IP |
| 1386 addresses and networks. |
| 1387 |
| 1388 """ |
| 1389 |
| 1390 _ALL_ONES = (2**IPV6LENGTH) - 1 |
| 1391 _HEXTET_COUNT = 8 |
| 1392 _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef') |
| 1393 |
| 1394 def __init__(self, address): |
| 1395 self._version = 6 |
| 1396 self._max_prefixlen = IPV6LENGTH |
| 1397 |
| 1398 def _ip_int_from_string(self, ip_str): |
| 1399 """Turn an IPv6 ip_str into an integer. |
| 1400 |
| 1401 Args: |
| 1402 ip_str: A string, the IPv6 ip_str. |
| 1403 |
| 1404 Returns: |
| 1405 A long, the IPv6 ip_str. |
| 1406 |
| 1407 Raises: |
| 1408 AddressValueError: if ip_str isn't a valid IPv6 Address. |
| 1409 |
| 1410 """ |
| 1411 parts = ip_str.split(':') |
| 1412 |
| 1413 # An IPv6 address needs at least 2 colons (3 parts). |
| 1414 if len(parts) < 3: |
| 1415 raise AddressValueError(ip_str) |
| 1416 |
| 1417 # If the address has an IPv4-style suffix, convert it to hexadecimal. |
| 1418 if '.' in parts[-1]: |
| 1419 ipv4_int = IPv4Address(parts.pop())._ip |
| 1420 parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF)) |
| 1421 parts.append('%x' % (ipv4_int & 0xFFFF)) |
| 1422 |
| 1423 # An IPv6 address can't have more than 8 colons (9 parts). |
| 1424 if len(parts) > self._HEXTET_COUNT + 1: |
| 1425 raise AddressValueError(ip_str) |
| 1426 |
| 1427 # Disregarding the endpoints, find '::' with nothing in between. |
| 1428 # This indicates that a run of zeroes has been skipped. |
| 1429 try: |
| 1430 skip_index, = ( |
| 1431 [i for i in xrange(1, len(parts) - 1) if not parts[i]] or |
| 1432 [None]) |
| 1433 except ValueError: |
| 1434 # Can't have more than one '::' |
| 1435 raise AddressValueError(ip_str) |
| 1436 |
| 1437 # parts_hi is the number of parts to copy from above/before the '::' |
| 1438 # parts_lo is the number of parts to copy from below/after the '::' |
| 1439 if skip_index is not None: |
| 1440 # If we found a '::', then check if it also covers the endpoints. |
| 1441 parts_hi = skip_index |
| 1442 parts_lo = len(parts) - skip_index - 1 |
| 1443 if not parts[0]: |
| 1444 parts_hi -= 1 |
| 1445 if parts_hi: |
| 1446 raise AddressValueError(ip_str) # ^: requires ^:: |
| 1447 if not parts[-1]: |
| 1448 parts_lo -= 1 |
| 1449 if parts_lo: |
| 1450 raise AddressValueError(ip_str) # :$ requires ::$ |
| 1451 parts_skipped = self._HEXTET_COUNT - (parts_hi + parts_lo) |
| 1452 if parts_skipped < 1: |
| 1453 raise AddressValueError(ip_str) |
| 1454 else: |
| 1455 # Otherwise, allocate the entire address to parts_hi. The endpoints |
| 1456 # could still be empty, but _parse_hextet() will check for that. |
| 1457 if len(parts) != self._HEXTET_COUNT: |
| 1458 raise AddressValueError(ip_str) |
| 1459 parts_hi = len(parts) |
| 1460 parts_lo = 0 |
| 1461 parts_skipped = 0 |
| 1462 |
| 1463 try: |
| 1464 # Now, parse the hextets into a 128-bit integer. |
| 1465 ip_int = 0L |
| 1466 for i in xrange(parts_hi): |
| 1467 ip_int <<= 16 |
| 1468 ip_int |= self._parse_hextet(parts[i]) |
| 1469 ip_int <<= 16 * parts_skipped |
| 1470 for i in xrange(-parts_lo, 0): |
| 1471 ip_int <<= 16 |
| 1472 ip_int |= self._parse_hextet(parts[i]) |
| 1473 return ip_int |
| 1474 except ValueError: |
| 1475 raise AddressValueError(ip_str) |
| 1476 |
| 1477 def _parse_hextet(self, hextet_str): |
| 1478 """Convert an IPv6 hextet string into an integer. |
| 1479 |
| 1480 Args: |
| 1481 hextet_str: A string, the number to parse. |
| 1482 |
| 1483 Returns: |
| 1484 The hextet as an integer. |
| 1485 |
| 1486 Raises: |
| 1487 ValueError: if the input isn't strictly a hex number from [0..FFFF]. |
| 1488 |
| 1489 """ |
| 1490 # Whitelist the characters, since int() allows a lot of bizarre stuff. |
| 1491 if not self._HEX_DIGITS.issuperset(hextet_str): |
| 1492 raise ValueError |
| 1493 hextet_int = int(hextet_str, 16) |
| 1494 if hextet_int > 0xFFFF: |
| 1495 raise ValueError |
| 1496 return hextet_int |
| 1497 |
| 1498 def _compress_hextets(self, hextets): |
| 1499 """Compresses a list of hextets. |
| 1500 |
| 1501 Compresses a list of strings, replacing the longest continuous |
| 1502 sequence of "0" in the list with "" and adding empty strings at |
| 1503 the beginning or at the end of the string such that subsequently |
| 1504 calling ":".join(hextets) will produce the compressed version of |
| 1505 the IPv6 address. |
| 1506 |
| 1507 Args: |
| 1508 hextets: A list of strings, the hextets to compress. |
| 1509 |
| 1510 Returns: |
| 1511 A list of strings. |
| 1512 |
| 1513 """ |
| 1514 best_doublecolon_start = -1 |
| 1515 best_doublecolon_len = 0 |
| 1516 doublecolon_start = -1 |
| 1517 doublecolon_len = 0 |
| 1518 for index in range(len(hextets)): |
| 1519 if hextets[index] == '0': |
| 1520 doublecolon_len += 1 |
| 1521 if doublecolon_start == -1: |
| 1522 # Start of a sequence of zeros. |
| 1523 doublecolon_start = index |
| 1524 if doublecolon_len > best_doublecolon_len: |
| 1525 # This is the longest sequence of zeros so far. |
| 1526 best_doublecolon_len = doublecolon_len |
| 1527 best_doublecolon_start = doublecolon_start |
| 1528 else: |
| 1529 doublecolon_len = 0 |
| 1530 doublecolon_start = -1 |
| 1531 |
| 1532 if best_doublecolon_len > 1: |
| 1533 best_doublecolon_end = (best_doublecolon_start + |
| 1534 best_doublecolon_len) |
| 1535 # For zeros at the end of the address. |
| 1536 if best_doublecolon_end == len(hextets): |
| 1537 hextets += [''] |
| 1538 hextets[best_doublecolon_start:best_doublecolon_end] = [''] |
| 1539 # For zeros at the beginning of the address. |
| 1540 if best_doublecolon_start == 0: |
| 1541 hextets = [''] + hextets |
| 1542 |
| 1543 return hextets |
| 1544 |
| 1545 def _string_from_ip_int(self, ip_int=None): |
| 1546 """Turns a 128-bit integer into hexadecimal notation. |
| 1547 |
| 1548 Args: |
| 1549 ip_int: An integer, the IP address. |
| 1550 |
| 1551 Returns: |
| 1552 A string, the hexadecimal representation of the address. |
| 1553 |
| 1554 Raises: |
| 1555 ValueError: The address is bigger than 128 bits of all ones. |
| 1556 |
| 1557 """ |
| 1558 if not ip_int and ip_int != 0: |
| 1559 ip_int = int(self._ip) |
| 1560 |
| 1561 if ip_int > self._ALL_ONES: |
| 1562 raise ValueError('IPv6 address is too large') |
| 1563 |
| 1564 hex_str = '%032x' % ip_int |
| 1565 hextets = [] |
| 1566 for x in range(0, 32, 4): |
| 1567 hextets.append('%x' % int(hex_str[x:x+4], 16)) |
| 1568 |
| 1569 hextets = self._compress_hextets(hextets) |
| 1570 return ':'.join(hextets) |
| 1571 |
| 1572 def _explode_shorthand_ip_string(self): |
| 1573 """Expand a shortened IPv6 address. |
| 1574 |
| 1575 Args: |
| 1576 ip_str: A string, the IPv6 address. |
| 1577 |
| 1578 Returns: |
| 1579 A string, the expanded IPv6 address. |
| 1580 |
| 1581 """ |
| 1582 if isinstance(self, _BaseNet): |
| 1583 ip_str = str(self.ip) |
| 1584 else: |
| 1585 ip_str = str(self) |
| 1586 |
| 1587 ip_int = self._ip_int_from_string(ip_str) |
| 1588 parts = [] |
| 1589 for i in xrange(self._HEXTET_COUNT): |
| 1590 parts.append('%04x' % (ip_int & 0xFFFF)) |
| 1591 ip_int >>= 16 |
| 1592 parts.reverse() |
| 1593 if isinstance(self, _BaseNet): |
| 1594 return '%s/%d' % (':'.join(parts), self.prefixlen) |
| 1595 return ':'.join(parts) |
| 1596 |
| 1597 @property |
| 1598 def max_prefixlen(self): |
| 1599 return self._max_prefixlen |
| 1600 |
| 1601 @property |
| 1602 def packed(self): |
| 1603 """The binary representation of this address.""" |
| 1604 return v6_int_to_packed(self._ip) |
| 1605 |
| 1606 @property |
| 1607 def version(self): |
| 1608 return self._version |
| 1609 |
| 1610 @property |
| 1611 def is_multicast(self): |
| 1612 """Test if the address is reserved for multicast use. |
| 1613 |
| 1614 Returns: |
| 1615 A boolean, True if the address is a multicast address. |
| 1616 See RFC 2373 2.7 for details. |
| 1617 |
| 1618 """ |
| 1619 return self in IPv6Network('ff00::/8') |
| 1620 |
| 1621 @property |
| 1622 def is_reserved(self): |
| 1623 """Test if the address is otherwise IETF reserved. |
| 1624 |
| 1625 Returns: |
| 1626 A boolean, True if the address is within one of the |
| 1627 reserved IPv6 Network ranges. |
| 1628 |
| 1629 """ |
| 1630 return (self in IPv6Network('::/8') or |
| 1631 self in IPv6Network('100::/8') or |
| 1632 self in IPv6Network('200::/7') or |
| 1633 self in IPv6Network('400::/6') or |
| 1634 self in IPv6Network('800::/5') or |
| 1635 self in IPv6Network('1000::/4') or |
| 1636 self in IPv6Network('4000::/3') or |
| 1637 self in IPv6Network('6000::/3') or |
| 1638 self in IPv6Network('8000::/3') or |
| 1639 self in IPv6Network('A000::/3') or |
| 1640 self in IPv6Network('C000::/3') or |
| 1641 self in IPv6Network('E000::/4') or |
| 1642 self in IPv6Network('F000::/5') or |
| 1643 self in IPv6Network('F800::/6') or |
| 1644 self in IPv6Network('FE00::/9')) |
| 1645 |
| 1646 @property |
| 1647 def is_unspecified(self): |
| 1648 """Test if the address is unspecified. |
| 1649 |
| 1650 Returns: |
| 1651 A boolean, True if this is the unspecified address as defined in |
| 1652 RFC 2373 2.5.2. |
| 1653 |
| 1654 """ |
| 1655 return self._ip == 0 and getattr(self, '_prefixlen', 128) == 128 |
| 1656 |
| 1657 @property |
| 1658 def is_loopback(self): |
| 1659 """Test if the address is a loopback address. |
| 1660 |
| 1661 Returns: |
| 1662 A boolean, True if the address is a loopback address as defined in |
| 1663 RFC 2373 2.5.3. |
| 1664 |
| 1665 """ |
| 1666 return self._ip == 1 and getattr(self, '_prefixlen', 128) == 128 |
| 1667 |
| 1668 @property |
| 1669 def is_link_local(self): |
| 1670 """Test if the address is reserved for link-local. |
| 1671 |
| 1672 Returns: |
| 1673 A boolean, True if the address is reserved per RFC 4291. |
| 1674 |
| 1675 """ |
| 1676 return self in IPv6Network('fe80::/10') |
| 1677 |
| 1678 @property |
| 1679 def is_site_local(self): |
| 1680 """Test if the address is reserved for site-local. |
| 1681 |
| 1682 Note that the site-local address space has been deprecated by RFC 3879. |
| 1683 Use is_private to test if this address is in the space of unique local |
| 1684 addresses as defined by RFC 4193. |
| 1685 |
| 1686 Returns: |
| 1687 A boolean, True if the address is reserved per RFC 3513 2.5.6. |
| 1688 |
| 1689 """ |
| 1690 return self in IPv6Network('fec0::/10') |
| 1691 |
| 1692 @property |
| 1693 def is_private(self): |
| 1694 """Test if this address is allocated for private networks. |
| 1695 |
| 1696 Returns: |
| 1697 A boolean, True if the address is reserved per RFC 4193. |
| 1698 |
| 1699 """ |
| 1700 return self in IPv6Network('fc00::/7') |
| 1701 |
| 1702 @property |
| 1703 def ipv4_mapped(self): |
| 1704 """Return the IPv4 mapped address. |
| 1705 |
| 1706 Returns: |
| 1707 If the IPv6 address is a v4 mapped address, return the |
| 1708 IPv4 mapped address. Return None otherwise. |
| 1709 |
| 1710 """ |
| 1711 if (self._ip >> 32) != 0xFFFF: |
| 1712 return None |
| 1713 return IPv4Address(self._ip & 0xFFFFFFFF) |
| 1714 |
| 1715 @property |
| 1716 def teredo(self): |
| 1717 """Tuple of embedded teredo IPs. |
| 1718 |
| 1719 Returns: |
| 1720 Tuple of the (server, client) IPs or None if the address |
| 1721 doesn't appear to be a teredo address (doesn't start with |
| 1722 2001::/32) |
| 1723 |
| 1724 """ |
| 1725 if (self._ip >> 96) != 0x20010000: |
| 1726 return None |
| 1727 return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF), |
| 1728 IPv4Address(~self._ip & 0xFFFFFFFF)) |
| 1729 |
| 1730 @property |
| 1731 def sixtofour(self): |
| 1732 """Return the IPv4 6to4 embedded address. |
| 1733 |
| 1734 Returns: |
| 1735 The IPv4 6to4-embedded address if present or None if the |
| 1736 address doesn't appear to contain a 6to4 embedded address. |
| 1737 |
| 1738 """ |
| 1739 if (self._ip >> 112) != 0x2002: |
| 1740 return None |
| 1741 return IPv4Address((self._ip >> 80) & 0xFFFFFFFF) |
| 1742 |
| 1743 |
| 1744 class IPv6Address(_BaseV6, _BaseIP): |
| 1745 |
| 1746 """Represent and manipulate single IPv6 Addresses. |
| 1747 """ |
| 1748 |
| 1749 def __init__(self, address): |
| 1750 """Instantiate a new IPv6 address object. |
| 1751 |
| 1752 Args: |
| 1753 address: A string or integer representing the IP |
| 1754 |
| 1755 Additionally, an integer can be passed, so |
| 1756 IPv6Address('2001:4860::') == |
| 1757 IPv6Address(42541956101370907050197289607612071936L). |
| 1758 or, more generally |
| 1759 IPv6Address(IPv6Address('2001:4860::')._ip) == |
| 1760 IPv6Address('2001:4860::') |
| 1761 |
| 1762 Raises: |
| 1763 AddressValueError: If address isn't a valid IPv6 address. |
| 1764 |
| 1765 """ |
| 1766 _BaseV6.__init__(self, address) |
| 1767 |
| 1768 # Efficient constructor from integer. |
| 1769 if isinstance(address, (int, long)): |
| 1770 self._ip = address |
| 1771 if address < 0 or address > self._ALL_ONES: |
| 1772 raise AddressValueError(address) |
| 1773 return |
| 1774 |
| 1775 # Constructing from a packed address |
| 1776 if isinstance(address, Bytes): |
| 1777 try: |
| 1778 hi, lo = struct.unpack('!QQ', address) |
| 1779 except struct.error: |
| 1780 raise AddressValueError(address) # Wrong length. |
| 1781 self._ip = (hi << 64) | lo |
| 1782 return |
| 1783 |
| 1784 # Assume input argument to be string or any object representation |
| 1785 # which converts into a formatted IP string. |
| 1786 addr_str = str(address) |
| 1787 if not addr_str: |
| 1788 raise AddressValueError('') |
| 1789 |
| 1790 self._ip = self._ip_int_from_string(addr_str) |
| 1791 |
| 1792 |
| 1793 class IPv6Network(_BaseV6, _BaseNet): |
| 1794 |
| 1795 """This class represents and manipulates 128-bit IPv6 networks. |
| 1796 |
| 1797 Attributes: [examples for IPv6('2001:658:22A:CAFE:200::1/64')] |
| 1798 .ip: IPv6Address('2001:658:22a:cafe:200::1') |
| 1799 .network: IPv6Address('2001:658:22a:cafe::') |
| 1800 .hostmask: IPv6Address('::ffff:ffff:ffff:ffff') |
| 1801 .broadcast: IPv6Address('2001:658:22a:cafe:ffff:ffff:ffff:ffff') |
| 1802 .netmask: IPv6Address('ffff:ffff:ffff:ffff::') |
| 1803 .prefixlen: 64 |
| 1804 |
| 1805 """ |
| 1806 |
| 1807 |
| 1808 def __init__(self, address, strict=False): |
| 1809 """Instantiate a new IPv6 Network object. |
| 1810 |
| 1811 Args: |
| 1812 address: A string or integer representing the IPv6 network or the IP |
| 1813 and prefix/netmask. |
| 1814 '2001:4860::/128' |
| 1815 '2001:4860:0000:0000:0000:0000:0000:0000/128' |
| 1816 '2001:4860::' |
| 1817 are all functionally the same in IPv6. That is to say, |
| 1818 failing to provide a subnetmask will create an object with |
| 1819 a mask of /128. |
| 1820 |
| 1821 Additionally, an integer can be passed, so |
| 1822 IPv6Network('2001:4860::') == |
| 1823 IPv6Network(42541956101370907050197289607612071936L). |
| 1824 or, more generally |
| 1825 IPv6Network(IPv6Network('2001:4860::')._ip) == |
| 1826 IPv6Network('2001:4860::') |
| 1827 |
| 1828 strict: A boolean. If true, ensure that we have been passed |
| 1829 A true network address, eg, 192.168.1.0/24 and not an |
| 1830 IP address on a network, eg, 192.168.1.1/24. |
| 1831 |
| 1832 Raises: |
| 1833 AddressValueError: If address isn't a valid IPv6 address. |
| 1834 NetmaskValueError: If the netmask isn't valid for |
| 1835 an IPv6 address. |
| 1836 ValueError: If strict was True and a network address was not |
| 1837 supplied. |
| 1838 |
| 1839 """ |
| 1840 _BaseNet.__init__(self, address) |
| 1841 _BaseV6.__init__(self, address) |
| 1842 |
| 1843 # Constructing from an integer or packed bytes. |
| 1844 if isinstance(address, (int, long, Bytes)): |
| 1845 self.ip = IPv6Address(address) |
| 1846 self._ip = self.ip._ip |
| 1847 self._prefixlen = self._max_prefixlen |
| 1848 self.netmask = IPv6Address(self._ALL_ONES) |
| 1849 return |
| 1850 |
| 1851 # Assume input argument to be string or any object representation |
| 1852 # which converts into a formatted IP prefix string. |
| 1853 addr = str(address).split('/') |
| 1854 |
| 1855 if len(addr) > 2: |
| 1856 raise AddressValueError(address) |
| 1857 |
| 1858 self._ip = self._ip_int_from_string(addr[0]) |
| 1859 self.ip = IPv6Address(self._ip) |
| 1860 |
| 1861 if len(addr) == 2: |
| 1862 if self._is_valid_netmask(addr[1]): |
| 1863 self._prefixlen = int(addr[1]) |
| 1864 else: |
| 1865 raise NetmaskValueError(addr[1]) |
| 1866 else: |
| 1867 self._prefixlen = self._max_prefixlen |
| 1868 |
| 1869 self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen)) |
| 1870 |
| 1871 if strict: |
| 1872 if self.ip != self.network: |
| 1873 raise ValueError('%s has host bits set' % |
| 1874 self.ip) |
| 1875 if self._prefixlen == (self._max_prefixlen - 1): |
| 1876 self.iterhosts = self.__iter__ |
| 1877 |
| 1878 def _is_valid_netmask(self, prefixlen): |
| 1879 """Verify that the netmask/prefixlen is valid. |
| 1880 |
| 1881 Args: |
| 1882 prefixlen: A string, the netmask in prefix length format. |
| 1883 |
| 1884 Returns: |
| 1885 A boolean, True if the prefix represents a valid IPv6 |
| 1886 netmask. |
| 1887 |
| 1888 """ |
| 1889 try: |
| 1890 prefixlen = int(prefixlen) |
| 1891 except ValueError: |
| 1892 return False |
| 1893 return 0 <= prefixlen <= self._max_prefixlen |
| 1894 |
| 1895 @property |
| 1896 def with_netmask(self): |
| 1897 return self.with_prefixlen |
| OLD | NEW |