def _iprange_to_glob(lb, ub): # Internal function to process individual IP globs. t1 = [int(_) for _ in str(lb).split('.')] t2 = [int(_) for _ in str(ub).split('.')] tokens = [] seen_hyphen = False seen_asterisk = False for i in range(4): if t1[i] == t2[i]: # A normal octet. tokens.append(str(t1[i])) elif (t1[i] == 0) and (t2[i] == 255): # An asterisk octet. tokens.append('*') seen_asterisk = True else: # Create a hyphenated octet - only one allowed per IP glob. if not seen_asterisk: if not seen_hyphen: tokens.append('%s-%s' % (t1[i], t2[i])) seen_hyphen = True else: raise AddrConversionError( 'only 1 hyphenated octet per IP glob allowed!') else: raise AddrConversionError( "asterisks are not allowed before hyphenated octets!") return '.'.join(tokens)
def cidr_to_glob(cidr): """ A function that accepts an IP subnet in a glob-style format and returns a list of CIDR subnets that exactly matches the specified glob. :param cidr: an IP object CIDR subnet. :return: a list of one or more IP addresses and subnets. """ ip = IPNetwork(cidr) globs = iprange_to_globs(ip[0], ip[-1]) if len(globs) != 1: # There should only ever be a one to one mapping between a CIDR and # an IP glob range. raise AddrConversionError('bad CIDR to IP glob conversion!') return globs[0]
def iprange_to_globs(start, end): """ A function that accepts an arbitrary start and end IP address or subnet and returns one or more glob-style IP ranges. :param start: the start IP address or subnet. :param end: the end IP address or subnet. :return: a list containing one or more IP globs. """ start = IPAddress(start) end = IPAddress(end) if start.version != 4 and end.version != 4: raise AddrConversionError('IP glob ranges only support IPv4!') def _iprange_to_glob(lb, ub): # Internal function to process individual IP globs. t1 = [int(_) for _ in str(lb).split('.')] t2 = [int(_) for _ in str(ub).split('.')] tokens = [] seen_hyphen = False seen_asterisk = False for i in range(4): if t1[i] == t2[i]: # A normal octet. tokens.append(str(t1[i])) elif (t1[i] == 0) and (t2[i] == 255): # An asterisk octet. tokens.append('*') seen_asterisk = True else: # Create a hyphenated octet - only one allowed per IP glob. if not seen_asterisk: if not seen_hyphen: tokens.append('%s-%s' % (t1[i], t2[i])) seen_hyphen = True else: raise AddrConversionError( 'only 1 hyphenated octet per IP glob allowed!') else: raise AddrConversionError( "asterisks are not allowed before hyphenated octets!") return '.'.join(tokens) globs = [] try: # IP range can be represented by a single glob. ipglob = _iprange_to_glob(start, end) if not valid_glob(ipglob): #TODO: this is a workaround, it is produces non-optimal but valid #TODO: glob conversions. Fix inner function so that is always #TODO: produces a valid glob. raise AddrConversionError('invalid ip glob created') globs.append(ipglob) except AddrConversionError: # Break IP range up into CIDRs before conversion to globs. # #TODO: this is still not completely optimised but is good enough #TODO: for the moment. # for cidr in iprange_to_cidrs(start, end): ipglob = _iprange_to_glob(cidr[0], cidr[-1]) globs.append(ipglob) return globs