+def netlen_to_length(netlen):
+ """Convert a network-length to the length of the block in ip
+ addresses."""
+
+ return 1 << (32 - netlen);
+
+def netblock_to_cidr(start, end):
+ """Convert an arbitrary network block expressed as a start and end
+ address (inclusive) into a series of valid CIDR blocks."""
+
+ def largest_prefix(length):
+ # 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 netlen_to_mask(n):
+ # convert the network length into its netmask
+ return ~((1 << (32 - n)) - 1)
+
+
+ # convert the start and ending addresses of the netblock to Cidr
+ # object, mostly so we can get the numeric versions of their
+ # addresses.
+ cs = valid_cidr(start)
+ ce = valid_cidr(end)
+
+ # if either the start or ending addresses aren't valid ipv4
+ # address, quit now.
+ if not cs or not ce:
+ return None
+
+ # 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)
+
+ res = []; s = cs.numaddr
+ while block_len > 0:
+ mask = netlen_to_mask(netlen)
+ # 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(s, netlen)
+ res.append(Cidr(s, netlen))
+ # and setup for the next round:
+ cur_len = netlen_to_length(netlen)
+ s += cur_len
+ block_len -= cur_len
+ netlen = largest_prefix(block_len + 1)
+ return res
+