pvl/dns/reverse.py
changeset 740 74352351d6f5
parent 499 51bab9649e77
equal deleted inserted replaced
739:5149c39f3dfc 740:74352351d6f5
     1 import ipaddr
     1 import ipaddress
     2 import math
     2 import math
     3 
     3 
     4 def reverse_ipv4 (ip) :
     4 def reverse_ipv4 (ip) :
     5     """
     5     """
     6         Return in-addr.arpa reverse for given IPv4 prefix.
     6         Return in-addr.arpa reverse for given IPv4 prefix.
    54         nibbles = [nibble for nibblepair in nibbles for nibble in nibblepair]
    54         nibbles = [nibble for nibblepair in nibbles for nibble in nibblepair]
    55 
    55 
    56         # take the suffix
    56         # take the suffix
    57         nibbles = nibbles[-(hostbits / 4):]
    57         nibbles = nibbles[-(hostbits / 4):]
    58         
    58         
    59         # reverse in hex
    59         # reveurse in hex
    60         return '.'.join(reversed(["{0:x}".format(x) for x in nibbles]))
    60         return '.'.join(reversed(["{0:x}".format(x) for x in nibbles]))
    61 
    61 
    62     else :
    62     else :
    63         raise ValueError("unsupported address version: %s" % (prefix, ))
    63         raise ValueError("unsupported address version: %s" % (prefix, ))
    64 
    64 
    78     """
    78     """
    79         Group an iterable of hexadecimal nibbles into hextets.
    79         Group an iterable of hexadecimal nibbles into hextets.
    80     """
    80     """
    81 
    81 
    82     for i in xrange(0, len(parts), 4) :
    82     for i in xrange(0, len(parts), 4) :
    83         yield ''.join(parts[i:i+4])
    83         yield u''.join(parts[i:i+4])
    84     
    84     
    85     # suffix ::
    85     # suffix ::
    86     if len(parts) < 32 :
    86     if len(parts) < 32 :
    87         yield ''
    87         yield u''
    88         yield ''
    88         yield u''
    89 
    89 
    90 def parse_prefix (prefix) :
    90 def parse_prefix (prefix) :
    91     """
    91     """
    92         Return an ipaddr.IPNetwork from given filesystem-compatbile IPv4/IPv6 prefix-ish variant.
    92         Return an ipaddress.IPNetwork from given filesystem-compatbile IPv4/IPv6 prefix-ish variant.
    93 
    93 
    94         Supports partial IPv4 prefixes on octet boundaries.
    94         Supports partial IPv4 prefixes on octet boundaries.
    95         Supports partial IPv6 prefixes on nibble boundaries.
    95         Supports partial IPv6 prefixes on nibble boundaries.
    96         Supports IPv4 prefxies using "-" as the prefix separator in place of "/".
    96         Supports IPv4 prefxies using "-" as the prefix separator in place of "/".
    97 
    97 
    98         >>> parse_prefix('127.0.0.0/8')
    98         >>> print parse_prefix('127.0.0.0/8')
    99         IPv4Network('127.0.0.0/8')
    99         127.0.0.0/8
   100         >>> parse_prefix('192.0.2.128/26')
   100         >>> print parse_prefix('192.0.2.128/26')
   101         IPv4Network('192.0.2.128/26')
   101         192.0.2.128/26
   102         >>> parse_prefix('192.0.2.128-26')
   102         >>> print parse_prefix('192.0.2.128-26')
   103         IPv4Network('192.0.2.128/26')
   103         192.0.2.128/26
   104         >>> parse_prefix('127.')
   104         >>> print parse_prefix('127.')
   105         IPv4Network('127.0.0.0/8')
   105         127.0.0.0/8
   106         >>> parse_prefix('10')
   106         >>> print parse_prefix('10')
   107         IPv4Network('10.0.0.0/8')
   107         10.0.0.0/8
   108         >>> parse_prefix('192.168')
   108         >>> print parse_prefix('192.168')
   109         IPv4Network('192.168.0.0/16')
   109         192.168.0.0/16
   110         >>> parse_prefix('fe80::')
   110         >>> print parse_prefix('fe80::')
   111         IPv6Network('fe80::/16')
   111         fe80::/16
   112         >>> parse_prefix('2001:db8::')
   112         >>> print parse_prefix('2001:db8::')
   113         IPv6Network('2001:db8::/32')
   113         2001:db8::/32
   114         >>> parse_prefix('2001:db8:1:2')
   114         >>> print parse_prefix('2001:db8:1:2')
   115         IPv6Network('2001:db8:1:2::/64')
   115         2001:db8:1:2::/64
   116     """
   116     """
   117 
   117 
       
   118     prefix = unicode(prefix)
       
   119 
   118     if '/' in prefix :
   120     if '/' in prefix :
   119         return ipaddr.IPNetwork(prefix)
   121         return ipaddress.ip_network(prefix)
   120     
   122     
   121     elif '-' in prefix :
   123     elif '-' in prefix :
   122         return ipaddr.IPNetwork(prefix.replace('-', '/'))
   124         return ipaddress.ip_network(prefix.replace('-', '/'))
   123 
   125 
   124     elif '.' in prefix or prefix.isdigit() :
   126     elif '.' in prefix or prefix.isdigit() :
   125         parts = prefix.rstrip('.').split('.')
   127         parts = prefix.rstrip('.').split('.')
   126         prefixlen = len(parts) * 8
   128         prefixlen = len(parts) * 8
   127         
   129         
   128         return ipaddr.IPv4Network('{prefix}/{prefixlen}'.format(
   130         return ipaddress.IPv4Network(u'{prefix}/{prefixlen}'.format(
   129             prefix      = '.'.join(parts + ['0' for i in xrange(4 - len(parts))]),
   131             prefix      = u'.'.join(parts + [u'0' for i in xrange(4 - len(parts))]),
   130             prefixlen   = prefixlen,
   132             prefixlen   = prefixlen,
   131         ))
   133         ))
   132    
   134    
   133     elif ':' in prefix :
   135     elif ':' in prefix :
   134         parts = list(_split_ipv6_parts(prefix))
   136         parts = list(_split_ipv6_parts(prefix))
   135         prefixlen = len(parts) * 4
   137         prefixlen = len(parts) * 4
   136 
   138 
   137         return ipaddr.IPv6Network('{prefix}/{prefixlen}'.format(
   139         return ipaddress.IPv6Network(u'{prefix}/{prefixlen}'.format(
   138             prefix      = ':'.join(_build_ipv6_parts(parts)),
   140             prefix      = u':'.join(_build_ipv6_parts(parts)),
   139             prefixlen   = prefixlen,
   141             prefixlen   = prefixlen,
   140         ))
   142         ))
   141 
   143 
   142     else :
   144     else :
   143         raise ValueError("Unrecognized IP prefix string: %s" % (prefix, ))
   145         raise ValueError("Unrecognized IP prefix string: %s" % (prefix, ))