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
14 from netaddr import AddrFormatError, AddrConversionError, AT_UNSPEC, \
15 AT_INET, AT_INET6, AT_LINK, AT_EUI64, AT_NAMES
16
17 from netaddr.strategy import ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64, \
18 AddrStrategy
19
20 from netaddr.eui import OUI, IAB
21
22
23 AT_STRATEGIES = {
24 AT_UNSPEC : None,
25 AT_INET : ST_IPV4,
26 AT_INET6 : ST_IPV6,
27 AT_LINK : ST_EUI48,
28 AT_EUI64 : ST_EUI64,
29 }
30
31
33 """
34 A descriptor that checks addr_type property assignments for validity and
35 also keeps the strategy property in sync with any changes made.
36 """
38 """
39 Constructor.
40
41 @param addr_types: a list of address types constants that are
42 acceptable for assignment to the addr_type property.
43 """
44 self.addr_types = addr_types
45
46 - def __set__(self, instance, value):
47 if value not in self.addr_types:
48 raise ValueError('addr_type %r is invalid for objects of ' \
49 'the %s() class!' % (value, instance.__class__.__name__))
50 instance.__dict__['addr_type'] = value
51 instance.__dict__['strategy'] = AT_STRATEGIES[value]
52
53
55 """
56 A descriptor that checks assignments to the named parameter passed to the
57 constructor. It accepts network addresses in either string format or as
58 network byte order integers. String based addresses are converted to their
59 integer equivalents before assignment to the named parameter. Also ensures
60 that addr_type and strategy are set correctly when parsing string based
61 addresses.
62 """
64 """
65 Descriptor constructor.
66
67 @param name: the name of attribute which will be assigned the value.
68 """
69 self.name = name
70
71 - def __set__(self, instance, value):
100
101
103 """
104 A descriptor that checks strategy property assignments for validity and
105 also keeps the addr_type property in sync with any changes made.
106 """
108 """
109 Constructor.
110
111 @param strategies: a list of strategy objects that are acceptable for
112 assignment to the strategy property.
113 """
114 self.strategies = strategies
115
116 - def __set__(self, instance, value):
117 if value not in self.strategies:
118 raise Exception('%r is not a supported strategy!' % value)
119 instance.__dict__['strategy'] = value
120 instance.__dict__['addr_type'] = instance.strategy.addr_type
121
122
124 """
125 A descriptor that checks prefixlen property assignments for validity based
126 on address type. Also accepts netmasks and hostmasks which can easily be
127 converted to the equivalent prefixlen integer.
128 """
130 """
131 Constructor.
132
133 @param class_id: (optional) the name of the class that uses this
134 descriptor.
135 """
136 self.class_id = class_id
137
138 - def __set__(self, instance, value):
179
180
205
206
208 """
209 The base class containing common functionality for all subclasses
210 representing various network address types.
211
212 It is a fully functioning class (as opposed to a virtual class) with a
213 heuristic constructor that detects the type of address via the first
214 argument if it is a string and sets itself up accordingly. If the first
215 argument is an integer, then a constant must be provided via the second
216 argument indicating the address type explicitly.
217
218 Objects of this class behave differently dependent upon the type of address
219 they represent.
220 """
221 STRATEGIES = (ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64)
222 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6, AT_LINK, AT_EUI64)
223
224
225 value = AddrValueDescriptor('value')
226 strategy = StrategyDescriptor(STRATEGIES)
227 addr_type = AddrTypeDescriptor(ADDR_TYPES)
228
230 """
231 Constructor.
232
233 @param addr: the string form of a network address, or a network byte
234 order integer within the supported range for the address type.
235
236 @param addr_type: (optional) the network address type. If addr is an
237 integer, this argument becomes mandatory.
238 """
239 self.addr_type = addr_type
240 self.value = addr
241
243 """@return: hash of this address suitable for dict keys, sets etc"""
244 return hash((self.value, self.addr_type))
245
247 """@return: value of this address as a network byte order integer"""
248 return self.value
249
251 """@return: value of this address as a network byte order integer"""
252 return self.value
253
257
259 """@return: executable Python string to recreate equivalent object"""
260 return "%s(%r)" % (self.__class__.__name__, str(self))
261
265
269
271 """
272 @return: standard Python binary representation of this address. A back
273 port of the format provided by the builtin bin() type available in
274 Python 2.6.x and higher."""
275 return self.strategy.int_to_bin(self.value)
276
278 """@return: The size (width) of this address in bits"""
279 return self.strategy.width
280
284
286 """
287 @return: The integer value of the word referenced by index (both
288 positive and negative). Raises C{IndexError} if index is out
289 of bounds. Also supports Python list slices for accessing
290 word groups.
291 """
292 if isinstance(index, (int, long)):
293
294 num_words = self.strategy.num_words
295 if not (-num_words) <= index <= (num_words - 1):
296 raise IndexError('index out range for address type!')
297 return self.strategy.int_to_words(self.value)[index]
298 elif isinstance(index, slice):
299
300 words = self.strategy.int_to_words(self.value)
301 return [words[i] for i in range(*index.indices(len(words)))]
302 else:
303 raise TypeError('unsupported type %r!' % index)
304
306 """Sets the value of the word referenced by index in this address"""
307 if isinstance(index, slice):
308
309 raise NotImplementedError('settable slices not yet supported!')
310
311 if not isinstance(index, (int, long)):
312 raise TypeError('index not an integer!')
313
314 if not 0 <= index <= (self.strategy.num_words - 1):
315 raise IndexError('index %d outside address type boundary!' % index)
316
317 if not isinstance(value, (int, long)):
318 raise TypeError('value not an integer!')
319
320 if not 0 <= value <= self.strategy.max_word:
321 raise IndexError('value %d outside word size maximum of %d bits!'
322 % (value, self.strategy.word_size))
323
324 words = list(self.strategy.int_to_words(self.value))
325 words[index] = value
326 self.value = self.strategy.words_to_int(words)
327
329 """@return: network byte order hexadecimal string of this address"""
330 return hex(self.value).rstrip('L').lower()
331
333 """
334 Increment value of network address by specified amount. Behaves like
335 an unsigned integer, rolling over to zero when it reaches the maximum
336 value threshold.
337
338 @param num: size of increment
339 """
340 try:
341 new_value = self.value + num
342 if new_value > self.strategy.max_int:
343 self.value = new_value - (self.strategy.max_int + 1)
344 else:
345 self.value = new_value
346 except TypeError:
347 raise TypeError('Increment value must be an integer!')
348 return self
349
351 """
352 Decrement value of network address by specified amount. Behaves like
353 an unsigned integer, rolling over to maximum value when it goes below
354 zero.
355
356 @param num: size of decrement
357 """
358 try:
359 new_value = self.value - num
360 if new_value < 0:
361 self.value = new_value + (self.strategy.max_int + 1)
362 else:
363 self.value = new_value
364 except TypeError:
365 raise TypeError('Decrement value must be an integer!')
366 return self
367
369 """
370 @param other: an integer or int-like object.
371
372 @return: A new (potentially larger) Addr class/subclass instance.
373 """
374 return self.__class__(self.value + int(other), self.addr_type)
375
377 """
378 @param other: an integer or int-like object.
379
380 @return: A new (potentially smaller) Addr class/subclass instance.
381 """
382 return self.__class__(self.value - int(other), self.addr_type)
383
385 """
386 @return: C{True} if this address is numerically the same as other,
387 C{False} otherwise.
388 """
389 try:
390 return (self.addr_type, self.value) == (other.addr_type, other.value)
391 except AttributeError:
392 return False
393
395 """
396 @return: C{True} if this address is not numerically the same other,
397 C{False} otherwise.
398 """
399 try:
400 return (self.addr_type, self.value) != (other.addr_type, other.value)
401 except AttributeError:
402 return False
403
405 """
406 @return: C{True} if this address is numerically lower in value than
407 other, C{False} otherwise.
408 """
409 try:
410 return (self.addr_type, self.value) < (other.addr_type, other.value)
411 except AttributeError:
412 return False
413
415 """
416 @return: C{True} if this address is numerically lower or equal in
417 value to other, C{False} otherwise.
418 """
419 try:
420 return (self.addr_type, self.value) <= (other.addr_type, other.value)
421 except AttributeError:
422 return False
423
425 """
426 @return: C{True} if this address is numerically greater in value than
427 other, C{False} otherwise.
428 """
429 try:
430 return (self.addr_type, self.value) > (other.addr_type, other.value)
431 except AttributeError:
432 return False
433
435 """
436 @return: C{True} if this address is numerically greater or equal in
437 value to other, C{False} otherwise.
438 """
439 try:
440 return (self.addr_type, self.value) >= (other.addr_type, other.value)
441 except AttributeError:
442 return False
444 """
445 @param other: an integer or int-like object.
446
447 @return: bitwise OR (x | y) of self.value with other.value.
448 """
449 return self.__class__(self.value | other.value, self.addr_type)
450
452 """
453 @param other: an integer or int-like object.
454
455 @return: bitwise AND (x & y) of self.value with other.value.
456 """
457 return self.__class__(self.value | other.value, self.addr_type)
458
460 """
461 @param other: an integer or int-like object.
462
463 @return: bitwise exclusive OR (x ^ y) of self.value with other.value.
464 """
465 return self.__class__(self.value ^ other.value, self.addr_type)
466
468 """
469 @param numbits: size of shift (in bits).
470
471 @return: integer value of this IP address shifted left by x bits.
472 """
473 return self.__class__(self.value << numbits, self.addr_type)
474
476 """
477 @param numbits: size of shift (in bits).
478
479 @return: integer value of this IP address right shifted by x bits.
480 """
481 return self.__class__(self.value >> numbits, self.addr_type)
482
484 """
485 @param other: an integer or int-like object.
486
487 @return: inversion (~x) of self.value.
488 """
489 return self.__class__(~self.value)
490
491
493 """
494 Represents an IEEE EUI (Extended Unique Identifier) indentifier.
495
496 Input parser is flexible, supporting EUI-48 (including the many Media
497 Access Control variants) and EUI-64.
498 """
499 STRATEGIES = (ST_EUI48, ST_EUI64)
500 ADDR_TYPES = (AT_UNSPEC, AT_LINK, AT_EUI64)
501
502
503 strategy = StrategyDescriptor(STRATEGIES)
504 addr_type = AddrTypeDescriptor(ADDR_TYPES)
505
507 """
508 Constructor.
509
510 @param addr: an EUI-48 (MAC) or EUI-64 address string or a network
511 byte order integer.
512
513 @param addr_type: (optional) the specific EUI address type (C{AT_LINK}
514 or C{AT_EUI64}). If addr is an integer, this argument is mandatory.
515 """
516 super(EUI, self).__init__(addr, addr_type)
517
519 """
520 @param fmt: callable used on return values. Default: L{OUI} object.
521 Also Supports str(), unicode(), int() and long().
522
523 @return: The OUI (Organisationally Unique Identifier) for this EUI.
524 """
525 if callable(fmt) and fmt in (OUI, int, long):
526 return fmt(self.value >> 24)
527 elif callable(fmt) and fmt in (str, unicode, None):
528 return '-'.join(["%02x" % i for i in self[0:3]]).upper()
529 else:
530 raise TypeError("unsupported formatter callable: %r!" % fmt)
531
533 """@return: The EI (Extension Identifier) for this EUI"""
534 if self.strategy == ST_EUI48:
535 return '-'.join(["%02x" % i for i in self[3:6]]).upper()
536 elif self.strategy == ST_EUI64:
537 return '-'.join(["%02x" % i for i in self[3:8]]).upper()
538
540 """@return: True if this EUI is an IAB address, False otherwise"""
541 return 0x50c2000 <= (self.value >> 12) <= 0x50c2fff
542
544 """
545 @param fmt: callable used on return values. Default: L{IAB} object.
546 Also Supports str(), unicode(), int() and long().
547
548 @return: If isiab() is True, the IAB (Individual Address Block)
549 is returned, None otherwise.
550 """
551 if self.isiab():
552 if callable(fmt) and fmt in (IAB, int, long):
553 return fmt(self.value >> 12)
554 elif callable(fmt) and fmt in (str, unicode, None):
555 usermask = (1 << (self.strategy.width - 36)) - 1
556 last_eui = self.value | usermask
557 first_eui = last_eui - usermask
558 iab_words = self.strategy.int_to_words(first_eui)
559 return '-'.join(["%02x" % i for i in iab_words]).upper()
560 else:
561 raise TypeError("unsupported formatter callable: %r!" % fmt)
562
564 """
565 @return: The value of this EUI object as a new 64-bit EUI object.
566 - If this object represents an EUI-48 it is converted to EUI-64
567 as per the standard.
568 - If this object is already and EUI-64, it just returns a new,
569 numerically equivalent object is returned instead.
570 """
571 if self.addr_type == AT_LINK:
572 eui64_words = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
573 ["%02x" % i for i in self[3:6]]
574
575 return self.__class__('-'.join(eui64_words))
576 else:
577 return EUI(str(self))
578
580 """
581 @return: new link local IPv6 L{IP} object based on this L{EUI} using
582 technique described in RFC 4291. B{Please Note:} this technique
583 poses security risks in certain scenarios. Please read RFC 4941 for
584 details. Reference: RFCs 4291 and 4941.
585 """
586 prefix = 'fe80:0000:0000:0000:'
587
588
589 self[0] += 2
590
591 if self.addr_type == AT_LINK:
592
593 suffix = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
594 ["%02x" % i for i in self[3:6]]
595 else:
596 suffix = ["%02x" % i for i in list(self)]
597
598 suffix = ["%02x%02x" % (int(x[0], 16), int(x[1], 16)) for x in \
599 zip(suffix[::2], suffix[1::2])]
600
601
602 self[0] -= 2
603
604 eui64 = ':'.join(suffix)
605 addr = prefix + eui64
606 return IP(addr)
607
609 """
610 @return: A record dict containing IEEE registration details for this
611 EUI (MAC-48) if available, None otherwise.
612 """
613 data = {'OUI': self.oui().registration()}
614 if self.isiab():
615 data['IAB'] = self.iab().registration()
616 return data
617
618
620 """
621 Represents B{individual} IPv4 and IPv6 addresses.
622
623 B{Please Note:} this class is intended to provide low-level functionality
624 to individual IP addresses such as octet/hextet access, integer/hex/binary
625 conversions, etc. If you are coming from other libraries you may expect to
626 find much higher level networking operations here. While the inclusion of
627 a bitmask prefix or netmask to indicate subnet membership is permitted by
628 the class constructor they are provided only as a convenience to the user.
629
630 All higher level subnet and network operations can be found in objects of
631 classes L{CIDR}, L{IPRange} and L{Wildcard}. There are handy helper methods
632 here, (C{.cidr()}, C{.iprange()} and C{.wildcard()}) that return pre-initialised
633 objects of those classes without you having to call them explicitly.
634
635 Example usage ::
636
637 >>> ip = IP('10.0.0.1')
638 >>> list(ip) == [10, 0, 0, 1]
639 True
640 >>> ip += 1
641 >>> str(ip) == '10.0.0.2'
642 True
643
644 >>> IP('10.0.0.0/28').iprange()
645 IPRange('10.0.0.0', '10.0.0.15')
646
647 >>> IP('10.0.0.64/24').cidr()
648 CIDR('10.0.0.0/24')
649
650 >>> IP('192.168.0.1/255.255.253.0').wildcard()
651 Wildcard('192.168.0-1.*')
652
653 >>> ipv6 = IP('fe80::20f:1fff:fe12:e733')
654 >>> ipv6[0:4]
655 [65152, 0, 0, 0]
656
657 >>> IP('fe80::20f:1fff:fe12:e733/64').cidr()
658 CIDR('fe80::/64')
659
660 See those classes for details on the functionality they provide.
661 """
662 STRATEGIES = (ST_IPV4, ST_IPV6)
663 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
664 TRANSLATE_STR = ''.join([chr(_) for _ in range(256)])
665
666
667 strategy = StrategyDescriptor(STRATEGIES)
668 addr_type = AddrTypeDescriptor(ADDR_TYPES)
669 prefixlen = PrefixLenDescriptor()
670
672 """
673 Constructor.
674
675 @param addr: an IPv4 or IPv6 address string with an optional subnet
676 prefix or a network byte order integer.
677
678 @param addr_type: (optional) the IP address type (C{AT_INET} or
679 C{AT_INET6}). If L{addr} is an integer, this argument is mandatory.
680 """
681 prefixlen = None
682
683 try:
684 if '/' in addr:
685 (addr, prefixlen) = addr.split('/', 1)
686 except TypeError:
687
688 pass
689
690
691
692 super(IP, self).__init__(addr, addr_type)
693
694
695 if prefixlen is None:
696 self.__dict__['prefixlen'] = self.strategy.width
697 else:
698 self.prefixlen = prefixlen
699
701 """
702 @return: C{True} if this addr is a mask that would return a host id,
703 C{False} otherwise.
704 """
705 int_val = (self.value ^ self.strategy.max_int) + 1
706 return (int_val & (int_val - 1) == 0)
707
709 """
710 @return: If this address is a valid netmask, the number of non-zero
711 bits are returned, otherwise it returns the width in bits for
712 based on the version, 32 for IPv4 and 128 for IPv6.
713 """
714 if not self.is_netmask():
715 return self.strategy.width
716
717 bits = self.strategy.int_to_bits(self.value)
718 mask_bits = bits.translate(IP.TRANSLATE_STR, ':.0')
719 mask_length = len(mask_bits)
720
721 if not 1 <= mask_length <= self.strategy.width:
722 raise ValueError('Unexpected mask length %d for address type!' \
723 % mask_length)
724
725 return mask_length
726
730
732 """
733 @return: C{True} if this address is a mask that would return a host
734 id, C{False} otherwise.
735 """
736 int_val = self.value + 1
737 return (int_val & (int_val-1) == 0)
738
740 """
741 @return: Returns the FQDN for this IP address via a DNS query
742 using gethostbyaddr() Python's socket module.
743 """
744 try:
745 return _socket.gethostbyaddr(str(self))[0]
746 except:
747 return
748
755
761
770
772 """
773 @return: A new version 4 L{IP} object numerically equivalent this
774 address. If this object is already IPv4 then a copy is returned. If
775 this object is IPv6 and its value is compatible with IPv4, a new IPv4
776 L{IP} object is returned.
777
778 Raises an L{AddrConversionError} is IPv6 address cannot be converted.
779 """
780 ip_addr = None
781 if self.addr_type == AT_INET:
782 ip_addr = IP(self.value, AT_INET)
783 ip_addr.prefixlen = self.prefixlen
784 elif self.addr_type == AT_INET6:
785 words = self.strategy.int_to_words(self.value)
786
787 if words[0:6] == (0, 0, 0, 0, 0, 0):
788 ip_addr = IP(self.value, AT_INET)
789 ip_addr.prefixlen = self.prefixlen - 96
790
791 elif words[0:6] == (0, 0, 0, 0, 0, 0xffff):
792 ip_addr = IP(self.value - 0xffff00000000, AT_INET)
793 ip_addr.prefixlen = self.prefixlen - 96
794 else:
795 raise AddrConversionError('IPv6 address %s not suitable for' \
796 'IPv4 conversion!' % self)
797 return ip_addr
798
799 - def ipv6(self, ipv4_compatible=False):
800 """
801 B{Please Note:} the IPv4-Mapped IPv6 address format is now considered
802 deprecated. Reference: RFC 4291
803
804 @param ipv4_compatible: If C{True} returns an IPv4-Mapped address
805 (::ffff:x.x.x.x), an IPv4-Compatible (::x.x.x.x) address
806 otherwise. Default: False (IPv4-Mapped).
807
808 @return: A new L{IP} version 6 object that is numerically equivalent
809 this address. If this object is already IPv6 then a copy of this
810 object is returned. If this object is IPv4, a new version 6 L{IP}
811 object is returned.
812 """
813 ip_addr = None
814 if self.addr_type == AT_INET6:
815 ip_addr = IP(self.value, AT_INET6)
816 ip_addr.prefixlen = self.prefixlen - 96
817 elif self.addr_type == AT_INET:
818 ip_addr = IP(self.value, AT_INET6)
819 if ipv4_compatible:
820
821 ip_addr[5] = 0
822 else:
823
824 ip_addr[5] = 0xffff
825 ip_addr.prefixlen = self.prefixlen + 96
826 return ip_addr
827
829 """@return: C{True} if this IP is unicast, C{False} otherwise"""
830 return not self.is_multicast()
831
833 """
834 @return: C{True} if this IP is loopback address (not for network
835 transmission), C{False} otherwise.
836 References: RFC 3330 and 4291.
837 """
838 if self.addr_type == AT_INET:
839 return self in CIDR('127/8')
840 elif self.addr_type == AT_INET6:
841 return self == IP('::1')
842
844 """@return: C{True} if this IP is multicast, C{False} otherwise"""
845 if self.addr_type == AT_INET:
846 return self in CIDR('224/4')
847 elif self.addr_type == AT_INET6:
848 return self in CIDR('ff00::/8')
849
851 """
852 @return: C{True} if this IP is for internal/private use only
853 (i.e. non-public), C{False} otherwise. Reference: RFCs 1918,
854 3330, 4193, 3879 and 2365.
855 """
856 if self.addr_type == AT_INET:
857 for cidr in (CIDR('192.168/16'), CIDR('10/8'),CIDR('172.16/12'),
858 CIDR('192.0.2.0/24'), CIDR('239.192/14')):
859 if self in cidr:
860 return True
861 elif self.addr_type == AT_INET6:
862
863 return self in CIDR('fc00::/7')
864
865 if self.is_link_local():
866 return True
867
868 return False
869
871 """
872 @return: C{True} if this IP is link-local address C{False} otherwise.
873 Reference: RFCs 3927 and 4291.
874 """
875 if self.addr_type == AT_INET:
876 return self in CIDR('169.254/16')
877 elif self.addr_type == AT_INET6:
878 return self in CIDR('fe80::/10')
879
881 """
882 @return: C{True} if this IP is in IANA reserved range, C{False}
883 otherwise. Reference: RFCs 3330 and 3171.
884 """
885 if self.addr_type == AT_INET:
886
887 for cidr in (CIDR('240/4'), CIDR('234/7'), CIDR('236/7'),
888 Wildcard('225-231.*.*.*'), Wildcard('234-238.*.*.*')):
889 if self in cidr:
890 return True
891 if self.addr_type == AT_INET6:
892 for cidr in (CIDR('ff00::/12'),CIDR('::/8'), CIDR('0100::/8'),
893 CIDR('0200::/7'), CIDR('0400::/6'), CIDR('0800::/5'),
894 CIDR('1000::/4'), CIDR('4000::/3'), CIDR('6000::/3'),
895 CIDR('8000::/3'), CIDR('A000::/3'), CIDR('C000::/3'),
896 CIDR('E000::/4'), CIDR('F000::/5'), CIDR('F800::/6'),
897 CIDR('FE00::/9')):
898 if self in cidr:
899 return True
900 return False
901
903 """
904 @return: C{True} if this IP is IPv4-compatible IPv6 address, C{False}
905 otherwise.
906 """
907 return self.addr_type == AT_INET6 and (self.value >> 32) == 0xffff
908
910 """
911 @return: C{True} if this IP is IPv4-mapped IPv6 address, C{False}
912 otherwise.
913 """
914 return self.addr_type == AT_INET6 and (self.value >> 32) == 0
915
917 """
918 @return: A record dict containing IANA registration details for this
919 IP address if available, None otherwise.
920 """
921
922
923
924
925 import netaddr.ip
926 return netaddr.ip.query(self)
927
929 """@return: common string representation for this IP address"""
930 return self.strategy.int_to_str(self.value)
931
933 """@return: executable Python string to recreate equivalent object."""
934 if self.prefixlen == self.strategy.width:
935 return "%s('%s')" % (self.__class__.__name__, str(self))
936
937 return "%s('%s/%d')" % (self.__class__.__name__, str(self),
938 self.prefixlen)
939
940
941 -def nrange(start, stop, step=1, fmt=None):
942 """
943 An xrange work alike generator that produces sequences of IP addresses
944 based on start and stop addresses, in intervals of step size.
945
946 @param start: first IP address string or L{IP} object in range.
947
948 @param stop: last IP address string or L{IP} object in range
949
950 @param step: (optional) size of step between address in range.
951 (Default: 1)
952
953 @param fmt: (optional) callable used on addresses returned.
954 (Default: None - L{IP} objects). Supported options :-
955 - C{str} - IP address strings
956 - C{int}, C{long} - IP address integer (network byte order)
957 - C{hex} - IP address as a hexadecimal number
958 - L{IP} class/subclass or callable that accepts C{addr_value} and
959 C{addr_type} arguments.
960 """
961 if not isinstance(start, IP):
962 if isinstance(start, (str, unicode)):
963 start = IP(start)
964 else:
965 raise TypeError('start is not recognised address in string ' \
966 'format or IP class/subclass instance!')
967 else:
968
969 if fmt is None:
970 fmt = start.__class__
971
972 if not isinstance(stop, IP):
973 if isinstance(stop, (str, unicode)):
974 stop = IP(stop)
975 else:
976 raise TypeError('stop is not recognised address string ' \
977 'or IP class/subclass instance!')
978
979 if not isinstance(step, (int, long)):
980 raise TypeError('step must be type int|long, not %s!' % type(step))
981
982 if start.addr_type != stop.addr_type:
983 raise TypeError('start and stop are not the same address type!')
984
985 if step == 0:
986 raise ValueError('step argument cannot be zero')
987
988 negative_step = False
989 addr_type = start.addr_type
990
991
992
993 start_fmt = start.__class__
994 start = int(start)
995 stop = int(stop)
996
997 if step < 0:
998 negative_step = True
999
1000 index = start - step
1001
1002
1003 if fmt is None:
1004 fmt = IP
1005
1006 if fmt in (int, long, hex):
1007
1008 while True:
1009 index += step
1010 if negative_step:
1011 if not index >= stop:
1012 return
1013 else:
1014 if not index <= stop:
1015 return
1016 yield fmt(index)
1017 elif fmt in (str, unicode):
1018
1019 while True:
1020 index += step
1021 if negative_step:
1022 if not index >= stop:
1023 return
1024 else:
1025 if not index <= stop:
1026 return
1027 yield str(start_fmt(index, addr_type))
1028 else:
1029
1030 while True:
1031 index += step
1032 if negative_step:
1033 if not index >= stop:
1034 return
1035 else:
1036 if not index <= stop:
1037 return
1038
1039 yield fmt(index, addr_type)
1040
1041
1043 """
1044 Represents arbitrary contiguous blocks of IPv4 and IPv6 addresses using
1045 only a lower and upper bound IP address.
1046
1047 It is the base class for more specialised block types such as L{CIDR()}
1048 and L{Wildcard()}. There is no requirement that the boundary IP addresses
1049 fall on strict bitmask boundaries.
1050
1051 The sort order for sequence of mixed version L{IPRange} objects is IPv4
1052 followed by IPv6, based on the range's magnitude (size).
1053 """
1054 STRATEGIES = (ST_IPV4, ST_IPV6)
1055 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
1056
1057
1058 strategy = StrategyDescriptor(STRATEGIES)
1059 addr_type = AddrTypeDescriptor(ADDR_TYPES)
1060 first = AddrValueDescriptor('first')
1061 last = AddrValueDescriptor('last')
1062 fmt = FormatDescriptor(IP)
1063
1065 """
1066 Constructor.
1067
1068 @param first: start address for this IP address range.
1069
1070 @param last: stop address for this IP address range.
1071
1072 @param fmt: (optional) callable used to create return values.
1073 Default: L{IP()} objects. See L{nrange()} documentations for
1074 more details on the various options.
1075 """
1076
1077
1078 self.addr_type = AT_UNSPEC
1079 self.first = first
1080 self.last = last
1081 if self.last < self.first:
1082 raise IndexError('start address is greater than stop address!')
1083 self.fmt = fmt
1084
1086 """
1087 @return: The hash of this address range. Allow them to be used in sets
1088 and as keys in dictionaries.
1089 """
1090 return hash((self.first, self.last, self.addr_type))
1091
1093 """
1094 @return: The total number of network addresses in this range.
1095 - Use this method only for ranges that contain less than
1096 C{2^31} addresses or try the L{size()} method. Raises an
1097 C{IndexError} if size is exceeded.
1098 """
1099 size = self.size()
1100 if size > (2 ** 31):
1101
1102 raise IndexError("range contains greater than 2^31 addresses! " \
1103 "Use obj.size() instead.")
1104 return size
1105
1107 """
1108 @return: The total number of network addresses in this range.
1109 - Use this method in preference to L{__len__()} when size of
1110 ranges potentially exceeds C{2^31} addresses.
1111 """
1112 return self.last - self.first + 1
1113
1134
1136 """
1137 @return: The IP address(es) in this address range referenced by
1138 index/slice. Slicing objects can produce large sequences so
1139 generator objects are returned instead of a list. Wrapping a slice
1140 with C{list()} or C{tuple()} may be required dependent on context
1141 in which it is called.
1142 """
1143
1144 if isinstance(index, (int, long)):
1145 if (- self.size()) <= index < 0:
1146
1147 return self.format(self.last + index + 1)
1148 elif 0 <= index <= (self.size() - 1):
1149
1150 return self.format(self.first + index)
1151 else:
1152 raise IndexError('index out range for address range size!')
1153 elif isinstance(index, slice):
1154
1155
1156
1157
1158
1159
1160
1161
1162 (start, stop, step) = index.indices(self.size())
1163
1164 start_addr = IP(self.first + start, self.addr_type)
1165 end_addr = IP(self.first + stop - step, self.addr_type)
1166 return nrange(start_addr, end_addr, step, fmt=self.fmt)
1167 else:
1168 raise TypeError('unsupported type %r!' % index)
1169
1171 """
1172 @return: An iterator object providing access to all network addresses
1173 within this range.
1174 """
1175 start_addr = IP(self.first, self.addr_type)
1176 end_addr = IP(self.last, self.addr_type)
1177 return nrange(start_addr, end_addr, fmt=self.fmt)
1178
1180 """
1181 @param addr: and IP/IPRange class/subclass instance or IP string value
1182 to be compared.
1183
1184 @return: C{True} if given address or range falls within this range,
1185 C{False} otherwise.
1186 """
1187 if isinstance(addr, (str, unicode)):
1188
1189 c_addr = IP(addr)
1190 if c_addr.addr_type == self.addr_type:
1191 if self.first <= int(c_addr) <= self.last:
1192 return True
1193 elif isinstance(addr, IP):
1194
1195 if self.first <= int(addr) <= self.last:
1196 return True
1197 elif issubclass(addr.__class__, IPRange):
1198
1199 if addr.first >= self.first and addr.last <= self.last:
1200 return True
1201 else:
1202 raise TypeError('%r is an unsupported type or class!' % addr)
1203
1204 return False
1205
1207 """
1208 @param other: an address object of the same address type as C{self}.
1209
1210 @return: C{True} if the boundaries of this range are the same as
1211 other, C{False} otherwise.
1212 """
1213 try:
1214 return (self.addr_type, self.first, self.last) == \
1215 (other.addr_type, other.first, other.last)
1216 except AttributeError:
1217 return False
1218
1220 """
1221 @param other: an address object of the same address type as C{self}.
1222
1223 @return: C{True} if the boundaries of this range are not the same as
1224 other, C{False} otherwise.
1225 """
1226 try:
1227 return (self.addr_type, self.first, self.last) != \
1228 (other.addr_type, other.first, other.last)
1229 except AttributeError:
1230 return False
1231
1233 """
1234 @param other: an address object of the same address type as C{self}.
1235
1236 @return: C{True} if the boundaries of this range are less than other,
1237 C{False} otherwise.
1238 """
1239 try:
1240 return (self.addr_type, self.first, self.last) < \
1241 (other.addr_type, other.first, other.last)
1242 except AttributeError:
1243 return False
1244
1246 """
1247 @param other: an address object of the same address type as C{self}.
1248
1249 @return: C{True} if the boundaries of this range are less or equal to
1250 other, C{False} otherwise.
1251 """
1252 try:
1253 return (self.addr_type, self.first, self.last) <= \
1254 (other.addr_type, other.first, other.last)
1255 except AttributeError:
1256 return False
1257
1259 """
1260 @param other: an address object of the same address type as C{self}.
1261
1262 @return: C{True} if the boundaries of this range are greater than
1263 other, C{False} otherwise.
1264 """
1265 try:
1266 return (self.addr_type, self.first, self.last) > \
1267 (other.addr_type, other.first, other.last)
1268 except AttributeError:
1269 return False
1270
1272 """
1273 @param other: an address object of the same address type as C{self}.
1274
1275 @return: C{True} if the boundaries of this range are greater or equal
1276 to other, C{False} otherwise.
1277 """
1278 try:
1279 return (self.addr_type, self.first, self.last) >= \
1280 (other.addr_type, other.first, other.last)
1281 except AttributeError:
1282 return False
1283
1285 """
1286 Increments start and end addresses of this range by the current size.
1287
1288 Raises IndexError if the result exceeds address range maximum.
1289 """
1290 try:
1291 new_first = self.first + (self.size() * i)
1292 new_last = self.last + (self.size() * i)
1293 except TypeError:
1294 raise TypeError('Increment value must be an integer!')
1295
1296 if new_last > self.strategy.max_int:
1297 raise IndexError('Invalid increment is outside address boundary!')
1298
1299 self.first = new_first
1300 self.last = new_last
1301
1302 return self
1303
1305 """
1306 Decrements start and end addresses of this range by the current size.
1307
1308 Raises IndexError if the result is less than zero.
1309 """
1310 try:
1311 new_first = self.first - (self.size() * i)
1312 new_last = self.last - (self.size() * i)
1313 except TypeError:
1314 raise TypeError('Decrement value must be an integer!')
1315
1316 if new_last < 0:
1317 raise IndexError('Invalid decrement is outside address boundary!')
1318
1319 self.first = new_first
1320 self.last = new_last
1321
1322 return self
1323
1334
1336 """
1337 @return: A list of one or more L{CIDR} objects covering this address
1338 range. B{Please Note:} a list is returned even if this range maps
1339 to a single CIDR because arbitrary ranges may not be aligned with
1340 base 2 subnet sizes and will therefore return multiple CIDRs.
1341 """
1342
1343
1344 cidr_list = []
1345
1346
1347 start = IP(self.first, self.addr_type)
1348 end = IP(self.last, self.addr_type)
1349
1350 cidr_span = CIDR.span([start, end])
1351
1352 if cidr_span.first == self.first and cidr_span.last == self.last:
1353
1354 cidr_list = [cidr_span]
1355 elif cidr_span.last == self.last:
1356
1357 ip = IP(start)
1358 first_int_val = int(ip)
1359 ip -= 1
1360 cidr_remainder = cidr_span - ip
1361
1362 first_found = False
1363 for cidr in cidr_remainder:
1364 if cidr.first == first_int_val:
1365 first_found = True
1366 if first_found:
1367 cidr_list.append(cidr)
1368 elif cidr_span.first == self.first:
1369
1370 ip = IP(end)
1371 last_int_val = int(ip)
1372 ip += 1
1373 cidr_remainder = cidr_span - ip
1374
1375 last_found = False
1376 for cidr in cidr_remainder:
1377 cidr_list.append(cidr)
1378 if cidr.last == last_int_val:
1379 break
1380 elif cidr_span.first <= self.first and cidr_span.last >= self.last:
1381
1382 ip = IP(start)
1383 first_int_val = int(ip)
1384 ip -= 1
1385 cidr_remainder = cidr_span - ip
1386
1387
1388 first_found = False
1389 for cidr in cidr_remainder:
1390 if cidr.first == first_int_val:
1391 first_found = True
1392 if first_found:
1393 cidr_list.append(cidr)
1394
1395
1396 ip = IP(end)
1397 last_int_val = int(ip)
1398 ip += 1
1399 cidr_remainder = cidr_list.pop() - ip
1400
1401 last_found = False
1402 for cidr in cidr_remainder:
1403 cidr_list.append(cidr)
1404 if cidr.last == last_int_val:
1405 break
1406
1407
1408 if self.fmt in (str, unicode):
1409 cidr_list = [self.fmt(c) for c in cidr_list]
1410
1411 return cidr_list
1412
1414 """
1415 @return: A L{Wildcard} object equivalent to this CIDR.
1416 - If CIDR was initialised with C{fmt=str}, a wildcard string
1417 is returned, in all other cases a L{Wildcard} object is
1418 returned.
1419 - Only supports IPv4 CIDR addresses.
1420 """
1421 t1 = self.strategy.int_to_words(self.first)
1422 t2 = self.strategy.int_to_words(self.last)
1423
1424 if self.addr_type != AT_INET:
1425 raise AddrConversionError('wildcards only suitable for IPv4 ' \
1426 'ranges!')
1427
1428 tokens = []
1429
1430 seen_hyphen = False
1431 seen_asterisk = False
1432
1433 for i in range(4):
1434 if t1[i] == t2[i]:
1435
1436 tokens.append(str(t1[i]))
1437 elif (t1[i] == 0) and (t2[i] == 255):
1438
1439 tokens.append('*')
1440 seen_asterisk = True
1441 else:
1442
1443 if not seen_asterisk:
1444 if not seen_hyphen:
1445 tokens.append('%s-%s' % (t1[i], t2[i]))
1446 seen_hyphen = True
1447 else:
1448 raise SyntaxError('only one hyphenated octet per ' \
1449 'wildcard permitted!')
1450 else:
1451 raise SyntaxError("* chars aren't permitted before ' \
1452 'hyphenated octets!")
1453
1454 wildcard = '.'.join(tokens)
1455
1456 if self.fmt == str:
1457 return wildcard
1458
1459 return Wildcard(wildcard)
1460
1462 """
1463 @return: True if other's boundary is equal to or within this range.
1464 False otherwise.
1465 """
1466 if isinstance(other, (str, unicode)):
1467 other = CIDR(other)
1468
1469 if not hasattr(other, 'addr_type'):
1470 raise TypeError('%r is an unsupported argument type!' % other)
1471
1472 if self.addr_type != other.addr_type:
1473 raise TypeError('Ranges must be the same address type!')
1474
1475 return self.first >= other.first and self.last <= other.last
1476
1478 """
1479 @return: True if other's boundary is equal to or contains this range.
1480 False otherwise.
1481 """
1482 if isinstance(other, (str, unicode)):
1483 other = CIDR(other)
1484
1485 if not hasattr(other, 'addr_type'):
1486 raise TypeError('%r is an unsupported argument type!' % other)
1487
1488 if self.addr_type != other.addr_type:
1489 raise TypeError('Ranges must be the same address type!')
1490
1491 return self.first <= other.first and self.last >= other.last
1492
1494 """
1495 @return: True if other's boundary touches the boundary of this
1496 address range, False otherwise.
1497 """
1498 if isinstance(other, (str, unicode)):
1499 other = CIDR(other)
1500
1501 if not hasattr(other, 'addr_type'):
1502 raise TypeError('%r is an unsupported argument type!' % other)
1503
1504 if self.addr_type != other.addr_type:
1505 raise TypeError('addresses must be of the same type!')
1506
1507 if isinstance(other, IPRange):
1508
1509 if self.first == (other.last + 1):
1510 return True
1511
1512
1513 if self.last == (other.first - 1):
1514 return True
1515 elif isinstance(other, IP):
1516
1517 if self.first == (other.value + 1):
1518 return True
1519
1520
1521 if self.last == (other.value - 1):
1522 return True
1523 else:
1524 raise TypeError('unexpected error for argument: %r!')
1525
1526 return False
1527
1529 """
1530 @return: True if other's boundary crosses the boundary of this address
1531 range, False otherwise.
1532 """
1533 if isinstance(other, (str, unicode)):
1534 other = CIDR(other)
1535
1536 if not hasattr(other, 'addr_type'):
1537 raise TypeError('%r is an unsupported argument type!' % other)
1538
1539 if self.addr_type != other.addr_type:
1540 raise TypeError('Ranges must be the same address type!')
1541
1542
1543 if self.first <= other.last <= self.last:
1544 return True
1545
1546
1547 if self.first <= other.first <= self.last:
1548 return True
1549
1550 return False
1551
1555
1561
1562
1563 -class CIDR(IPRange):
1564 """
1565 Represents blocks of IPv4 and IPv6 addresses using CIDR (Classless
1566 Inter-Domain Routing) notation.
1567
1568 CIDR is a method of categorising contiguous blocks of both IPv4 and IPv6
1569 addresses. It is very scalable allowing for the optimal usage of the IP
1570 address space. It permits the aggregation of networks via route
1571 summarisation (supernetting) where adjacent routes can be combined into a
1572 single route easily. This greatly assists in the reduction of routing
1573 table sizes and improves network router efficiency.
1574
1575 CIDR blocks are represented by a base network address and a prefix
1576 indicating the size of the (variable length) subnet mask. These are
1577 separated by a single '/' character. Subnet sizes increase in powers of
1578 base 2 aligning to bit boundaries.
1579
1580 It is technically invalid to have non-zero bits in a CIDR address to the
1581 right of the implied netmask. For user convenience this is however
1582 configurable and can be disabled using a constructor argument.
1583
1584 The constructor accepts CIDRs expressed in one of 4 different ways :-
1585
1586 A) Standard CIDR format :-
1587
1588 IPv4::
1589
1590 x.x.x.x/y -> 192.0.2.0/24
1591
1592 where the x's represent the network address and y is the netmask
1593 prefix between 0 and 32.
1594
1595 IPv6::
1596
1597 x::/y -> fe80::/10
1598
1599 where the x's represent the network address and y is the netmask
1600 prefix between 0 and 128.
1601
1602 B) Abbreviated CIDR format (IPv4 only)::
1603
1604 x -> 192
1605 x/y -> 10/8
1606 x.x/y -> 192.168/16
1607 x.x.x/y -> 192.168.0/24
1608
1609 which are equivalent to::
1610
1611 x.0.0.0/y -> 192.0.0.0/24
1612 x.0.0.0/y -> 10.0.0.0/8
1613 x.x.0.0/y -> 192.168.0.0/16
1614 x.x.x.0/y -> 192.168.0.0/24
1615
1616 - The trailing zeros are implicit.
1617 - Old classful IP address rules apply if y is omitted.
1618
1619 C) Hybrid CIDR format (prefix replaced by netmask) :-
1620
1621 IPv4::
1622
1623 x.x.x.x/y.y.y.y -> 192.0.2.0/255.255.255.0
1624
1625 IPv6::
1626
1627 x::/y:: -> fe80::/ffc0::
1628
1629 where the y's represent a valid netmask.
1630
1631 D) ACL-style CIDR format (prefix is replaced by a hostmask) :-
1632
1633 Akin to Cisco's ACL (Access Control List) bitmasking (reverse
1634 netmasks).
1635
1636 IPv4::
1637
1638 x.x.x.x/y.y.y.y -> 192.0.2.0/0.0.0.255
1639
1640 IPv6::
1641
1642 x::/y:: -> fe80::/3f:ffff:ffff:ffff:ffff:ffff:ffff:ffff
1643
1644 where the y's represent a valid hostmask.
1645
1646 Reference: RFCs 1338 and 4632.
1647 """
1648 STRATEGIES = (ST_IPV4, ST_IPV6)
1649 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
1650
1651
1652 strategy = StrategyDescriptor(STRATEGIES)
1653 addr_type = AddrTypeDescriptor(ADDR_TYPES)
1654 prefixlen = PrefixLenDescriptor('CIDR')
1655 fmt = FormatDescriptor(IP)
1656
1658 """
1659 A static method that converts abbreviated IPv4 CIDRs to their more
1660 verbose equivalent.
1661
1662 @param abbrev_cidr: an abbreviated CIDR.
1663
1664 Uses the old-style classful IP address rules to decide on a default
1665 subnet prefix if one is not explicitly provided.
1666
1667 Only supports IPv4 addresses.
1668
1669 Examples ::
1670
1671 10 - 10.0.0.0/8
1672 10/16 - 10.0.0.0/16
1673 128 - 128.0.0.0/16
1674 128/8 - 128.0.0.0/8
1675 192.168 - 192.168.0.0/16
1676
1677 @return: A verbose CIDR from an abbreviated CIDR or old-style classful
1678 network address, C{None} if format provided was not recognised or
1679 supported.
1680 """
1681
1682
1683 def classful_prefix(octet):
1684 octet = int(octet)
1685 if not 0 <= octet <= 255:
1686 raise IndexError('Invalid octet: %r!' % octet)
1687 if 0 <= octet <= 127:
1688 return 8
1689 elif 128 <= octet <= 191:
1690 return 16
1691 elif 192 <= octet <= 223:
1692 return 24
1693 elif octet == 224:
1694 return 4
1695 elif 225 <= octet <= 239:
1696 return 8
1697 return 32
1698
1699 start = ''
1700 tokens = []
1701 prefix = None
1702
1703 if isinstance(abbrev_cidr, (str, unicode)):
1704
1705 if ':' in abbrev_cidr:
1706 return None
1707 try:
1708
1709 i = int(abbrev_cidr)
1710 tokens = [str(i), '0', '0', '0']
1711 return "%s%s/%s" % (start, '.'.join(tokens), classful_prefix(i))
1712
1713 except ValueError:
1714
1715 part_addr = abbrev_cidr
1716 tokens = []
1717
1718 if part_addr == '':
1719
1720 return None
1721
1722 if '/' in part_addr:
1723 (part_addr, prefix) = part_addr.split('/', 1)
1724
1725
1726 if prefix is not None:
1727 try:
1728 if not 0 <= int(prefix) <= 32:
1729 return None
1730 except ValueError:
1731 return None
1732
1733 if '.' in part_addr:
1734 tokens = part_addr.split('.')
1735 else:
1736 tokens = [part_addr]
1737
1738 if 1 <= len(tokens) <= 4:
1739 for i in range(4 - len(tokens)):
1740 tokens.append('0')
1741 else:
1742
1743 return None
1744
1745 if prefix is None:
1746 try:
1747 prefix = classful_prefix(tokens[0])
1748 except ValueError:
1749 return None
1750
1751 return "%s%s/%s" % (start, '.'.join(tokens), prefix)
1752
1753 except TypeError:
1754 pass
1755 except IndexError:
1756 pass
1757
1758
1759 return None
1760
1761 - def span(addrs, fmt=None):
1762 """
1763 Static method that accepts a sequence of IP addresses and/or CIDRs,
1764 Wildcards and IPRanges returning a single CIDR that is large enough
1765 to span the lowest and highest IP addresses in the sequence (with
1766 a possible overlap on either end).
1767
1768 @param addrs: a sequence of IP, CIDR, Wildcard or IPRange objects
1769 and/or their string representations.
1770
1771 @param fmt: (optional) callable used on return values.
1772 (Default: None - L{CIDR} object) Also accepts str() and unicode().
1773
1774 @return: a single CIDR object spanning all addresses.
1775 """
1776 if not isinstance(addrs, (list, tuple)):
1777 raise TypeError('expected address sequence is not iterable!')
1778
1779 if not len(addrs) > 1:
1780 raise ValueError('sequence must contain 2 or more elements!')
1781
1782 if fmt not in (None, str, unicode):
1783 raise ValueError('unsupported formatter %r!' % fmt)
1784
1785
1786 if not isinstance(addrs, list):
1787 addrs = list(addrs)
1788
1789
1790
1791 for (i, addr) in enumerate(addrs):
1792 if isinstance(addr, (str, unicode)):
1793 try:
1794 obj = IP(addr)
1795 addrs[i] = obj
1796 continue
1797 except:
1798 pass
1799 try:
1800 obj = CIDR(addr)
1801 addrs[i] = obj
1802 continue
1803 except:
1804 pass
1805 try:
1806 obj = Wildcard(addr)
1807 addrs[i] = obj
1808 continue
1809 except:
1810 pass
1811
1812
1813 addrs.sort()
1814 lowest = addrs[0]
1815 highest = addrs[-1]
1816
1817 if isinstance(lowest, IPRange):
1818
1819 lowest = IP(lowest.first, lowest.addr_type)
1820
1821 if isinstance(highest, IPRange):
1822
1823 highest = IP(highest.last, highest.addr_type)
1824
1825 if lowest.addr_type != highest.addr_type:
1826 raise TypeError('address types are not the same!')
1827
1828 cidr = highest.cidr()
1829
1830 while cidr.prefixlen > 0:
1831 if highest in cidr and lowest not in cidr:
1832 cidr.prefixlen -= 1
1833 else:
1834 break
1835
1836
1837 if fmt is not None:
1838 return fmt(cidr)
1839
1840 return cidr
1841
1842 abbrev_to_verbose = staticmethod(abbrev_to_verbose)
1843 span = staticmethod(span)
1844
1846 """
1847 Constructor.
1848
1849 @param cidr: a valid IPv4/IPv6 CIDR address or abbreviated IPv4
1850 network address.
1851
1852 @param fmt: (optional) callable used on return values.
1853 Default: L{IP} class. See L{nrange()} documentations for
1854 more details on the various options.
1855
1856 @param strict: (optional) performs a test to ensure there are no
1857 non-zero bits to the right of the subnet mask or prefix when it is
1858 applied to the base address. (default: True)
1859 """
1860 cidr_arg = cidr
1861
1862
1863 verbose_cidr = CIDR.abbrev_to_verbose(cidr)
1864 if verbose_cidr is not None:
1865 cidr = verbose_cidr
1866
1867 if not isinstance(cidr, (str, unicode)):
1868 raise TypeError('%r is not a valid CIDR!' % cidr)
1869
1870
1871 try:
1872 (network, mask) = cidr.split('/', 1)
1873 except ValueError:
1874 raise AddrFormatError('CIDR objects %r require a subnet prefix!' \
1875 % cidr_arg)
1876
1877
1878
1879 first = IP(network)
1880 self.strategy = first.strategy
1881 self.prefixlen = mask
1882
1883 strategy = first.strategy
1884 addr_type = strategy.addr_type
1885
1886 hostmask = (1 << (strategy.width - self.prefixlen)) - 1
1887
1888 last = IP(first.value | hostmask, addr_type)
1889
1890 if strict:
1891
1892 netmask = strategy.max_int ^ hostmask
1893 host = (first.value | netmask) - netmask
1894 if host != 0:
1895 raise ValueError('%s contains non-zero bits right of the ' \
1896 '%d-bit mask! Did you mean %s instead?' \
1897 % (first, self.prefixlen,
1898 strategy.int_to_str(int(last) - hostmask)))
1899 else:
1900
1901 first.value = strategy.int_to_str(int(last) - hostmask)
1902
1903 super(CIDR, self).__init__(first, last, fmt)
1904
1906 """
1907 Subtract another CIDR from this one.
1908
1909 @param other: a CIDR object that is greater than or equal to C{self}.
1910
1911 @return: A list of CIDR objects than remain after subtracting C{other}
1912 from C{self}.
1913 """
1914 cidrs = []
1915
1916 if self.prefixlen == self.strategy.width:
1917
1918 return cidrs
1919
1920 new_prefixlen = self.prefixlen + 1
1921 i_lower = self.first
1922 i_upper = self.first + (2 ** (self.strategy.width - new_prefixlen))
1923
1924 lower = CIDR('%s/%d' % (self.strategy.int_to_str(i_lower),
1925 new_prefixlen))
1926 upper = CIDR('%s/%d' % (self.strategy.int_to_str(i_upper),
1927 new_prefixlen))
1928
1929 while other.prefixlen >= new_prefixlen:
1930 if other in lower:
1931 matched = i_lower
1932 unmatched = i_upper
1933 elif other in upper:
1934 matched = i_upper
1935 unmatched = i_lower
1936
1937 cidr = CIDR('%s/%d' % (self.strategy.int_to_str(unmatched),
1938 new_prefixlen))
1939
1940 cidrs.append(cidr)
1941
1942 new_prefixlen += 1
1943
1944 if new_prefixlen > self.strategy.width:
1945 break
1946
1947 i_lower = matched
1948 i_upper = matched + (2 ** (self.strategy.width - new_prefixlen))
1949
1950 lower = CIDR('%s/%d' % (self.strategy.int_to_str(i_lower),
1951 new_prefixlen))
1952 upper = CIDR('%s/%d' % (self.strategy.int_to_str(i_upper),
1953 new_prefixlen))
1954
1955 cidrs.sort()
1956
1957
1958 if self.fmt is str:
1959 return [str(cidr) for cidr in cidrs]
1960
1961 return cidrs
1962
1964 """
1965 Add another CIDR to this one returning a CIDR supernet that will
1966 contain both in the smallest possible sized range.
1967
1968 @param other: a CIDR object.
1969
1970 @return: A new (potentially larger) CIDR object.
1971 """
1972 cidr = CIDR.span([self, other])
1973 if self.fmt is str:
1974 return str(cidr)
1975 return cidr
1976
1978 """@return: The network (first) address in this CIDR block."""
1979 return self[0]
1980
1982 """
1983 B{Please Note:} although IPv6 doesn't actually recognise the concept of
1984 a 'broadcast' address as the last address in a subnet (as in IPv4) so
1985 many other libraries do this that it isn't worth trying to resist.
1986 This issue raises so many user queries that it is easier to dispense
1987 with the theory and be pragmatic instead.
1988
1989 @return: The broadcast (last) address in this CIDR block.
1990 """
1991 return self[-1]
1992
1998
2003
2004 network = property(network)
2005 broadcast = property(broadcast)
2006 netmask = property(netmask)
2007 hostmask = property(hostmask)
2008
2010 """
2011 @return: An iterator object providing access to all valid host IP
2012 addresses within the specified CIDR block.
2013 - with IPv4 the network and broadcast addresses are always
2014 excluded. Any smaller than 4 hosts yields an emtpy list.
2015 - with IPv6 only the unspecified address '::' is excluded from
2016 the yielded list.
2017 """
2018 if self.addr_type == AT_INET:
2019
2020 if self.size() >= 4:
2021 return nrange( IP(self.first+1, self.addr_type),
2022 IP(self.last-1, self.addr_type), fmt=self.fmt)
2023 else:
2024 return iter([])
2025 elif self.addr_type == AT_INET6:
2026
2027 if self.first == 0:
2028
2029 return nrange(IP(self.first+1, self.addr_type),
2030 IP(self.last, self.addr_type), fmt=self.fmt)
2031 else:
2032 return iter(self)
2033
2034 - def subnet(self, prefixlen, count=None, fmt=None):
2035 """
2036 A generator that returns CIDR subnets based on the current network
2037 base address and provided CIDR prefix and count.
2038
2039 @param prefixlen: a CIDR prefix.
2040
2041 @param count: number of consecutive CIDRs to be returned.
2042
2043 @param fmt: callable used on return values.
2044 Default: None - L{CIDR} objects. str() and unicode() supported.
2045
2046 @return: an iterator (as lists could potentially be very large)
2047 containing CIDR subnets below this CIDR's base address.
2048 """
2049 if not 0 <= self.prefixlen <= self.strategy.width:
2050 raise ValueError('prefixlen %d out of bounds for address type!' \
2051 % prefixlen)
2052
2053 if not self.prefixlen <= prefixlen:
2054 raise ValueError('prefixlen less than current CIDR prefixlen!')
2055
2056
2057 width = self.strategy.width
2058 max_count = 2 ** (width - self.prefixlen) / 2 ** (width - prefixlen)
2059
2060 if count is None:
2061 count = max_count
2062
2063 if 1 < count < max_count:
2064 raise ValueError('count not within current CIDR boundaries!')
2065
2066 base_address = self.strategy.int_to_str(self.first)
2067
2068 if fmt is None:
2069
2070 for i in xrange(count):
2071 cidr = CIDR('%s/%d' % (base_address, prefixlen))
2072 cidr.first += cidr.size() * i
2073 cidr.prefixlen = prefixlen
2074 yield cidr
2075 elif fmt in (str, unicode):
2076
2077 cidr = CIDR('%s/%d' % (base_address, prefixlen))
2078 for i in xrange(count):
2079 cidr.first += cidr.size() * i
2080 cidr.prefixlen = prefixlen
2081 yield fmt(cidr)
2082 else:
2083 raise TypeError('unsupported fmt callable %r' % fmt)
2084
2086 """
2087 @return: A list of a copy of this L{CIDR} object. This method is here
2088 mainly for compatibility with IPRange interface.
2089 """
2090 cidr_copy = CIDR('%s/%d' % (self.strategy.int_to_str(self.first),
2091 self.prefixlen))
2092
2093
2094 if self.fmt in (str, unicode):
2095 return [self.fmt(cidr_copy)]
2096
2097 return [cidr_copy]
2098
2101
2103 """@return: executable Python string to recreate equivalent object."""
2104 return "%s('%s/%d')" % (self.__class__.__name__,
2105 self.strategy.int_to_str(self.first), self.prefixlen)
2106
2107
2109 """
2110 Represents blocks of IPv4 addresses using a wildcard or glob style syntax.
2111
2112 Individual octets can be represented using the following shortcuts :
2113
2114 1. C{*} - the asterisk octet (represents values 0 through 255)
2115 2. C{'x-y'} - the hyphenated octet (represents values x through y)
2116
2117 A few basic rules also apply :
2118
2119 1. x must always be greater than y, therefore :
2120
2121 - x can only be 0 through 254
2122 - y can only be 1 through 255
2123
2124 2. only one hyphenated octet per wildcard is allowed
2125 3. only asterisks are permitted after a hyphenated octet
2126
2127 Example wildcards ::
2128
2129 '192.168.0.1' # a single address
2130 '192.168.0.0-31' # 32 addresses
2131 '192.168.0.*' # 256 addresses
2132 '192.168.0-1.*' # 512 addresses
2133 '192.168-169.*.*' # 131,072 addresses
2134 '*.*.*.*' # the whole IPv4 address space
2135
2136 Aside
2137 =====
2138 I{Wildcard ranges are not directly equivalent to CIDR blocks as they
2139 can represent address ranges that do not fall on strict bit mask
2140 boundaries. They are very suitable in configuration files being more
2141 obvious and readable than their CIDR equivalents, especially for admins
2142 and users without much networking knowledge or experience.}
2143
2144 I{All CIDR blocks can always be represented as wildcard ranges but the
2145 reverse is not true. Wildcards are almost but not quite as flexible
2146 as IPRange objects.}
2147 """
2148 STRATEGIES = (ST_IPV4,)
2149 ADDR_TYPES = (AT_UNSPEC, AT_INET)
2150
2151
2152 strategy = StrategyDescriptor(STRATEGIES)
2153 addr_type = AddrTypeDescriptor(ADDR_TYPES)
2154 fmt = FormatDescriptor(IP)
2155
2157 """
2158 A static method that validates wildcard address ranges.
2159
2160 @param wildcard: an IPv4 wildcard address.
2161
2162 @return: True if wildcard address is valid, False otherwise.
2163 """
2164
2165
2166
2167
2168 seen_hyphen = False
2169 seen_asterisk = False
2170 try:
2171 octets = wildcard.split('.')
2172 if len(octets) != 4:
2173 return False
2174 for o in octets:
2175 if '-' in o:
2176 if seen_hyphen:
2177 return False
2178 seen_hyphen = True
2179 if seen_asterisk:
2180
2181 return False
2182 (o1, o2) = [int(i) for i in o.split('-')]
2183 if o1 >= o2:
2184 return False
2185 if not 0 <= o1 <= 254:
2186 return False
2187 if not 1 <= o2 <= 255:
2188 return False
2189 elif o == '*':
2190 seen_asterisk = True
2191 else:
2192 if seen_hyphen is True:
2193 return False
2194 if seen_asterisk is True:
2195 return False
2196 if not 0 <= int(o) <= 255:
2197 return False
2198 except AttributeError:
2199 return False
2200 except ValueError:
2201 return False
2202 return True
2203
2204 is_valid = staticmethod(is_valid)
2205
2207 """
2208 Constructor.
2209
2210 @param wildcard: a valid IPv4 wildcard address
2211
2212 @param fmt: (optional) callable used on return values.
2213 Default: L{IP} objects. See L{nrange()} documentations for
2214 more details on the various options..
2215 """
2216 if not Wildcard.is_valid(wildcard):
2217 raise AddrFormatError('%r is not a recognised wildcard address!' \
2218 % wildcard)
2219 t1 = []
2220 t2 = []
2221
2222 for octet in wildcard.split('.'):
2223 if '-' in octet:
2224 oct_tokens = octet.split('-')
2225 t1 += [oct_tokens[0]]
2226 t2 += [oct_tokens[1]]
2227 elif octet == '*':
2228 t1 += ['0']
2229 t2 += ['255']
2230 else:
2231 t1 += [octet]
2232 t2 += [octet]
2233
2234 first = '.'.join(t1)
2235 last = '.'.join(t2)
2236 super(Wildcard, self).__init__(first, last, fmt=fmt)
2237
2238 if self.addr_type != AT_INET:
2239 raise AddrFormatError('Wildcard syntax only supports IPv4!')
2240
2242 t1 = self.strategy.int_to_words(self.first)
2243 t2 = self.strategy.int_to_words(self.last)
2244
2245 tokens = []
2246
2247 seen_hyphen = False
2248 seen_asterisk = False
2249
2250 for i in range(4):
2251 if t1[i] == t2[i]:
2252
2253 tokens.append(str(t1[i]))
2254 elif (t1[i] == 0) and (t2[i] == 255):
2255
2256 tokens.append('*')
2257 seen_asterisk = True
2258 else:
2259
2260 if not seen_asterisk:
2261 if not seen_hyphen:
2262 tokens.append('%s-%s' % (t1[i], t2[i]))
2263 seen_hyphen = True
2264 else:
2265 raise AddrFormatError('only one hyphenated octet ' \
2266 ' per wildcard allowed!')
2267 else:
2268 raise AddrFormatError('asterisks not permitted before ' \
2269 'hyphenated octets!')
2270
2271 return '.'.join(tokens)
2272
2274 """@return: executable Python string to recreate equivalent object."""
2275 return "%s(%r)" % (self.__class__.__name__, str(self))
2276
2277
2278
2280 """
2281 B{*EXPERIMENTAL*} A customised Python set class that deals with collections
2282 of IPRange class and subclass instances.
2283 """
2285 """
2286 Constructor.
2287
2288 @param addrs: A sequence of IPRange class/subclass instances used to
2289 pre-populate the set. Individual CIDR objects can be added and
2290 removed after instantiation with the usual set methods, add() and
2291 remove().
2292 """
2293 for addr in addrs:
2294 if isinstance(addr, IP):
2295 self.add(addr.cidr())
2296 if isinstance(addr, str):
2297 try:
2298 self.add(CIDR(addr))
2299 except:
2300 pass
2301 try:
2302 ip = IP(addr)
2303 self.add(ip.cidr())
2304 except:
2305 pass
2306 try:
2307 wildcard = Wildcard(addr)
2308 try:
2309 self.add(wildcard.cidr())
2310 except:
2311 self.add(wildcard)
2312 except:
2313 pass
2314 else:
2315 self.add(addr)
2316
2318 """
2319 @return: True if C{other} IP or IPRange class/subclass instance
2320 matches any of the members in this IPRangeSet, False otherwise.
2321 """
2322 for addr in self:
2323 if other in addr:
2324 return True
2325
2327 """
2328 @param other: An IP or IPRange class/subclass instance.
2329
2330 @return: The first IP or IPRange class/subclass instance object that
2331 matches C{other} from any of the members in this IPRangeSet, None
2332 otherwise.
2333 """
2334 for addr in self:
2335 if other in addr:
2336 return addr
2337
2339 """
2340 @param other: An IP or IPRange class/subclass instance.
2341
2342 @return: All IP or IPRange class/subclass instances matching C{other}
2343 from this IPRangeSet, an empty list otherwise.
2344 """
2345 addrs = []
2346 for addr in self:
2347 if other in addr:
2348 addrs.append(addr)
2349 return addrs
2350
2352 """
2353 @param other: An IP or IPRange class/subclass instance.
2354
2355 @return: The smallest IP or IPRange class/subclass instance matching
2356 C{other} from this IPRangeSet, None otherwise.
2357 """
2358 addrs = self.all_matches(other)
2359 addrs.sort()
2360 return addrs[0]
2361
2362
2364 """
2365 @param other: An IP or IPRange class/subclass instance.
2366
2367 @return: The largest IP or IPRange class/subclass instance matching
2368 C{other} from this IPRangeSet, None otherwise.
2369 """
2370 addrs = self.all_matches(other)
2371 addrs.sort()
2372 return addrs[-1]
2373