1
2
3
4
5
6
7 """
8 network address classes (IP, EUI) and associated aggregate classes (CIDR,
9 Wildcard and IPRange).
10 """
11 import math as _math
12 import socket as _socket
13 import re as _re
14
15 from netaddr import AddrFormatError, AddrConversionError, AT_UNSPEC, \
16 AT_INET, AT_INET6, AT_LINK, AT_EUI64, AT_NAMES
17
18 from netaddr.strategy import ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64, \
19 AddrStrategy
20
21 from netaddr.eui import OUI, IAB
22
23 from netaddr.util import num_bits
24
25
26 AT_STRATEGIES = {
27 AT_UNSPEC : None,
28 AT_INET : ST_IPV4,
29 AT_INET6 : ST_IPV6,
30 AT_LINK : ST_EUI48,
31 AT_EUI64 : ST_EUI64,
32 }
36 """
37 A descriptor that checks addr_type property assignments for validity and
38 also keeps the strategy property in sync with any changes made.
39 """
41 """
42 Constructor.
43
44 @param addr_types: a list of address types constants that are
45 acceptable for assignment to the addr_type property.
46 """
47 self.addr_types = addr_types
48
49 - def __set__(self, instance, value):
50 if value not in self.addr_types:
51 raise ValueError('addr_type %r is invalid for objects of ' \
52 'the %s() class!' % (value, instance.__class__.__name__))
53 instance.__dict__['addr_type'] = value
54 instance.__dict__['strategy'] = AT_STRATEGIES[value]
55
58 """
59 A descriptor that checks assignments to the named parameter passed to the
60 constructor.
61
62 It accepts network addresses in either strings format or as unsigned
63 integers. String based addresses are converted to their integer
64 equivalents before assignment to the named parameter. Also ensures that
65 addr_type and strategy are set correctly when parsing string based
66 addresses.
67 """
69 """
70 Descriptor constructor.
71
72 @param name: the name of attribute which will be assigned the value.
73 """
74 self.name = name
75
76 - def __set__(self, instance, value):
105
108 """
109 A descriptor that checks strategy property assignments for validity and
110 also keeps the addr_type property in sync with any changes made.
111 """
113 """
114 Constructor.
115
116 @param strategies: a list of valid strategy objects that are suitable
117 for assignment to the strategy property.
118 """
119 self.strategies = strategies
120
121 - def __set__(self, instance, value):
122 if value not in self.strategies:
123 raise ValueError('%r is not a supported strategy!' % value)
124 new_strategy = value
125 instance.__dict__['strategy'] = new_strategy
126 instance.__dict__['addr_type'] = new_strategy.addr_type
127
130 """
131 A descriptor that checks prefixlen property assignments for validity based
132 on address type. Also accepts netmasks and hostmasks which can easily be
133 converted to the equivalent prefixlen integer.
134 """
136 """
137 Constructor.
138
139 @param class_id: (optional) the name of the class that uses this
140 descriptor.
141 """
142 self.class_id = class_id
143
144 - def __set__(self, instance, value):
176
202
203
204 -class Addr(object):
205 """
206 The base class containing common functionality for all subclasses
207 representing various network address types.
208
209 It is a fully functioning class (as opposed to a virtual class) with a
210 heuristic constructor that detects the type of address via the first
211 argument if it is a string and sets itself up accordingly. If the first
212 argument is an integer, then a constant must be provided via the second
213 argument indicating the address type explicitly.
214
215 Objects of this class behave differently dependent upon the type of address
216 they represent.
217 """
218 STRATEGIES = (ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64)
219 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6, AT_LINK, AT_EUI64)
220
221
222 value = AddrValueDescriptor('value')
223 strategy = StrategyDescriptor(STRATEGIES)
224 addr_type = AddrTypeDescriptor(ADDR_TYPES)
225
227 """
228 Constructor.
229
230 @param addr: the string form of a network address, or a network byte
231 order integer within the supported range for the address type.
232
233 @param addr_type: (optional) the network address type. If addr is an
234 integer, this argument becomes mandatory.
235 """
236 self.addr_type = addr_type
237 self.value = addr
238
240 """@return: hash of this address suitable for dict keys, sets etc"""
241 return hash((self.addr_type, self.value))
242
244 """@return: value of this address as an unsigned integer"""
245 return self.value
246
248 """@return: value of this address as an unsigned integer"""
249 return self.value
250
254
256 """@return: executable Python string to recreate equivalent object"""
257 return "%s(%r)" % (self.__class__.__name__, str(self))
258
259 - def bits(self, word_sep=None):
260 """
261 @param word_sep: (optional) the separator to insert between words.
262 Default: None - use default separator for address type.
263
264 @return: human-readable binary digit string of this address"""
265 return self.strategy.int_to_bits(self.value, word_sep)
266
270
272 """
273 @return: standard Python binary representation of this address. A back
274 port of the format provided by the builtin bin() type available in
275 Python 2.6.x and higher."""
276 return self.strategy.int_to_bin(self.value)
277
279 """@return: The size (width) of this address in bits"""
280 return self.strategy.width
281
285
287 """
288 @return: The integer value of the word referenced by index (both
289 positive and negative). Raises C{IndexError} if index is out
290 of bounds. Also supports Python list slices for accessing
291 word groups.
292 """
293 if isinstance(index, (int, long)):
294
295 num_words = self.strategy.num_words
296 if not (-num_words) <= index <= (num_words - 1):
297 raise IndexError('index out range for address type!')
298 return self.strategy.int_to_words(self.value)[index]
299 elif isinstance(index, slice):
300
301 words = self.strategy.int_to_words(self.value)
302 return [words[i] for i in range(*index.indices(len(words)))]
303 else:
304 raise TypeError('unsupported type %r!' % index)
305
307 """Sets the value of the word referenced by index in this address"""
308 if isinstance(index, slice):
309
310 raise NotImplementedError('settable slices not yet supported!')
311
312 if not isinstance(index, (int, long)):
313 raise TypeError('index not an integer!')
314
315 if not 0 <= index <= (self.strategy.num_words - 1):
316 raise IndexError('index %d outside address type boundary!' % index)
317
318 if not isinstance(value, (int, long)):
319 raise TypeError('value not an integer!')
320
321 if not 0 <= value <= self.strategy.max_word:
322 raise ValueError('value %d outside word size maximum of %d bits!'
323 % (value, self.strategy.word_size))
324
325 words = list(self.strategy.int_to_words(self.value))
326 words[index] = value
327 self.value = self.strategy.words_to_int(words)
328
330 """
331 @return: hexadecimal string representation of this address (in network
332 byte order).
333 """
334 return hex(self.value).rstrip('L').lower()
335
337 """
338 Increment value of network address by specified amount. Behaves like
339 an unsigned integer, rolling over to zero when it reaches the maximum
340 value threshold.
341
342 @param num: size of increment
343 """
344 try:
345 new_value = self.value + num
346 if new_value > self.strategy.max_int:
347 self.value = new_value - (self.strategy.max_int + 1)
348 else:
349 self.value = new_value
350 except TypeError:
351 raise TypeError('Increment value must be an integer!')
352 return self
353
355 """
356 Decrement value of network address by specified amount. Behaves like
357 an unsigned integer, rolling over to maximum value when it goes below
358 zero.
359
360 @param num: size of decrement
361 """
362 try:
363 new_value = self.value - num
364 if new_value < 0:
365 self.value = new_value + (self.strategy.max_int + 1)
366 else:
367 self.value = new_value
368 except TypeError:
369 raise TypeError('Decrement value must be an integer!')
370 return self
371
373 """
374 @param other: an integer or int-like object.
375
376 @return: A new (potentially larger) Addr class/subclass instance.
377 """
378 return self.__class__(self.value + int(other), self.addr_type)
379
381 """
382 @param other: an integer or int-like object.
383
384 @return: A new (potentially smaller) Addr class/subclass instance.
385 """
386 return self.__class__(self.value - int(other), self.addr_type)
387
389 """
390 @return: C{True} if this address is numerically the same as other,
391 C{False} otherwise.
392 """
393 try:
394 return (self.addr_type, self.value) == (other.addr_type,
395 other.value)
396 except AttributeError:
397 return False
398
400 """
401 @return: C{False} if this address is numerically the same as the
402 other, C{True} otherwise.
403 """
404 try:
405 return (self.addr_type, self.value) != (other.addr_type,
406 other.value)
407 except AttributeError:
408 return True
409
411 """
412 @return: C{True} if this address is numerically lower in value than
413 other, C{False} otherwise.
414 """
415 try:
416 return (self.addr_type, self.value) < (other.addr_type,
417 other.value)
418 except AttributeError:
419 return False
420
422 """
423 @return: C{True} if this address is numerically lower or equal in
424 value to other, C{False} otherwise.
425 """
426 try:
427 return (self.addr_type, self.value) <= (other.addr_type,
428 other.value)
429 except AttributeError:
430 return False
431
433 """
434 @return: C{True} if this address is numerically greater in value than
435 other, C{False} otherwise.
436 """
437 try:
438 return (self.addr_type, self.value) > (other.addr_type,
439 other.value)
440 except AttributeError:
441 return False
442
444 """
445 @return: C{True} if this address is numerically greater or equal in
446 value to other, C{False} otherwise.
447 """
448 try:
449 return (self.addr_type, self.value) >= (other.addr_type,
450 other.value)
451 except AttributeError:
452 return False
453
455 """
456 @param other: An Addr (sub)class instance (or int-like object).
457
458 @return: bitwise OR (x | y) between the integer value of this IP
459 address and another.
460 """
461 return self.__class__(self.value | other.value, self.addr_type)
462
464 """
465 @param other: An Addr (sub)class instance (or int-like object).
466
467 @return: bitwise AND (x & y) between the integer value of this
468 address and another.
469 """
470 return self.__class__(self.value & other.value, self.addr_type)
471
473 """
474 @param other: An Addr (sub)class instance (or int-like object).
475
476 @return: bitwise exclusive OR (x ^ y) between the integer value of
477 this address and another.
478 """
479 return self.__class__(self.value ^ other.value, self.addr_type)
480
482 """
483 @param numbits: size of bitwise shift.
484
485 @return: an address based on this one with its integer value
486 left shifted by x bits.
487 """
488 return self.__class__(self.value << numbits, self.addr_type)
489
491 """
492 @param numbits: size of bitwise shift.
493
494 @return: an address based on this one with its integer value
495 right shifted by x bits.
496 """
497 return self.__class__(self.value >> numbits, self.addr_type)
498
500 """
501 @return: True if the numerical value of this address is not zero,
502 False otherwise.
503 """
504 return bool(self.value)
505
506
507 -class EUI(Addr):
508 """
509 Represents an IEEE EUI (Extended Unique Identifier) indentifier.
510
511 Input parser is flexible, supporting EUI-48 (including the many Media
512 Access Control variants) and EUI-64.
513 """
514 STRATEGIES = (ST_EUI48, ST_EUI64)
515 ADDR_TYPES = (AT_UNSPEC, AT_LINK, AT_EUI64)
516
517
518 strategy = StrategyDescriptor(STRATEGIES)
519 addr_type = AddrTypeDescriptor(ADDR_TYPES)
520
522 """
523 Constructor.
524
525 @param addr: an EUI-48 (MAC) or EUI-64 address in string format or as
526 an unsigned integer.
527
528 @param addr_type: (optional) the specific EUI address type (C{AT_LINK}
529 or C{AT_EUI64}). This argument is used mainly to differentiate
530 EUI48 and EUI48 identifiers that may be numerically equivalent.
531 """
532
533
534 if addr_type == AT_UNSPEC:
535 if 0 <= addr <= 0xffffffffffff:
536 addr_type = AT_LINK
537 elif 0xffffffffffff < addr <= 0xffffffffffffffff:
538 addr_type = AT_EUI64
539
540 super(EUI, self).__init__(addr, addr_type)
541
543 """
544 @param fmt: callable used on return values. Default: L{OUI} object.
545 Also Supports str(), unicode(), int() and long().
546
547 @return: The OUI (Organisationally Unique Identifier) for this EUI.
548 """
549 if callable(fmt) and fmt in (OUI, int, long):
550 return fmt(self.value >> 24)
551 elif callable(fmt) and fmt in (str, unicode, None):
552 return '-'.join(["%02x" % i for i in self[0:3]]).upper()
553 else:
554 raise TypeError("unsupported formatter callable: %r!" % fmt)
555
557 """@return: The EI (Extension Identifier) for this EUI"""
558 if self.strategy == ST_EUI48:
559 return '-'.join(["%02x" % i for i in self[3:6]]).upper()
560 elif self.strategy == ST_EUI64:
561 return '-'.join(["%02x" % i for i in self[3:8]]).upper()
562
564 """@return: True if this EUI is an IAB address, False otherwise"""
565 return 0x50c2000 <= (self.value >> 12) <= 0x50c2fff
566
568 """
569 @param fmt: callable used on return values. Default: L{IAB} object.
570 Also Supports str(), unicode(), int() and long().
571
572 @return: If isiab() is True, the IAB (Individual Address Block)
573 is returned, None otherwise.
574 """
575 if self.isiab():
576 if callable(fmt) and fmt in (IAB, int, long):
577 return fmt(self.value >> 12)
578 elif callable(fmt) and fmt in (str, unicode, None):
579 usermask = (1 << (self.strategy.width - 36)) - 1
580 last_eui = self.value | usermask
581 first_eui = last_eui - usermask
582 iab_words = self.strategy.int_to_words(first_eui)
583 return '-'.join(["%02x" % i for i in iab_words]).upper()
584 else:
585 raise TypeError("unsupported formatter callable: %r!" % fmt)
586
588 """
589 @return: The value of this EUI object as a new 64-bit EUI object.
590 - If this object represents an EUI-48 it is converted to EUI-64
591 as per the standard.
592 - If this object is already and EUI-64, it just returns a new,
593 numerically equivalent object is returned instead.
594 """
595 if self.addr_type == AT_LINK:
596 eui64_words = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
597 ["%02x" % i for i in self[3:6]]
598
599 return self.__class__('-'.join(eui64_words))
600 else:
601 return EUI(str(self))
602
604 """
605 @return: new link local IPv6 L{IP} object based on this L{EUI} using
606 technique described in RFC 4291. B{Please Note:} this technique
607 poses security risks in certain scenarios. Please read RFC 4941 for
608 details. Reference: RFCs 4291 and 4941.
609 """
610 prefix = 'fe80:0000:0000:0000:'
611
612
613 self[0] += 2
614
615 if self.addr_type == AT_LINK:
616
617 suffix = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
618 ["%02x" % i for i in self[3:6]]
619 else:
620 suffix = ["%02x" % i for i in list(self)]
621
622 suffix = ["%02x%02x" % (int(x[0], 16), int(x[1], 16)) for x in \
623 zip(suffix[::2], suffix[1::2])]
624
625
626 self[0] -= 2
627
628 eui64 = ':'.join(suffix)
629 addr = prefix + eui64 + '/64'
630 return IP(addr)
631
633 """
634 @return: A record dict containing IEEE registration details for this
635 EUI (MAC-48) if available, None otherwise.
636 """
637 data = {'OUI': self.oui().registration()}
638 if self.isiab():
639 data['IAB'] = self.iab().registration()
640 return data
641
644 """
645 Represents B{individual} IPv4 and IPv6 addresses.
646
647 B{Please Note:} this class is intended to provide low-level functionality
648 to individual IP addresses such as octet/hextet access, integer/hex/binary
649 conversions, etc. If you are coming from other libraries you may expect to
650 find much higher level networking operations here. While the inclusion of
651 a bitmask prefix or netmask to indicate subnet membership is permitted by
652 the class constructor they are provided only as a convenience to the user.
653
654 All higher level subnet and network operations can be found in objects of
655 classes L{CIDR}, L{IPRange} and L{Wildcard}. There are handy helper methods
656 here, (C{.cidr()}, C{.iprange()} and C{.wildcard()}) that return pre-initialised
657 objects of those classes without you having to call them explicitly.
658
659 Example usage ::
660
661 >>> ip = IP('10.0.0.1')
662 >>> list(ip) == [10, 0, 0, 1]
663 True
664 >>> ip += 1
665 >>> str(ip) == '10.0.0.2'
666 True
667
668 >>> IP('10.0.0.0/28').iprange()
669 IPRange('10.0.0.0', '10.0.0.15')
670
671 >>> IP('10.0.0.64/24').cidr()
672 CIDR('10.0.0.0/24')
673
674 >>> IP('192.168.0.1/255.255.253.0').wildcard()
675 Wildcard('192.168.0-1.*')
676
677 >>> ipv6 = IP('fe80::20f:1fff:fe12:e733')
678 >>> ipv6[0:4]
679 [65152, 0, 0, 0]
680
681 >>> IP('fe80::20f:1fff:fe12:e733/64').cidr()
682 CIDR('fe80::/64')
683
684 See those classes for details on the functionality they provide.
685 """
686 STRATEGIES = (ST_IPV4, ST_IPV6)
687 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
688 TRANSLATE_STR = ''.join([chr(_) for _ in range(256)])
689
690
691 strategy = StrategyDescriptor(STRATEGIES)
692 addr_type = AddrTypeDescriptor(ADDR_TYPES)
693 prefixlen = PrefixLenDescriptor()
694
696 """
697 Constructor.
698
699 @param addr: an IPv4 or IPv6 address string with an optional subnet
700 prefix or an unsigned integer.
701
702 @param addr_type: (optional) the IP address type (C{AT_INET} or
703 C{AT_INET6}). This argument is used mainly to differentiate IPv4
704 and IPv6 addresses that may be numerically equivalent.
705 """
706 prefixlen = None
707
708 try:
709 if '/' in addr:
710 (addr, prefixlen) = addr.split('/', 1)
711 except TypeError:
712
713 pass
714
715
716
717 if addr_type == AT_UNSPEC:
718 if 0 <= addr <= 0xffffffff:
719 addr_type = AT_INET
720 elif 0xffffffff < addr <= 0xffffffffffffffffffffffffffffffff:
721 addr_type = AT_INET6
722
723
724
725 super(IP, self).__init__(addr, addr_type)
726
727
728 if prefixlen is None:
729 self.__dict__['prefixlen'] = self.strategy.width
730 else:
731 self.prefixlen = prefixlen
732
734 """
735 @return: C{True} if this addr is a mask that would return a host id,
736 C{False} otherwise.
737 """
738 int_val = (self.value ^ self.strategy.max_int) + 1
739 return (int_val & (int_val - 1) == 0)
740
742 """
743 @return: If this address is a valid netmask, the number of non-zero
744 bits are returned, otherwise it returns the width in bits for
745 based on the version, 32 for IPv4 and 128 for IPv6.
746 """
747 if not self.is_netmask():
748 return self.strategy.width
749
750 bits = self.strategy.int_to_bits(self.value)
751 mask_bits = bits.translate(IP.TRANSLATE_STR, ':.0')
752 mask_length = len(mask_bits)
753
754 if not 0 <= mask_length <= self.strategy.width:
755 raise ValueError('Unexpected mask length %d for address type!' \
756 % mask_length)
757
758 return mask_length
759
763
765 """
766 @return: C{True} if this address is a mask that would return a host
767 id, C{False} otherwise.
768 """
769 int_val = self.value + 1
770 return (int_val & (int_val-1) == 0)
771
773 """
774 @return: Returns the FQDN for this IP address via a DNS query
775 using gethostbyaddr() Python's socket module.
776 """
777 try:
778 return _socket.gethostbyaddr(str(self))[0]
779 except:
780 return
781
782 - def cidr(self, strict=True):
783 """
784 @param strict: (optional) If True and non-zero bits are found to the
785 right of the subnet mask/prefix a ValueError is raised. If False,
786 CIDR returned has these bits automatically truncated.
787 (default: True)
788
789 @return: A L{CIDR} object based on this IP address
790 """
791 hostmask = (1 << (self.strategy.width - self.prefixlen)) - 1
792 start = (self.value | hostmask) - hostmask
793 network = self.strategy.int_to_str(start)
794 return CIDR("%s/%d" % (network, self.prefixlen), strict=strict)
795
801
810
812 """
813 @return: A new version 4 L{IP} object numerically equivalent this
814 address. If this object is already IPv4 then a copy is returned. If
815 this object is IPv6 and its value is compatible with IPv4, a new IPv4
816 L{IP} object is returned.
817
818 Raises an L{AddrConversionError} is IPv6 address cannot be converted.
819 """
820 ip_addr = None
821 if self.addr_type == AT_INET:
822 ip_addr = IP(self.value, AT_INET)
823 ip_addr.prefixlen = self.prefixlen
824 elif self.addr_type == AT_INET6:
825 words = self.strategy.int_to_words(self.value)
826
827 if words[0:6] == (0, 0, 0, 0, 0, 0):
828 ip_addr = IP(self.value, AT_INET)
829 ip_addr.prefixlen = self.prefixlen - 96
830
831 elif words[0:6] == (0, 0, 0, 0, 0, 0xffff):
832 ip_addr = IP(self.value - 0xffff00000000, AT_INET)
833 ip_addr.prefixlen = self.prefixlen - 96
834 else:
835 raise AddrConversionError('IPv6 address %s not suitable for' \
836 'IPv4 conversion!' % self)
837 return ip_addr
838
839 - def ipv6(self, ipv4_compatible=False):
840 """
841 B{Please Note:} the IPv4-Mapped IPv6 address format is now considered
842 deprecated. Reference: RFC 4291
843
844 @param ipv4_compatible: If C{True} returns an IPv4-Mapped address
845 (::ffff:x.x.x.x), an IPv4-Compatible (::x.x.x.x) address
846 otherwise. Default: False (IPv4-Mapped).
847
848 @return: A new L{IP} version 6 object that is numerically equivalent
849 this address. If this object is already IPv6 then a copy of this
850 object is returned. If this object is IPv4, a new version 6 L{IP}
851 object is returned.
852 """
853 ip_addr = None
854 if self.addr_type == AT_INET6:
855 ip_addr = IP(self.value, AT_INET6)
856 ip_addr.prefixlen = self.prefixlen - 96
857 elif self.addr_type == AT_INET:
858 ip_addr = IP(self.value, AT_INET6)
859 if ipv4_compatible:
860
861 ip_addr[5] = 0
862 else:
863
864 ip_addr[5] = 0xffff
865 ip_addr.prefixlen = self.prefixlen + 96
866 return ip_addr
867
869 """@return: C{True} if this IP is unicast, C{False} otherwise"""
870 return not self.is_multicast()
871
873 """
874 @return: C{True} if this IP is loopback address (not for network
875 transmission), C{False} otherwise.
876 References: RFC 3330 and 4291.
877 """
878 if self.addr_type == AT_INET:
879 return self in CIDR('127/8')
880 elif self.addr_type == AT_INET6:
881 return self == IP('::1')
882
884 """@return: C{True} if this IP is multicast, C{False} otherwise"""
885 if self.addr_type == AT_INET:
886 return self in CIDR('224/4')
887 elif self.addr_type == AT_INET6:
888 return self in CIDR('ff00::/8')
889
891 """
892 @return: C{True} if this IP is for internal/private use only
893 (i.e. non-public), C{False} otherwise. Reference: RFCs 1918,
894 3330, 4193, 3879 and 2365.
895 """
896 if self.addr_type == AT_INET:
897 for cidr in (CIDR('192.168/16'), CIDR('10/8'),CIDR('172.16/12'),
898 CIDR('192.0.2.0/24'), CIDR('239.192/14')):
899 if self in cidr:
900 return True
901 elif self.addr_type == AT_INET6:
902
903 return self in CIDR('fc00::/7')
904
905 if self.is_link_local():
906 return True
907
908 return False
909
911 """
912 @return: C{True} if this IP is link-local address C{False} otherwise.
913 Reference: RFCs 3927 and 4291.
914 """
915 if self.addr_type == AT_INET:
916 return self in CIDR('169.254/16')
917 elif self.addr_type == AT_INET6:
918 return self in CIDR('fe80::/10')
919
921 """
922 @return: C{True} if this IP is in IANA reserved range, C{False}
923 otherwise. Reference: RFCs 3330 and 3171.
924 """
925 if self.addr_type == AT_INET:
926
927 for cidr in (CIDR('240/4'), CIDR('234/7'), CIDR('236/7'),
928 Wildcard('225-231.*.*.*'), Wildcard('234-238.*.*.*')):
929 if self in cidr:
930 return True
931 if self.addr_type == AT_INET6:
932 for cidr in (CIDR('ff00::/12'),CIDR('::/8'), CIDR('0100::/8'),
933 CIDR('0200::/7'), CIDR('0400::/6'), CIDR('0800::/5'),
934 CIDR('1000::/4'), CIDR('4000::/3'), CIDR('6000::/3'),
935 CIDR('8000::/3'), CIDR('A000::/3'), CIDR('C000::/3'),
936 CIDR('E000::/4'), CIDR('F000::/5'), CIDR('F800::/6'),
937 CIDR('FE00::/9')):
938 if self in cidr:
939 return True
940 return False
941
943 """
944 @return: C{True} if this IP is IPv4-compatible IPv6 address, C{False}
945 otherwise.
946 """
947 return self.addr_type == AT_INET6 and (self.value >> 32) == 0xffff
948
950 """
951 @return: C{True} if this IP is IPv4-mapped IPv6 address, C{False}
952 otherwise.
953 """
954 return self.addr_type == AT_INET6 and (self.value >> 32) == 0
955
957 """
958 @return: A record dict containing IANA registration details for this
959 IP address if available, None otherwise.
960 """
961
962
963
964
965 import netaddr.ip
966 return netaddr.ip.query(self)
967
969 """@return: common string representation for this IP address"""
970 return self.strategy.int_to_str(self.value)
971
973 """@return: executable Python string to recreate equivalent object."""
974 if self.prefixlen == self.strategy.width:
975 return "%s('%s')" % (self.__class__.__name__, str(self))
976
977 return "%s('%s/%d')" % (self.__class__.__name__, str(self),
978 self.prefixlen)
979
980
981 -def nrange(start, stop, step=1, fmt=None):
982 """
983 An xrange work alike generator that produces sequences of IP addresses
984 based on start and stop addresses, in intervals of step size.
985
986 @param start: first IP address string or L{IP} object in range.
987
988 @param stop: last IP address string or L{IP} object in range
989
990 @param step: (optional) size of step between address in range.
991 (Default: 1)
992
993 @param fmt: (optional) callable used on addresses returned.
994 (Default: None - L{IP} objects). Supported options :-
995 - C{str} - IP address in string format
996 - C{int}, C{long} - IP address as an unsigned integer
997 - C{hex} - IP address as a hexadecimal number
998 - L{IP} class/subclass or callable that accepts C{addr_value} and
999 C{addr_type} arguments.
1000 """
1001 if not isinstance(start, IP):
1002 if isinstance(start, (str, unicode)):
1003 start = IP(start)
1004 else:
1005 raise TypeError('start is not recognised address in string ' \
1006 'format or IP class/subclass instance!')
1007 else:
1008
1009 if fmt is None:
1010 fmt = start.__class__
1011
1012 if not isinstance(stop, IP):
1013 if isinstance(stop, (str, unicode)):
1014 stop = IP(stop)
1015 else:
1016 raise TypeError('stop is not recognised address string ' \
1017 'or IP class/subclass instance!')
1018
1019 if not isinstance(step, (int, long)):
1020 raise TypeError('step must be type int|long, not %s!' % type(step))
1021
1022 if start.addr_type != stop.addr_type:
1023 raise TypeError('start and stop are not the same address type!')
1024
1025 if step == 0:
1026 raise ValueError('step argument cannot be zero')
1027
1028 negative_step = False
1029 addr_type = start.addr_type
1030
1031
1032
1033 start_fmt = start.__class__
1034 start = int(start)
1035 stop = int(stop)
1036
1037 if step < 0:
1038 negative_step = True
1039
1040 index = start - step
1041
1042
1043 if fmt is None:
1044 fmt = IP
1045
1046 if fmt in (int, long, hex):
1047
1048 while True:
1049 index += step
1050 if negative_step:
1051 if not index >= stop:
1052 return
1053 else:
1054 if not index <= stop:
1055 return
1056 yield fmt(index)
1057 elif fmt in (str, unicode):
1058
1059 while True:
1060 index += step
1061 if negative_step:
1062 if not index >= stop:
1063 return
1064 else:
1065 if not index <= stop:
1066 return
1067 yield str(start_fmt(index, addr_type))
1068 else:
1069
1070 while True:
1071 index += step
1072 if negative_step:
1073 if not index >= stop:
1074 return
1075 else:
1076 if not index <= stop:
1077 return
1078
1079 yield fmt(index, addr_type)
1080
1083 """
1084 Represents arbitrary contiguous blocks of IPv4 and IPv6 addresses using
1085 only a lower and upper bound IP address.
1086
1087 It is the base class for more specialised block types such as L{CIDR()}
1088 and L{Wildcard()}. There is no requirement that the boundary IP addresses
1089 fall on strict bitmask boundaries.
1090
1091 The sort order for sequence of mixed version L{IPRange} objects is IPv4
1092 followed by IPv6, based on the range's magnitude (size).
1093 """
1094 STRATEGIES = (ST_IPV4, ST_IPV6)
1095 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
1096
1097
1098 strategy = StrategyDescriptor(STRATEGIES)
1099 addr_type = AddrTypeDescriptor(ADDR_TYPES)
1100 first = AddrValueDescriptor('first')
1101 last = AddrValueDescriptor('last')
1102 fmt = FormatDescriptor(IP)
1103
1105 """
1106 Constructor.
1107
1108 @param first: start address for this IP address range.
1109
1110 @param last: stop address for this IP address range.
1111
1112 @param fmt: (optional) callable used to create return values.
1113 Default: L{IP()} objects. See L{nrange()} documentations for
1114 more details on the various options.
1115 """
1116
1117
1118 self.addr_type = AT_UNSPEC
1119 self.first = first
1120 self.last = last
1121 if self.last < self.first:
1122 raise IndexError('start address is greater than stop address!')
1123 self.fmt = fmt
1124
1126 """
1127 @return: The hash of this address range. Allow them to be used in sets
1128 and as keys in dictionaries.
1129 """
1130 return hash((self.addr_type, self.first, self.last))
1131
1133 """
1134 @return: A 3-element tuple (first, last, addr_type) which represent
1135 the basic details of this IPRange object.
1136 """
1137 return self.first, self.last, self.addr_type
1138
1140 """
1141 @return: The total number of network addresses in this range.
1142 - Use this method only for ranges that contain less than
1143 C{2^31} addresses or try the L{size()} method. Raises an
1144 C{IndexError} if size is exceeded.
1145 """
1146 size = self.size()
1147 if size > (2 ** 31):
1148
1149 raise IndexError("range contains greater than 2^31 addresses! " \
1150 "Use obj.size() instead.")
1151 return size
1152
1154 """
1155 @return: The total number of network addresses in this range.
1156 - Use this method in preference to L{__len__()} when size of
1157 ranges potentially exceeds C{2^31} addresses.
1158 """
1159 return self.last - self.first + 1
1160
1181
1183 """
1184 @return: The IP address(es) in this address range referenced by
1185 index/slice. Slicing objects can produce large sequences so
1186 generator objects are returned instead of a list. Wrapping a slice
1187 with C{list()} or C{tuple()} may be required dependent on context
1188 in which it is called.
1189 """
1190
1191 if isinstance(index, (int, long)):
1192 if (- self.size()) <= index < 0:
1193
1194 return self.format(self.last + index + 1)
1195 elif 0 <= index <= (self.size() - 1):
1196
1197 return self.format(self.first + index)
1198 else:
1199 raise IndexError('index out range for address range size!')
1200 elif isinstance(index, slice):
1201
1202
1203
1204
1205
1206
1207
1208
1209 (start, stop, step) = index.indices(self.size())
1210
1211 start_addr = IP(self.first + start, self.addr_type)
1212 end_addr = IP(self.first + stop - step, self.addr_type)
1213 return nrange(start_addr, end_addr, step, fmt=self.fmt)
1214 else:
1215 raise TypeError('unsupported type %r!' % index)
1216
1218 """
1219 @return: An iterator object providing access to all network addresses
1220 within this range.
1221 """
1222 start_addr = IP(self.first, self.addr_type)
1223 end_addr = IP(self.last, self.addr_type)
1224 return nrange(start_addr, end_addr, fmt=self.fmt)
1225
1227 """
1228 @param addr: and IP/IPRange class/subclass instance or IP string value
1229 to be compared.
1230
1231 @return: C{True} if given address or range falls within this range,
1232 C{False} otherwise.
1233 """
1234 if isinstance(addr, (str, unicode)):
1235
1236 c_addr = IP(addr)
1237 if c_addr.addr_type == self.addr_type:
1238 if self.first <= int(c_addr) <= self.last:
1239 return True
1240 elif isinstance(addr, IP):
1241
1242 if self.first <= int(addr) <= self.last:
1243 return True
1244 elif issubclass(addr.__class__, IPRange):
1245
1246 if addr.first >= self.first and addr.last <= self.last:
1247 return True
1248 else:
1249 raise TypeError('%r is an unsupported type or class!' % addr)
1250
1251 return False
1252
1254 """
1255 @param other: an address object of the same address type as C{self}.
1256
1257 @return: C{True} if the boundaries of this range are the same as
1258 other, C{False} otherwise.
1259 """
1260 try:
1261 return (self.addr_type, self.first, self.last) == \
1262 (other.addr_type, other.first, other.last)
1263 except AttributeError:
1264 return False
1265
1267 """
1268 @param other: an address object of the same address type as C{self}.
1269
1270 @return: C{False} if the boundaries of this range are the same as
1271 other, C{True} otherwise.
1272 """
1273 try:
1274 return (self.addr_type, self.first, self.last) != \
1275 (other.addr_type, other.first, other.last)
1276 except AttributeError:
1277 return True
1278
1280 """
1281 @param other: an address object of the same address type as C{self}.
1282
1283 @return: C{True} if the boundaries of this range are less than other,
1284 C{False} otherwise.
1285 """
1286 try:
1287
1288
1289
1290 s_sortkey = self.strategy.width - num_bits(self.size())
1291 o_sortkey = other.strategy.width - num_bits(other.size())
1292
1293 return (self.addr_type, self.first, s_sortkey) < \
1294 (other.addr_type, other.first, o_sortkey)
1295 except AttributeError:
1296 return False
1297
1299 """
1300 @param other: an address object of the same address type as C{self}.
1301
1302 @return: C{True} if the boundaries of this range are less or equal to
1303 other, C{False} otherwise.
1304 """
1305 try:
1306
1307
1308
1309 s_sortkey = self.strategy.width - num_bits(self.size())
1310 o_sortkey = other.strategy.width - num_bits(other.size())
1311
1312 return (self.addr_type, self.first, s_sortkey) <= \
1313 (other.addr_type, other.first, o_sortkey)
1314 except AttributeError:
1315 return False
1316
1318 """
1319 @param other: an address object of the same address type as C{self}.
1320
1321 @return: C{True} if the boundaries of this range are greater than
1322 other, C{False} otherwise.
1323 """
1324 try:
1325
1326
1327
1328 s_sortkey = self.strategy.width - num_bits(self.size())
1329 o_sortkey = other.strategy.width - num_bits(other.size())
1330
1331 return (self.addr_type, self.first, s_sortkey) > \
1332 (other.addr_type, other.first, o_sortkey)
1333 except AttributeError:
1334 return False
1335
1337 """
1338 @param other: an address object of the same address type as C{self}.
1339
1340 @return: C{True} if the boundaries of this range are greater or equal
1341 to other, C{False} otherwise.
1342 """
1343 try:
1344
1345
1346
1347 s_sortkey = self.strategy.width - num_bits(self.size())
1348 o_sortkey = other.strategy.width - num_bits(other.size())
1349
1350 return (self.addr_type, self.first, s_sortkey) >= \
1351 (other.addr_type, other.first, o_sortkey)
1352 except AttributeError:
1353 return False
1354
1356 """
1357 Increments start and end addresses of this range by the current size.
1358
1359 Raises IndexError if the result exceeds address range maximum.
1360 """
1361 try:
1362 new_first = self.first + (self.size() * i)
1363 new_last = self.last + (self.size() * i)
1364 except TypeError:
1365 raise TypeError('Increment value must be an integer!')
1366
1367 if new_last > self.strategy.max_int:
1368 raise IndexError('Invalid increment is outside address boundary!')
1369
1370 self.first = new_first
1371 self.last = new_last
1372
1373 return self
1374
1376 """
1377 Decrements start and end addresses of this range by the current size.
1378
1379 Raises IndexError if the result is less than zero.
1380 """
1381 try:
1382 new_first = self.first - (self.size() * i)
1383 new_last = self.last - (self.size() * i)
1384 except TypeError:
1385 raise TypeError('Decrement value must be an integer!')
1386
1387 if new_last < 0:
1388 raise IndexError('Invalid decrement is outside address boundary!')
1389
1390 self.first = new_first
1391 self.last = new_last
1392
1393 return self
1394
1405
1407 """
1408 @return: A list of one or more L{CIDR} objects covering this address
1409 range. B{Please Note:} a list is returned even if this range maps
1410 to a single CIDR because arbitrary ranges may not be aligned with
1411 base 2 subnet sizes and will therefore return multiple CIDRs.
1412 """
1413
1414
1415 cidr_list = []
1416
1417
1418 start = IP(self.first, self.addr_type)
1419 end = IP(self.last, self.addr_type)
1420
1421 cidr_span = CIDR.span([start, end])
1422
1423 if cidr_span.first == self.first and cidr_span.last == self.last:
1424
1425 cidr_list = [cidr_span]
1426 elif cidr_span.last == self.last:
1427
1428 ip = IP(start)
1429 first_int_val = int(ip)
1430 ip -= 1
1431 cidr_remainder = cidr_span - ip
1432
1433 first_found = False
1434 for cidr in cidr_remainder:
1435 if cidr.first == first_int_val:
1436 first_found = True
1437 if first_found:
1438 cidr_list.append(cidr)
1439 elif cidr_span.first == self.first:
1440
1441 ip = IP(end)
1442 last_int_val = int(ip)
1443 ip += 1
1444 cidr_remainder = cidr_span - ip
1445
1446 last_found = False
1447 for cidr in cidr_remainder:
1448 cidr_list.append(cidr)
1449 if cidr.last == last_int_val:
1450 break
1451 elif cidr_span.first <= self.first and cidr_span.last >= self.last:
1452
1453 ip = IP(start)
1454 first_int_val = int(ip)
1455 ip -= 1
1456 cidr_remainder = cidr_span - ip
1457
1458
1459 first_found = False
1460 for cidr in cidr_remainder:
1461 if cidr.first == first_int_val:
1462 first_found = True
1463 if first_found:
1464 cidr_list.append(cidr)
1465
1466
1467 ip = IP(end)
1468 last_int_val = int(ip)
1469 ip += 1
1470 cidr_remainder = cidr_list.pop() - ip
1471
1472 last_found = False
1473 for cidr in cidr_remainder:
1474 cidr_list.append(cidr)
1475 if cidr.last == last_int_val:
1476 break
1477
1478
1479 if self.fmt in (str, unicode):
1480 cidr_list = [self.fmt(c) for c in cidr_list]
1481
1482 return cidr_list
1483
1485 """
1486 @return: A L{Wildcard} object equivalent to this CIDR.
1487 - If CIDR was initialised with C{fmt=str}, a wildcard string
1488 is returned, in all other cases a L{Wildcard} object is
1489 returned.
1490 - Only supports IPv4 CIDR addresses.
1491 """
1492 t1 = self.strategy.int_to_words(self.first)
1493 t2 = self.strategy.int_to_words(self.last)
1494
1495 if self.addr_type != AT_INET:
1496 raise AddrConversionError('wildcards only suitable for IPv4 ' \
1497 'ranges!')
1498
1499 tokens = []
1500
1501 seen_hyphen = False
1502 seen_asterisk = False
1503
1504 for i in range(4):
1505 if t1[i] == t2[i]:
1506
1507 tokens.append(str(t1[i]))
1508 elif (t1[i] == 0) and (t2[i] == 255):
1509
1510 tokens.append('*')
1511 seen_asterisk = True
1512 else:
1513
1514 if not seen_asterisk:
1515 if not seen_hyphen:
1516 tokens.append('%s-%s' % (t1[i], t2[i]))
1517 seen_hyphen = True
1518 else:
1519 raise SyntaxError('only one hyphenated octet per ' \
1520 'wildcard permitted!')
1521 else:
1522 raise SyntaxError("* chars aren't permitted before ' \
1523 'hyphenated octets!")
1524
1525 wildcard = '.'.join(tokens)
1526
1527 if self.fmt == str:
1528 return wildcard
1529
1530 return Wildcard(wildcard)
1531
1533 """
1534 @return: True if other's boundary is equal to or within this range.
1535 False otherwise.
1536 """
1537 if isinstance(other, (str, unicode)):
1538 other = CIDR(other)
1539
1540 if not hasattr(other, 'addr_type'):
1541 raise TypeError('%r is an unsupported argument type!' % other)
1542
1543 if self.addr_type != other.addr_type:
1544 raise TypeError('Ranges must be the same address type!')
1545
1546 return self.first >= other.first and self.last <= other.last
1547
1549 """
1550 @return: True if other's boundary is equal to or contains this range.
1551 False otherwise.
1552 """
1553 if isinstance(other, (str, unicode)):
1554 other = CIDR(other)
1555
1556 if not hasattr(other, 'addr_type'):
1557 raise TypeError('%r is an unsupported argument type!' % other)
1558
1559 if self.addr_type != other.addr_type:
1560 raise TypeError('Ranges must be the same address type!')
1561
1562 return self.first <= other.first and self.last >= other.last
1563
1565 """
1566 @return: True if other's boundary touches the boundary of this
1567 address range, False otherwise.
1568 """
1569 if isinstance(other, (str, unicode)):
1570 other = CIDR(other)
1571
1572 if not hasattr(other, 'addr_type'):
1573 raise TypeError('%r is an unsupported argument type!' % other)
1574
1575 if self.addr_type != other.addr_type:
1576 raise TypeError('addresses must be of the same type!')
1577
1578 if isinstance(other, IPRange):
1579
1580 if self.first == (other.last + 1):
1581 return True
1582
1583
1584 if self.last == (other.first - 1):
1585 return True
1586 elif isinstance(other, IP):
1587
1588 if self.first == (other.value + 1):
1589 return True
1590
1591
1592 if self.last == (other.value - 1):
1593 return True
1594 else:
1595 raise TypeError('unexpected error for argument: %r!')
1596
1597 return False
1598
1600 """
1601 @return: True if other's boundary crosses the boundary of this address
1602 range, False otherwise.
1603 """
1604 if isinstance(other, (str, unicode)):
1605 other = CIDR(other)
1606
1607 if not hasattr(other, 'addr_type'):
1608 raise TypeError('%r is an unsupported argument type!' % other)
1609
1610 if self.addr_type != other.addr_type:
1611 raise TypeError('Ranges must be the same address type!')
1612
1613
1614 if self.first <= other.last <= self.last:
1615 return True
1616
1617
1618 if self.first <= other.first <= self.last:
1619 return True
1620
1621 return False
1622
1626
1632
1635 """
1636 @param cidr: a CIDR object or CIDR string value (acceptable by CIDR class
1637 constructor).
1638
1639 @return: a tuple containing CIDR in binary string format and addr_type.
1640 """
1641 if not hasattr(cidr, 'network'):
1642 cidr = CIDR(cidr, strict=False)
1643
1644 bits = cidr.network.bits(word_sep='')
1645 return (bits[0:cidr.prefixlen], cidr.addr_type)
1646
1649 """
1650 @param bits: a CIDR in binary string format.
1651
1652 @param addr_type: (optional) CIDR address type (IP version).
1653 (Default: AT_UNSPEC - auto-select) If not specified AT_INET (IPv4) is
1654 assumed if length of binary string is <= /32. If binary string
1655 is > /32 and <= /128 AT_INET6 (IPv6) is assumed. Useful when you have
1656 IPv6 addresses with a prefixlen of /32 or less.
1657
1658 @param fmt: (optional) callable invoked on return CIDR.
1659 (Default: None - CIDR object). Also accepts str() and unicode().
1660
1661 @return: a CIDR object or string (determined by fmt).
1662 """
1663 if _re.match('^[01]+$', bits) is None:
1664 raise ValueError('%r is an invalid bit string!' % bits)
1665
1666 num_bits = len(bits)
1667 strategy = None
1668 if addr_type == AT_UNSPEC:
1669 if 0 <= num_bits <= 32:
1670 strategy = ST_IPV4
1671 elif 33 < num_bits <= 128:
1672 strategy = ST_IPV6
1673 else:
1674 raise ValueError('Invalid number of bits: %s!' % bits)
1675 elif addr_type == AT_INET:
1676 strategy = ST_IPV4
1677 elif addr_type == AT_INET6:
1678 strategy = ST_IPV6
1679 else:
1680 raise ValueError('strategy auto-select failure for %r!' % bits)
1681
1682 if bits == '':
1683 return CIDR('%s/0' % strategy.int_to_str(0))
1684
1685 cidr = None
1686 bits = bits + '0' * (strategy.width - num_bits)
1687 ip = strategy.int_to_str(strategy.bits_to_int(bits))
1688 cidr = CIDR('%s/%d' % (ip, num_bits))
1689
1690 if fmt is not None:
1691 return fmt(cidr)
1692
1693 return cidr
1694
1695
1696 -class CIDR(IPRange):
1697 """
1698 Represents blocks of IPv4 and IPv6 addresses using CIDR (Classless
1699 Inter-Domain Routing) notation.
1700
1701 CIDR is a method of categorising contiguous blocks of both IPv4 and IPv6
1702 addresses. It is very scalable allowing for the optimal usage of the IP
1703 address space. It permits the aggregation of networks via route
1704 summarisation (supernetting) where adjacent routes can be combined into a
1705 single route easily. This greatly assists in the reduction of routing
1706 table sizes and improves network router efficiency.
1707
1708 CIDR blocks are represented by a base network address and a prefix
1709 indicating the size of the (variable length) subnet mask. These are
1710 separated by a single '/' character. Subnet sizes increase in powers of
1711 base 2 aligning to bit boundaries.
1712
1713 It is technically invalid to have non-zero bits in a CIDR address to the
1714 right of the implied netmask. For user convenience this is however
1715 configurable and can be disabled using a constructor argument.
1716
1717 The constructor accepts CIDRs expressed in one of 4 different ways :-
1718
1719 A) Standard CIDR format :-
1720
1721 IPv4::
1722
1723 x.x.x.x/y -> 192.0.2.0/24
1724
1725 where the x's represent the network address and y is the netmask
1726 prefix between 0 and 32.
1727
1728 IPv6::
1729
1730 x::/y -> fe80::/10
1731
1732 where the x's represent the network address and y is the netmask
1733 prefix between 0 and 128.
1734
1735 B) Abbreviated CIDR format (IPv4 only)::
1736
1737 x -> 192
1738 x/y -> 10/8
1739 x.x/y -> 192.168/16
1740 x.x.x/y -> 192.168.0/24
1741
1742 which are equivalent to::
1743
1744 x.0.0.0/y -> 192.0.0.0/24
1745 x.0.0.0/y -> 10.0.0.0/8
1746 x.x.0.0/y -> 192.168.0.0/16
1747 x.x.x.0/y -> 192.168.0.0/24
1748
1749 - The trailing zeros are implicit.
1750 - Old classful IP address rules apply if y is omitted.
1751
1752 C) Hybrid CIDR format (prefix replaced by netmask) :-
1753
1754 IPv4::
1755
1756 x.x.x.x/y.y.y.y -> 192.0.2.0/255.255.255.0
1757
1758 IPv6::
1759
1760 x::/y:: -> fe80::/ffc0::
1761
1762 where the y's represent a valid netmask.
1763
1764 D) ACL-style CIDR format (prefix is replaced by a hostmask) :-
1765
1766 Akin to Cisco's ACL (Access Control List) bitmasking (reverse
1767 netmasks).
1768
1769 IPv4::
1770
1771 x.x.x.x/y.y.y.y -> 192.0.2.0/0.0.0.255
1772
1773 IPv6::
1774
1775 x::/y:: -> fe80::/3f:ffff:ffff:ffff:ffff:ffff:ffff:ffff
1776
1777 where the y's represent a valid hostmask.
1778
1779 Reference: RFCs 1338 and 4632.
1780 """
1781 STRATEGIES = (ST_IPV4, ST_IPV6)
1782 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
1783
1784
1785 strategy = StrategyDescriptor(STRATEGIES)
1786 addr_type = AddrTypeDescriptor(ADDR_TYPES)
1787 prefixlen = PrefixLenDescriptor('CIDR')
1788 fmt = FormatDescriptor(IP)
1789
1790 @staticmethod
1792 """
1793 A static method that converts abbreviated IPv4 CIDRs to their more
1794 verbose equivalent.
1795
1796 @param abbrev_cidr: an abbreviated CIDR.
1797
1798 Uses the old-style classful IP address rules to decide on a default
1799 subnet prefix if one is not explicitly provided.
1800
1801 Only supports IPv4 addresses.
1802
1803 Examples ::
1804
1805 10 - 10.0.0.0/8
1806 10/16 - 10.0.0.0/16
1807 128 - 128.0.0.0/16
1808 128/8 - 128.0.0.0/8
1809 192.168 - 192.168.0.0/16
1810
1811 @return: A verbose CIDR from an abbreviated CIDR or old-style classful
1812 network address, C{None} if format provided was not recognised or
1813 supported.
1814 """
1815
1816
1817 def classful_prefix(octet):
1818 octet = int(octet)
1819 if not 0 <= octet <= 255:
1820 raise IndexError('Invalid octet: %r!' % octet)
1821 if 0 <= octet <= 127:
1822 return 8
1823 elif 128 <= octet <= 191:
1824 return 16
1825 elif 192 <= octet <= 223:
1826 return 24
1827 elif octet == 224:
1828 return 4
1829 elif 225 <= octet <= 239:
1830 return 8
1831 return 32
1832
1833 start = ''
1834 tokens = []
1835 prefix = None
1836
1837 if isinstance(abbrev_cidr, (str, unicode)):
1838
1839 if ':' in abbrev_cidr:
1840 return None
1841 try:
1842
1843 i = int(abbrev_cidr)
1844 tokens = [str(i), '0', '0', '0']
1845 return "%s%s/%s" % (start, '.'.join(tokens), classful_prefix(i))
1846
1847 except ValueError:
1848
1849 part_addr = abbrev_cidr
1850 tokens = []
1851
1852 if part_addr == '':
1853
1854 return None
1855
1856 if '/' in part_addr:
1857 (part_addr, prefix) = part_addr.split('/', 1)
1858
1859
1860 if prefix is not None:
1861 try:
1862 if not 0 <= int(prefix) <= 32:
1863 return None
1864 except ValueError:
1865 return None
1866
1867 if '.' in part_addr:
1868 tokens = part_addr.split('.')
1869 else:
1870 tokens = [part_addr]
1871
1872 if 1 <= len(tokens) <= 4:
1873 for i in range(4 - len(tokens)):
1874 tokens.append('0')
1875 else:
1876
1877 return None
1878
1879 if prefix is None:
1880 try:
1881 prefix = classful_prefix(tokens[0])
1882 except ValueError:
1883 return None
1884
1885 return "%s%s/%s" % (start, '.'.join(tokens), prefix)
1886
1887 except TypeError:
1888 pass
1889 except IndexError:
1890 pass
1891
1892
1893 return None
1894
1895 @staticmethod
1896 - def span(addrs, fmt=None):
1897 """
1898 Static method that accepts a sequence of IP addresses and/or CIDRs,
1899 Wildcards and IPRanges returning a single CIDR that is large enough
1900 to span the lowest and highest IP addresses in the sequence (with
1901 a possible overlap on either end).
1902
1903 @param addrs: a sequence of IP, CIDR, Wildcard or IPRange objects
1904 and/or their string representations.
1905
1906 @param fmt: (optional) callable used on return values.
1907 (Default: None - L{CIDR} object) Also accepts str() and unicode().
1908
1909 @return: a single CIDR object spanning all addresses.
1910 """
1911 if not isinstance(addrs, (list, tuple)):
1912 raise TypeError('expected address sequence is not iterable!')
1913
1914 if not len(addrs) > 1:
1915 raise ValueError('sequence must contain 2 or more elements!')
1916
1917 if fmt not in (None, str, unicode):
1918 raise ValueError('unsupported formatter %r!' % fmt)
1919
1920
1921 if not isinstance(addrs, list):
1922 addrs = list(addrs)
1923
1924
1925
1926 for (i, addr) in enumerate(addrs):
1927 if isinstance(addr, (str, unicode)):
1928 try:
1929 obj = IP(addr)
1930 addrs[i] = obj
1931 continue
1932 except:
1933 pass
1934 try:
1935 obj = CIDR(addr)
1936 addrs[i] = obj
1937 continue
1938 except:
1939 pass
1940 try:
1941 obj = Wildcard(addr)
1942 addrs[i] = obj
1943 continue
1944 except:
1945 pass
1946
1947
1948 addrs.sort()
1949 lowest = addrs[0]
1950 highest = addrs[-1]
1951
1952 if isinstance(lowest, IPRange):
1953
1954 lowest = IP(lowest.first, lowest.addr_type)
1955
1956 if isinstance(highest, IPRange):
1957
1958 highest = IP(highest.last, highest.addr_type)
1959
1960 if lowest.addr_type != highest.addr_type:
1961 raise TypeError('address types are not the same!')
1962
1963 cidr = highest.cidr()
1964
1965 while cidr.prefixlen > 0:
1966 if highest in cidr and lowest not in cidr:
1967 cidr.prefixlen -= 1
1968 else:
1969 break
1970
1971
1972 if fmt is not None:
1973 return fmt(cidr)
1974
1975 return cidr
1976
1977 @staticmethod
1979 """
1980 Static method that accepts a sequence of IP addresses and/or CIDRs
1981 returning a summarized sequence of merged CIDRs where possible. This
1982 method doesn't create any CIDR that are inclusive of any addresses
1983 other than those found in the original sequence provided.
1984
1985 @param cidrs: a list or tuple of IP and/or CIDR objects.
1986
1987 @param fmt: callable used on return values.
1988 (Default: None - L{CIDR} objects). str() and unicode() supported.
1989
1990 @return: a possibly smaller list of CIDRs covering sequence passed in.
1991 """
1992 if not hasattr(cidrs, '__iter__'):
1993 raise ValueError('A sequence or iterable is expected!')
1994
1995
1996 ipv4_bit_cidrs = set()
1997 ipv6_bit_cidrs = set()
1998
1999
2000
2001 for cidr in cidrs:
2002 (bits, addr_type) = cidr_to_bits(cidr)
2003 if addr_type == AT_INET:
2004 ipv4_bit_cidrs.add(bits)
2005 elif addr_type == AT_INET6:
2006 ipv6_bit_cidrs.add(bits)
2007 else:
2008 raise ValueError('Unknown address type found!')
2009
2010
2011 def _reduce_bit_cidrs(cidrs):
2012 new_cidrs = []
2013
2014 cidrs.sort()
2015
2016
2017 while 1:
2018 finished = True
2019 while len(cidrs) > 0:
2020 if len(new_cidrs) == 0:
2021 new_cidrs.append(cidrs.pop(0))
2022 if len(cidrs) == 0:
2023 break
2024
2025 (new_cidr, subs) = _re.subn(r'^([01]+)0 \1[1]$',
2026 r'\1', '%s %s' % (new_cidrs[-1], cidrs[0]))
2027 if subs:
2028
2029 new_cidrs[-1] = new_cidr
2030 cidrs.pop(0)
2031 finished = False
2032 else:
2033
2034 (new_cidr, subs) = _re.subn(r'^([01]+) \1[10]+$',
2035 r'\1', '%s %s' % (new_cidrs[-1], cidrs[0]))
2036 if subs:
2037
2038 new_cidrs[-1] = new_cidr
2039 cidrs.pop(0)
2040 finished = False
2041 else:
2042
2043 new_cidrs.append(cidrs.pop(0))
2044 if finished:
2045 break
2046 else:
2047
2048 cidrs = new_cidrs
2049 new_cidrs = []
2050
2051 return new_cidrs
2052
2053 new_cidrs = []
2054
2055
2056 for bit_cidr in _reduce_bit_cidrs(list(ipv4_bit_cidrs)):
2057 new_cidrs.append(bits_to_cidr(bit_cidr, fmt=fmt))
2058
2059
2060 for bit_cidr in _reduce_bit_cidrs(list(ipv6_bit_cidrs)):
2061 new_cidrs.append(bits_to_cidr(bit_cidr, fmt=fmt))
2062
2063 return new_cidrs
2064
2065 - def __init__(self, cidr, fmt=IP, strict=True, expand_abbrev=True):
2066 """
2067 Constructor.
2068
2069 @param cidr: a valid IPv4/IPv6 CIDR address or abbreviated IPv4
2070 network address.
2071
2072 @param fmt: (optional) callable used on return values.
2073 Default: L{IP} class. See L{nrange()} documentations for
2074 more details on the various options.
2075
2076 @param strict: (optional) If True and non-zero bits are found to the
2077 right of the subnet mask/prefix a ValueError is raised. If False,
2078 CIDR returned has these bits automatically truncated.
2079 (default: True)
2080
2081 @param expand_abbrev: (optional) If True, enables the abbreviated CIDR
2082 expansion routine. If False, abbreviated CIDRs will be considered
2083 invalid addresses, raising an AddrFormatError exception.
2084 (default: True)
2085 """
2086 cidr_arg = cidr
2087
2088 if expand_abbrev:
2089
2090 verbose_cidr = CIDR.abbrev_to_verbose(cidr)
2091 if verbose_cidr is not None:
2092 cidr = verbose_cidr
2093
2094 if not isinstance(cidr, (str, unicode)):
2095 raise TypeError('%r is not a valid CIDR!' % cidr)
2096
2097
2098 try:
2099 (network, mask) = cidr.split('/', 1)
2100 except ValueError:
2101 network = cidr
2102 mask = None
2103
2104
2105
2106 first = IP(network)
2107 self.strategy = first.strategy
2108
2109 if mask is None:
2110
2111 self.__dict__['prefixlen'] = first.strategy.width
2112 else:
2113 self.prefixlen = mask
2114
2115 strategy = first.strategy
2116 addr_type = strategy.addr_type
2117
2118 hostmask = (1 << (strategy.width - self.prefixlen)) - 1
2119
2120 last = IP(first.value | hostmask, addr_type)
2121
2122 if strict:
2123
2124 netmask = strategy.max_int ^ hostmask
2125 host = (first.value | netmask) - netmask
2126 if host != 0:
2127 raise ValueError('%s contains non-zero bits right of the ' \
2128 '%d-bit mask! Did you mean %s instead?' \
2129 % (first, self.prefixlen,
2130 strategy.int_to_str(int(last) - hostmask)))
2131 else:
2132
2133 first.value = strategy.int_to_str(int(last) - hostmask)
2134
2135 super(CIDR, self).__init__(first, last, fmt)
2136
2138 """
2139 Subtract another CIDR from this one.
2140
2141 @param other: a CIDR object that is greater than or equal to C{self}.
2142
2143 @return: A list of CIDR objects than remain after subtracting C{other}
2144 from C{self}.
2145 """
2146 cidrs = []
2147
2148 if hasattr(other, 'value'):
2149
2150 other = other.cidr()
2151
2152 if other.last < self.first:
2153
2154 if self.fmt is str:
2155 return [str(self.cidrs()[0])]
2156 else:
2157 return [self.cidrs()[0]]
2158 elif self.last < other.first:
2159
2160
2161 if self.fmt is str:
2162 return [str(self.cidrs()[0])]
2163 else:
2164 return [self.cidrs()[0]]
2165
2166 new_prefixlen = self.prefixlen + 1
2167
2168 if new_prefixlen <= self.strategy.width:
2169 i_lower = self.first
2170 i_upper = self.first + (2 ** (self.strategy.width - new_prefixlen))
2171
2172 lower = CIDR('%s/%d' % (self.strategy.int_to_str(i_lower),
2173 new_prefixlen))
2174 upper = CIDR('%s/%d' % (self.strategy.int_to_str(i_upper),
2175 new_prefixlen))
2176
2177 while other.prefixlen >= new_prefixlen:
2178 if other in lower:
2179 matched = i_lower
2180 unmatched = i_upper
2181 elif other in upper:
2182 matched = i_upper
2183 unmatched = i_lower
2184 else:
2185
2186 cidrs.append(self.cidrs()[0])
2187 break
2188
2189 cidr = CIDR('%s/%d' % (self.strategy.int_to_str(unmatched),
2190 new_prefixlen))
2191
2192 cidrs.append(cidr)
2193
2194 new_prefixlen += 1
2195
2196 if new_prefixlen > self.strategy.width:
2197 break
2198
2199 i_lower = matched
2200 i_upper = matched + (2 ** (self.strategy.width - new_prefixlen))
2201
2202 lower = CIDR('%s/%d' % (self.strategy.int_to_str(i_lower),
2203 new_prefixlen))
2204 upper = CIDR('%s/%d' % (self.strategy.int_to_str(i_upper),
2205 new_prefixlen))
2206
2207 cidrs.sort()
2208
2209
2210 if self.fmt is str:
2211 return [str(cidr) for cidr in cidrs]
2212
2213 return cidrs
2214
2216 """
2217 Add another CIDR to this one returning a CIDR supernet that will
2218 contain both in the smallest possible sized range.
2219
2220 @param other: a CIDR object.
2221
2222 @return: A new (potentially larger) CIDR object.
2223 """
2224 cidr = CIDR.span([self, other])
2225 if self.fmt is str:
2226 return str(cidr)
2227 return cidr
2228
2229 @property
2231 """@return: The network (first) address in this CIDR block."""
2232 return self[0]
2233
2234 @property
2236 """
2237 B{Please Note:} although IPv6 doesn't actually recognise the concept of
2238 broadcast addresses per se (as in IPv4), so many other libraries do
2239 this that it isn't worth trying to resist the trend just for the sake
2240 of making a theoretical point.
2241
2242 @return: The broadcast (last) address in this CIDR block.
2243 """
2244 return self[-1]
2245
2246 @property
2252
2253 @property
2258
2260 """
2261 @param step: the number of CIDRs between this CIDR and the expected
2262 one. Default: 1 - the preceding CIDR.
2263
2264 @return: The immediate (adjacent) predecessor of this CIDR.
2265 """
2266 cidr_copy = CIDR('%s/%d' % (self.strategy.int_to_str(self.first),
2267 self.prefixlen))
2268 cidr_copy -= step
2269
2270 if self.fmt in (str, unicode):
2271 return self.fmt(cidr_copy)
2272 return cidr_copy
2273
2274 - def next(self, step=1):
2275 """
2276 @param step: the number of CIDRs between this CIDR and the expected
2277 one. Default: 1 - the succeeding CIDR.
2278
2279 @return: The immediate (adjacent) successor of this CIDR.
2280 """
2281 cidr_copy = CIDR('%s/%d' % (self.strategy.int_to_str(self.first),
2282 self.prefixlen))
2283 cidr_copy += step
2284
2285 if self.fmt in (str, unicode):
2286 return self.fmt(cidr_copy)
2287 return cidr_copy
2288
2290 """
2291 @return: An iterator object providing access to all valid host IP
2292 addresses within the specified CIDR block.
2293 - with IPv4 the network and broadcast addresses are always
2294 excluded. Any smaller than 4 hosts yields an emtpy list.
2295 - with IPv6 only the unspecified address '::' is excluded from
2296 the yielded list.
2297 """
2298 if self.addr_type == AT_INET:
2299
2300 if self.size() >= 4:
2301 return nrange( IP(self.first+1, self.addr_type),
2302 IP(self.last-1, self.addr_type), fmt=self.fmt)
2303 else:
2304 return iter([])
2305 elif self.addr_type == AT_INET6:
2306
2307 if self.first == 0:
2308
2309 return nrange(IP(self.first+1, self.addr_type),
2310 IP(self.last, self.addr_type), fmt=self.fmt)
2311 else:
2312 return iter(self)
2313
2314 - def supernet(self, prefixlen=0, fmt=None):
2315 """
2316 Provides a list of supernet CIDRs for the current CIDR between the size
2317 of the current prefix and (if specified) the end CIDR prefix.
2318
2319 @param prefixlen: (optional) a CIDR prefix for the maximum supernet.
2320 Default: 0 - returns all possible supernets.
2321
2322 @param fmt: callable used on return values.
2323 Default: None - L{CIDR} objects. str() and unicode() supported.
2324
2325 @return: an tuple containing CIDR supernets that contain this one.
2326 """
2327 if not 0 <= prefixlen <= self.strategy.width:
2328 raise ValueError('prefixlen %r invalid for IP version!' \
2329 % prefixlen)
2330
2331
2332 cidr = self.cidrs()[0]
2333 cidr.fmt = fmt
2334
2335 supernets = []
2336 while cidr.prefixlen > prefixlen:
2337 cidr.prefixlen -= 1
2338 supernets.append(cidr.cidrs()[0])
2339
2340 return list(reversed(supernets))
2341
2342 - def subnet(self, prefixlen, count=None, fmt=None):
2343 """
2344 A generator that returns CIDR subnets based on the current network
2345 base address and provided CIDR prefix and count.
2346
2347 @param prefixlen: a CIDR prefix.
2348
2349 @param count: number of consecutive CIDRs to be returned.
2350
2351 @param fmt: callable used on return values.
2352 Default: None - L{CIDR} objects. str() and unicode() supported.
2353
2354 @return: an iterator (as lists could potentially be very large)
2355 containing CIDR subnets below this CIDR's base address.
2356 """
2357 if not 0 <= self.prefixlen <= self.strategy.width:
2358 raise ValueError('prefixlen %d out of bounds for address type!' \
2359 % prefixlen)
2360
2361 if not self.prefixlen <= prefixlen:
2362 raise ValueError('prefixlen less than current CIDR prefixlen!')
2363
2364
2365 width = self.strategy.width
2366 max_count = 2 ** (width - self.prefixlen) / 2 ** (width - prefixlen)
2367
2368 if count is None:
2369 count = max_count
2370
2371 if not 1 <= count <= max_count:
2372 raise ValueError('count not within current CIDR boundaries!')
2373
2374 base_address = self.strategy.int_to_str(self.first)
2375
2376
2377 if fmt is None and self.fmt in (str, unicode):
2378 fmt = self.fmt
2379
2380 if fmt is None:
2381
2382 for i in xrange(count):
2383 cidr = CIDR('%s/%d' % (base_address, prefixlen))
2384 cidr.first += cidr.size() * i
2385 cidr.prefixlen = prefixlen
2386 yield cidr
2387 elif fmt in (str, unicode):
2388
2389 for i in xrange(count):
2390 cidr = CIDR('%s/%d' % (base_address, prefixlen))
2391 cidr.first += cidr.size() * i
2392 cidr.prefixlen = prefixlen
2393 yield fmt(cidr)
2394 else:
2395 raise TypeError('unsupported fmt callable %r' % fmt)
2396
2398 """
2399 @return: A list of a copy of this L{CIDR} object. This method is here
2400 mainly for compatibility with IPRange interface.
2401 """
2402 cidr_copy = CIDR('%s/%d' % (self.strategy.int_to_str(self.first),
2403 self.prefixlen))
2404
2405
2406 if self.fmt in (str, unicode):
2407 return [self.fmt(cidr_copy)]
2408
2409 return [cidr_copy]
2410
2413
2415 """@return: executable Python string to recreate equivalent object."""
2416 return "%s('%s/%d')" % (self.__class__.__name__,
2417 self.strategy.int_to_str(self.first), self.prefixlen)
2418
2421 """
2422 Represents blocks of IPv4 addresses using a wildcard or glob style syntax.
2423
2424 Individual octets can be represented using the following shortcuts :
2425
2426 1. C{*} - the asterisk octet (represents values 0 through 255)
2427 2. C{'x-y'} - the hyphenated octet (represents values x through y)
2428
2429 A few basic rules also apply :
2430
2431 1. x must always be greater than y, therefore :
2432
2433 - x can only be 0 through 254
2434 - y can only be 1 through 255
2435
2436 2. only one hyphenated octet per wildcard is allowed
2437 3. only asterisks are permitted after a hyphenated octet
2438
2439 Example wildcards ::
2440
2441 '192.168.0.1' # a single address
2442 '192.168.0.0-31' # 32 addresses
2443 '192.168.0.*' # 256 addresses
2444 '192.168.0-1.*' # 512 addresses
2445 '192.168-169.*.*' # 131,072 addresses
2446 '*.*.*.*' # the whole IPv4 address space
2447
2448 Aside
2449 =====
2450 I{Wildcard ranges are not directly equivalent to CIDR blocks as they
2451 can represent address ranges that do not fall on strict bit mask
2452 boundaries. They are very suitable in configuration files being more
2453 obvious and readable than their CIDR equivalents, especially for admins
2454 and users without much networking knowledge or experience.}
2455
2456 I{All CIDR blocks can always be represented as wildcard ranges but the
2457 reverse is not true. Wildcards are almost but not quite as flexible
2458 as IPRange objects.}
2459 """
2460 STRATEGIES = (ST_IPV4,)
2461 ADDR_TYPES = (AT_UNSPEC, AT_INET)
2462
2463
2464 strategy = StrategyDescriptor(STRATEGIES)
2465 addr_type = AddrTypeDescriptor(ADDR_TYPES)
2466 fmt = FormatDescriptor(IP)
2467
2468 @staticmethod
2470 """
2471 A static method that validates wildcard address ranges.
2472
2473 @param wildcard: an IPv4 wildcard address.
2474
2475 @return: True if wildcard address is valid, False otherwise.
2476 """
2477
2478
2479
2480
2481 seen_hyphen = False
2482 seen_asterisk = False
2483 try:
2484 octets = wildcard.split('.')
2485 if len(octets) != 4:
2486 return False
2487 for o in octets:
2488 if '-' in o:
2489 if seen_hyphen:
2490 return False
2491 seen_hyphen = True
2492 if seen_asterisk:
2493
2494 return False
2495 (o1, o2) = [int(i) for i in o.split('-')]
2496 if o1 >= o2:
2497 return False
2498 if not 0 <= o1 <= 254:
2499 return False
2500 if not 1 <= o2 <= 255:
2501 return False
2502 elif o == '*':
2503 seen_asterisk = True
2504 else:
2505 if seen_hyphen is True:
2506 return False
2507 if seen_asterisk is True:
2508 return False
2509 if not 0 <= int(o) <= 255:
2510 return False
2511 except AttributeError:
2512 return False
2513 except ValueError:
2514 return False
2515 return True
2516
2518 """
2519 Constructor.
2520
2521 @param wildcard: a valid IPv4 wildcard address
2522
2523 @param fmt: (optional) callable used on return values.
2524 Default: L{IP} objects. See L{nrange()} documentations for
2525 more details on the various options..
2526 """
2527 if not Wildcard.is_valid(wildcard):
2528 raise AddrFormatError('%r is not a recognised wildcard address!' \
2529 % wildcard)
2530 t1 = []
2531 t2 = []
2532
2533 for octet in wildcard.split('.'):
2534 if '-' in octet:
2535 oct_tokens = octet.split('-')
2536 t1 += [oct_tokens[0]]
2537 t2 += [oct_tokens[1]]
2538 elif octet == '*':
2539 t1 += ['0']
2540 t2 += ['255']
2541 else:
2542 t1 += [octet]
2543 t2 += [octet]
2544
2545 first = '.'.join(t1)
2546 last = '.'.join(t2)
2547 super(Wildcard, self).__init__(first, last, fmt=fmt)
2548
2549 if self.addr_type != AT_INET:
2550 raise AddrFormatError('Wildcard syntax only supports IPv4!')
2551
2553 t1 = self.strategy.int_to_words(self.first)
2554 t2 = self.strategy.int_to_words(self.last)
2555
2556 tokens = []
2557
2558 seen_hyphen = False
2559 seen_asterisk = False
2560
2561 for i in range(4):
2562 if t1[i] == t2[i]:
2563
2564 tokens.append(str(t1[i]))
2565 elif (t1[i] == 0) and (t2[i] == 255):
2566
2567 tokens.append('*')
2568 seen_asterisk = True
2569 else:
2570
2571 if not seen_asterisk:
2572 if not seen_hyphen:
2573 tokens.append('%s-%s' % (t1[i], t2[i]))
2574 seen_hyphen = True
2575 else:
2576 raise AddrFormatError('only one hyphenated octet ' \
2577 ' per wildcard allowed!')
2578 else:
2579 raise AddrFormatError('asterisks not permitted before ' \
2580 'hyphenated octets!')
2581
2582 return '.'.join(tokens)
2583
2585 """@return: executable Python string to recreate equivalent object."""
2586 return "%s(%r)" % (self.__class__.__name__, str(self))
2587
2591 """
2592 B{*EXPERIMENTAL*} A customised Python set class that deals with collections
2593 of IPRange class and subclass instances.
2594 """
2596 """
2597 Constructor.
2598
2599 @param addrs: A sequence of IPRange class/subclass instances used to
2600 pre-populate the set. Individual CIDR objects can be added and
2601 removed after instantiation with the usual set methods, add() and
2602 remove().
2603 """
2604 for addr in addrs:
2605 if isinstance(addr, IP):
2606 self.add(addr.cidr())
2607 if isinstance(addr, str):
2608 try:
2609 self.add(CIDR(addr))
2610 except:
2611 pass
2612 try:
2613 ip = IP(addr)
2614 self.add(ip.cidr())
2615 except:
2616 pass
2617 try:
2618 wildcard = Wildcard(addr)
2619 try:
2620 self.add(wildcard.cidr())
2621 except:
2622 self.add(wildcard)
2623 except:
2624 pass
2625 else:
2626 self.add(addr)
2627
2629 """
2630 @return: True if C{other} IP or IPRange class/subclass instance
2631 matches any of the members in this IPRangeSet, False otherwise.
2632 """
2633 for addr in self:
2634 if other in addr:
2635 return True
2636
2638 """
2639 @param other: An IP or IPRange class/subclass instance.
2640
2641 @return: The first IP or IPRange class/subclass instance object that
2642 matches C{other} from any of the members in this IPRangeSet, None
2643 otherwise.
2644 """
2645 for addr in self:
2646 if other in addr:
2647 return addr
2648
2650 """
2651 @param other: An IP or IPRange class/subclass instance.
2652
2653 @return: All IP or IPRange class/subclass instances matching C{other}
2654 from this IPRangeSet, an empty list otherwise.
2655 """
2656 addrs = []
2657 for addr in self:
2658 if other in addr:
2659 addrs.append(addr)
2660 return addrs
2661
2663 """
2664 @param other: An IP or IPRange class/subclass instance.
2665
2666 @return: The smallest IP or IPRange class/subclass instance matching
2667 C{other} from this IPRangeSet, None otherwise.
2668 """
2669 addrs = self.all_matches(other)
2670 addrs.sort()
2671 return addrs[0]
2672
2674 """
2675 @param other: An IP or IPRange class/subclass instance.
2676
2677 @return: The largest IP or IPRange class/subclass instance matching
2678 C{other} from this IPRangeSet, None otherwise.
2679 """
2680 addrs = self.all_matches(other)
2681 addrs.sort()
2682 return addrs[-1]
2683