1
2
3
4
5
6
7 """
8 network addresses and associated aggregates (CIDR, Wilcard, etc).
9 """
10 import math as _math
11 from netaddr import AddrFormatError, AddrConversionError
12 from netaddr.strategy import AT_UNSPEC, AT_LINK, AT_INET, AT_INET6, \
13 AT_EUI64, ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64
14
15
17 """
18 The base class containing common functionality for all subclasses
19 representing various network address types.
20
21 It is a fully functioning class (as opposed to a virtual class) with a
22 heuristic constructor that detects the type of address via the first
23 argument if it is a string and sets itself up accordingly. If the first
24 argument is an integer, then a constant must be provided via the second
25 argument indicating the address type explicitly.
26
27 Objects of this class behave differently dependent upon the type of address
28 they represent.
29 """
31 """
32 Constructor.
33
34 @param addr: the string form of a network address, or a network byte
35 order integer within the supported range for the address type.
36
37 @param addr_type: (optional) the network address type. If addr is an
38 integer, this argument becomes mandatory.
39 """
40 if not isinstance(addr, (str, unicode, int, long)):
41 raise TypeError("addr must be an network address string or a " \
42 "positive integer!")
43
44 if isinstance(addr, (int, long)) and addr_type is None:
45 raise ValueError("addr_type must be provided with int/long " \
46 "address values!")
47
48 self.value = None
49 self.strategy = None
50
51 if addr_type is AT_UNSPEC:
52
53 for strategy in (ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64):
54 if strategy.valid_str(addr):
55 self.strategy = strategy
56 break
57 elif addr_type == AT_INET:
58 self.strategy = ST_IPV4
59 elif addr_type == AT_INET6:
60 self.strategy = ST_IPV6
61 elif addr_type == AT_LINK:
62 self.strategy = ST_EUI48
63 elif addr_type == AT_EUI64:
64 self.strategy = ST_EUI64
65
66 if self.strategy is None:
67
68 raise AddrFormatError("%r is not a recognised address format!" \
69 % addr)
70
71 if addr is None:
72 addr = 0
73
74 self.addr_type = self.strategy.addr_type
75 self.setvalue(addr)
76
77
79 """
80 Sets the value of this address.
81
82 @param addr: the string form of a network address, or a network byte
83 order integer value within the supported range for the address type.
84 - Raises a C{TypeError} if addr is of an unsupported type.
85 - Raises an C{OverflowError} if addr is an integer outside the
86 bounds for this address type.
87 """
88 if isinstance(addr, (str, unicode)):
89 self.value = self.strategy.str_to_int(addr)
90 elif isinstance(addr, (int, long)):
91 if self.strategy.valid_int(addr):
92 self.value = addr
93 else:
94 raise OverflowError('%r cannot be represented in %r bits!' \
95 % (addr, self.strategy.width))
96 else:
97 raise TypeError('%r is an unsupported type!')
98
100 """
101 @return: The value of this address as an network byte order integer.
102 """
103 return self.value
104
106 """
107 @return: The value of this address as an network byte order integer.
108 """
109 return self.value
110
112 """
113 @return: The common string representation for this address type.
114 """
115 return self.strategy.int_to_str(self.value)
116
118 """
119 @return: An executable Python statement that can recreate an object
120 with an equivalent state.
121 """
122 return "netaddr.address.%s(%r)" % (self.__class__.__name__, str(self))
123
125 """
126 @return: A human-readable binary digit string for this address type.
127 """
128 return self.strategy.int_to_bits(self.value)
129
131 """
132 @return: The size of this address (in bits).
133 """
134 return self.strategy.width
135
137 """
138 @return: An iterator over individual words in this address.
139 """
140 return iter(self.strategy.int_to_words(self.value))
141
143 """
144 @return: The integer value of the word indicated by index. Raises an
145 C{IndexError} if index is wrong size for address type. Full
146 slicing is also supported.
147 """
148 if isinstance(index, (int, long)):
149
150 word_count = self.strategy.word_count
151 if not (-word_count) <= index <= (word_count - 1):
152 raise IndexError('index out range for address type!')
153 return self.strategy.int_to_words(self.value)[index]
154 elif isinstance(index, slice):
155
156 words = self.strategy.int_to_words(self.value)
157 return [words[i] for i in range(*index.indices(len(words)))]
158 else:
159 raise TypeError('unsupported type %r!' % index)
160
161
163 """
164 Sets the value of the word of this address indicated by index.
165 """
166 if isinstance(index, slice):
167
168 raise NotImplementedError('settable slices not yet supported!')
169
170 if not isinstance(index, (int, long)):
171 raise TypeError('index not an integer!')
172
173 if not 0 <= index <= (self.strategy.word_count - 1):
174 raise IndexError('index %d outside address type boundary!' % index)
175
176 if not isinstance(value, (int, long)):
177 raise TypeError('value not an integer!')
178
179 if not 0 <= value <= (2 ** self.strategy.word_size - 1):
180 raise IndexError('value %d outside word size maximum of %d bits!'
181 % (value, self.strategy.word_size))
182
183 words = list(self.strategy.int_to_words(self.value))
184 words[index] = value
185 self.setvalue(self.strategy.words_to_int(words))
186
188 """
189 @return: The value of this address as a network byte order hexadecimal
190 number.
191 """
192 return hex(self.value).rstrip('L').lower()
193
195 """
196 Increments network address by specified value.
197
198 If the result exceeds address type maximum, it rolls around the
199 minimum boundary.
200 """
201 try:
202 new_value = self.value + i
203 if new_value > self.strategy.max_int:
204 self.value = new_value - (self.strategy.max_int + 1)
205 else:
206 self.value = new_value
207 except TypeError:
208 raise TypeError('Increment value must be an integer!')
209 return self
210
212 """
213 Decrements network address by specified value.
214
215 If the result exceeds address type minimum, it rolls around the
216 maximum boundary.
217 """
218 try:
219 new_value = self.value - i
220 if new_value < self.strategy.min_int:
221 self.value = new_value + (self.strategy.max_int + 1)
222 else:
223 self.value = new_value
224 except TypeError:
225 raise TypeError('Decrement value must be an integer!')
226 return self
227
229 """
230 @return: C{True} if this network address instance has the same
231 numerical value as another, C{False} otherwise.
232 """
233 if int(self) == int(other):
234 return True
235 return False
236
238 """
239 @return: C{True} if this network address instance has a lower
240 numerical value than another, C{False} otherwise.
241 """
242 if int(self) < int(other):
243 return True
244 return False
245
247 """
248 @return: C{True} if this network address instance has a lower or
249 equivalent numerical value than another, C{False} otherwise.
250 """
251 if int(self) <= int(other):
252 return True
253 return False
254
256 """
257 @return: C{True} if this network address instance has a higher
258 numerical value than another, C{False} otherwise.
259 """
260 if int(self) > int(other):
261 return True
262 return False
263
265 """
266 @return: C{True} if this network address instance has a higher or
267 equivalent numerical value than another, C{False} otherwise.
268 """
269 if int(self) >= int(other):
270 return True
271 return False
272
274 """
275 @return: The integer constant identifying this object's address type.
276 """
277 return self.strategy.addr_type
278
279
281 """
282 EUI objects represent IEEE Extended Unique Identifiers. Input parsing is
283 flexible, supporting EUI-48, EUI-64 and all MAC (Media Access Control)
284 address flavours.
285 """
287 """
288 Constructor.
289
290 @param addr: an EUI/MAC address string or a network byte order
291 integer.
292
293 @param addr_type: (optional) the specific EUI address type (C{AT_LINK}
294 or C{AT_EUI64}). If addr is an integer, this argument is mandatory.
295 """
296 if not isinstance(addr, (str, unicode, int, long)):
297 raise TypeError("addr must be an EUI/MAC network address " \
298 "string or a positive integer!")
299
300 if isinstance(addr, (int, long)) and addr_type is None:
301 raise ValueError("addr_type must be provided with integer " \
302 "address values!")
303
304 self.value = None
305 self.strategy = None
306
307 if addr_type is AT_UNSPEC:
308
309 for strategy in (ST_EUI48, ST_EUI64):
310 if strategy.valid_str(addr):
311 self.strategy = strategy
312 break
313 elif addr_type == AT_LINK:
314 self.strategy = ST_EUI48
315 elif addr_type == AT_EUI64:
316 self.strategy = ST_EUI64
317
318 if self.strategy is None:
319
320 raise AddrFormatError("%r is not a recognised EUI or MAC " \
321 "address format!" % addr)
322
323 if addr is None:
324 addr = 0
325
326 self.addr_type = self.strategy.addr_type
327 self.setvalue(addr)
328
330 """
331 @return: The OUI (Organisationally Unique Identifier) for this EUI.
332 """
333 return '-'.join(["%02x" % i for i in self[0:3]]).upper()
334
336 """
337 @return: The EI (Extension Identifier) for this EUI.
338 """
339 if self.strategy == ST_EUI48:
340 return '-'.join(["%02x" % i for i in self[3:6]]).upper()
341 elif self.strategy == ST_EUI64:
342 return '-'.join(["%02x" % i for i in self[3:8]]).upper()
343
345 """
346 @return: The value of this EUI object as a new 64-bit EUI object.
347 - If this object represents an EUI-48 it is converted to EUI-64 as
348 per the standard.
349 - If this object is already and EUI-64, it just returns a new,
350 numerically equivalent object is returned instead.
351 """
352 if self.addr_type == AT_LINK:
353 eui64_words = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
354 ["%02x" % i for i in self[3:6]]
355
356 return self.__class__('-'.join(eui64_words))
357 else:
358 return EUI(str(self))
359
361 """
362 @return: An IPv6 L{IP} object initialised using the value of this
363 L{EUI}.
364 - B{See RFC 4921 for details}.
365 """
366 prefix = 'fe80:0000:0000:0000:'
367
368
369 self[0] += 2
370
371 if self.addr_type == AT_LINK:
372
373 suffix = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
374 ["%02x" % i for i in self[3:6]]
375 else:
376 suffix = ["%02x" % i for i in list(self)]
377
378 suffix = ["%02x%02x" % (int(x[0], 16), int(x[1], 16)) for x in \
379 zip(suffix[::2], suffix[1::2])]
380
381
382 self[0] -= 2
383
384 eui64 = ':'.join(suffix)
385 addr = prefix + eui64
386 return IP(addr)
387
388
389
391 """
392 A class whose objects represent Internet Protocol network addresses. Both
393 IPv4 and IPv6 are fully supported and include an optional subnet bit mask
394 prefix, for example ::
395
396 192.168.0.1/24
397 fe80::20f:1fff:fe12:e733/64
398
399 This class B{does not make a requirement to omit non-zero bits to the
400 right of the subnet prefix} when it is applied to the address.
401
402 See the L{CIDR()} class if you require B{*strict*} subnet prefix checking.
403 """
405 """
406 Constructor.
407
408 @param addr: an IPv4 or IPv6 address string with an optional subnet
409 prefix or a network byte order integer.
410
411 @param addr_type: (optional) the IP address type (C{AT_INET} or
412 C{AT_INET6}). If L{addr} is an integer, this argument is mandatory.
413 """
414 if not isinstance(addr, (str, unicode, int, long)):
415 raise TypeError("addr must be an network address string or a " \
416 "positive integer!")
417
418 if isinstance(addr, (int, long)) and addr_type is AT_UNSPEC:
419 raise ValueError("addr_type must be provided with int/long " \
420 "address values!")
421
422 self.value = None
423 self.strategy = None
424 self.prefix = None
425
426 if addr_type == AT_UNSPEC:
427 pass
428 elif addr_type == AT_INET:
429 self.strategy = ST_IPV4
430 elif addr_type == AT_INET6:
431 self.strategy = ST_IPV6
432 else:
433 raise ValueError('%r is an unsupported address type!')
434
435 if addr is None:
436 addr = 0
437
438 self.setvalue(addr)
439
440
442 """
443 Sets the value of this address.
444
445 @param addr: the string form of an IP address, or a network byte order
446 int/long value within the supported range for the address type.
447 - Raises a C{TypeError} if addr is of an unsupported type.
448 - Raises an C{OverflowError} if addr is an integer outside the
449 bounds for this address type.
450 """
451 if isinstance(addr, (str, unicode)):
452
453 if '/' in addr:
454 (addr, masklen) = addr.split('/', 1)
455 self.prefix = int(masklen)
456
457
458 for strategy in (ST_IPV4, ST_IPV6):
459 if strategy.valid_str(addr):
460 self.strategy = strategy
461 break
462
463 if self.strategy is None:
464 raise AddrFormatError('%r is not a valid IPv4/IPv6 address!' \
465 % addr)
466
467 self.addr_type = self.strategy.addr_type
468 self.value = self.strategy.str_to_int(addr)
469
470 elif isinstance(addr, (int, long)):
471 if self.strategy.valid_int(addr):
472 self.addr_type = self.strategy.addr_type
473 self.value = addr
474 else:
475 raise OverflowError('%r cannot be represented in %r bits!' \
476 % (addr, self.strategy.width))
477 else:
478 raise TypeError('%r is an unsupported type!')
479
480
481 if self.prefix == None:
482 self.prefix = self.strategy.width
483
485 """
486 @return: C{True} if this addr is a mask that would return a host id,
487 C{False} otherwise.
488 """
489
490
491 bits = self.strategy.int_to_bits(self.value).replace('.', '')
492
493 if bits[0] != '1':
494
495 return False
496
497
498 bits = bits.lstrip('1')
499
500 seen_zero = False
501 for i in bits:
502 if i == '0' and seen_zero is False:
503 seen_zero = True
504 elif i == '1' and seen_zero is True:
505 return False
506
507 return True
508
510 """
511 @return: The number of bits set to one in this address if it is a
512 netmask, zero otherwise.
513 """
514 if not self.is_netmask():
515 return self.strategy.width
516
517 bits = self.strategy.int_to_bits(self.value)
518 translate_str = ''.join([chr(_i) for _i in range(256)])
519 mask_bits = bits.translate(translate_str, '.0')
520 mask_length = len(mask_bits)
521
522 if not 1 <= mask_length <= self.strategy.width:
523 raise ValueError('Unexpected mask length %d for address type!' \
524 % mask_length)
525
526 return mask_length
527
529 """
530 @return: The reverse DNS lookup string for this IP address.
531 """
532 return self.strategy.int_to_arpa(self.value)
533
535 """
536 @return: C{True} if this address is a mask that would return a host
537 id, C{False} otherwise.
538 """
539
540
541 bits = self.strategy.int_to_bits(self.value).replace('.', '')
542
543 if bits[0] != '0':
544
545 return False
546
547
548 bits = bits.lstrip('0')
549
550 seen_one = False
551 for i in bits:
552 if i == '1' and seen_one is False:
553 seen_one = True
554 elif i == '0' and seen_one is True:
555 return False
556
557 return True
558
560 """
561 @return: A valid L{CIDR} object for this IP address.
562 """
563 hostmask = (1 << (self.strategy.width - self.prefix)) - 1
564 start = (self.value | hostmask) - hostmask
565 network = self.strategy.int_to_str(start)
566 return CIDR("%s/%s" % (network, self.prefix))
567
569 """
570 @return: The subnet prefix of this IP address.
571 """
572 return int(self.prefix)
573
575 """
576 @return: The common string representation for this IP address.
577 """
578 return self.strategy.int_to_str(self.value)
579
581 """
582 @return: An executable Python statement that can recreate an object
583 with an equivalent state.
584 """
585 return "netaddr.address.%s('%s/%d')" % (self.__class__.__name__,
586 str(self), self.prefix)
587
588
589 -def nrange(start, stop, step=1, klass=None):
590 """
591 A generator producing sequences of network addresses based on start and
592 stop values, in intervals of step.
593
594 @param start: first network address as string or instance of L{Addr}
595 (sub)class.
596
597 @param stop: last network address as string or instance of L{Addr}
598 (sub)class.
599
600 @param step: (optional) size of step between addresses in range.
601 Default is 1.
602
603 @param klass: (optional) the class used to create objects returned.
604 Default: L{Addr} class.
605
606 - C{str} returns string representation of network address
607 - C{int}, C{long} and C{hex} return expected values
608 - L{Addr} (sub)class or duck type* return objects of that class. If
609 you use your own duck class, make sure you handle both arguments
610 C{(addr_value, addr_type)} passed to the constructor.
611 """
612 if not issubclass(start.__class__, Addr):
613 if isinstance(start, (str, unicode)):
614 start = Addr(start)
615 else:
616 raise TypeError('start is not recognised address in string ' \
617 'format or an that is a (sub)class of Addr!')
618 else:
619
620 if klass is None:
621 klass = start.__class__
622
623 if not issubclass(stop.__class__, Addr):
624 if isinstance(stop, (str, unicode)):
625 stop = Addr(stop)
626 else:
627 raise TypeError('stop is not recognised address in string ' \
628 'format or an that is a (sub)class of Addr!')
629
630 if not isinstance(step, (int, long)):
631 raise TypeError('step must be type int|long, not %s!' % type(step))
632
633 if start.addr_type != stop.addr_type:
634 raise TypeError('start and stop are not the same address type!')
635
636 if step == 0:
637 raise ValueError('step argument cannot be zero')
638
639 negative_step = False
640 addr_type = start.addr_type
641
642 if step < 0:
643 negative_step = True
644
645 index = int(start) - step
646
647
648 if klass is None:
649 klass = Addr
650
651 if klass in (int, long, hex):
652
653 while True:
654 index += step
655 if negative_step:
656 if not index >= int(stop):
657 return
658 else:
659 if not index <= int(stop):
660 return
661 yield klass(index)
662
663 elif klass in (str, unicode):
664
665 while True:
666 index += step
667 if negative_step:
668 if not index >= int(stop):
669 return
670 else:
671 if not index <= int(stop):
672 return
673
674 yield str(start.__class__(index, addr_type))
675 else:
676
677 while True:
678 index += step
679 if negative_step:
680 if not index >= int(stop):
681 return
682 else:
683 if not index <= int(stop):
684 return
685
686 yield klass(index, addr_type)
687
688
690 """
691 A block of contiguous network addresses bounded by an arbitrary start and
692 stop address. There is no requirement that they fall on strict bit mask
693 boundaries, unlike L{CIDR} addresses.
694
695 The only network address aggregate supporting all network address types.
696 Most AddrRange subclasses only support a subset of address types.
697 """
698 - def __init__(self, start_addr, stop_addr, klass=None):
699 """
700 Constructor.
701
702 @param start_addr: start address for this network address range.
703
704 @param stop_addr: stop address for this network address range.
705
706 @param klass: (optional) class used to create each object returned.
707 Default: L{Addr()} objects. See L{nrange()} documentations for
708 additional details on options.
709 """
710
711 if not issubclass(start_addr.__class__, Addr):
712 if isinstance(start_addr, (str, unicode)):
713 self.start_addr = Addr(start_addr)
714 else:
715 raise TypeError('start_addr is not recognised address in ' \
716 'string format or an that is a (sub)class of Addr!')
717 else:
718 self.start_addr = start_addr
719
720
721 if klass is None:
722 klass = start_addr.__class__
723
724
725 if klass is None:
726 self.klass = Addr
727 else:
728 self.klass = klass
729
730
731 if not issubclass(stop_addr.__class__, Addr):
732 if isinstance(stop_addr, (str, unicode)):
733 self.stop_addr = Addr(stop_addr)
734 else:
735 raise TypeError('stop_addr is not recognised address in ' \
736 'string format or an that is a (sub)class of Addr!')
737 else:
738 self.stop_addr = stop_addr
739
740 if self.start_addr.addr_type != self.stop_addr.addr_type:
741 raise TypeError('start_addr and stop_addr are not the same ' \
742 'address type!')
743
744 self.addr_type = self.start_addr.addr_type
745
746 if self.stop_addr < self.start_addr:
747 raise IndexError('stop_addr must be greater than start_addr!')
748
750 """
751 Police assignments to various class attributes to ensure nothing gets
752 broken accidentally.
753 """
754 if name == 'klass':
755 if isinstance(value, type):
756 if value in (str, int, long, unicode):
757 pass
758 elif issubclass(value, Addr):
759 pass
760 else:
761 raise TypeError("unsupported type %r for klass!" % value)
762 elif value is hex:
763
764 pass
765 else:
766 raise ValueError("unsupported value %r for klass!" % value)
767
768 self.__dict__[name] = value
769
771 """
772 Protected method. B{*** Not intended for public use ***}
773 """
774
775
776 if self.klass in (str, unicode):
777 return str(addr)
778 elif self.klass in (int, long, hex):
779 return self.klass(int(addr))
780 else:
781 return self.klass(int(addr), self.addr_type)
782
784 """
785 @return: The lower boundary network address of this range.
786 """
787 return self._retval(self.start_addr)
788
790 """
791 @return: The upper boundary network address of this range.
792 """
793 return self._retval(self.stop_addr)
794
796 """
797 @return: The total number of network addresses in this range.
798 - Use this method only for ranges that contain less than
799 C{2^31} addresses or try the L{size()} method. Raises an
800 C{IndexError} if size is exceeded.
801 """
802 size = self.size()
803 if size > (2 ** 31):
804
805 raise IndexError("range contains more than 2^31 addresses! " \
806 "Use size() method instead.")
807 return size
808
810 """
811 @return: The total number of network addresses in this range.
812 - Use this method in preference to L{__len__()} when size of
813 ranges exceeds C{2^31} addresses.
814 """
815 return int(self.stop_addr) - int(self.start_addr) + 1
816
818 """
819 @return: The network address(es) in this address range indicated by
820 index/slice. Slicing objects can produce large sequences so
821 generator objects are returned instead to the usual sequences.
822 Wrapping a raw slice with C{list()} or C{tuple()} may be required
823 dependent on context.
824 """
825 if isinstance(index, (int, long)):
826 if (- self.size()) <= index < 0:
827
828 addr_type = self.stop_addr.addr_type
829 index_addr = Addr(int(self.stop_addr), addr_type)
830 index_addr += (index + 1)
831 return self._retval(index_addr)
832 elif 0 <= index <= (self.size() - 1):
833
834 addr_type = self.start_addr.addr_type
835 index_addr = Addr(int(self.start_addr), addr_type)
836 index_addr += index
837 return self._retval(index_addr)
838 else:
839 raise IndexError('index out range for address range size!')
840 elif isinstance(index, slice):
841
842 addr_type = self.start_addr.addr_type
843 int_start_addr = int(self.start_addr)
844
845
846
847
848
849
850
851 (start, stop, step) = index.indices(self.size())
852
853 return nrange(Addr(int_start_addr + start, addr_type),
854 Addr(int_start_addr + stop - step, addr_type),
855 step, klass=self.klass)
856 else:
857 raise TypeError('unsupported type %r!' % index)
858
860 """
861 @return: An iterator object providing access to all network addresses
862 within this range.
863 """
864 return nrange(self.start_addr, self.stop_addr, klass=self.klass)
865
867 """
868 @param addr: object of Addr/AddrRange (sub)class or a network address
869 string to be compared.
870
871 @return: C{True} if given address or range falls within this range,
872 C{False} otherwise.
873 """
874 if isinstance(addr, (str, unicode)):
875
876 if self.start_addr <= Addr(addr) <= self.stop_addr:
877 return True
878 elif issubclass(addr.__class__, Addr):
879
880 if self.start_addr <= addr <= self.stop_addr:
881 return True
882 elif issubclass(addr.__class__, AddrRange):
883
884 if (addr.start_addr >= self.start_addr) \
885 and (addr.stop_addr <= self.stop_addr):
886 return True
887 else:
888 raise TypeError('%r is an unsupported class or type!' % addr)
889
890 return False
891
893 """
894 @param other: an address object of the same address type as C{self}.
895
896 @return: C{True} if the boundary of this range is the same as other,
897 C{False} otherwise.
898 """
899 if self.start_addr.addr_type != other.start_addr.addr_type:
900 raise TypeError('comparison failure due to type mismatch!')
901
902 if int(self.start_addr) == int(other.start_addr):
903 if int(self.stop_addr) == int(other.stop_addr):
904 return True
905
906 return False
907
909 """
910 @param other: an address object of the same address type as C{self}.
911
912 @return: C{True} if the boundary of this range is not the same as
913 other, C{False} otherwise.
914 """
915 if self.start_addr.addr_type != other.start_addr.addr_type:
916 raise TypeError('comparison failure due to type mismatch!')
917
918 if int(self.start_addr) != int(other.start_addr):
919 return True
920
921 return False
922
924 """
925 @param other: an address object of the same address type as C{self}.
926
927 @return: C{True} if the lower boundary of this range is less than
928 other, C{False} otherwise.
929 """
930 if self.start_addr.addr_type != other.start_addr.addr_type:
931 raise TypeError('comparison failure due to type mismatch!')
932
933 if int(self.start_addr) < int(other.start_addr):
934 return True
935
936 return False
937
939 """
940 @param other: an address object of the same address type as C{self}.
941
942 @return: C{True} if the lower boundary of this range is less or equal
943 to other, C{False} otherwise.
944 """
945 if self.start_addr.addr_type != other.start_addr.addr_type:
946 raise TypeError('comparison failure due to type mismatch!')
947
948 if int(self.start_addr) <= int(other.start_addr):
949 return True
950
951 return False
952
954 """
955 @param other: an address object of the same address type as C{self}.
956
957 @return: C{True} if the lower boundary of this range is greater than
958 other, C{False} otherwise.
959 """
960 if self.start_addr.addr_type != other.start_addr.addr_type:
961 raise TypeError('comparison failure due to type mismatch!')
962
963 if int(self.start_addr) > int(other.start_addr):
964 return True
965
966 return False
967
969 """
970 @param other: an address object of the same address type as C{self}.
971
972 @return: C{True} if the lower boundary of this range is greater or
973 equal to other, C{False} otherwise.
974 """
975 if self.start_addr.addr_type != other.start_addr.addr_type:
976 raise TypeError('comparison failure due to type mismatch!')
977
978 if int(self.start_addr) >= int(other.start_addr):
979 return True
980
981 return False
982
984 return "%s-%s" % (self.start_addr, self.stop_addr)
985
987 """
988 @return: An executable Python statement that can recreate an object
989 with an equivalent state.
990 """
991 return "netaddr.address.%s(%r, %r)" % (self.__class__.__name__,
992 str(self.start_addr), str(self.stop_addr))
993
994
996 """
997 @param addr: an abbreviated CIDR network address.
998
999 Uses the old-style classful IP address rules to decide on a default subnet
1000 prefix if one is not explicitly provided.
1001
1002 Only supports IPv4 and IPv4 mapped IPv6 addresses.
1003
1004 Examples ::
1005
1006 10 - 10.0.0.0/8
1007 10/16 - 10.0.0.0/16
1008 128 - 128.0.0.0/16
1009 128/8 - 128.0.0.0/8
1010 192.168 - 192.168.0.0/16
1011 ::192.168 - ::192.168.0.0/128
1012 ::ffff:192.168/120 - ::ffff:192.168.0.0/120
1013
1014 @return: A verbose CIDR from an abbreviated CIDR or old-style classful
1015 network address, C{None} if format provided was not recognised or
1016 supported.
1017 """
1018
1019
1020 def classful_prefix(octet):
1021 octet = int(octet)
1022 prefix = 32
1023 if not 0 <= octet <= 255:
1024 raise IndexError('Invalid octet: %r!' % octet)
1025 if 0 <= octet <= 127:
1026
1027 prefix = 8
1028 elif 128 <= octet <= 191:
1029
1030 prefix = 16
1031 elif 192 <= octet <= 223:
1032
1033 prefix = 24
1034 elif 224 <= octet <= 239:
1035
1036 prefix = 8
1037 return prefix
1038
1039 start = ''
1040 tokens = []
1041 prefix = None
1042
1043
1044 if isinstance(addr, (str, unicode)):
1045
1046
1047 if ':' in addr:
1048 return None
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062 try:
1063
1064 i = int(addr)
1065 tokens = [str(i), '0', '0', '0']
1066 return "%s%s/%s" % (start, '.'.join(tokens), classful_prefix(i))
1067
1068 except ValueError:
1069
1070 part_addr = addr
1071 tokens = []
1072
1073 if part_addr == '':
1074
1075 return None
1076
1077 if '/' in part_addr:
1078 (part_addr, prefix) = part_addr.split('/', 1)
1079
1080 if '.' in part_addr:
1081 tokens = part_addr.split('.')
1082 else:
1083 tokens = [part_addr]
1084
1085 if 1 <= len(tokens) <= 4:
1086 for i in range(4 - len(tokens)):
1087 tokens.append('0')
1088 else:
1089
1090 return None
1091
1092 if prefix is None:
1093 prefix = classful_prefix(tokens[0])
1094
1095 return "%s%s/%s" % (start, '.'.join(tokens), prefix)
1096
1097 except TypeError:
1098 pass
1099 except IndexError:
1100 pass
1101
1102
1103 return None
1104
1105
1106 -class CIDR(AddrRange):
1107 """
1108 A block of contiguous IPv4 or IPv6 network addresses defined by a base
1109 network address and a bitmask prefix or subnet mask address indicating the
1110 size/extent of the subnet.
1111
1112 This class B{does not accept any non zero bits to be set right of the
1113 bitmask} (unlike the L{IP} class which is less strict). Doing so raises an
1114 L{AddrFormatError} exception.
1115
1116 Examples of supported formats :-
1117
1118 1. CIDR address format - C{<address>/<mask_length>}::
1119
1120 192.168.0.0/16
1121
1122 2. Address and subnet mask combo ::
1123
1124 192.168.0.0/255.255.0.0 == 192.168.0.0/16
1125
1126 3. Partial or abbreviated formats. Prefixes may be omitted and in this
1127 case old classful default prefixes apply ::
1128
1129 10 == 10.0.0.0/8
1130 10.0 == 10.0.0.0/8
1131 10/8 == 10.0.0.0/8
1132
1133 128 == 128.0.0.0/16
1134 128.0 == 128.0.0.0/16
1135 128/16 == 128.0.0.0/16
1136
1137 192 == 10.0.0.0/24
1138 192.168.0 == 192.168.0.0/24
1139 192.168/16 == 192.168.0.0/16
1140 """
1142 """
1143 Constructor.
1144
1145 @param addr_mask: a valid IPv4/IPv6 CIDR address or abbreviated
1146 IPv4 network address
1147
1148 @param klass: (optional) type, BIF or class used to create each
1149 object returned. Default: L{IP} class. See L{nrange()}
1150 documentations for additional details on options.
1151 """
1152 verbose_addr_mask = abbrev_to_cidr(addr_mask)
1153 if verbose_addr_mask is not None:
1154 addr_mask = verbose_addr_mask
1155
1156 tokens = addr_mask.split('/')
1157
1158 if len(tokens) != 2:
1159 raise AddrFormatError('%r is not a recognised CIDR ' \
1160 'format!' % addr_mask)
1161
1162 addr = IP(tokens[0])
1163
1164 try:
1165
1166 prefixlen = int(tokens[1])
1167 except ValueError:
1168
1169 mask = IP(tokens[1])
1170 if not mask.is_netmask():
1171 raise AddrFormatError('%r does not contain a valid ' \
1172 'subnet mask!' % addr_mask)
1173 prefixlen = mask.prefixlen()
1174 if mask.addr_type != addr.addr_type:
1175 raise AddrFormatError('Address and netmask types do ' \
1176 'not match!')
1177
1178 if not 0 <= prefixlen <= addr.strategy.width:
1179 raise IndexError('CIDR prefix out of bounds for %s addresses!' \
1180 % addr.strategy.name)
1181
1182 self.mask_len = prefixlen
1183 width = addr.strategy.width
1184 self.addr_type = addr.strategy.addr_type
1185
1186 int_hostmask = (1 << (width - self.mask_len)) - 1
1187 int_stop = int(addr) | int_hostmask
1188 int_start = int_stop - int_hostmask
1189 int_netmask = addr.strategy.max_int ^ int_hostmask
1190
1191 start_addr = IP(int_start, self.addr_type)
1192 stop_addr = IP(int_stop, self.addr_type)
1193
1194 super(self.__class__, self).__init__(start_addr, stop_addr,
1195 klass=klass)
1196
1197 self.netmask_addr = IP(int_netmask, self.addr_type)
1198 self.hostmask_addr = IP(int_hostmask, self.addr_type)
1199
1200
1201 host = (int(addr) | int_netmask) - int_netmask
1202 if host != 0:
1203 raise TypeError('non-zero bits to the right of netmask! ' \
1204 'Try %s instead.' % str(self))
1205
1207 """
1208 @return: The subnet mask address of this CIDR range.
1209 """
1210 return self._retval(self.netmask_addr)
1211
1213 """
1214 @return: The host mask address of this CIDR range.
1215 """
1216 return self._retval(self.hostmask_addr)
1217
1219 """
1220 @return: Size of mask (in bits) of this CIDR range.
1221 """
1222 return self.mask_len
1223
1225 return "%s/%s" % (self.start_addr, self.mask_len)
1226
1228 """
1229 @return: An executable Python statement that can recreate an object
1230 with an equivalent state.
1231 """
1232 return "netaddr.address.%s('%s/%d')" % (self.__class__.__name__,
1233 str(self.start_addr), self.mask_len)
1234
1236 """
1237 @return: A L{Wildcard} object equivalent to this CIDR.
1238 - If CIDR was initialised with C{klass=str} a wildcard string is
1239 returned, in all other cases a L{Wildcard} object is returned.
1240 - Only supports IPv4 CIDR addresses.
1241 """
1242 t1 = tuple(self.start_addr)
1243 t2 = tuple(self.stop_addr)
1244
1245 if self.addr_type != AT_INET:
1246 raise AddrConversionError('IPv6 CIDR addresses are invalid!')
1247
1248 tokens = []
1249
1250 seen_hyphen = False
1251 seen_asterisk = False
1252
1253 for i in range(4):
1254 if t1[i] == t2[i]:
1255
1256 tokens.append(str(t1[i]))
1257 elif (t1[i] == 0) and (t2[i] == 255):
1258
1259 tokens.append('*')
1260 seen_asterisk = True
1261 else:
1262
1263 if not seen_asterisk:
1264 if not seen_hyphen:
1265 tokens.append('%s-%s' % (t1[i], t2[i]))
1266 seen_hyphen = True
1267 else:
1268 raise SyntaxError('only one hyphenated octet per ' \
1269 'wildcard permitted!')
1270 else:
1271 raise SyntaxError("* chars aren't permitted before ' \
1272 'hyphenated octets!")
1273
1274 wildcard = '.'.join(tokens)
1275
1276 if self.klass == str:
1277 return wildcard
1278
1279 return Wildcard(wildcard)
1280
1281
1283 """
1284 A block of contiguous IPv4 network addresses defined using a wildcard
1285 style syntax.
1286
1287 Individual octets can be represented using the following shortcuts :
1288
1289 1. C{*} - the asterisk octet (represents values 0 through 255)
1290 2. C{'x-y'} - the hyphenated octet (represents values x through y)
1291
1292 A few basic rules also apply :
1293
1294 1. x must always be greater than y, therefore :
1295
1296 - x can only be 0 through 254
1297 - y can only be 1 through 255
1298
1299 2. only one hyphenated octet per wildcard is allowed
1300 3. only asterisks are permitted after a hyphenated octet
1301
1302 Example wildcards ::
1303
1304 '192.168.0.1' # a single address
1305 '192.168.0.0-31' # 32 addresses
1306 '192.168.0.*' # 256 addresses
1307 '192.168.0-1.*' # 512 addresses
1308 '192.168-169.*.*' # 131,072 addresses
1309 '*.*.*.*' # the whole IPv4 address space
1310
1311 Aside
1312 =====
1313 I{Wildcard ranges are not directly equivalent to CIDR ranges as they
1314 can represent address ranges that do not fall on strict bit mask
1315 boundaries.}
1316
1317 I{All CIDR ranges can be represented as wildcard ranges but the reverse
1318 isn't always true.}
1319 """
1321 """
1322 Constructor.
1323
1324 @param wildcard: a valid IPv4 wildcard address
1325
1326 @param klass: (optional) class used to create each return object.
1327 Default: L{IP} objects. See L{nrange()} documentations for
1328 additional details on options.
1329 """
1330
1331
1332
1333
1334 def _is_wildcard(wildcard):
1335 """
1336 True if wildcard address is valid, False otherwise.
1337 """
1338 seen_hyphen = False
1339 seen_asterisk = False
1340
1341 try:
1342 octets = wildcard.split('.')
1343 if len(octets) != 4:
1344 return False
1345 for o in octets:
1346 if '-' in o:
1347 if seen_hyphen:
1348 return False
1349 seen_hyphen = True
1350 if seen_asterisk:
1351
1352 return False
1353 (o1, o2) = [int(i) for i in o.split('-')]
1354 if o1 >= o2:
1355 return False
1356 if not 0 <= o1 <= 254:
1357 return False
1358 if not 1 <= o2 <= 255:
1359 return False
1360 elif o == '*':
1361 seen_asterisk = True
1362 else:
1363 if seen_hyphen is True:
1364 return False
1365 if seen_asterisk is True:
1366 return False
1367 if not 0 <= int(o) <= 255:
1368 return False
1369 except AttributeError:
1370 return False
1371 except ValueError:
1372 return False
1373
1374 return True
1375
1376
1377 if not _is_wildcard(wildcard):
1378 raise AddrFormatError('%r is not a recognised wildcard address!' \
1379 % wildcard)
1380
1381 t1 = []
1382 t2 = []
1383
1384 for octet in wildcard.split('.'):
1385 if '-' in octet:
1386 oct_tokens = octet.split('-')
1387 t1 += [oct_tokens[0]]
1388 t2 += [oct_tokens[1]]
1389 elif octet == '*':
1390 t1 += ['0']
1391 t2 += ['255']
1392 else:
1393 t1 += [octet]
1394 t2 += [octet]
1395
1396 start_addr = IP('.'.join(t1))
1397 stop_addr = IP('.'.join(t2))
1398
1399 if start_addr.addr_type != AT_INET:
1400 raise AddrFormatError('%s is an invalid IPv4 wildcard!' \
1401 % start_addr)
1402
1403 super(self.__class__, self).__init__(start_addr, stop_addr,
1404 klass=klass)
1405
1407 """
1408 @return: A valid L{CIDR} object for this wildcard. If conversion fails
1409 an L{AddrConversionError} is raised as not all wildcards ranges are
1410 valid CIDR ranges.
1411 """
1412 size = self.size()
1413
1414 if size & (size - 1) != 0:
1415 raise AddrConversionError('%s cannot be represented with CIDR' \
1416 % str(self))
1417
1418 (mantissa, exponent) = _math.frexp(size)
1419
1420
1421
1422
1423
1424 if mantissa != 0.5:
1425 raise AddrConversionError('%s cannot be represented with CIDR' \
1426 % str(self))
1427
1428 prefix = 32 - int(exponent - 1)
1429 network = str(self.start_addr)
1430 try:
1431 cidr = CIDR("%s/%d" % (network, prefix))
1432 except:
1433 raise AddrConversionError('%s cannot be represented with CIDR' \
1434 % str(self))
1435
1436 if self.klass == str:
1437 return str(cidr)
1438
1439 return cidr
1440
1442 t1 = tuple(self.start_addr)
1443 t2 = tuple(self.stop_addr)
1444
1445 tokens = []
1446
1447 seen_hyphen = False
1448 seen_asterisk = False
1449
1450 for i in range(4):
1451 if t1[i] == t2[i]:
1452
1453 tokens.append(str(t1[i]))
1454 elif (t1[i] == 0) and (t2[i] == 255):
1455
1456 tokens.append('*')
1457 seen_asterisk = True
1458 else:
1459
1460 if not seen_asterisk:
1461 if not seen_hyphen:
1462 tokens.append('%s-%s' % (t1[i], t2[i]))
1463 seen_hyphen = True
1464 else:
1465
1466 raise AddrFormatError('only one hyphenated octet ' \
1467 ' per wildcard allowed!')
1468 else:
1469
1470 raise AddrFormatError('asterisks not permitted before ' \
1471 'hyphenated octets!')
1472
1473 return '.'.join(tokens)
1474
1476 """
1477 @return: An executable Python statement that can recreate an object
1478 with an equivalent state.
1479 """
1480 return "netaddr.address.%s(%r)" % (self.__class__.__name__, str(self))
1481
1482 if __name__ == '__main__':
1483 pass
1484