#!/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:])
