#!/usr/bin/env python
# zoek de eerste vrije (== niet in een wleiden.conf gedefinieerde) interlink
# range
# lodewijk@wirelessleiden.nl
import re
import sys
import glob

def parseaddr(s):
	f = s.split('.')
	return (long(f[0]) << 24L) + \
		(long(f[1]) << 16L) + \
		(long(f[2]) << 8L) + \
		long(f[3])

def showaddr(a):
	return "%d.%d.%d.%d" % ((a >> 24) & 0xff, (a >> 16) & 0xff, (a >> 8) & 0xff, a & 0xff)

def get_ranges(interlink, size, aantal):
	numaddrs = 1 << (32 - size)
	
	substre = re.compile("^(\$[a-zA-Z][^ =]*) ?= ?'([^']*)';")
	
	
	bezet = {}
	
	for fname in glob.glob("*/wleiden.conf"):
		substs = {}
		lineNr = 0
		for l in open(fname):
			lineNr += 1
			l = l[:-1]
			match = substre.match(l)
			if match != None:
				substs[match.group(1)] = match.group(2)
			if l.startswith("IP=") or l.startswith("$master_ip="):
				if l.startswith("$master_ip="):
					right = l.split("'")[1]
				else:
					right = l[3:]
				if '/' not in right:
					addr = right
					mask = 32
				else:
					addr, mask = right.split('/')
					if addr in substs:
						addr = substs[addr]
				try:
					addr = parseaddr(addr)
					mask = int(mask)
					addr = addr & ~((1 << (32 - mask)) - 1)
					for i in range(0, (1 << (32 - mask))):
						bezet[addr + i] = 1
				except ValueError, e:
					print "[FOUT] in bestand '%s' regel '%i': %s" % (fname, lineNr, l)

	# Fetching smallest in use IP 
	# XXX: Currently not used for anything
	i = parseaddr("255.255.255.255")
	for k in bezet.keys():
		if k < i:
			i = k
	
	# Interlinks are living in special ranges usually
	if interlink:
		i = parseaddr("172.16.3.0")
	else:
		i = parseaddr("172.17.0.0")
	
	ranges = []
	for n in xrange(aantal):
		okay = False
		while not okay: 
			while bezet.has_key(i):
				i = i + numaddrs
			
			# Assume Ok, till we find a already used IP
			okay = True
			for j in range(numaddrs):
				if bezet.has_key(i + j):
					i = i + numaddrs
					okay = False
					break
		ranges.append(i)
		bezet[i] = 1

	return ranges

def main():
	if len(sys.argv) < 2:
		print "Gebruik: %s <interlink|subnet> <grootte> [aantal]" % sys.argv[0]
		print "Voorbeelden:"
		print "\tVoor drie /29 interlinks - '%s interlink 29 3'" % sys.argv[0]
		print "\tVoor een (1) /24 subnet  - '%s subnet 24'" % sys.argv[0]
		exit(1)
	
	# Argument parsing
	interlink = sys.argv[1] == 'interlink'
	size = int(sys.argv[2])
	try:
		aantal = int(sys.argv[3])
	except (KeyError,IndexError):
	    aantal = 1
	
	ranges = get_ranges(interlink, size, aantal)
	numaddrs = 1 << (32 - size)

	for i in ranges:
		print "%s/%d:" % (showaddr(i), size),
		if size > 28:
			print " en ".join([showaddr(i) for i in range(i + 1, i + numaddrs - 1)])
		else:
			print " en ".join([showaddr(i) for i in range(i + 1, i + 4)]),
			print "...",
			print " en ".join([showaddr(i) for i in range(i + numaddrs - 7, i + numaddrs - 4)])

if __name__ == "__main__":
    main()
