import socket, types, copy, bisect, struct
-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):
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);
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
(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:
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):
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;
if isinstance(address, Cidr): return address
try:
- c = Cidr.create(address)
+ c = new(address)
return c
except (ValueError, socket.error):
return False
# 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
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)
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
# 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()
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), "? ", \
("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)
ci.add("127.0.0.1/24", "net-local-1");
ci.add("127.0.0.1/32", "net-local-2");
- ci.add(Cidr.Cidr.create("216.168.224.0", 22), "net-vrsn-1")
- ci.add(Cidr.Cidr.create("216.168.252.1", 32), "net-vrsn-2")
+ ci.add(Cidr.new("216.168.224.0", 22), "net-vrsn-1")
+ ci.add(Cidr.new("216.168.252.1", 32), "net-vrsn-2")
ci.add("24.36.191.0/24", "net-foo-c")
ci.add("24.36.191.32/27", "net-foo-sub-c")
ci.add("24.36/16", "net-foo-b")
ci.add("48.12.6.0 - 48.12.6.95", "net-bar-1")
print "finding exactly 127.0.0.0/24"
- res = ci.find(Cidr.Cidr.create("127.0.0.0/24"))
+ res = ci.find(Cidr.new("127.0.0.0/24"))
print res
print "finding exactly 127.0.0.16/32"
- res = ci.find(Cidr.Cidr.create("127.0.0.16/32"))
+ res = ci.find(Cidr.new("127.0.0.16/32"))
print res
print "finding exactly 3ffe:4:5:6::0/64"
print res
print "finding supernets of 127.0.0.16/32"
- res = ci.find_supernets(Cidr.Cidr.create("127.0.0.16/32"))
+ res = ci.find_supernets(Cidr.new("127.0.0.16/32"))
print res
print "finding supernets of 24.36.191.32/27"
- res = ci.find(Cidr.Cidr.create("24.36.191.32/27"), 1)
+ res = ci.find(Cidr.new("24.36.191.32/27"), 1)
print res
print "finding supernets of 24.36.191.33/27"
- res = ci.find_supernets(Cidr.Cidr.create("24.36.191.33/27"))
+ res = ci.find_supernets(Cidr.new("24.36.191.33/27"))
print res
print "finding supernets of 24.36.191.64/27"
- res = ci.find_supernets(Cidr.Cidr.create("24.36.191.64/27"))
+ res = ci.find_supernets(Cidr.new("24.36.191.64/27"))
print res
print "finding supernets of 3ffe:4:5:6:7::0/80"
print res
print "finding subnets of 127.0/16"
- res = ci.find_subnets(Cidr.Cidr.create("127.0/16"))
+ res = ci.find_subnets(Cidr.new("127.0/16"))
print res
print "finding subnets of 3ffe:4::0/32"