From ed8d61f5cc3f189dce340762925fc6070ff0687c Mon Sep 17 00:00:00 2001 From: Leonardo Date: Wed, 19 May 2010 18:03:24 +0200 Subject: [PATCH] Ora supportiamo anche i nomi a dominio. --- pywhoisd.conf | 9 ++-- pywhoisd.db | 37 ++++++++++++++- pywhoisd.py | 143 ++++++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 149 insertions(+), 40 deletions(-) diff --git a/pywhoisd.conf b/pywhoisd.conf index b3b8f8b..2ab6977 100644 --- a/pywhoisd.conf +++ b/pywhoisd.conf @@ -11,7 +11,8 @@ config_file = pywhoisd.db; # This sets the welcome banner that will be displayed to user # contacting us on port 43 -welcome_banner = This is the whoisd server for the GNet autonomous network. - If you'd like to become part of out network visit us - at http://linus.robol.it/gnet/ or (if you have access now) - http://linus.leo.gnet/gnet/. See you soon!; \ No newline at end of file +welcome_banner = This is the whoisd server for the GNet + autonomous network. If you'd like to become part + of our network visit us at http://linus.robol.it/gnet/ + or (if you have access now) http://linus.leo.gnet/gnet/. + See you soon!; \ No newline at end of file diff --git a/pywhoisd.db b/pywhoisd.db index 4d82709..8eb7c14 100644 --- a/pywhoisd.db +++ b/pywhoisd.db @@ -30,5 +30,40 @@ net 6.15.1.0/24 { name = Lawvere net; owner = Giorgio Mossa ; ns = 6.20.10.1; - ciao = pirla; +}; + +net 6.11.1.0/24 { + name = Freschi GNet; + owner = Luca Freschi ; + ns = 6.20.10.1; +}; + +net 6.0.0.0/8 { + name = GNET; + owner = undefined; + ns = 6.20.10.1, 6.22.22.22; +}; + +domain leo.gnet { + name = Leo Gnet; + owner = Leonardo Robol ; + ns = 6.20.10.1; +}; + +domain ineff.gnet { + name = Ineff Gnet; + owner = Giorgio Mossa ; + ns = 6.20.10.1; +}; + +domain lf.gnet { + name = Luca GNet; + owner = Luca Freschi ; + ns = 6.20.10.1; +}; + +domain gnet { + name = GNET; + owner = Undefined; + ns = 6.20.10.1, 6.22.22.22; }; \ No newline at end of file diff --git a/pywhoisd.py b/pywhoisd.py index 142d6ec..93befc7 100755 --- a/pywhoisd.py +++ b/pywhoisd.py @@ -5,34 +5,28 @@ # provide a basic whois for GNet. # -import SocketServer, re, math +import SocketServer, re, math, syslog from ipcalc import IP, Network +# Dictionaries that will contain runtime data +# for the server ip_database = {} domain_database = {} config = {} -def ip_in_subnet(ip, network, subnet): - ip = map(int, ip.split(".")) - network = map(int, network.split(".")) - if "." in subnet: - subnet = map(int, subnet.split(".")) - subnet = map(lambda x: 255 - x, subnet) - subnet = math.log(subnet[3] + subnet[2] * 256 + subnet[1] * pow(256,2) + subnet[0] * pow(256,3), 2) - subnet = pow(2, 32 - int(subnet)) - ip = ip[3] + ip[2] * 256 + ip[1] * pow(256,2) + ip[0] * pow(256,3) - network = network[3] + network[2] * 256 + network[1] * pow(256,2) + network[0]*pow(256,3) - if ((ip - network) < subnet) and (ip-network >= 0): - return True - else: - return False +def Log(message): + print message + syslog.syslog (message) def get_net_of_ip(ip): + """ + Get network in which the given ip is + """ interesting_networks = [] for (address, net) in ip_database.items(): if IP(ip) in Network(address): interesting_networks.append (address) - return address + return interesting_networks def format_output(field, value): """ @@ -43,17 +37,24 @@ def format_output(field, value): return " "*4 + output def format_message(message): + """ + Normal message of the server + """ output = "\n" for line in message.split("\n"): line = line.strip() - output += """\n %% """ + line.ljust(85) + """ %%""" + output += """\n %% """ + line.ljust(65) + """ %%""" return output + "\n\n" def resolve_ip(ip): + """ + Resolve an ip: it search all the data that match it + """ output = "" nets = get_net_of_ip(ip) for net in nets: output += format_message("GNet whoisd answering for ip %s" % ip) + output += format_output ("Range", net) net = ip_database[net] if net.name is not None: output += format_output ("Name", net.name) @@ -66,14 +67,46 @@ def resolve_ip(ip): for k, v in net.data.items(): output += format_output (k.capitalize(),v) if len(nets) == 0: + output = format_message("IP %s not found\n" % ip) - output += format_message("Bye") return output +def get_domains_of_name(domain): + interesting_domains = [] + for domain_name, domain_data in domain_database.items(): + if domain.endswith(domain_name): + interesting_domains.append (domain_name) + + return interesting_domains + def resolve_domain(domain): - return format_message("Feature not yet implemented") + """ + Resolve a domain. It is not yet implemented + """ + output = "" + domains = get_domains_of_name(domain) + for d in domains: + output += format_message("GNet whoisd answering for domain %s" % d) + output += format_output ("Domain", d) + domain = domain_database[d] + if domain.name is not None: + output += format_output ("Name", domain.name) + if domain.owner is not None: + output += format_output ("Owner", domain.owner) + if domain.ns is not None: + output += format_output ("Nameserver", domain.ns) + if len(domain.data.items()) > 0: + output += format_message("Additional data") + for k, v in domain.data.items(): + output += format_output (k.capitalize(),v) + if len(domains) == 0: + return format_message("No domain found for %s" % domain) + return output def hello(): + """ + Say hello, server! + """ if config.has_key('welcome_banner'): return config['welcome_banner'] else: @@ -93,38 +126,50 @@ class WhoisRequestHandler(SocketServer.StreamRequestHandler): request = self.rfile.readline().strip() if re.search(r"\d+\.\d+\.\d+\.\d+", request.strip()): - try: - response += resolve_ip(request.split("/")[0]) - except Exception, e: - response = format_message("An error occured while processing the request, aborting.\n%s" % e) + response += resolve_ip(request.split("/")[0]) else: response += resolve_domain(request) + response += format_message("Bye") self.request.send (response) return class Net(): - + # + # Net is a class representing the network + # contained in the local database and the + # net obtained from other whois server. + # + # It act as a C struct containing only the + # data and no method. def __init__(self, name, owner, ns, data): self.name = name self.owner = owner self.ns = ns self.data = data +class Domain(): + # + # + # + def __init__(self, name, owner, ns, data): + self.name, self.owner, self.ns = name, owner, ns + self.data = data + def populate_databases(config_file): """ Populate databases with the data of our zones """ - print "Populating database" + Log ("Populating database with entry in %s" % config_file) try: f = open(config_file, 'r') - data = f.read() + config_data = f.read() except IOError: - print >>stderr, "Error while loading config file. exiting" + Log ("Error while loading config file. exiting") - nets = re.findall (r"net\s+(\d+\.\d+\.\d+\.\d+[/\d]*)[\s|\n]+\{([^\}]+)\};", data) + nets = re.findall (r"net\s+(\d+\.\d+\.\d+\.\d+[/\d]*)[\s|\n]+\{([^\}]+)\};", config_data) for net in nets: - print "> net %s loaded" % net[0] + Log ("Loading net %s" % net[0]) fields = re.findall(r"(\w+)\s*=\s*([^;]+);", net[1]) name, owner, ns = None, None, None data = {} @@ -140,14 +185,42 @@ def populate_databases(config_file): ip_database[net[0]] = Net(name = name, owner = owner, ns = ns, data = data) -def parse_config_file(config_file): + domains = re.findall(r"domain\s+([^\s]+)[\s|\n]+\{([^\}]+)\};", config_data) + for domain in domains: + Log ("Loading domain %s" % domain[0]) + fields = re.findall(r"(\w+)\s*=\s*([^;]+);", domain[1]) + name, owner, ns = None, None, None + data = {} + for field, value in fields: + if field.lower() == 'name': + name = value.strip() + elif field.lower() == 'owner': + owner = value.strip() + elif field.lower() == 'ns': + ns = value.strip() + else: + data[field] = value + domain_database[domain[0]] = Domain(name = name, owner = owner, ns = ns, + data = data) + +def parse_config_file(config_file): + """ + Parse config file and load_data into memory + """ config = {} f = open(config_file, 'r') content = f.read() f.close() for (key, value) in re.findall(r"([^\s]+)\s*=\s*([^;]+)\s*;", content): - config[key] = value + # Gestiamo in maniera particolare + # i campi che mi forniscono un array. + if key == "master_domains": + config[key] = [] + for domain in eval(value): + config[key].append(domain) + else: + config[key] = value return config @@ -157,13 +230,13 @@ if __name__ == "__main__": config = parse_config_file ('pywhoisd.conf') populate_databases(config['config_file']) - host, port = "localhost", 43 - server = SocketServer.TCPServer((host, port), WhoisRequestHandler) + host, port = "0.0.0.0", 43 + server = SocketServer.ThreadingTCPServer((host, port), WhoisRequestHandler) + server.allow_reuse_address = True try: server.serve_forever(0.1) except KeyboardInterrupt: - print "Exiting...", - print "done" + Log ("Exiting...") -- 2.1.4