Specifically, it is representing a contiguous IPv4 network block
that can be expressed as a ip-address/network-length pair."""
+ base_mask = 0xFFFFFFFF
+ msb_mask = 0x80000000
+
def __init__(self, address, netlen = -1):
"""This takes either a formatted string in CIDR notation:
(e.g., "127.0.0.1/32"), A tuple consisting of an formatting
return False
def _base_mask(self, numaddr):
- return numaddr & 0xFFFFFFFFL
+ return numaddr & CidrV4.base_mask
def _max_netlen(self):
return 32
return socket.inet_ntoa(packed_numaddr)
def _mask(self, len):
- return self._base_mask(0xFFFFFFFF << (32 - len))
-
+ return self._base_mask(CidrV4.base_mask << (32 - len))
class CidrV6(Cidr):
"""A class representing a CIDRized IPv6 network value.
Specifically, it is representing a contiguous IPv6 network block
that can be expressed as a ipv6-address/network-length pair."""
- ip6_base_mask = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL # 128-bits of all ones.
- ip6_lower_mask = 0x0000000000000000FFFFFFFFFFFFFFFFL
- ip6_upper_mask = 0xFFFFFFFFFFFFFFFF0000000000000000L
+ base_mask = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL # 128-bits of all ones.
+ msb_mask = 0x80000000000000000000000000000000L
+ lower_mask = 0x0000000000000000FFFFFFFFFFFFFFFFL
+ upper_mask = 0xFFFFFFFFFFFFFFFF0000000000000000L
def __init__(self, address, netlen = -1):
return False
def _base_mask(self, numaddr):
- return numaddr & CidrV6.ip6_base_mask
+ return numaddr & CidrV6.base_mask
def _max_netlen(self):
return 128
return (upper << 64) | lower
def _convert_ipaddr(self, numaddr):
- upper = (numaddr & CidrV6.ip6_upper_mask) >> 64;
- lower = numaddr & CidrV6.ip6_lower_mask;
+ upper = (numaddr & CidrV6.upper_mask) >> 64;
+ lower = numaddr & CidrV6.lower_mask;
packed_numaddr = struct.pack("!QQ", upper, lower)
return socket.inet_ntop(socket.AF_INET6, packed_numaddr)
def _mask(self, len):
- return self._base_mask(CidrV6.ip6_base_mask << (128 - len))
+ return self._base_mask(CidrV6.base_mask << (128 - len))
def valid_cidr(address):
"""Convert an arbitrary network block expressed as a start and end
address (inclusive) into a series of valid CIDR blocks."""
- def largest_prefix_v4(length):
+ def largest_prefix(length, max_netlen, msb_mask):
# calculates the largest network length (smallest mask length)
# that can fit within the block length.
i = 1; v = length
- while i <= 32:
- if v & 0x80000000: break
- i += 1; v <<= 1
- return i
- def largest_prefix_v6(length):
- i = 1; v = length
- while i <= 128:
- if v & 0x80000000000000000000000000000000L: break
+ while i <= max_netlen:
+ if v & msb_mask: break
i += 1; v <<= 1
return i
- def netlen_to_mask_v4(n):
+ def netlen_to_mask(n, max_netlen, base_mask):
# convert the network length into its netmask
- return ~((1 << (32 - n)) - 1)
- def netlen_to_mask_v6(n):
- return ~((1 << (128 -n)) - 1)
+ return ~((1 << (max_netlen - n)) - 1) & base_mask
+ def netlen_to_length(n, max_netlen, base_mask):
+ return 1 << (max_netlen - n) & base_mask
# convert the start and ending addresses of the netblock to Cidr
# object, mostly so we can get the numeric versions of their
# if either the start or ending addresses aren't valid addresses,
# quit now.
if not cs or not ce:
- print "Invalid start or end address"
return None
# if the start and ending addresses aren't in the same family, quit now
if cs.is_ipv6() != ce.is_ipv6():
- print "start and end address not same family"
return None
- if cs.is_ipv6():
- largest_prefix = largest_prefix_v6
- netlen_to_mask = netlen_to_mask_v6
- else:
- largest_prefix = largest_prefix_v4
- netlen_to_mask = netlen_to_mask_v4
+ max_netlen = cs._max_netlen()
+ msb_mask = cs.msb_mask
+ base_mask = cs.base_mask
# calculate the number of IP address in the netblock
block_len = ce.numaddr - cs.numaddr
-
# calcuate the largest CIDR block size that fits
- netlen = largest_prefix(block_len + 1)
+ netlen = largest_prefix(block_len + 1, max_netlen, msb_mask)
res = []; s = cs.numaddr
while block_len > 0:
- mask = netlen_to_mask(netlen)
+ mask = netlen_to_mask(netlen, max_netlen, base_mask)
# check to see if our current network length is valid
if (s & mask) != s:
# if not, shrink the network block size
netlen += 1
continue
# otherwise, we have a valid CIDR block, so add it to the list
- cv = Cidr.create(s, netlen)
res.append(Cidr.create(s, netlen))
# and setup for the next round:
- cur_len = netlen_to_length(netlen)
+ cur_len = netlen_to_length(netlen, max_netlen, base_mask)
s += cur_len
block_len -= cur_len
- netlen = largest_prefix(block_len + 1)
+ netlen = largest_prefix(block_len + 1, max_netlen, msb_mask)
return res
# test driver
clist.sort()
print "sorted list of cidr object:\n ", clist
+ k = Cidr.create("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), "? ", \
+ str(k.is_supernet(j))
+ print "subnet: ", str(j), " subnet of ", str(k), "? ", \
+ str(j.is_subnet(k))
+ print "subnet: ", str(k), " subnet of ", str(j), "? ", \
+ str(k.is_subnet(j))
netblocks = [ ("192.168.10.0", "192.168.10.255"),
("192.168.10.0", "192.168.10.63"),
("24.33.41.22", "24.33.41.37"),
("196.11.1.0", "196.11.30.255"),
("192.247.1.0", "192.247.10.255"),
- ("3ffe:4:5::", "3ffe:4:5::ffff") ]
+ ("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)