1
2
3
4
5
6
7 """
8 classes and functions representing supported network addresses and associated
9 aggregation options.
10 """
11 from netaddr.strategy import AT_UNSPEC, AT_LINK, AT_INET, AT_INET6, \
12 AT_EUI64, ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64
13
14
15 _TRANSLATE_STR = ''.join([chr(_i) for _i in range(256)])
16
17
19 """
20 A class whose objects represent network addresses of different types based
21 on arguments passed to the constructor.
22
23 The address type can either be auto-detected from the string form of the
24 address or specified explicitly via the second argument.
25
26 The behaviour of this class varies depending on the type of address that
27 it represents.
28 """
30 """
31 Constructor.
32
33 addr - the string form of a network address, or a network byte order
34 int/long value within the supported range for the address type.
35
36 addr_type - (optional) the network address type. If addr is an int or
37 long, this argument becomes mandatory.
38 """
39 if not isinstance(addr, (str, unicode, int, long)):
40 raise Exception("addr must be an address in string form or a " \
41 "positive int/long!")
42
43 if isinstance(addr, (int, long)) and addr_type is None:
44 raise Exception("addr_type must be provided with int/long " \
45 "address values!")
46
47 self.value = None
48 self.strategy = None
49
50 if addr_type is AT_UNSPEC:
51
52 for strategy in (ST_IPV4, ST_IPV6, ST_EUI48, ST_EUI64):
53 if strategy.valid_str(addr):
54 self.strategy = strategy
55 break
56 elif addr_type == AT_INET:
57 self.strategy = ST_IPV4
58 elif addr_type == AT_INET6:
59 self.strategy = ST_IPV6
60 elif addr_type == AT_LINK:
61 self.strategy = ST_EUI48
62 elif addr_type == AT_EUI64:
63 self.strategy = ST_EUI64
64
65 if self.strategy is None:
66
67 raise Exception("Failed to detect address type from %r!" % addr)
68
69 if addr is None:
70 addr = 0
71
72 self.addr_type = self.strategy.addr_type
73 self.setvalue(addr)
74
76 """
77 Sets the value of this address.
78
79 addr - the string form of a network address, or a network byte order
80 int/long value within the supported range for the address type.
81
82 Raises a TypeError if addr is of an unsupported type.
83
84 Raises an OverflowError if addr is an int/long value that is is out of
85 bounds for the address type this instance represents.
86 """
87 if isinstance(addr, (str, unicode)):
88 self.value = self.strategy.str_to_int(addr)
89 elif isinstance(addr, (int, long)):
90 if self.strategy.valid_int(addr):
91 self.value = addr
92 else:
93 raise OverflowError('%r cannot be represented in %r bits!' \
94 % (addr, self.strategy.width))
95 else:
96 raise TypeError('%r is an unsupported type!')
97
99 """
100 Returns the value of this address as an network byte order int, if
101 possible.
102
103 If the value of int is greater than 2 ** 31 - 1, a long is returned
104 instead of an int (standard Python behaviour).
105 """
106 return self.value
107
109 """
110 Returns the value of this address as a network byte order long int.
111
112 If the value of int is less than 2 ** 31 - 1, an int is returned
113 instead of a long (standard Python behaviour).
114 """
115 return self.value
116
118 """
119 Return the string representation for this address. Format varies
120 dependent on address type.
121 """
122 return self.strategy.int_to_str(self.value)
123
125 """
126 Return a human-readable binary digit string representation of this
127 address.
128 """
129 return self.strategy.int_to_bits(self.value)
130
132 """
133 Return the size of this address (in bits).
134 """
135 return self.strategy.width
136
138 """
139 Provide an iterator over words (based on word_size) in this address.
140 """
141 return iter(self.strategy.int_to_words(self.value))
142
144 """
145 Return the integer value of the word indicated by index. Raises an
146 IndexError exception if index is wrong size for address type
147
148 Full slicing support is also available.
149 """
150 if isinstance(index, (int, long)):
151
152 word_count = self.strategy.word_count
153 if not (-word_count) <= index <= (word_count - 1):
154 raise IndexError('index out range for address type!')
155 return self.strategy.int_to_words(self.value)[index]
156 elif isinstance(index, slice):
157
158 words = self.strategy.int_to_words(self.value)
159 return [words[i] for i in range(*index.indices(len(words)))]
160 else:
161 raise TypeError('unsupported type %r!' % index)
162
163
165 """
166 Set the value of the word of this address indicated by index.
167 """
168 if isinstance(index, slice):
169
170 raise NotImplementedError
171
172 if not isinstance(index, (int, long)):
173 raise TypeError('index not an integer!')
174
175 if not 0 <= index <= (self.strategy.word_count - 1):
176 raise IndexError('index %d outside address type boundary!' % index)
177
178 if not isinstance(value, (int, long)):
179 raise TypeError('value not an integer!')
180
181 if not 0 <= value <= (2 ** self.strategy.word_size - 1):
182 raise IndexError('value %d outside word size maximum of %d bits!'
183 % (value, self.strategy.word_size))
184
185 words = list(self.strategy.int_to_words(self.value))
186 words[index] = value
187 self.setvalue(self.strategy.words_to_int(words))
188
190 """
191 Returns the value of this address as a network byte order hexadecimal
192 string.
193 """
194 return hex(self.value).rstrip('L').lower()
195
197 """
198 Increment the value of this network address by the specified value.
199
200 If the result exceeds maximum value for the address type, it rolls
201 around the minimum boundary value.
202 """
203 try:
204 new_value = self.value + increment
205 if new_value > self.strategy.max_int:
206
207 self.value = new_value - (self.strategy.max_int + 1)
208 else:
209 self.value = new_value
210 except TypeError:
211 raise Exception('Increment requires int or long!')
212
213 return self
214
216 """
217 Decrement the value of this network address by specified value.
218
219 If the result is lower than the address type mininum value it rolls
220 around the maximum boundary value.
221 """
222 try:
223 new_value = self.value - decrement
224 if new_value < self.strategy.min_int:
225
226 self.value = new_value + (self.strategy.max_int + 1)
227 else:
228 self.value = new_value
229 except TypeError:
230 raise Exception('Decrement requires int or long!')
231
232 return self
233
235 """
236 True if this network address instance has the same numerical value as
237 another, False otherwise.
238 """
239 if int(self) == int(other):
240 return True
241 return False
242
244 """
245 True if this network address instance has a lower numerical value than
246 another, False otherwise.
247 """
248 if int(self) < int(other):
249 return True
250 return False
251
253 """
254 True if this network address instance has a lower or equivalent
255 numerical value than another, False otherwise.
256 """
257 if int(self) <= int(other):
258 return True
259 return False
260
262 """
263 True if this network address instance has a higher numerical value
264 than another, False otherwise.
265 """
266 if int(self) > int(other):
267 return True
268 return False
269
271 """
272 True if this network address instance has a higher or equivalent
273 numerical value than another, False otherwise.
274 """
275 if int(self) >= int(other):
276 return True
277 return False
278
279
280
282 """
283 A class whose objects represent IEEE Extended Unique Identifiers. Supports
284 EUI-48 (along with common MAC flavours) and EUI-64.
285 """
287 """
288 Constructor.
289
290 addr - the string form of an EUI-48/64 address or a network byte
291 order int/long value.
292
293 addr_type - (optional) the EUI address type (AT_LINK or AT_EUI64). If
294 addr is an int or long, this argument becomes mandatory.
295 """
296 if not isinstance(addr, (str, unicode, int, long)):
297 raise Exception("addr must be an address in string form or a " \
298 "positive int/long!")
299
300 if isinstance(addr, (int, long)) and addr_type is None:
301 raise Exception("addr_type must be provided with int/long " \
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 Exception("Failed to detect EUI type from %r!" % addr)
321
322 if addr is None:
323 addr = 0
324
325 self.addr_type = self.strategy.addr_type
326 self.setvalue(addr)
327
329 """
330 Returns the OUI (Organisationally Unique Identifier for this
331 EUI-48/MAC address.
332 """
333 return '-'.join(["%02x" % i for i in self[0:3]]).upper()
334
336 """
337 Returns the EI (Extension Identifier) for this EUI-48 address.
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 Returns the value of this EUI object as a new EUI address initialised
347 as a 64-bit EUI.
348
349 So if this address represents an EUI-48 address it converts the value
350 of this address to EUI-64 as per the standard.
351
352 If this class is already and EUI-64 address, it just returns a new
353 object that is numerically equivalent to itself.
354 """
355 if self.addr_type == AT_LINK:
356 eui64_words = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
357 ["%02x" % i for i in self[3:6]]
358
359 return self.__class__('-'.join(eui64_words))
360 else:
361 return EUI(str(self))
362
364 """
365 Returns an IP() object class (IPv6 address type) initialised using the
366 value of this EUI.
367 """
368 prefix = 'fe80:0000:0000:0000:'
369
370
371 self[0] += 2
372
373 if self.addr_type == AT_LINK:
374
375 suffix = ["%02x" % i for i in self[0:3]] + ['ff', 'fe'] + \
376 ["%02x" % i for i in self[3:6]]
377 else:
378 suffix = ["%02x" % i for i in list(self)]
379
380 suffix = ["%02x%02x" % (int(x[0], 16), int(x[1], 16)) for x in \
381 zip(suffix[::2], suffix[1::2])]
382
383
384 self[0] -= 2
385
386 eui64 = ':'.join(suffix)
387 addr = prefix + eui64
388 return IP(addr)
389
390
391
393 """
394 A class whose objects represent Internet Protocol network addresses that
395 can be either IPv4 or IPv6.
396 """
398 """
399 Constructor.
400
401 addr - the string form of a IPv4 or IPv6 address, or a network byte
402 order int/long value.
403
404 addr_type - (optional) the IP address type (AT_INET or AT_INET6). If
405 addr is an int or long, this argument becomes mandatory.
406 """
407 if not isinstance(addr, (str, unicode, int, long)):
408 raise Exception("addr must be an address in string form or a " \
409 "positive int/long!")
410
411 if isinstance(addr, (int, long)) and addr_type is None:
412 raise Exception("addr_type must be provided with int/long " \
413 "address values!")
414
415 self.value = None
416 self.strategy = None
417
418 if addr_type is AT_UNSPEC:
419
420 for strategy in (ST_IPV4, ST_IPV6):
421 if strategy.valid_str(addr):
422 self.strategy = strategy
423 break
424 elif addr_type == AT_INET:
425 self.strategy = ST_IPV4
426 elif addr_type == AT_INET6:
427 self.strategy = ST_IPV6
428
429 if self.strategy is None:
430
431 raise Exception("Failed to detect IP version from %r!" % addr)
432
433 if addr is None:
434 addr = 0
435
436 self.addr_type = self.strategy.addr_type
437 self.setvalue(addr)
438
440 """
441 Returns True if this addr is a mask that would return a host id,
442 False otherwise.
443 """
444
445
446 bits = self.strategy.int_to_bits(self.value).replace('.', '')
447
448 if bits[0] != '1':
449
450 return False
451
452
453 bits = bits.lstrip('1')
454
455 seen_zero = False
456 for i in bits:
457 if i == '0' and seen_zero is False:
458 seen_zero = True
459 elif i == '1' and seen_zero is True:
460 return False
461
462 return True
463
465 """
466 Returns the number of bits set to 1 if this address is a netmask, zero
467 otherwise.
468 """
469 if not self.is_netmask():
470 return self.strategy.width
471
472 bits = self.strategy.int_to_bits(self.value)
473 mask_bits = bits.translate(_TRANSLATE_STR, '.0')
474 mask_length = len(mask_bits)
475
476 if not 1 <= mask_length <= self.strategy.width:
477 raise Exception('Unexpected mask length %d for address type!' \
478 % mask_length)
479
480 return mask_length
481
483 """
484 Returns the reverse DNS lookup string for this IP address.
485 """
486 return self.strategy.int_to_arpa(self.value)
487
489 """
490 Returns True if this address is a mask that would return a network id,
491 False otherwise.
492 """
493
494
495 bits = self.strategy.int_to_bits(self.value).replace('.', '')
496
497 if bits[0] != '0':
498
499 return False
500
501
502 bits = bits.lstrip('0')
503
504 seen_one = False
505 for i in bits:
506 if i == '1' and seen_one is False:
507 seen_one = True
508 elif i == '0' and seen_one is True:
509 return False
510
511 return True
512
513
514 -def nrange(start, stop, step=1, klass=None):
515 """
516 A generator producing sequences of addresses based on start and stop
517 values, in intervals of step.
518
519 start - first network address as string or instance of Addr (sub)class.
520
521 stop - last network address as string or instance of Addr (sub)class.
522
523 step - (optional) size of step between addresses in range. Default is 1.
524
525 klass - (optional) a class used to create each object returned.
526 Default: Addr objects.
527
528 a) str returns string representation of network address
529
530 b) int, long and hex return actual values
531
532 c) Addr (sub)class or duck type(*) return objects of that class.
533
534 (*) - if you use your own duck class, make sure you handle 2 arguments
535 passed in (addr_value, addr_type) to avoid frustration.
536 """
537 if not issubclass(start.__class__, Addr):
538 if isinstance(start, (str, unicode)):
539 start = Addr(start)
540 else:
541 raise TypeError('start is not recognised address in string ' \
542 'format or an that is a (sub)class of Addr!')
543 else:
544
545 if klass is None:
546 klass = start.__class__
547
548 if not issubclass(stop.__class__, Addr):
549 if isinstance(stop, (str, unicode)):
550 stop = Addr(stop)
551 else:
552 raise TypeError('stop is not recognised address in string ' \
553 'format or an that is a (sub)class of Addr!')
554
555 if not isinstance(step, (int, long)):
556 raise TypeError('step must be type int|long, not %s!' % type(step))
557
558 if start.addr_type != stop.addr_type:
559 raise TypeError('start and stop are not the same address type!')
560
561 if step == 0:
562 raise ValueError('step argument cannot be zero')
563
564 negative_step = False
565 addr_type = start.addr_type
566
567 if step < 0:
568 negative_step = True
569
570 index = int(start) - step
571
572
573 if klass is None:
574 klass = Addr
575
576 if klass in (int, long, hex):
577
578 while True:
579 index += step
580 if negative_step:
581 if not index >= int(stop):
582 return
583 else:
584 if not index <= int(stop):
585 return
586 yield klass(index)
587
588 elif klass in (str, unicode):
589
590 while True:
591 index += step
592 if negative_step:
593 if not index >= int(stop):
594 return
595 else:
596 if not index <= int(stop):
597 return
598
599 yield str(start.__class__(index, addr_type))
600 else:
601
602 while True:
603 index += step
604 if negative_step:
605 if not index >= int(stop):
606 return
607 else:
608 if not index <= int(stop):
609 return
610
611 yield klass(index, addr_type)
612
613
615 """
616 Represents a block of contiguous network addresses bounded by an arbitrary
617 start and stop address. There is no requirement that they fall on strict
618 bit mask boundaries.
619
620 This is the only network address aggregate class that supports all network
621 address types (essentially Addr (sub)class objects). Most if not all
622 subclasses of AddrRange tend towards support for only a subset of address
623 types.
624 """
625 - def __init__(self, start_addr, stop_addr, klass=None):
626 """
627 Constructor.
628
629 start_addr - start address for this network address range.
630
631 stop_addr - stop address for this network address range.
632
633 klass - (optional) class used to create each return object.
634 Default: Addr objects. See nrange() documentations for
635 additional details on options.
636 """
637
638 if not issubclass(start_addr.__class__, Addr):
639 if isinstance(start_addr, (str, unicode)):
640 self.start_addr = Addr(start_addr)
641 else:
642 raise TypeError('start_addr is not recognised address in ' \
643 'string format or an that is a (sub)class of Addr!')
644 else:
645 self.start_addr = start_addr
646
647
648 if klass is None:
649 klass = start_addr.__class__
650
651
652 if klass is None:
653 self.klass = Addr
654 else:
655 self.klass = klass
656
657
658 if not issubclass(stop_addr.__class__, Addr):
659 if isinstance(stop_addr, (str, unicode)):
660 self.stop_addr = Addr(stop_addr)
661 else:
662 raise TypeError('stop_addr is not recognised address in ' \
663 'string format or an that is a (sub)class of Addr!')
664 else:
665 self.stop_addr = stop_addr
666
667 if self.start_addr.addr_type != self.stop_addr.addr_type:
668 raise TypeError('start_addr and stop_addr are not the same ' \
669 'address type!')
670
671 self.addr_type = self.start_addr.addr_type
672
673 if self.stop_addr < self.start_addr:
674 raise IndexError('stop_addr must be greater than start_addr!')
675
677 """
678 Protected method. Not for public use!
679 """
680
681
682 if self.klass in (str, unicode):
683 return str(addr)
684 elif self.klass in (int, long, hex):
685 return self.klass(int(addr))
686 else:
687 return self.klass(int(addr), self.addr_type)
688
690 """
691 Returns the Addr instance for the lower boundary of this network
692 address range.
693 """
694 return self._retval(self.start_addr)
695
697 """
698 Returns the Addr instance for the upper boundary of this network
699 address range.
700 """
701 return self._retval(self.stop_addr)
702
704 """
705 Return total number of addresses to be found in this address range.
706
707 NB - Use this method only for ranges that contain less than 2 ** 31
708 addresses. Raises an IndexError if size is exceeded.
709 """
710 size = self.size()
711 if size > (2 ** 31):
712
713 raise IndexError("AddrRange contains more than 2^31 addresses! " \
714 "Try using size() method instead.")
715 return size
716
718 """
719 Return total number of addresses to be found in this address range.
720
721 NB - Use this method in preference to __len__() when size of ranges
722 exceeds 2 ** 31 addresses.
723 """
724 return int(self.stop_addr) - int(self.start_addr) + 1
725
727 """
728 Return the Addr instance from this address range indicated by index
729 or slice.
730
731 Raises an IndexError exception if index is out of bounds in relation
732 to size of address range.
733
734 Slicing objects of this class can potentially produce truly massive
735 sequences so generators are returned in preference to sequences. The
736 extra step of wrapping a raw slice with list() or tuple() may be
737 required dependent on context.
738 """
739 if isinstance(index, (int, long)):
740 if (- self.size()) <= index < 0:
741
742 addr_type = self.stop_addr.addr_type
743 index_addr = Addr(int(self.stop_addr), addr_type)
744 index_addr += (index + 1)
745 return self._retval(index_addr)
746 elif 0 <= index <= (self.size() - 1):
747
748 addr_type = self.start_addr.addr_type
749 index_addr = Addr(int(self.start_addr), addr_type)
750 index_addr += index
751 return self._retval(index_addr)
752 else:
753 raise IndexError('index out range for address range size!')
754 elif isinstance(index, slice):
755
756 addr_type = self.start_addr.addr_type
757 int_start_addr = int(self.start_addr)
758
759
760
761
762
763
764
765 (start, stop, step) = index.indices(self.size())
766
767 return nrange(Addr(int_start_addr + start, addr_type),
768 Addr(int_start_addr + stop - step, addr_type),
769 step, klass=self.klass)
770 else:
771 raise TypeError('unsupported type %r!' % index)
772
774 """
775 Returns an iterator object providing lazily evaluated access to all
776 Addr() instances within this network address range.
777 """
778 return nrange(self.start_addr, self.stop_addr, klass=self.klass)
779
781 """
782 Returns True if given address or address range falls within the
783 boundary of this network address False otherwise.
784
785 addr - object of (sub)class Addr/AddrRange or string based address to
786 be compared.
787 """
788 if isinstance(addr, (str, unicode)):
789
790 if self.start_addr <= Addr(addr) <= self.stop_addr:
791 return True
792 elif issubclass(addr.__class__, Addr):
793
794 if self.start_addr <= addr <= self.stop_addr:
795 return True
796 elif issubclass(addr.__class__, AddrRange):
797
798 if (addr.start_addr >= self.start_addr) \
799 and (addr.stop_addr <= self.stop_addr):
800 return True
801 else:
802 raise Exception('%r is an unsupported object/type!' % addr)
803
804 return False
805
807 """
808 True if the boundary addresses of this address range are the same as
809 those of the other and the address types they represent are the same,
810 False otherwise.
811 """
812 if self.start_addr.addr_type != other.start_addr.addr_type:
813 raise TypeError('comparison failure due to type mismatch!')
814
815 if int(self.start_addr) == int(other.start_addr):
816 if int(self.stop_addr) == int(other.stop_addr):
817 return True
818
819 return False
820
822 """
823 True if the boundary addresses of this address range are not the same
824 as those of the other, False otherwise.
825
826 Raises a TypeError if address type of other is not the same as self.
827 """
828 if self.start_addr.addr_type != other.start_addr.addr_type:
829 raise TypeError('comparison failure due to type mismatch!')
830
831 if int(self.start_addr) != int(other.start_addr):
832 return True
833
834 return False
835
837 """
838 True if the lower boundary address of this address range is less than
839 that of the other and the address types they represent are the same,
840 False otherwise.
841 """
842 if self.start_addr.addr_type != other.start_addr.addr_type:
843 raise TypeError('comparison failure due to type mismatch!')
844
845 if int(self.start_addr) < int(other.start_addr):
846 return True
847
848 return False
849
851 """
852 True if the lower boundary address of this address range is less than
853 or equal to that of the other and the address types they represent
854 are the same, False otherwise.
855 """
856 if self.start_addr.addr_type != other.start_addr.addr_type:
857 raise TypeError('comparison failure due to type mismatch!')
858
859 if int(self.start_addr) <= int(other.start_addr):
860 return True
861
862 return False
863
865 """
866 True if the lower boundary address of this address range is greater
867 than that of the other and the address types they represent are the
868 same, False otherwise.
869 """
870 if self.start_addr.addr_type != other.start_addr.addr_type:
871 raise TypeError('comparison failure due to type mismatch!')
872
873 if int(self.start_addr) > int(other.start_addr):
874 return True
875
876 return False
877
879 """
880 True if the lower boundary address of this address range is greater
881 than or equal to that of the other and the address types they
882 represent are the same, False otherwise.
883 """
884 if self.start_addr.addr_type != other.start_addr.addr_type:
885 raise TypeError('comparison failure due to type mismatch!')
886
887 if int(self.start_addr) >= int(other.start_addr):
888 return True
889
890 return False
891
893 return "%s-%s" % (self.start_addr, self.stop_addr)
894
895
896 -class CIDR(AddrRange):
897 """
898 Represents a block of contiguous IPv4/IPv6 network addresses defined by an
899 IP address prefix and either a prefix mask measured in bits or
900 alternatively a traditional subnet mask in IP address format.
901
902 Examples of supported formats :-
903
904 1) CIDR address format - <address>/<mask_length>
905
906 192.168.0.0/16
907
908 2) Address and subnet mask combo :-
909
910 192.168.0.0/255.255.0.0
911 """
913 """
914 Constructor.
915
916 addr_mask - a valid CIDR address (IPv4 and IPv6 types supported).
917
918 klass - (optional) class used to create each return object.
919 Default: IP objects. See nrange() documentations for
920 additional details on options.
921 """
922 tokens = addr_mask.split('/')
923
924 if len(tokens) != 2:
925 raise Exception('%r is not a recognised CIDR format!' \
926 % addr_mask)
927
928 addr = IP(tokens[0])
929
930 try:
931
932 prefixlen = int(tokens[1])
933 except ValueError:
934
935 mask = IP(tokens[1])
936 if not mask.is_netmask():
937 raise Exception('%r does not contain a valid subnet mask!' \
938 % addr_mask)
939 prefixlen = mask.prefixlen()
940 if mask.addr_type != addr.addr_type:
941 raise Exception('Address and netmask types do not match!')
942
943 self._addr = addr
944
945 if not 0 <= prefixlen <= self._addr.strategy.width:
946 raise IndexError('CIDR prefix is out of bounds for %s addresses' \
947 % self._addr.strategy.name)
948
949 self.mask_len = prefixlen
950 width = self._addr.strategy.width
951 self.addr_type = self._addr.strategy.addr_type
952
953 int_hostmask = (1 << (width - self.mask_len)) - 1
954 int_stop = int(self._addr) | int_hostmask
955 int_start = int_stop - int_hostmask
956 int_netmask = self._addr.strategy.max_int ^ int_hostmask
957
958 start_addr = IP(int_start, self.addr_type)
959 stop_addr = IP(int_stop, self.addr_type)
960
961 super(self.__class__, self).__init__(start_addr, stop_addr,
962 klass=klass)
963
964 self.netmask_addr = IP(int_netmask, self.addr_type)
965 self.hostmask_addr = IP(int_hostmask, self.addr_type)
966
968 """
969 Returns the network address used to initialize this CIDR range.
970 """
971 if self.klass in (str, unicode):
972 return str(self._addr)
973 elif self.klass in (int, long, hex):
974 return self.klass(int(self._addr))
975 else:
976 return self.klass(int(self._addr), self.addr_type)
977
979 """
980 Returns the subnet mask address for this CIDR range.
981 """
982 return self._retval(self.netmask_addr)
983
985 """
986 Returns the host mask address for this CIDR range.
987 """
988 return self._retval(self.hostmask_addr)
989
991 """
992 Returns size of mask (in bits) for this CIDR range.
993 """
994 return self.mask_len
995
997 return "%s/%d" % (self.start_addr, self.mask_len)
998
999
1001 """
1002 Represents a block of contiguous IPv4 network addresses defined using a
1003 wildcard/glob style syntax.
1004
1005 Individual octets can be represented using the following shortcuts :-
1006
1007 1) The asterisk '*' octet.
1008
1009 This represents the values 0 through 255.
1010
1011 2) The hyphenated octet 'x-y'
1012
1013 This represents a range of values between x and y.
1014
1015 x must always be greater than y, therefore :-
1016
1017 values of x are 0 through 254
1018 values of y are 1 through 255
1019
1020 NB - only one hyphenated octet per wildcard is allowed.
1021
1022 Example wildcards :-
1023
1024 '192.168.0.1' # a single address
1025 '192.168.0.0-31' # 32 addresses
1026 '192.168.0.*' # 256 addresses
1027 '192.168.0-1.*' # 512 addresses
1028 '192.168-169.*.*' # 131,072 addresses
1029 '*.*.*.*' # the whole IPv4 address space
1030
1031 Aside: Wildcard ranges are not directly equivalent to CIDR ranges as they
1032 can represent address ranges that do not conform to bit mask boundaries.
1033 All CIDR ranges can be represented as wilcard ranges but the reverse isn't
1034 always true.
1035 """
1037 """
1038 Constructor.
1039
1040 wildcard - a valid wildcard address (only IPv4 is supported).
1041
1042 klass - (optional) class used to create each return object.
1043 Default: IP objects. See nrange() documentations for
1044 additional details on options.
1045 """
1046 if not self.is_wildcard(wildcard):
1047 raise Exception('Invalid wildcard address range %r!' \
1048 % wildcard)
1049
1050 l_tokens = []
1051 u_tokens = []
1052
1053 for octet in wildcard.split('.'):
1054 if '-' in octet:
1055 oct_tokens = octet.split('-')
1056 l_tokens += [oct_tokens[0]]
1057 u_tokens += [oct_tokens[1]]
1058 elif octet == '*':
1059 l_tokens += ['0']
1060 u_tokens += ['255']
1061 else:
1062 l_tokens += [octet]
1063 u_tokens += [octet]
1064
1065 start_addr = IP('.'.join(l_tokens))
1066 stop_addr = IP('.'.join(u_tokens))
1067
1068 if start_addr.addr_type != AT_INET:
1069 raise Exception('%s is an invalid IPv4 wildcard!' % start_addr)
1070
1071 super(self.__class__, self).__init__(start_addr, stop_addr,
1072 klass=klass)
1073
1075 """
1076 True if wildcard address is valid, False otherwise.
1077 """
1078 seen_hyphen = False
1079 seen_asterisk = False
1080
1081 try:
1082 octets = wildcard.split('.')
1083 if len(octets) != 4:
1084 return False
1085 for octet in octets:
1086 if '-' in octet:
1087 if seen_hyphen:
1088 return False
1089 seen_hyphen = True
1090
1091 if seen_asterisk:
1092
1093 return False
1094 (oct1, oct2) = map(lambda x: int(x), octet.split('-'))
1095 if oct1 >= oct2:
1096 return False
1097 if not 0 <= oct1 <= 254:
1098 return False
1099 if not 1 <= oct2 <= 255:
1100 return False
1101 elif octet == '*':
1102 seen_asterisk = True
1103 elif octet != '*':
1104 if not 0 <= int(octet) <= 255:
1105 return False
1106 except AttributeError:
1107 return False
1108 except ValueError:
1109 return False
1110 return True
1111
1113 t1 = tuple(self.start_addr)
1114 t2 = tuple(self.stop_addr)
1115
1116 tokens = []
1117
1118 seen_hyphen = False
1119 seen_asterisk = False
1120
1121 for i in range(4):
1122 if t1[i] == t2[i]:
1123
1124 tokens.append(str(t1[i]))
1125 elif (t1[i] == 0) and (t2[i] == 255):
1126
1127 tokens.append('*')
1128 seen_asterisk = True
1129 else:
1130
1131 if not seen_asterisk:
1132 if not seen_hyphen:
1133 tokens.append('%s-%s' % (t1[i], t2[i]))
1134 seen_hyphen = True
1135 else:
1136 raise Exception('only one hyphenated octet ' \
1137 ' per wildcard allowed!')
1138 else:
1139 raise Exception('asterisks not permitted before ' \
1140 'hyphenated octets!')
1141
1142 return '.'.join(tokens)
1143
1144
1145 if __name__ == '__main__':
1146 pass
1147