Package netaddr :: Module strategy
[frames] | no frames]

Source Code for Module netaddr.strategy

  1  #!/usr/bin/env python 
  2  #----------------------------------------------------------------------------- 
  3  #   Copyright (c) 2008, David P. D. Moss. All rights reserved. 
  4  # 
  5  #   Released under the BSD license. See the LICENSE file for details. 
  6  #----------------------------------------------------------------------------- 
  7  """ 
  8  classes that implement the behaviour of each network address type, constants 
  9  used to identify them and shared strategy instances used by address objects. 
 10  """ 
 11  import socket as _socket 
 12  import struct as _struct 
 13   
 14  #----------------------------------------------------------------------------- 
 15  #  Constants. 
 16  #----------------------------------------------------------------------------- 
 17   
 18  #   True if platform is natively big-endian, False otherwise. 
 19  BIG_ENDIAN_PLATFORM = _struct.pack('=h', 1) == _struct.pack('>h', 1) 
 20   
 21  #   Address type constants, used to identify the precise type of an 
 22  #   AddressStrategy instance. 
 23  AT_UNSPEC = 0x0 
 24  AT_INET   = 0x4 
 25  AT_INET6  = 0x6 
 26  AT_LINK   = 0x30 
 27  AT_EUI64  = 0x40 
 28   
 29  #   Address type description lookup dict. 
 30  AT_DESCR = { 
 31      AT_UNSPEC : 'Unspecified', 
 32      AT_LINK   : 'MAC (Media Access Control)', 
 33      AT_EUI64  : '64-bit IEEE Extended Unique Identifier', 
 34      AT_INET   : 'Internet Protocol (version 4)', 
 35      AT_INET6  : 'Internet Protocol (version 6)', 
 36  } 
 37   
 38  #----------------------------------------------------------------------------- 
39 -def _BYTES_TO_BITS():
40 """ 41 Generates a 256 element list of 8-bit binary digit strings. List index is 42 equivalent to the bit string value. 43 """ 44 lookup = [] 45 bits_per_byte = range(7, -1, -1) 46 for num in range(256): 47 bits = 8*[None] 48 for i in bits_per_byte: 49 bits[i] = '01'[num&1] 50 num >>= 1 51 lookup.append(''.join(bits)) 52 return lookup
53 54 _BYTES_TO_BITS = _BYTES_TO_BITS() 55 56 #-----------------------------------------------------------------------------
57 -class AddrStrategy(object):
58 """ 59 Very basic support for all common operations performed on each network 60 type. 61 62 There are usually subclasses for each address type that over-ride methods 63 implemented here to optimise their performance and add additional 64 features. 65 """
66 - def __init__(self, width, word_size, delimiter, word_fmt='%x', 67 addr_type=AT_UNSPEC, hex_words=True, to_upper=False):
68 69 self.width = width 70 self.min_int = 0 71 self.max_int = 2 ** width - 1 72 73 self.word_size = word_size 74 self.word_count = width / word_size 75 self.min_word = 0 76 self.max_word = 2 ** word_size - 1 77 78 self.delimiter = delimiter 79 self.word_fmt = word_fmt 80 81 self.hex_words = hex_words 82 83 self.word_base = 16 84 if self.hex_words is False: 85 self.word_base = 10 86 87 self.addr_type = addr_type 88 89 self.to_upper = to_upper 90 91 try: 92 self.name = AT_DESCR[addr_type] 93 except KeyError: 94 self.name = AT_DESCR[AT_UNSPEC]
95 96 #------------------------------------------------------------------------- 97 # Binary methods. 98 #------------------------------------------------------------------------- 99
100 - def valid_bits(self, bits):
101 """ 102 Returns True if network address in readable binary form is valid for 103 this address type, False otherwise. 104 """ 105 if not isinstance(bits, (str, unicode)): 106 return False 107 108 bits = bits.replace(self.delimiter, '') 109 110 if len(bits) != self.width: 111 return False 112 113 try: 114 if self.min_int <= int(bits, 2) <= self.max_int: 115 return True 116 except ValueError: 117 return False 118 119 return False
120
121 - def bits_to_int(self, bits):
122 """ 123 Returns a network byte order integer that is equivalent to value 124 represented by network address in readable binary form. 125 """ 126 words = self.bits_to_words(bits) 127 return self.words_to_int(words)
128
129 - def bits_to_str(self, bits):
130 """ 131 Returns a network address in string form that is equivalent to value 132 represented by network address in readable binary form. 133 """ 134 words = self.bits_to_words(bits) 135 return self.words_to_str(words)
136
137 - def bits_to_words(self, bits):
138 """ 139 Returns an integer word sequence that is equivalent to value 140 represented by network address in readable binary form. 141 """ 142 if not self.valid_bits(bits): 143 raise Exception('%r is not a valid readable binary form string' \ 144 ' for address type!' % bits) 145 146 word_bits = bits.split(self.delimiter) 147 148 if len(word_bits) != self.word_count: 149 raise Exception('invalid number of words found in binary form ' \ 150 'string for address type!' % bits) 151 152 return tuple([int(i, 2) for i in word_bits])
153 154 #------------------------------------------------------------------------- 155 # Integer methods. 156 #------------------------------------------------------------------------- 157
158 - def valid_int(self, int_val):
159 """ 160 Returns True if network byte order integer falls within the boundaries 161 of this address type, False otherwise. 162 """ 163 if not isinstance(int_val, (int, long)): 164 return False 165 166 if self.min_int <= int_val <= self.max_int: 167 return True 168 169 return False
170
171 - def int_to_str(self, int_val):
172 """ 173 Returns a network address in string form that is equivalent to value 174 represented by a network byte order integer. 175 """ 176 words = self.int_to_words(int_val) 177 tokens = [self.word_fmt % i for i in words] 178 addr = self.delimiter.join(tokens) 179 180 if self.to_upper is True: 181 return addr.upper() 182 183 return addr
184
185 - def int_to_bits(self, int_val):
186 """ 187 Returns a network address in readable binary form that is equivalent 188 to value represented by a network byte order integer. 189 """ 190 bit_words = [] 191 192 for word in self.int_to_words(int_val): 193 bits = self.word_to_bits(word) 194 bit_words.append(bits) 195 196 return self.delimiter.join(bit_words)
197
198 - def int_to_words(self, int_val):
199 """ 200 Returns an integer word sequence that is equivalent to value 201 represented by a network byte order integer. 202 """ 203 if not self.valid_int(int_val): 204 raise Exception('%r is not a valid int/long value supported ' \ 205 'by this address type!' % int_val) 206 207 words = [] 208 209 for i in range(self.word_count): 210 word = int_val & (2 ** self.word_size - 1) 211 words.append(int(word)) 212 int_val >>= self.word_size 213 214 words.reverse() 215 216 return tuple(words)
217 218 #------------------------------------------------------------------------- 219 # String methods. 220 #------------------------------------------------------------------------- 221
222 - def valid_str(self, addr):
223 """ 224 Returns True if network address in string form is valid for this 225 address type, False otherwise. 226 """ 227 if not isinstance(addr, (str, unicode)): 228 return False 229 230 tokens = addr.split(self.delimiter) 231 232 if len(tokens) != self.word_count: 233 return False 234 235 try: 236 for token in tokens: 237 int_val = int(token, self.word_base) 238 if not self.min_word <= int_val <= self.max_word: 239 return False 240 except TypeError: 241 return False 242 except ValueError: 243 return False 244 245 return True
246
247 - def str_to_int(self, addr):
248 """ 249 Returns a network byte order integer that is equivalent to value 250 represented by network address in string form. 251 """ 252 words = self.str_to_words(addr) 253 return self.words_to_int(words)
254
255 - def str_to_bits(self, addr):
256 """ 257 Returns a network address in readable binary form that is equivalent 258 to value represented by network address in string form. 259 """ 260 words = self.str_to_words(addr) 261 return self.words_to_bits(words)
262
263 - def str_to_words(self, addr):
264 """ 265 Returns an integer word sequence that is equivalent in value to the 266 network address in string form. 267 """ 268 if not self.valid_str(addr): 269 raise Exception('%r is not a recognised string representation' \ 270 ' of this address type!' % addr) 271 272 words = addr.split(self.delimiter) 273 274 return tuple([ int(word, self.word_base) for word in words ])
275 276 #------------------------------------------------------------------------- 277 # Word list methods. 278 #------------------------------------------------------------------------- 279
280 - def valid_words(self, words):
281 """ 282 Returns True if word sequence is valid for this address type, False 283 otherwise. 284 """ 285 if not isinstance(words, (list, tuple)): 286 return False 287 288 if len(words) != self.word_count: 289 return False 290 291 for i in words: 292 if not isinstance(i, (int, long)): 293 return False 294 295 if not self.min_word <= i <= self.max_word: 296 return False 297 298 return True
299
300 - def words_to_int(self, words):
301 """ 302 Returns a network byte order integer that is equivalent to value 303 represented by word sequence. 304 """ 305 if not self.valid_words(words): 306 raise Exception('%r is not a valid word list!' % words) 307 308 # tuples have no reverse() method and reversed() is only in 2.4 309 if isinstance(words, tuple): 310 words = list(words) 311 words.reverse() 312 313 int_val = 0 314 for i, num in enumerate(words): 315 word = num 316 word = word << self.word_size * i 317 int_val = int_val | word 318 319 return int_val
320
321 - def words_to_str(self, words):
322 """ 323 Returns a network address in string form that is equivalent to value 324 represented by word sequence. 325 """ 326 if not self.valid_words(words): 327 raise Exception('%r is not a valid word list!' % words) 328 329 tokens = [self.word_fmt % i for i in words] 330 addr = self.delimiter.join(tokens) 331 332 return addr
333
334 - def words_to_bits(self, words):
335 """ 336 Returns a network address in readable binary form that is equivalent 337 to value represented by word sequence. 338 """ 339 if not self.valid_words(words): 340 raise Exception('%r is not a valid word list!' % words) 341 342 bit_words = [] 343 344 for word in words: 345 bits = self.word_to_bits(word) 346 bit_words.append(bits) 347 348 return self.delimiter.join(bit_words)
349 350 #------------------------------------------------------------------------- 351 # Other methods. 352 #------------------------------------------------------------------------- 353
354 - def word_to_bits(self, int_val):
355 """ 356 Returns an integer word value for this address type in a fixed width 357 readable binary form. 358 """ 359 bits = [] 360 361 while int_val: 362 bits.append(_BYTES_TO_BITS[int_val&255]) 363 int_val >>= 8 364 365 bits.reverse() 366 367 bit_str = ''.join(bits) or '0'*self.word_size 368 369 return ('0'*self.word_size+bit_str)[-self.word_size:]
370
371 - def description(self):
372 """ 373 Returns description string detailing setup of this AddrStrategy 374 instance. Useful for debugging. 375 """ 376 tokens = [] 377 for k in sorted(self.__dict__): 378 v = self.__dict__[k] 379 if isinstance(v, bool): 380 tokens.append("%s: %r" % (k, v)) 381 elif isinstance(v, (int, long)): 382 tokens.append( 383 "%s: %r (%s)" % (k, v, hex(v).rstrip('L').lower())) 384 else: 385 tokens.append("%s: %r" % (k, v)) 386 return "\n".join(tokens)
387 388 #-----------------------------------------------------------------------------
389 -class IPv4Strategy(AddrStrategy):
390 """ 391 An optimised AddrStrategy for IP version 4 address processing. 392 393 It uses the struct module's pack() and unpack() along with the socket 394 module's inet_ntoa() and inet_aton() functions making it almost 2.5 times 395 faster than a standard AddrStrategy configured for processing IPv4. 396 397 However, bear in mind that these modules might not be available everywhere. 398 Runtimes such as Google App Engine gut the socket module. struct is also 399 limited to processing 32-bit integer which is fine here but isn't suitable 400 for 128-bit IPv6 processing. 401 """
402 - def __init__(self):
403 super(self.__class__, self).__init__(width=32, word_size=8, 404 word_fmt='%d', delimiter='.', addr_type=AT_INET, hex_words=False)
405
406 - def str_to_int(self, addr):
407 """ 408 Returns a network byte order integer that is equivalent to value 409 represented by the IPv4 dotted decimal address string. 410 """ 411 if not self.valid_str(addr): 412 raise Exception('%r is not a valid IPv4 dotted decimal' \ 413 ' address string.!' % addr) 414 415 return _struct.unpack('>I', _socket.inet_aton(addr))[0]
416
417 - def int_to_str(self, int_val):
418 """ 419 Returns an IPv4 dotted decimal address string that is equivalent to 420 value represented by a 32 bit integer in network byte order. 421 """ 422 if not self.valid_int(int_val): 423 raise Exception('%r is not a valid 32-bit int or long!' % int_val) 424 425 return _socket.inet_ntoa(_struct.pack('>I', int_val))
426
427 - def int_to_words(self, int_val):
428 """ 429 Returns an integer word (octet) sequence that is equivalent to value 430 represented by network byte order integer. 431 """ 432 if not self.valid_int(int_val): 433 raise Exception('%r is not a valid int/long value supported ' \ 434 'by this address type!' % int_val) 435 436 return _struct.unpack('4B', _struct.pack('>I', int_val))
437
438 - def words_to_int(self, octets):
439 """ 440 Returns a network byte order integer that is equivalent to value 441 represented by word (octet) sequence. 442 """ 443 if not self.valid_words(octets): 444 raise Exception('%r is not a valid octet list for an IPv4 ' \ 445 'address!' % octets) 446 return _struct.unpack('>I', _struct.pack('4B', *octets))[0]
447
448 - def int_to_arpa(self, int_val):
449 """ 450 Returns the reverse DNS lookup for an IPv4 address in network byte 451 order integer form. 452 """ 453 words = ["%d" % i for i in self.int_to_words(int_val)] 454 words.reverse() 455 words.extend(['in-addr', 'arpa']) 456 return '.'.join(words)
457 458 #-----------------------------------------------------------------------------
459 -class IPv6Strategy(AddrStrategy):
460 """ 461 Implements the operations that can be performed on an Internet Protocol 462 version 6 network address. 463 464 Supports all address formats detailed in RFC 4291. 465 466 NB - This class would benefit greatly from access to inet_pton/inet_ntop() 467 function calls in Python's socket module. Sadly, it isn't available so 468 we'll have to put up with the pure-Python implementation here for now. 469 """
470 - def __init__(self):
471 super(self.__class__, self).__init__(addr_type=AT_INET6, 472 width=128, word_size=16, word_fmt='%x', delimiter=':')
473
474 - def valid_str(self, addr):
475 """ 476 Returns True if IPv6 network address string is valid, False otherwise. 477 """ 478 if not isinstance(addr, (str, unicode)): 479 return False 480 481 if '::' in addr: 482 # IPv6 compact mode. 483 try: 484 prefix, suffix = addr.split('::') 485 except ValueError: 486 return False 487 488 l_prefix = [] 489 l_suffix = [] 490 491 if prefix != '': 492 l_prefix = prefix.split(':') 493 494 if suffix != '': 495 l_suffix = suffix.split(':') 496 497 # IPv6 compact IPv4 compatibility mode. 498 if len(l_suffix) and '.' in l_suffix[-1]: 499 ipv4_str = l_suffix[-1] 500 if ST_IPV4.valid_str(ipv4_str): 501 ipv4_int = ST_IPV4.str_to_int(ipv4_str) 502 ipv4_words = ST_IPV4.int_to_words(ipv4_int) 503 l_suffix.pop() 504 l_suffix.append( 505 ''.join(["%x" % i for i in ipv4_words[0:2]])) 506 l_suffix.append( 507 ''.join(["%x" % i for i in ipv4_words[2:]])) 508 509 token_count = len(l_prefix) + len(l_suffix) 510 511 if not 0 <= token_count <= self.word_count - 1: 512 return False 513 514 try: 515 for token in l_prefix + l_suffix: 516 word = int(token, 16) 517 if not self.min_word <= word <= self.max_word: 518 return False 519 except ValueError: 520 return False 521 else: 522 # IPv6 verbose mode. 523 if ':' in addr: 524 tokens = addr.split(':') 525 526 if '.' in addr: 527 ipv6_prefix = tokens[:-1] 528 if ipv6_prefix[:-1] != ['0', '0', '0', '0', '0']: 529 return False 530 if ipv6_prefix[-1].lower() not in ('0', 'ffff'): 531 return False 532 # IPv6 verbose IPv4 compatibility mode. 533 if len(tokens) != (self.word_count - 1): 534 return False 535 ipv4_str = tokens[-1] 536 if ST_IPV4.valid_str(ipv4_str): 537 ipv4_int = ST_IPV4.str_to_int(ipv4_str) 538 ipv4_words = ST_IPV4.int_to_words(ipv4_int) 539 tokens.pop() 540 tokens.append( 541 ''.join(["%x" % i for i in ipv4_words[0:2]])) 542 tokens.append( 543 ''.join(["%x" % i for i in ipv4_words[2:]])) 544 else: 545 # IPv6 verbose mode. 546 if len(tokens) != self.word_count: 547 return False 548 try: 549 for token in tokens: 550 word = int(token, 16) 551 if not self.min_word <= word <= self.max_word: 552 return False 553 except ValueError: 554 return False 555 else: 556 return False 557 558 return True
559
560 - def str_to_int(self, addr):
561 """ 562 Returns the equivalent network byte order integer for a given IP 563 version 6 address. 564 565 e.g. '::1' -> 1 (loopback) 566 """ 567 if not self.valid_str(addr): 568 raise Exception("'%s' is an invalid IPv6 address!" % addr) 569 570 values = [] 571 572 if addr == '::': 573 # Unspecified address. 574 return 0 575 elif '::' in addr: 576 # Abbreviated form IPv6 address. 577 prefix, suffix = addr.split('::') 578 579 if prefix == '': 580 l_prefix = ['0'] 581 else: 582 l_prefix = prefix.split(':') 583 584 if suffix == '': 585 l_suffix = ['0'] 586 else: 587 l_suffix = suffix.split(':') 588 589 # Check for IPv4 compatibility address form. 590 if len(l_suffix) and '.' in l_suffix[-1]: 591 if len(l_suffix) > 2: 592 return False 593 if len(l_suffix) == 2 and l_suffix[0].lower() != 'ffff': 594 return False 595 596 ipv4_str = l_suffix[-1] 597 if ST_IPV4.valid_str(ipv4_str): 598 ipv4_int = ST_IPV4.str_to_int(ipv4_str) 599 ipv4_words = ST_IPV4.int_to_words(ipv4_int) 600 l_suffix.pop() 601 l_suffix.append( 602 ''.join(["%x" % i for i in ipv4_words[0:2]])) 603 l_suffix.append( 604 ''.join(["%x" % i for i in ipv4_words[2:]])) 605 606 gap_size = 8 - ( len(l_prefix) + len(l_suffix) ) 607 608 values = ["%04x" % int(i, 16) for i in l_prefix] \ 609 + ['0000' for i in range(gap_size)] \ 610 + ["%04x" % int(i, 16) for i in l_suffix] 611 else: 612 # Verbose form IPv6 address. 613 if '.' in addr: 614 # IPv4 compatiblility mode. 615 tokens = addr.split(':') 616 ipv4_str = tokens[-1] 617 if ST_IPV4.valid_str(ipv4_str): 618 ipv4_int = ST_IPV4.str_to_int(ipv4_str) 619 ipv4_words = ST_IPV4.int_to_words(ipv4_int) 620 tokens.pop() 621 tokens.append(''.join(["%x" % i for i in ipv4_words[0:2]])) 622 tokens.append(''.join(["%x" % i for i in ipv4_words[2:]])) 623 624 values = ["%04x" % int(i, 16) for i in tokens] 625 else: 626 # non IPv4 compatiblility mode. 627 values = ["%04x" % int(i, 16) for i in addr.split(':')] 628 629 value = int(''.join(values), 16) 630 631 return value
632
633 - def int_to_str(self, int_val, compact=True, word_fmt=None):
634 """ 635 Returns the IP version 6 string form equal to the network byte order 636 integer value provided. The output is configurable :- 637 638 compact - (optional) if True, use '::' to represent the first adjacent 639 group of words with a value of zero. (default: True). 640 """ 641 # Use basic parent class implementation if compact string form is 642 # not required. 643 if not compact: 644 return super(self.__class__, self).int_to_str(int_val) 645 646 the_word_fmt = self.word_fmt 647 if word_fmt is not None: 648 the_word_fmt = word_fmt 649 650 if not self.valid_int(int_val): 651 raise Exception('%r is not a valid int/long value supported ' \ 652 'by this address type!' % int_val) 653 654 tokens = [] 655 for i in range(self.word_count): 656 word = int_val & 0xffff 657 tokens += [the_word_fmt % word] 658 int_val >>= 16 659 660 tokens.reverse() 661 662 # This can probably be optimised. 663 if compact == True: 664 new_tokens = [] 665 compact_start = False 666 compact_end = False 667 for token in tokens: 668 if token == '0': 669 if compact_start == False and compact_end == False: 670 new_tokens += [''] 671 compact_start = True 672 elif compact_start == True and compact_end == False: 673 pass 674 else: 675 new_tokens += ['0'] 676 else: 677 if compact_start == True: 678 compact_end = True 679 new_tokens += [token] 680 681 # Post loop fixups. 682 if len(new_tokens) == 1 and new_tokens[0] == '': 683 new_tokens += ['', ''] 684 elif new_tokens[-1] == '': 685 new_tokens += [''] 686 elif new_tokens[0] == '': 687 new_tokens.insert(0, '') 688 689 tokens = new_tokens 690 691 return ':'.join(tokens)
692
693 - def int_to_arpa(self, int_val):
694 """ 695 Returns the reverse DNS lookup for an IPv6 address in network byte 696 order integer form. 697 """ 698 addr = self.int_to_str(int_val, word_fmt='%04x') 699 tokens = list(addr.replace(':', '')) 700 tokens.reverse() 701 # We won't support ip6.int here - see RFC 3152 for details. 702 tokens = tokens + ['ip6', 'arpa'] 703 return '.'.join(tokens)
704 705 #-----------------------------------------------------------------------------
706 -class EUI48Strategy(AddrStrategy):
707 """ 708 Implements the operations that can be performed on an IEEE 48-bit EUI 709 (Extended Unique Identifer). For all intents and purposes here, a MAC 710 address. 711 712 Supports most common MAC address formats including Cisco's string format. 713 """
714 - def __init__(self):
715 super(self.__class__, self).__init__(addr_type=AT_LINK, width=48, 716 word_size=8, word_fmt='%02x', delimiter='-', to_upper=True)
717
718 - def valid_str(self, addr):
719 """ 720 Returns True if MAC address string is valid, False otherwise. 721 """ 722 if not isinstance(addr, (str, unicode)): 723 return False 724 725 try: 726 if '.' in addr: 727 # Cisco style. 728 words = [int("0x%s" % i, 0) for i in addr.split('.')] 729 if len(words) != 3: 730 return False 731 for i in words: 732 if not (0 <= i <= 0xffff): 733 return False 734 else: 735 if '-' in addr: 736 # Windows style. 737 words = [int("0x%s" % i, 0) for i in addr.split('-')] 738 elif ':' in addr: 739 # UNIX style. 740 words = [int("0x%s" % i, 0) for i in addr.split(':')] 741 if len(words) != 6: 742 return False 743 for i in words: 744 if not (0 <= i <= 0xff): 745 return False 746 except TypeError: 747 return False 748 except ValueError: 749 return False 750 751 return True
752
753 - def str_to_words(self, addr):
754 """ 755 Returns an integer word sequence that is equivalent in value to MAC 756 address in string form. 757 """ 758 if not self.valid_str(addr): 759 raise Exception('%r is not a recognised string representation' \ 760 ' of this address type!' % addr) 761 762 if ':' in addr: 763 # UNIX style. 764 words = addr.split(':') 765 return tuple([ int(word, self.word_base) for word in words ]) 766 elif '-' in addr: 767 # Windows style. 768 words = addr.split('-') 769 return tuple([ int(word, self.word_base) for word in words ]) 770 elif '.' in addr: 771 # Cisco style. 772 words = [] 773 for num in addr.split('.'): 774 octets = [] 775 int_val = int(num, 16) 776 for i in range(2): 777 word = int_val & 0xff 778 octets.append(int(word)) 779 int_val >>= 8 780 octets.reverse() 781 words.extend(octets) 782 return tuple(words)
783
784 - def int_to_str(self, int_val, delimiter=None, word_fmt=None, 785 to_upper=True):
786 """ 787 Returns a MAC address in string form that is equivalent to value 788 represented by a network byte order integer. The output is 789 configurable :- 790 791 delimiter - (optional) the delimiter used between words in address 792 793 word_fmt - (optional) the string format used for each word in address 794 """ 795 the_delimiter = self.delimiter 796 if delimiter is not None: 797 the_delimiter = delimiter 798 799 the_word_fmt = self.word_fmt 800 if word_fmt is not None: 801 the_word_fmt = word_fmt 802 803 the_to_upper = self.to_upper 804 if to_upper is not True: 805 the_to_upper = to_upper 806 807 words = self.int_to_words(int_val) 808 tokens = [the_word_fmt % i for i in words] 809 addr = the_delimiter.join(tokens) 810 811 if the_to_upper is True: 812 return addr.upper() 813 814 return addr
815 816 #----------------------------------------------------------------------------- 817 # Shared strategy instances for supported address types. 818 # NB - underscores hide ugliness in external interface. 819 #----------------------------------------------------------------------------- 820 # Basic shared strategy instances. 821 _MAC_std = AddrStrategy(addr_type=AT_LINK, width=48, word_size=8, 822 word_fmt='%02x', delimiter=':') 823 824 _MAC_cisco_std = AddrStrategy(addr_type=AT_LINK, width=48, word_size=16, 825 word_fmt='%04x', delimiter='.') 826 827 _EUI64_std = AddrStrategy(addr_type=AT_EUI64, width=64, word_size=8, 828 word_fmt='%02x', delimiter='-', to_upper=True) 829 830 _IPv4_std = AddrStrategy(addr_type=AT_INET, width=32, word_size=8, 831 word_fmt='%d', delimiter='.', hex_words=False) 832 833 _IPv6_std = AddrStrategy(addr_type=AT_INET6, width=128, word_size=16, 834 word_fmt='%x', delimiter=':') 835 836 # Optimised shared strategy instances. 837 _EUI48_opt = EUI48Strategy() 838 _IPv4_opt = IPv4Strategy() 839 _IPv6_opt = IPv6Strategy() 840 841 # Names suitable for standard use namespace export. 842 ST_EUI48 = _EUI48_opt 843 ST_EUI64 = _EUI64_std 844 ST_IPV4 = _IPv4_opt 845 ST_IPV6 = _IPv6_opt 846 847 #----------------------------------------------------------------------------- 848 if __name__ == '__main__': 849 pass 850