#!/usr/bin/python

"""The purpose of this script is to take the RIPE NCC's delegation data
(-input) and transform them into IRCnet's I-Line structure. It will look
at all ipv4 and ipv6 allocations in a certain country (-country) and put
them into an output file (-output), using a class that is specified on
the commandline (-class)
Example usage:
$ gen-ilines.py  -input delegated-ripencc-latest -output ilines.ch.conf \
             -country CH -class 200
"""

import getopt
import sys
import types
import time
import os
import getpass
import socket

def usage():
  print """Usage:
  -h (-help): Help, this message
  -i (-input): The input file to select (default: delegated-ripencc-latest)
  -o (-output): The output file to write
  -c (-country): The two-letter country to select (default: 'CH')
  -y (-class): The Y-line class to put the I line in (default: 200)"""
  pass

def getmask(af, value):
	if af != "ipv6" and af != "ipv4":
		return False
	if af == "ipv6":
		if value < 16 or value > 48:
			return False
		return value

	mask_bits = 32
	ovalue = value
	while value > 1:
		mask_bits = mask_bits - 1
		value = value / 2
	if mask_bits > 24 or mask_bits < 8:
		return False
	return mask_bits

def main():
	try:
		opts, args = getopt.getopt(sys.argv[1:], "hi:o:c:y:",
			["help", "input=", "output=", "country=", "class="])
	except getopt.GetoptError, err:
		print str(err) # will print something like "option -a not recognized"
		usage()
		sys.exit(2)

	_output = None
	_input = "delegated-ripencc-latest"
	_class = 200
	_country = "CH"

	for o,a in opts:
		if o == "-h" or o == "-help":
			usage()
			sys.exit(2)
		elif o == "-i" or o == "-input":
			_input = a
		elif o == "-o" or o == "-output":
			_output = a
		elif o == "-c" or o == "-country":
			_country = a.upper()
		elif o == "-y" or o == "-class":
			_class = int(a)
		else:
			assert False, "unhandled option(s)"

	# Check input args a bit
	if _output == None:
		assert False, "-o (-output) Must set output file"
	if type(_class) != types.IntType:
		assert False, "-y (-class) must be an integer"
	
	try:
		ifile = open(_input, "r")
	except:
		assert False, "Could not open input file"
	try:
		ofile = open(_output, "w")
	except:
		assert False, "Coult not open output file"

	ofile.write("# File generated on %s by %s@%s\n" % (time.asctime(time.localtime(time.time())),
		getpass.getuser(), socket.gethostname()))
	ofile.write("# Commandline: %s\n" % ' '.join(sys.argv))
	ofile.write("# input=%s output=%s country=%s class=%s\n" %
		(_input, _output, _country, _class))

	line = ifile.readline().rstrip()
	fields = line.split("|")
	if len(fields) != 7:
		assert False, "Input file is not a 'delegated' file"
	if fields[0] != '2':
		assert False, "Input file version is not '2'"
	ofile.write("# First line: %s\n" % line)

	ofile.write("#\n\n")

	output_linecount = 0
	for line in ifile.readlines():
		fields = line.rstrip().split("|")
		if len(fields) != 7:
			continue
		if fields[2] != 'ipv4' and fields[2] != 'ipv6':
			continue
		if fields[1].upper() != _country:
			continue
		_network = fields[3]
		_mask = getmask(fields[2], int(fields[4]))
		if _mask == False:
			continue
		ofile.write("I%%*@%s/%s%%%%%%%%%d%%%% # %s\n" %
			(_network, _mask, _class, fields[5]))
		output_linecount = output_linecount + 1

	ofile.write("# Output %d I-lines\n" % (output_linecount))

	ifile.close()
	ofile.close()

if __name__ == "__main__":
	main()