#!/usr/bin/python2 # # nbinter is something to take a list of netblocks (or IP address # ranges) and report which ones are equal to, intersect, or are subsets # of others. # # usage: nbinter [arg arg [...]] # arg is an IP address, or 'IP-IP' for a range, or 'IP/LEN' for a CIDR # netblock. Frogs will eat your undershorts if the CIDR netblock is not # actually proper. # import sys sys.path.insert(1, "/u/cks/share/python") import string # look ma, netblock caculations: import netblock def die(str): sys.stderr.write(sys.argv[0] + ': ' + str + '\n') sys.exit(1) def warn(str): sys.stderr.write(sys.argv[0] + ': ' + str + '\n') # Adjacency is interesting to us only if it causes CIDR merging in the # output. def checkadjacent(r1, r2, a1, a2): if not r1.adjacent(r2): return r = r1 + r2 cs = r.tocidr() if len(cs) == 1: print "%s is adjacent to %s: merges to %s" % \ (a1, a2, cs[0]) def process(args): def apair(i,j): return (args[i], args[j]) once = 0 if args[0] == "-1": args.pop(0) once = 1 # Turn everything into IPRanges. ranges = [] for a in args: try: nb = netblock.IPRanges(a) except netblock.BadCIDRError: c = netblock.convcidr(a, 0) die("Bad CIDR %s. Should start at IP %s." % \ (a, netblock.ipstr(c[0]))) except netblock.NBError, e: die("bad argument %s: %s" % (a, str(e))) ranges.append(nb) # We could do this without xranges, but it would involve flailing # and mad popping. So, frankly, no. for i in xrange(0, len(ranges)): for j in xrange(i+1, len(ranges)): r1 = ranges[i] r2 = ranges[j] # Everything we care about requires intersection as # a basic start. if not r1.intersect(r2): if once: checkadjacent(r1, r2, args[i], args[j]) continue if r1 == r2: print "%s equals %s" % apair(i, j) elif r1.subset(r2): print "%s is a subset of %s" % apair(j, i) elif r2.subset(r1): print "%s is a subset of %s" % apair(i, j) else: print "%s intersects with %s" % apair(i, j) if once: break # Skip adjacency processing for one-shot runs. if once: return # The code here should scan for adjacency merges, and accumulate # them somehow. As unwritten code, we could call it perfect or # alternately somewhat lacking in features. if __name__ == "__main__": process(sys.argv[1:])