X-Git-Url: https://blacka.com/cgi-bin/gitweb.cgi?p=python-rwhoisd.git;a=blobdiff_plain;f=rwhoisd%2FCidr.py;h=88d46d3692ffa33d477b50634716b5bdd65d1832;hp=56238ea179d73fcb4f7012bf83df336374b5dc8f;hb=HEAD;hpb=1bb7b018fcc2f99564e8479826dcc109e7e5e5e4 diff --git a/rwhoisd/Cidr.py b/rwhoisd/Cidr.py index 56238ea..88d46d3 100644 --- a/rwhoisd/Cidr.py +++ b/rwhoisd/Cidr.py @@ -18,23 +18,27 @@ # USA import socket, types, copy, bisect, struct +import v6addr -class Cidr: - """A class representing a generic CIDRized network value.""" +def new(address, netlen = -1): + """Construct either a CidrV4 or CidrV6 object.""" - @staticmethod - def create(address, netlen = -1): - """Construct either a CidrV4 or CidrV6 object.""" - if isinstance(address, int): - return CidrV4(address, netlen) - if isinstance(address, long): - if address <= pow(2, 32): - return CidrV4(address, netlen) - return CidrV6(address, netlen) - if ":" in address: - return CidrV6(address, netlen) + # ints are probably v4 addresses. + if isinstance(address, int): return CidrV4(address, netlen) + # longs could be v4 addresses, but we will only assume so if the + # value is small. + if isinstance(address, long): + if address <= pow(2, 32): + return CidrV4(address, netlen) + return CidrV6(address, netlen) + # otherwise, a colon in the address is a dead giveaway. + if ":" in address: + return CidrV6(address, netlen) + return CidrV4(address, netlen) +class Cidr: + """A class representing a generic CIDRized network value.""" def _initialize(self, address, netlen): """This a common constructor that is used by the subclasses.""" @@ -122,7 +126,7 @@ class Cidr: def netmask(self): """return the netmask of this Cidr network""" return self._convert_ipaddr(self.mask) - + def length(self): """return the length (in number of addresses) of this network block""" return 1 << (self._max_netlen() - self.netlen); @@ -137,7 +141,7 @@ class Cidr: def clone(self): # we can get away with a shallow copy (so far) return copy.copy(self) - + def is_ipv6(self): if isinstance(self, CidrV6): return True return False @@ -170,9 +174,9 @@ class CidrV4(Cidr): (e.g., "127.0.0.1/32"), A tuple consisting of an formatting string IPv4 address and a numeric network length, or the same as two arguments.""" - + self._initialize(address, netlen) - + def _is_valid_address(self, address): """Returns True if the address is a legal IPv4 address.""" try: @@ -203,14 +207,14 @@ class CidrV6(Cidr): Specifically, it is representing a contiguous IPv6 network block that can be expressed as a ipv6-address/network-length pair.""" - + base_mask = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL # 128-bits of all ones. msb_mask = 0x80000000000000000000000000000000L lower_mask = 0x0000000000000000FFFFFFFFFFFFFFFFL upper_mask = 0xFFFFFFFFFFFFFFFF0000000000000000L def __init__(self, address, netlen = -1): - + self._initialize(address, netlen) def _is_valid_address(self, address): @@ -231,7 +235,7 @@ class CidrV6(Cidr): packed_numaddr = socket.inet_pton(socket.AF_INET6, addr) upper, lower = struct.unpack("!QQ", packed_numaddr); return (upper << 64) | lower - + def _convert_ipaddr(self, numaddr): upper = (numaddr & CidrV6.upper_mask) >> 64; lower = numaddr & CidrV6.lower_mask; @@ -250,7 +254,7 @@ def valid_cidr(address): if isinstance(address, Cidr): return address try: - c = Cidr.create(address) + c = new(address) return c except (ValueError, socket.error): return False @@ -286,7 +290,7 @@ def netblock_to_cidr(start, end): # if the start and ending addresses aren't in the same family, quit now if cs.is_ipv6() != ce.is_ipv6(): return None - + max_netlen = cs._max_netlen() msb_mask = cs.msb_mask base_mask = cs.base_mask @@ -295,7 +299,7 @@ def netblock_to_cidr(start, end): block_len = ce.numaddr - cs.numaddr # calcuate the largest CIDR block size that fits netlen = largest_prefix(block_len + 1, max_netlen, msb_mask) - + res = []; s = cs.numaddr while block_len > 0: mask = netlen_to_mask(netlen, max_netlen, base_mask) @@ -305,7 +309,7 @@ def netblock_to_cidr(start, end): netlen += 1 continue # otherwise, we have a valid CIDR block, so add it to the list - res.append(Cidr.create(s, netlen)) + res.append(new(s, netlen)) # and setup for the next round: cur_len = netlen_to_length(netlen, max_netlen, base_mask) s += cur_len @@ -316,25 +320,25 @@ def netblock_to_cidr(start, end): # test driver if __name__ == "__main__": import sys - a = Cidr.create("127.00.000.1/24") - b = Cidr.create("127.0.0.1", 32) - c = Cidr.create("24.232.119.192", 26) - d = Cidr.create("24.232.119.0", 24) - e = Cidr.create("24.224.0.0", 11) - f = Cidr.create("216.168.111.0/27"); - g = Cidr.create("127.0.0.2/31"); - h = Cidr.create("127.0.0.16/32") - i = Cidr.create("3ffe:4:201e:beef::0/64"); - j = Cidr.create("2001:3c01::/32") + a = new("127.00.000.1/24") + b = new("127.0.0.1", 32) + c = new("24.232.119.192", 26) + d = new("24.232.119.0", 24) + e = new("24.224.0.0", 11) + f = new("216.168.111.0/27"); + g = new("127.0.0.2/31"); + h = new("127.0.0.16/32") + i = new("3ffe:4:201e:beef::0/64"); + j = new("2001:3c01::/32") print f.addr print j.addr - + try: - bad = Cidr.create("24.261.119.0", 32) + bad = new("24.261.119.0", 32) except ValueError, x: print "error:", x - + print "cidr:", a, "num addresses:", a.length(), "ending address", \ a.end(), "netmask", a.netmask() @@ -348,7 +352,7 @@ if __name__ == "__main__": clist.sort() print "sorted list of cidr object:\n ", clist - k = Cidr.create("2001:3c01::1:0", 120) + k = new("2001:3c01::1:0", 120) print "supernet: ", str(j), " supernet of ", str(k), "? ", \ str(j.is_supernet(k)) print "supernet: ", str(k), " supernet of ", str(j), "? ", \ @@ -367,7 +371,7 @@ if __name__ == "__main__": ("10.131.43.3", "10.131.44.7"), ("3ffe:4:5::", "3ffe:4:5::ffff"), ("3ffe:4:5::", "3ffe:4:6::1")] - + for start, end in netblocks: print "netblock %s - %s:" % (start, end) blocks = netblock_to_cidr(start, end)