1
2
3
4
5
6
7 """
8 network address classes (IP, EUI) and associated aggregate classes (CIDR,
9 Wilcard, etc).
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
21 AT_STRATEGIES = {
22 AT_UNSPEC : None,
23 AT_INET : ST_IPV4,
24 AT_INET6 : ST_IPV6,
25 AT_LINK : ST_EUI48,
26 AT_EUI64 : ST_EUI64,
27 }
28
29
30
31
32
34 """
35 A descriptor that checks addr_type property assignments for validity and
36 also keeps the strategy property in sync with any changes made.
37 """
39 """
40 Constructor.
41
42 @param addr_types: a list of address types constants that are
43 acceptable for assignment to the addr_type property.
44 """
45 self.addr_types = addr_types
46
47 - def __set__(self, instance, value):
48 if value not in self.addr_types:
49 raise ValueError('addr_type %r is invalid for objects of ' \
50 'the %s() class!' % (value, instance.__class__.__name__))
51 instance.__dict__['addr_type'] = value
52 instance.__dict__['strategy'] = AT_STRATEGIES[value]
53
54
56 """
57 A descriptor that checks assignments to the named parameter passed to the
58 constructor. It accepts network addresses in either string format or as
59 network byte order integers. String based addresses are converted to their
60 integer equivalents before assignment to the named parameter. Also ensures
61 that addr_type and strategy are set correctly when parsing string based
62 addresses.
63 """
65 """
66 Descriptor constructor.
67
68 @param name: the name of attribute which will be assigned the value.
69 """
70 self.name = name
71
72 - def __set__(self, instance, value):
101
102
104 """
105 A descriptor that checks strategy property assignments for validity and
106 also keeps the addr_type property in sync with any changes made.
107 """
109 """
110 Constructor.
111
112 @param strategies: a list of strategy objects that are acceptable for
113 assignment to the strategy property.
114 """
115 self.strategies = strategies
116
117 - def __set__(self, instance, value):
118 if value not in self.strategies:
119 raise Exception('%r is not a supported strategy!' % value)
120 instance.__dict__['strategy'] = value
121 instance.__dict__['addr_type'] = instance.strategy.addr_type
122
123
125 """
126 A descriptor that checks prefixlen property assignments for validity based
127 on address type. Also accepts subnet masks which can easily be converted
128 to the equivalent prefixlen integer.
129 """
131 """
132 Constructor.
133
134 @param class_id: (optional) the name of the class that uses this
135 descriptor.
136 """
137 self.class_id = class_id
138
139 - def __set__(self, instance, value):
172
173
175 """
176 A descriptor that checks klass (data flavour) property assignments for
177 validity.
178 """
180 """
181 Constructor.
182
183 @param default_klass: the default class to use if klass property is
184 set to None.
185 """
186 self.default_klass = default_klass
187
188 - def __set__(self, instance, value):
189 if isinstance(value, type):
190 if value in (str, int, long, unicode):
191 pass
192 elif issubclass(value, Addr):
193 pass
194 else:
195 raise TypeError("%r is an unsupported klass type!" % value)
196 elif value is hex:
197
198 pass
199 elif value is None:
200
201 value = self.default_klass
202 else:
203 raise ValueError("%r is not a supported type, BIF or class!" \
204 % value)
205
206 instance.__dict__['klass'] = value
207
208
209
210
211
213 """
214 The base class containing common functionality for all subclasses
215 representing various network address types.
216
217 It is a fully functioning class (as opposed to a virtual class) with a
218 heuristic constructor that detects the type of address via the first
219 argument if it is a string and sets itself up accordingly. If the first
220 argument is an integer, then a constant must be provided via the second
221 argument indicating the address type explicitly.
222
223 Objects of this class behave differently dependent upon the type of address
224 they represent.
225 """
226 STRATEGIES = (ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64)
227 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6, AT_LINK, AT_EUI64)
228
229
230 value = AddrValueDescriptor('value')
231 strategy = StrategyDescriptor(STRATEGIES)
232 addr_type = AddrTypeDescriptor(ADDR_TYPES)
233
235 """
236 Constructor.
237
238 @param addr: the string form of a network address, or a network byte
239 order integer within the supported range for the address type.
240
241 @param addr_type: (optional) the network address type. If addr is an
242 integer, this argument becomes mandatory.
243 """
244 self.addr_type = addr_type
245 self.value = addr
246
248 """
249 @return: The hash of this address. Allows it to be used in sets and
250 as a key in dictionaries.
251 """
252 return hash((self.value, self.addr_type))
253
255 """
256 @return: The value of this address as an network byte order integer.
257 """
258 return self.value
259
261 """
262 @return: The value of this address as an network byte order integer.
263 """
264 return self.value
265
267 """
268 @return: The common string representation for this address type.
269 """
270 return self.strategy.int_to_str(self.value)
271
273 """
274 @return: An executable Python statement that can recreate an object
275 with an equivalent state.
276 """
277 return "netaddr.address.%s(%r)" % (self.__class__.__name__, str(self))
278
280 """
281 @return: A human-readable binary digit string for this address type.
282 """
283 return self.strategy.int_to_bits(self.value)
284
286 """
287 @return: The size of this address (in bits).
288 """
289 return self.strategy.width
290
292 """
293 @return: An iterator over individual words in this address.
294 """
295 return iter(self.strategy.int_to_words(self.value))
296
298 """
299 @return: The integer value of the word indicated by index. Raises an
300 C{IndexError} if index is wrong size for address type. Full
301 slicing is also supported.
302 """
303 if isinstance(index, (int, long)):
304
305 word_count = self.strategy.word_count
306 if not (-word_count) <= index <= (word_count - 1):
307 raise IndexError('index out range for address type!')
308 return self.strategy.int_to_words(self.value)[index]
309 elif isinstance(index, slice):
310
311 words = self.strategy.int_to_words(self.value)
312 return [words[i] for i in range(*index.indices(len(words)))]
313 else:
314 raise TypeError('unsupported type %r!' % index)
315
317 """
318 Sets the value of the word of this address indicated by index.
319 """
320 if isinstance(index, slice):
321
322 raise NotImplementedError('settable slices not yet supported!')
323
324 if not isinstance(index, (int, long)):
325 raise TypeError('index not an integer!')
326
327 if not 0 <= index <= (self.strategy.word_count - 1):
328 raise IndexError('index %d outside address type boundary!' % index)
329
330 if not isinstance(value, (int, long)):
331 raise TypeError('value not an integer!')
332
333 if not 0 <= value <= (2 ** self.strategy.word_size - 1):
334 raise IndexError('value %d outside word size maximum of %d bits!'
335 % (value, self.strategy.word_size))
336
337 words = list(self.strategy.int_to_words(self.value))
338 words[index] = value
339 self.value = self.strategy.words_to_int(words)
340
342 """
343 @return: The value of this address as a network byte order hexadecimal
344 number.
345 """
346 return hex(self.value).rstrip('L').lower()
347
349 """
350 Increments network address by specified value.
351
352 If the result exceeds address type maximum, it rolls around the
353 minimum boundary.
354 """
355 try:
356 new_value = self.value + i
357 if new_value > self.strategy.max_int:
358 self.value = new_value - (self.strategy.max_int + 1)
359 else:
360 self.value = new_value
361 except TypeError:
362 raise TypeError('Increment value must be an integer!')
363 return self
364
366 """
367 Decrements network address by specified value.
368
369 If the result exceeds address type minimum, it rolls around the
370 maximum boundary.
371 """
372 try:
373 new_value = self.value - i
374 if new_value < self.strategy.min_int:
375 self.value = new_value + (self.strategy.max_int + 1)
376 else:
377 self.value = new_value
378 except TypeError:
379 raise TypeError('Decrement value must be an integer!')
380 return self
381
383 """
384 @return: C{True} if this network address instance has the same
385 numerical value as another, C{False} otherwise.
386 """
387 try:
388 if (self.addr_type, self.value) == (other.addr_type, other.value):
389 return True
390 except AttributeError:
391 pass
392
393 return False
394
396 """
397 @return: C{True} if this network address instance does not have the
398 same numerical value as another, C{False} otherwise.
399 """
400 try:
401 if (self.addr_type, self.value) != (other.addr_type, other.value):
402 return True
403 except AttributeError:
404 pass
405
406 return False
407
409 """
410 @return: C{True} if this network address instance has a lower
411 numerical value than another, C{False} otherwise.
412 """
413 try:
414 if (self.addr_type, self.value) < (other.addr_type, other.value):
415 return True
416 except AttributeError:
417 pass
418
419 return False
420
422 """
423 @return: C{True} if this network address instance has a lower or
424 equivalent numerical value than another, C{False} otherwise.
425 """
426 try:
427 if (self.addr_type, self.value) <= (other.addr_type, other.value):
428 return True
429 except AttributeError:
430 pass
431
432 return False
433
435 """
436 @return: C{True} if this network address instance has a higher
437 numerical value than another, C{False} otherwise.
438 """
439 try:
440 if (self.addr_type, self.value) > (other.addr_type, other.value):
441 return True
442 except AttributeError:
443 pass
444
445 return False
446
448 """
449 @return: C{True} if this network address instance has a higher or
450 equivalent numerical value than another, C{False} otherwise.
451 """
452 try:
453 if (self.addr_type, self.value) >= (other.addr_type, other.value):
454 return True
455 except AttributeError:
456 pass
457
458 return False
459
460
462 """
463 EUI objects represent IEEE Extended Unique Identifiers. Input parsing is
464 flexible, supporting EUI-48, EUI-64 and all MAC (Media Access Control)
465 address flavours.
466 """
467 STRATEGIES = (ST_EUI48, ST_EUI64)
468 ADDR_TYPES = (AT_UNSPEC, AT_LINK, AT_EUI64)
469
470
471 strategy = StrategyDescriptor(STRATEGIES)
472 addr_type = AddrTypeDescriptor(ADDR_TYPES)
473
475 """
476 Constructor.
477
478 @param addr: an EUI/MAC address string or a network byte order
479 integer.
480
481 @param addr_type: (optional) the specific EUI address type (C{AT_LINK}
482 or C{AT_EUI64}). If addr is an integer, this argument is mandatory.
483 """
484 super(EUI, self).__init__(addr, addr_type)
485
487 """
488 @return: The OUI (Organisationally Unique Identifier) for this EUI.
489 """
490 return '-'.join(["%02x" % i for i in self[0:3]]).upper()
491
493 """
494 @return: The EI (Extension Identifier) for this EUI.
495 """
496 if self.strategy == ST_EUI48:
497 return '-'.join(["%02x" % i for i in self[3:6]]).upper()
498 elif self.strategy == ST_EUI64:
499 return '-'.join(["%02x" % i for i in self[3:8]]).upper()
500
502 """
503 @return: The value of this EUI object as a new 64-bit EUI object.
504 - If this object represents an EUI-48 it is converted to EUI-64 as
505 per the standard.
506 - If this object is already and EUI-64, it just returns a new,
507 numerically equivalent object is returned instead.
508 """
509 if self.addr_type == AT_LINK:
510 eui64_words = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
511 ["%02x" % i for i in self[3:6]]
512
513 return self.__class__('-'.join(eui64_words))
514 else:
515 return EUI(str(self))
516
518 """
519 @return: An IPv6 L{IP} object initialised using the value of this
520 L{EUI}.
521 - B{See RFC 4921 for details}.
522 """
523 prefix = 'fe80:0000:0000:0000:'
524
525
526 self[0] += 2
527
528 if self.addr_type == AT_LINK:
529
530 suffix = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
531 ["%02x" % i for i in self[3:6]]
532 else:
533 suffix = ["%02x" % i for i in list(self)]
534
535 suffix = ["%02x%02x" % (int(x[0], 16), int(x[1], 16)) for x in \
536 zip(suffix[::2], suffix[1::2])]
537
538
539 self[0] -= 2
540
541 eui64 = ':'.join(suffix)
542 addr = prefix + eui64
543 return IP(addr)
544
545
547 """
548 A class whose objects represent Internet Protocol network addresses. Both
549 IPv4 and IPv6 are fully supported and also permit the inclusion of bitmask
550 prefix or subnet mask address indicating the size/extent of the subnet,
551 for example ::
552
553 IPv4
554
555 192.168.0.1/24
556 192.168.0.1/255.255.255.0
557
558 IPv6
559
560 fe80::20f:1fff:fe12:e733/64
561 """
562 STRATEGIES = (ST_IPV4, ST_IPV6)
563 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
564 TRANSLATE_STR = ''.join([chr(i) for i in range(256)])
565 del i
566
567
568 strategy = StrategyDescriptor(STRATEGIES)
569 addr_type = AddrTypeDescriptor(ADDR_TYPES)
570 prefixlen = PrefixLenDescriptor()
571
573 """
574 Constructor.
575
576 @param addr: an IPv4 or IPv6 address string with an optional subnet
577 prefix or a network byte order integer.
578
579 @param addr_type: (optional) the IP address type (C{AT_INET} or
580 C{AT_INET6}). If L{addr} is an integer, this argument is mandatory.
581 """
582 prefixlen = None
583
584 try:
585 if '/' in addr:
586 (addr, prefixlen) = addr.split('/', 1)
587 except TypeError:
588
589 pass
590
591
592
593 super(IP, self).__init__(addr, addr_type)
594
595
596 if prefixlen is None:
597 self.prefixlen = self.strategy.width
598 else:
599 self.prefixlen = prefixlen
600
602 """
603 @return: C{True} if this addr is a mask that would return a host id,
604 C{False} otherwise.
605 """
606
607
608 bits = self.strategy.int_to_bits(self.value).replace('.', '')
609
610 if bits[0] != '1':
611
612 return False
613
614
615 bits = bits.lstrip('1')
616
617 seen_zero = False
618 for i in bits:
619 if i == '0' and seen_zero is False:
620 seen_zero = True
621 elif i == '1' and seen_zero is True:
622 return False
623
624 return True
625
627 """
628 @return: If this address is a valid netmask, the number of non-zero
629 bits are returned, otherwise it returns the width (in bits) for the
630 given address type (IPv4: 32, IPv6: 128).
631 """
632 if not self.is_netmask():
633 return self.strategy.width
634
635 bits = self.strategy.int_to_bits(self.value)
636 mask_bits = bits.translate(IP.TRANSLATE_STR, ':.0')
637 mask_length = len(mask_bits)
638
639 if not 1 <= mask_length <= self.strategy.width:
640 raise ValueError('Unexpected mask length %d for address type!' \
641 % mask_length)
642
643 return mask_length
644
646 """
647 @return: The reverse DNS lookup string for this IP address.
648 """
649 return self.strategy.int_to_arpa(self.value)
650
652 """
653 @return: C{True} if this address is a mask that would return a host
654 id, C{False} otherwise.
655 """
656
657
658 bits = self.strategy.int_to_bits(self.value).replace('.', '')
659
660 if bits[0] != '0':
661
662 return False
663
664
665 bits = bits.lstrip('0')
666
667 seen_one = False
668 for i in bits:
669 if i == '1' and seen_one is False:
670 seen_one = True
671 elif i == '0' and seen_one is True:
672 return False
673
674 return True
675
677 """
678 @return: Returns the FQDN for this IP address via a DNS query
679 using gethostbyaddr() Python's socket module.
680 """
681 try:
682 return _socket.gethostbyaddr(str(self))[0]
683 except:
684 return
685
694
696 """
697 @return: A new L{IP} object numerically equivalent this address.
698 - If its address type is IPv4.
699 - If object's address type is IPv6 and its value is mappable to
700 IPv4, a new IPv4 L{IP} object is returned instead.
701 - Raises an L{AddrConversionError} if IPv6 address is not mappable
702 to IPv4.
703 """
704 ip_addr = None
705 if self.addr_type == AT_INET:
706 ip_addr = IP(self.value, AT_INET)
707 elif self.addr_type == AT_INET6:
708 words = self.strategy.int_to_words(self.value)
709 if words[0:6] == (0,0,0,0,0,0):
710 ip_addr = IP(self.value, AT_INET)
711 elif words[0:6] == (0,0,0,0,0,65535):
712 ip_addr = IP(self.value - 0xffff00000000, AT_INET)
713 else:
714 raise AddrConversionError('IPv6 address %s too large for ' \
715 'conversion to IPv4!' % self)
716 return ip_addr
717
719 """
720 @return: A new L{IP} object numerically equivalent this address.
721 - If object's address type is IPv6.
722 - If object's address type is IPv4 a new IPv6 L{IP} object, as a
723 IPv4 mapped address is returned instead. Uses the preferred IPv4
724 embedded in IPv6 form - C{::ffff:x.x.x.x} ('mapped' address) over
725 the (now deprecated) form - C{::x.x.x.x} ('compatible' address).
726 B{See RFC 4921 for details}.
727 """
728 ip_addr = None
729 if self.addr_type == AT_INET6:
730 ip_addr = IP(self.value, AT_INET6)
731 elif self.addr_type == AT_INET:
732 ip_addr = IP(self.value, AT_INET6)
733 ip_addr[5] = 0xffff
734 return ip_addr
735
737 """
738 @return: C{True} if this address is unicast, C{False} otherwise.
739 """
740 if self.is_multicast():
741 return False
742 return True
743
745 """
746 @return: C{True} if this address is multicast, C{False} otherwise.
747 """
748 if self.addr_type == AT_INET:
749 if 0xe0000000 <= self.value <= 0xefffffff:
750 return True
751 elif self.addr_type == AT_INET6:
752 if 0xff000000000000000000000000000000 <= self.value <= \
753 0xffffffffffffffffffffffffffffffff:
754 return True
755 return False
756
758 """
759 @return: The common string representation for this IP address.
760 """
761 return self.strategy.int_to_str(self.value)
762
764 """
765 @return: An executable Python statement that can recreate an object
766 with an equivalent state.
767 """
768 if self.prefixlen == self.strategy.width:
769 return "netaddr.address.%s('%s')" % (self.__class__.__name__,
770 str(self))
771
772 return "netaddr.address.%s('%s/%d')" % (self.__class__.__name__,
773 str(self), self.prefixlen)
774
775
776
777
778
779 -def nrange(start, stop, step=1, klass=None):
780 """
781 A generator producing sequences of network addresses based on start and
782 stop values, in intervals of step.
783
784 @param start: first network address as string or instance of L{Addr}
785 (sub)class.
786
787 @param stop: last network address as string or instance of L{Addr}
788 (sub)class.
789
790 @param step: (optional) size of step between addresses in range.
791 Default is 1.
792
793 @param klass: (optional) the class used to create objects returned.
794 Default: L{Addr} class.
795
796 - C{str} returns string representation of network address
797 - C{int}, C{long} and C{hex} return expected values
798 - L{Addr} (sub)class or duck type* return objects of that class. If
799 you use your own duck class, make sure you handle both arguments
800 C{(addr_value, addr_type)} passed to the constructor.
801 """
802 if not issubclass(start.__class__, Addr):
803 if isinstance(start, (str, unicode)):
804 start = Addr(start)
805 else:
806 raise TypeError('start is not recognised address in string ' \
807 'format or an that is a (sub)class of Addr!')
808 else:
809
810 if klass is None:
811 klass = start.__class__
812
813 if not issubclass(stop.__class__, Addr):
814 if isinstance(stop, (str, unicode)):
815 stop = Addr(stop)
816 else:
817 raise TypeError('stop is not recognised address in string ' \
818 'format or an that is a (sub)class of Addr!')
819
820 if not isinstance(step, (int, long)):
821 raise TypeError('step must be type int|long, not %s!' % type(step))
822
823 if start.addr_type != stop.addr_type:
824 raise TypeError('start and stop are not the same address type!')
825
826 if step == 0:
827 raise ValueError('step argument cannot be zero')
828
829 negative_step = False
830 addr_type = start.addr_type
831
832
833
834 start_klass = start.__class__
835 start = int(start)
836 stop = int(stop)
837
838 if step < 0:
839 negative_step = True
840
841 index = start - step
842
843
844 if klass is None:
845 klass = Addr
846
847 if klass in (int, long, hex):
848
849 while True:
850 index += step
851 if negative_step:
852 if not index >= stop:
853 return
854 else:
855 if not index <= stop:
856 return
857 yield klass(index)
858 elif klass in (str, unicode):
859
860 while True:
861 index += step
862 if negative_step:
863 if not index >= stop:
864 return
865 else:
866 if not index <= stop:
867 return
868 yield str(start_klass(index, addr_type))
869 else:
870
871 while True:
872 index += step
873 if negative_step:
874 if not index >= stop:
875 return
876 else:
877 if not index <= stop:
878 return
879
880 yield klass(index, addr_type)
881
882
884 """
885 A block of contiguous network addresses bounded by an arbitrary start and
886 stop address. There is no requirement that they fall on strict bit mask
887 boundaries, unlike L{CIDR} addresses.
888
889 This is the only network address aggregate supporting all network address
890 types. Most AddrRange subclasses usually only support a subset of address
891 types.
892
893 A sequence of address ranges sort first by address type then by magnitude.
894 So for a list containing ranges of all currently supported address types,
895 IPv4 ranges come first, then IPv6, EUI-48 and lastly EUI-64.
896 """
897 STRATEGIES = (ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64)
898 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6, AT_LINK, AT_EUI64)
899
900
901 strategy = StrategyDescriptor(STRATEGIES)
902 addr_type = AddrTypeDescriptor(ADDR_TYPES)
903 first = AddrValueDescriptor('first')
904 last = AddrValueDescriptor('last')
905 klass = KlassDescriptor(Addr)
906
908 """
909 Constructor.
910
911 @param first: start address for this network address range.
912
913 @param last: stop address for this network address range.
914
915 @param klass: (optional) class used to create each object returned.
916 Default: L{Addr()} objects. See L{nrange()} documentations for
917 additional details on options.
918 """
919 self.addr_type = AT_UNSPEC
920 self.first = first
921 self.last = last
922 if self.last < self.first:
923 raise IndexError('start address is greater than stop address!')
924 self.klass = klass
925
927 """
928 @return: The hash of this address range. Allow them to be used in sets
929 and as keys in dictionaries.
930 """
931 return hash((self.first, self.last, self.addr_type))
932
934 """
935 @return: The total number of network addresses in this range.
936 - Use this method only for ranges that contain less than
937 C{2^31} addresses or try the L{size()} method. Raises an
938 C{IndexError} if size is exceeded.
939 """
940 size = self.size()
941 if size > (2 ** 31):
942
943 raise IndexError("range contains more than 2^31 addresses! " \
944 "Use size() method instead.")
945 return size
946
948 """
949 @return: The total number of network addresses in this range.
950 - Use this method in preference to L{__len__()} when size of
951 ranges exceeds C{2^31} addresses.
952 """
953 return self.last - self.first + 1
954
956 """
957 @param int_addr: an network address as a network byte order integer.
958
959 @return: a network address in whatever 'flavour' is required based on
960 the value of the klass property.
961 """
962 if self.klass in (str, unicode):
963 return self.strategy.int_to_str(int_addr)
964 elif self.klass in (int, long, hex):
965 return self.klass(int_addr)
966 else:
967 return self.klass(int_addr, self.addr_type)
968
970 """
971 @return: The network address(es) in this address range indicated by
972 index/slice. Slicing objects can produce large sequences so
973 generator objects are returned instead to the usual sequences.
974 Wrapping a raw slice with C{list()} or C{tuple()} may be required
975 dependent on context.
976 """
977
978 if isinstance(index, (int, long)):
979 if (- self.size()) <= index < 0:
980
981 return self.data_flavour(self.last + index + 1)
982 elif 0 <= index <= (self.size() - 1):
983
984 return self.data_flavour(self.first + index)
985 else:
986 raise IndexError('index out range for address range size!')
987 elif isinstance(index, slice):
988
989
990
991
992
993
994
995
996 (start, stop, step) = index.indices(self.size())
997
998 start_addr = Addr(self.first + start, self.addr_type)
999 end_addr = Addr(self.first + stop - step, self.addr_type)
1000 return nrange(start_addr, end_addr, step, klass=self.klass)
1001 else:
1002 raise TypeError('unsupported type %r!' % index)
1003
1005 """
1006 @return: An iterator object providing access to all network addresses
1007 within this range.
1008 """
1009 start_addr = Addr(self.first, self.addr_type)
1010 end_addr = Addr(self.last, self.addr_type)
1011 return nrange(start_addr, end_addr, klass=self.klass)
1012
1014 """
1015 @param addr: object of Addr/AddrRange (sub)class or a network address
1016 string to be compared.
1017
1018 @return: C{True} if given address or range falls within this range,
1019 C{False} otherwise.
1020 """
1021 if isinstance(addr, (str, unicode)):
1022
1023 c_addr = Addr(addr)
1024 if c_addr.addr_type == self.addr_type:
1025 if self.first <= int(c_addr) <= self.last:
1026 return True
1027 elif issubclass(addr.__class__, Addr):
1028
1029 if self.first <= int(addr) <= self.last:
1030 return True
1031 elif issubclass(addr.__class__, AddrRange):
1032
1033 if addr.first >= self.first and addr.last <= self.last:
1034 return True
1035 else:
1036 raise TypeError('%r is an unsupported type or class!' % addr)
1037
1038 return False
1039
1041 """
1042 @param other: an address object of the same address type as C{self}.
1043
1044 @return: C{True} if the boundaries of this range are the same as
1045 other, C{False} otherwise.
1046 """
1047 try:
1048 if (self.addr_type, self.first, self.last) == \
1049 (other.addr_type, other.first, other.last):
1050 return True
1051 except AttributeError:
1052 pass
1053
1054 return False
1055
1057 """
1058 @param other: an address object of the same address type as C{self}.
1059
1060 @return: C{True} if the boundaries of this range are not the same as
1061 other, C{False} otherwise.
1062 """
1063 try:
1064 if (self.addr_type, self.first, self.last) != \
1065 (other.addr_type, other.first, other.last):
1066 return True
1067 except AttributeError:
1068 pass
1069
1070 return False
1071
1073 """
1074 @param other: an address object of the same address type as C{self}.
1075
1076 @return: C{True} if the boundaries of this range are less than other,
1077 C{False} otherwise.
1078 """
1079 try:
1080 if (self.addr_type, self.first, self.last) < \
1081 (other.addr_type, other.first, other.last):
1082 return True
1083 except AttributeError:
1084 pass
1085
1086 return False
1087
1089 """
1090 @param other: an address object of the same address type as C{self}.
1091
1092 @return: C{True} if the boundaries of this range are less or equal to
1093 other, C{False} otherwise.
1094 """
1095 try:
1096 if (self.addr_type, self.first, self.last) <= \
1097 (other.addr_type, other.first, other.last):
1098 return True
1099 except AttributeError:
1100 pass
1101
1102 return False
1103
1105 """
1106 @param other: an address object of the same address type as C{self}.
1107
1108 @return: C{True} if the boundaries of this range are greater than
1109 other, C{False} otherwise.
1110 """
1111 try:
1112 if (self.addr_type, self.first, self.last) > \
1113 (other.addr_type, other.first, other.last):
1114 return True
1115 except AttributeError:
1116 pass
1117
1118 return False
1119
1121 """
1122 @param other: an address object of the same address type as C{self}.
1123
1124 @return: C{True} if the boundaries of this range are greater or equal
1125 to other, C{False} otherwise.
1126 """
1127 try:
1128 if (self.addr_type, self.first, self.last) >= \
1129 (other.addr_type, other.first, other.last):
1130 return True
1131 except AttributeError:
1132 pass
1133
1134 return False
1135
1137 """
1138 Increments start and end addresses of this range by the current size.
1139
1140 If the result exceeds address type range for the address type an
1141 IndexError is raised.
1142 """
1143 try:
1144 new_first = self.first + (self.size() * i)
1145 new_last = self.last + (self.size() * i)
1146 except TypeError:
1147 raise TypeError('Increment value must be an integer!')
1148
1149 if new_last > self.strategy.max_int:
1150 raise IndexError('Invalid increment is outside address boundary!')
1151
1152 self.first = new_first
1153 self.last = new_last
1154
1155 return self
1156
1158 """
1159 Decrements start and end addresses of this range by the current size.
1160
1161 If the result less than zero an IndexError is raised.
1162 """
1163 try:
1164 new_first = self.first - (self.size() * i)
1165 new_last = self.last - (self.size() * i)
1166 except TypeError:
1167 raise TypeError('Decrement value must be an integer!')
1168
1169 if new_last < self.strategy.min_int:
1170 raise IndexError('Invalid decrement is outside address boundary!')
1171
1172 self.first = new_first
1173 self.last = new_last
1174
1175 return self
1176
1180
1182 """
1183 @return: An executable Python statement that can recreate an object
1184 with an equivalent state.
1185 """
1186 return "netaddr.address.%s(%r, %r)" % (self.__class__.__name__,
1187 self.strategy.int_to_str(self.first),
1188 self.strategy.int_to_str(self.last))
1189
1190
1191 -class CIDR(AddrRange):
1192 """
1193 A block of contiguous IPv4 or IPv6 network addresses defined by a base
1194 network address and a bitmask prefix or subnet mask address indicating the
1195 size/extent of the subnet.
1196
1197 By default, this class does not allow any non-zero bits to be set right
1198 of the bitmask when it is applied to the supplied base address. Doing so
1199 raises an L{AddrFormatError} exception. However, it is now configurable
1200 and will allow a less strict base address if you ask for one. Be aware
1201 though that the bitmask will be applied to the base address and and
1202 trailing non-zero bits removed losing the original address. It will *not*
1203 be preserved!
1204
1205 Contrast this behaviour with the L{IP} class which is less strict and has
1206 a cidr() method for returning CIDR objects without any loss of
1207 information.
1208
1209 Examples of supported formats :-
1210
1211 1. CIDR address format - C{<address>/<mask_length>}::
1212
1213 192.168.0.0/16
1214 fe80::/64
1215
1216 2. Address and subnet mask combo ::
1217
1218 192.168.0.0/255.255.0.0 == 192.168.0.0/16
1219 fe80::/ffff:ffff:ffff:ffff:: == fe80::/64
1220
1221 3. Partial or abbreviated formats (IPv4 only). Prefixes may be omitted
1222 and in this case older class-based default prefixes apply ::
1223
1224 10 == 10.0.0.0/8
1225 10.0 == 10.0.0.0/8
1226 10/8 == 10.0.0.0/8
1227
1228 128 == 128.0.0.0/16
1229 128.0 == 128.0.0.0/16
1230 128/16 == 128.0.0.0/16
1231
1232 192 == 10.0.0.0/24
1233 192.168.0 == 192.168.0.0/24
1234 192.168/16 == 192.168.0.0/16
1235 """
1236 STRATEGIES = (ST_IPV4, ST_IPV6)
1237 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
1238
1239
1240 strategy = StrategyDescriptor(STRATEGIES)
1241 addr_type = AddrTypeDescriptor(ADDR_TYPES)
1242 prefixlen = PrefixLenDescriptor('CIDR')
1243 klass = KlassDescriptor(IP)
1244
1246 """
1247 A statis method that converts abbreviated CIDR addresses into their
1248 verbose form.
1249
1250 @param abbrev_cidr: an abbreviated CIDR network address.
1251
1252 Uses the old-style classful IP address rules to decide on a default
1253 subnet prefix if one is not explicitly provided.
1254
1255 Only supports IPv4 addresses.
1256
1257 Examples ::
1258
1259 10 - 10.0.0.0/8
1260 10/16 - 10.0.0.0/16
1261 128 - 128.0.0.0/16
1262 128/8 - 128.0.0.0/8
1263 192.168 - 192.168.0.0/16
1264
1265 @return: A verbose CIDR from an abbreviated CIDR or old-style classful
1266 network address, C{None} if format provided was not recognised or
1267 supported.
1268 """
1269
1270
1271 def classful_prefix(octet):
1272 octet = int(octet)
1273 prefix = 32
1274 if not 0 <= octet <= 255:
1275 raise IndexError('Invalid octet: %r!' % octet)
1276 if 0 <= octet <= 127:
1277
1278 prefix = 8
1279 elif 128 <= octet <= 191:
1280
1281 prefix = 16
1282 elif 192 <= octet <= 223:
1283
1284 prefix = 24
1285 elif octet == 224:
1286
1287 prefix = 4
1288 elif 225 <= octet <= 239:
1289 prefix = 8
1290 return prefix
1291
1292 start = ''
1293 tokens = []
1294 prefix = None
1295
1296
1297 if isinstance(abbrev_cidr, (str, unicode)):
1298
1299
1300 if ':' in abbrev_cidr:
1301 return None
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315 try:
1316
1317 i = int(abbrev_cidr)
1318 tokens = [str(i), '0', '0', '0']
1319 return "%s%s/%s" % (start, '.'.join(tokens), classful_prefix(i))
1320
1321 except ValueError:
1322
1323 part_addr = abbrev_cidr
1324 tokens = []
1325
1326 if part_addr == '':
1327
1328 return None
1329
1330 if '/' in part_addr:
1331 (part_addr, prefix) = part_addr.split('/', 1)
1332
1333
1334 if prefix is not None:
1335 try:
1336 if not 0 <= int(prefix) <= 32:
1337 return None
1338 except ValueError:
1339 return None
1340
1341 if '.' in part_addr:
1342 tokens = part_addr.split('.')
1343 else:
1344 tokens = [part_addr]
1345
1346 if 1 <= len(tokens) <= 4:
1347 for i in range(4 - len(tokens)):
1348 tokens.append('0')
1349 else:
1350
1351 return None
1352
1353 if prefix is None:
1354 try:
1355 prefix = classful_prefix(tokens[0])
1356 except ValueError:
1357 return None
1358
1359 return "%s%s/%s" % (start, '.'.join(tokens), prefix)
1360
1361 except TypeError:
1362 pass
1363 except IndexError:
1364 pass
1365
1366
1367 return None
1368
1369 abbrev_to_verbose = staticmethod(abbrev_to_verbose)
1370
1371 - def __init__(self, cidr, klass=IP, strict_bitmask=True):
1372 """
1373 Constructor.
1374
1375 @param cidr: a valid IPv4/IPv6 CIDR address or abbreviated IPv4
1376 network address.
1377
1378 @param klass: (optional) type, BIF or class used to create each
1379 object returned. Default: L{IP} class. See L{nrange()}
1380 documentations for additional details on options.
1381
1382 @param strict_bitmask: (optional) performs a test to ensure
1383 there are no non-zero bits to the right of the subnet mask or
1384 prefix when it is applied to the base address. (default: True)
1385 """
1386 cidr_arg = cidr
1387
1388
1389 verbose_cidr = CIDR.abbrev_to_verbose(cidr)
1390 if verbose_cidr is not None:
1391 cidr = verbose_cidr
1392
1393 if not isinstance(cidr, (str, unicode)):
1394 raise TypeError('%r is not a valid CIDR!' % cidr)
1395
1396
1397 try:
1398 (network, mask) = cidr.split('/', 1)
1399 except ValueError:
1400 raise AddrFormatError('%r is not a recognised CIDR!' % cidr_arg)
1401
1402 first = IP(network)
1403 self.strategy = first.strategy
1404 self.prefixlen = mask
1405
1406 strategy = first.strategy
1407 addr_type = strategy.addr_type
1408
1409 hostmask = (1 << (strategy.width - self.prefixlen)) - 1
1410 netmask = strategy.max_int ^ hostmask
1411
1412 last = IP(first.value | hostmask, addr_type)
1413
1414 if strict_bitmask:
1415
1416 host = (first.value | netmask) - netmask
1417 if host != 0:
1418 raise ValueError('%s contains non-zero bits right of the ' \
1419 '%d-bit mask! Did you mean %s instead?' \
1420 % (first, self.prefixlen,
1421 strategy.int_to_str(int(last) - hostmask)))
1422 else:
1423
1424 first.value = strategy.int_to_str(int(last) - hostmask)
1425
1426 super(CIDR, self).__init__(first, last, klass)
1427
1429 """
1430 Subtract another CIDR from this one.
1431
1432 @param other: a CIDR object that is greater than or equal to C{self}.
1433
1434 @return: A list of CIDR objects than remain after subtracting C{other}
1435 from C{self}.
1436 """
1437 cidrs = []
1438
1439 if self.prefixlen == self.strategy.width:
1440
1441 return cidrs
1442
1443 new_prefixlen = self.prefixlen + 1
1444 i_lower = self.first
1445 i_upper = self.first + (2 ** (self.strategy.width - new_prefixlen))
1446
1447 lower = CIDR('%s/%d' % (self.strategy.int_to_str(i_lower),
1448 new_prefixlen))
1449 upper = CIDR('%s/%d' % (self.strategy.int_to_str(i_upper),
1450 new_prefixlen))
1451
1452 while other.prefixlen >= new_prefixlen:
1453 if other in lower:
1454 matched = i_lower
1455 unmatched = i_upper
1456 elif other in upper:
1457 matched = i_upper
1458 unmatched = i_lower
1459
1460 cidr = CIDR('%s/%d' % (self.strategy.int_to_str(unmatched),
1461 new_prefixlen))
1462
1463 cidrs.append(cidr)
1464
1465 new_prefixlen += 1
1466
1467 if new_prefixlen > self.strategy.width:
1468 break
1469
1470 i_lower = matched
1471 i_upper = matched + (2 ** (self.strategy.width - new_prefixlen))
1472
1473 lower = CIDR('%s/%d' % (self.strategy.int_to_str(i_lower),
1474 new_prefixlen))
1475 upper = CIDR('%s/%d' % (self.strategy.int_to_str(i_upper),
1476 new_prefixlen))
1477
1478 cidrs.sort()
1479
1480
1481 if self.klass is str:
1482 return [str(cidr) for cidr in cidrs]
1483
1484 return cidrs
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1505
1512
1515
1517 """
1518 @return: An executable Python statement that can recreate an object
1519 with an equivalent state.
1520 """
1521 return "netaddr.address.%s('%s/%d')" % (self.__class__.__name__,
1522 self.strategy.int_to_str(self.first), self.prefixlen)
1523
1525 """
1526 @return: A L{Wildcard} object equivalent to this CIDR.
1527 - If CIDR was initialised with C{klass=str} a wildcard string is
1528 returned, in all other cases a L{Wildcard} object is returned.
1529 - Only supports IPv4 CIDR addresses.
1530 """
1531 t1 = self.strategy.int_to_words(self.first)
1532 t2 = self.strategy.int_to_words(self.last)
1533
1534 if self.addr_type != AT_INET:
1535 raise AddrConversionError('wildcards only suitable for IPv4 ' \
1536 'ranges!')
1537
1538 tokens = []
1539
1540 seen_hyphen = False
1541 seen_asterisk = False
1542
1543 for i in range(4):
1544 if t1[i] == t2[i]:
1545
1546 tokens.append(str(t1[i]))
1547 elif (t1[i] == 0) and (t2[i] == 255):
1548
1549 tokens.append('*')
1550 seen_asterisk = True
1551 else:
1552
1553 if not seen_asterisk:
1554 if not seen_hyphen:
1555 tokens.append('%s-%s' % (t1[i], t2[i]))
1556 seen_hyphen = True
1557 else:
1558 raise SyntaxError('only one hyphenated octet per ' \
1559 'wildcard permitted!')
1560 else:
1561 raise SyntaxError("* chars aren't permitted before ' \
1562 'hyphenated octets!")
1563
1564 wildcard = '.'.join(tokens)
1565
1566 if self.klass == str:
1567 return wildcard
1568
1569 return Wildcard(wildcard)
1570
1571
1573 """
1574 A block of contiguous IPv4 network addresses defined using a wildcard
1575 style syntax.
1576
1577 Individual octets can be represented using the following shortcuts :
1578
1579 1. C{*} - the asterisk octet (represents values 0 through 255)
1580 2. C{'x-y'} - the hyphenated octet (represents values x through y)
1581
1582 A few basic rules also apply :
1583
1584 1. x must always be greater than y, therefore :
1585
1586 - x can only be 0 through 254
1587 - y can only be 1 through 255
1588
1589 2. only one hyphenated octet per wildcard is allowed
1590 3. only asterisks are permitted after a hyphenated octet
1591
1592 Example wildcards ::
1593
1594 '192.168.0.1' # a single address
1595 '192.168.0.0-31' # 32 addresses
1596 '192.168.0.*' # 256 addresses
1597 '192.168.0-1.*' # 512 addresses
1598 '192.168-169.*.*' # 131,072 addresses
1599 '*.*.*.*' # the whole IPv4 address space
1600
1601 Aside
1602 =====
1603 I{Wildcard ranges are not directly equivalent to CIDR ranges as they
1604 can represent address ranges that do not fall on strict bit mask
1605 boundaries.}
1606
1607 I{All CIDR ranges can always be represented as wildcard ranges but the
1608 reverse isn't true in every case.}
1609 """
1610 STRATEGIES = (ST_IPV4, ST_IPV6)
1611 ADDR_TYPES = (AT_UNSPEC, AT_INET, AT_INET6)
1612
1613
1614 strategy = StrategyDescriptor(STRATEGIES)
1615 addr_type = AddrTypeDescriptor(ADDR_TYPES)
1616 klass = KlassDescriptor(IP)
1617
1619 """
1620 A static method that validates wildcard address ranges.
1621
1622 @param wildcard: an IPv4 wildcard address.
1623
1624 @return: True if wildcard address is valid, False otherwise.
1625 """
1626
1627
1628
1629 seen_hyphen = False
1630 seen_asterisk = False
1631 try:
1632 octets = wildcard.split('.')
1633 if len(octets) != 4:
1634 return False
1635 for o in octets:
1636 if '-' in o:
1637 if seen_hyphen:
1638 return False
1639 seen_hyphen = True
1640 if seen_asterisk:
1641
1642 return False
1643 (o1, o2) = [int(i) for i in o.split('-')]
1644 if o1 >= o2:
1645 return False
1646 if not 0 <= o1 <= 254:
1647 return False
1648 if not 1 <= o2 <= 255:
1649 return False
1650 elif o == '*':
1651 seen_asterisk = True
1652 else:
1653 if seen_hyphen is True:
1654 return False
1655 if seen_asterisk is True:
1656 return False
1657 if not 0 <= int(o) <= 255:
1658 return False
1659 except AttributeError:
1660 return False
1661 except ValueError:
1662 return False
1663 return True
1664
1665 is_valid = staticmethod(is_valid)
1666
1668 """
1669 Constructor.
1670
1671 @param wildcard: a valid IPv4 wildcard address
1672
1673 @param klass: (optional) class used to create each return object.
1674 Default: L{IP} objects. See L{nrange()} documentations for
1675 additional details on options.
1676 """
1677 if not Wildcard.is_valid(wildcard):
1678 raise AddrFormatError('%r is not a recognised wildcard address!' \
1679 % wildcard)
1680 t1 = []
1681 t2 = []
1682
1683 for octet in wildcard.split('.'):
1684 if '-' in octet:
1685 oct_tokens = octet.split('-')
1686 t1 += [oct_tokens[0]]
1687 t2 += [oct_tokens[1]]
1688 elif octet == '*':
1689 t1 += ['0']
1690 t2 += ['255']
1691 else:
1692 t1 += [octet]
1693 t2 += [octet]
1694
1695 first = '.'.join(t1)
1696 last = '.'.join(t2)
1697 super(self.__class__, self).__init__(first, last, klass=klass)
1698
1699 if self.addr_type != AT_INET:
1700 raise AddrFormatError('Wildcard syntax only supports IPv4!')
1701
1703 """
1704 @return: A valid L{CIDR} object for this wildcard. If conversion fails
1705 an L{AddrConversionError} is raised as not all wildcards ranges are
1706 valid CIDR ranges.
1707 """
1708 size = self.size()
1709
1710 if size & (size - 1) != 0:
1711 raise AddrConversionError('%s cannot be represented with CIDR' \
1712 % str(self))
1713
1714 (mantissa, exponent) = _math.frexp(size)
1715
1716
1717
1718
1719
1720 if mantissa != 0.5:
1721 raise AddrConversionError('%s cannot be represented with CIDR' \
1722 % str(self))
1723
1724 prefix = 32 - int(exponent - 1)
1725 network = self.strategy.int_to_str(self.first)
1726 try:
1727 cidr = CIDR("%s/%d" % (network, prefix))
1728 except:
1729 raise AddrConversionError('%s cannot be represented with CIDR' \
1730 % str(self))
1731
1732 if self.klass == str:
1733 return str(cidr)
1734
1735 return cidr
1736
1738 t1 = self.strategy.int_to_words(self.first)
1739 t2 = self.strategy.int_to_words(self.last)
1740
1741 tokens = []
1742
1743 seen_hyphen = False
1744 seen_asterisk = False
1745
1746 for i in range(4):
1747 if t1[i] == t2[i]:
1748
1749 tokens.append(str(t1[i]))
1750 elif (t1[i] == 0) and (t2[i] == 255):
1751
1752 tokens.append('*')
1753 seen_asterisk = True
1754 else:
1755
1756 if not seen_asterisk:
1757 if not seen_hyphen:
1758 tokens.append('%s-%s' % (t1[i], t2[i]))
1759 seen_hyphen = True
1760 else:
1761 raise AddrFormatError('only one hyphenated octet ' \
1762 ' per wildcard allowed!')
1763 else:
1764 raise AddrFormatError('asterisks not permitted before ' \
1765 'hyphenated octets!')
1766
1767 return '.'.join(tokens)
1768
1770 """
1771 @return: An executable Python statement that can recreate an object
1772 with an equivalent state.
1773 """
1774 return "netaddr.address.%s(%r)" % (self.__class__.__name__, str(self))
1775
1776
1777 if __name__ == '__main__':
1778 pass
1779