From 3b99e97a104a8207085b241f20b1e98e58afb9fc Mon Sep 17 00:00:00 2001 From: or3st3s Date: Thu, 20 Sep 2007 17:50:16 +0000 Subject: [PATCH] Se crea el repo del pymin. --- README | 21 +++++++ config/dhcp/dhcpd.conf | 41 ++++++++++++ config/dns/%%(zone1).zone | 25 ++++++++ config/dns/named.conf | 79 +++++++++++++++++++++++ dhcpd/dhcpd.conf | 23 +++++++ dhcpd/dhcpd.py | 121 ++++++++++++++++++++++++++++++++++++ dhcpd/dhcpd_config.pkl | 68 ++++++++++++++++++++ dhcpd/dhcpd_global.template | 13 ++++ dhcpd/dhcpd_host.template | 4 ++ dispatcher.py | 89 ++++++++++++++++++++++++++ pollserver.py | 39 ++++++++++++ udp_server.py | 11 ++++ 12 files changed, 534 insertions(+) create mode 100644 README create mode 100644 config/dhcp/dhcpd.conf create mode 100644 config/dns/%%(zone1).zone create mode 100644 config/dns/named.conf create mode 100644 dhcpd/dhcpd.conf create mode 100644 dhcpd/dhcpd.py create mode 100644 dhcpd/dhcpd_config.pkl create mode 100644 dhcpd/dhcpd_global.template create mode 100644 dhcpd/dhcpd_host.template create mode 100644 dispatcher.py create mode 100644 pollserver.py create mode 100644 udp_server.py diff --git a/README b/README new file mode 100644 index 0000000..24abc5d --- /dev/null +++ b/README @@ -0,0 +1,21 @@ +Esta es una estructura básica de lo que puede ser el daemon, con el mecanismo +básico de despacho de comandos. + +Para correr el ejemplo: +python pollserver.py + +luego desde otra consola escribir, podemos comunicarnos via netcat: +nc localhost 9999 + +y mandar comandos que comiencen con 'test': +test alal dldl flkg + +En la ventana del server debería aparecer algo como: +test: ('alal', 'dldl', 'flkg') + +Si no empieza con 'test' va a explotar el server porque todavía no tiene manejo +de errores, pero es fácil ponerlo. + +Para hacer una prueba simple del dispatcher: python dispatcher.py + +http://www.cisco.com/en/US/products/sw/iosswrel/ps5187/prod_command_reference_list.html \ No newline at end of file diff --git a/config/dhcp/dhcpd.conf b/config/dhcp/dhcpd.conf new file mode 100644 index 0000000..a35fbae --- /dev/null +++ b/config/dhcp/dhcpd.conf @@ -0,0 +1,41 @@ + +Configuracion de dhcp server: + +Variables globales: + +%(domain_name) = Nombre del dominio +%(dns_1) = DNS primario +%(dns_2) = DNS secundario +%(net_address) = Direccion de la red que se va a servir por DHCP +%(net_mask) = Mascara de la red +%(net_start) = Direccion inicial del rango de direcciones dinamicas +%(net_end) = Direccion final del rango de direcciones dinamicas +%(net_gateway) = Puerta de enlace de la red + + +Y esto es por host: + +%(host1_name) = Nombre del host +%(host1_mac) = MAC Address del host (ej. 00:00:12:34:56:78) +%(host1_ip) = Direccion IP del host + +----------------8<---------------------------------------------------- + +ddns-update-style none; + +option domain-name %(domain_name); +option domain-name-servers %(dns_1), %(dns_2); + +authoritative; + +log-facility local7; + +subnet %(net_address) netmask %(net_mask) { + range %(net_start) %(net_end); + option routers %(net_gateway); +} + +host %(host1_name) { + fixed-address %(host1_ip); + hardware ethernet %(host1_mac); +} diff --git a/config/dns/%%(zone1).zone b/config/dns/%%(zone1).zone new file mode 100644 index 0000000..b5d74c9 --- /dev/null +++ b/config/dns/%%(zone1).zone @@ -0,0 +1,25 @@ +Variables + +%(ns1) = Servidor de nombres de la zona (dominio) +%(ns2) = Servidor de nombres de la zona (dominio) + +%(zone1) = Nombre de la zona (dominio) +%(host_name1) = Nombre del host 1 (sin dominio) +%(host_name2) = Nombre del host 2 (sin dominio) + + + +------------------8<--------------- + +$TTL 1W +@ IN SOA %(ns1).%(zone1). root.%(zone1). ( + 2002081601 ; Serial + 28800 ; Refresh + 14400 ; Retry + 604800 ; Expire - 1 week + 86400 ) ; Minimum +@ IN NS %(ns1) + +%(host_name1) IN A %(host_ip1) +%(host_name2) IN A %(host_ip2) + diff --git a/config/dns/named.conf b/config/dns/named.conf new file mode 100644 index 0000000..bce1fd3 --- /dev/null +++ b/config/dns/named.conf @@ -0,0 +1,79 @@ +Servidor DNS + + +Variables: + + +%(isp_dns1) = Servidor primario del proveedor de internet +%(isp_dns2) = Servidor secundario del proveedor de internet +%(bind_addr1) = Direccion ip donde va a "escuchar" el servidor de dns +%(bind_addr2) = Direccion ip donde va a "escuchar" el servidor de dns +%(zone1) = "Zona" o dominio que va a manejar este DNS +%(zone2) = "Zona" o dominio que va a manejar este DNS + +-----------8<------------------------------------------------------------- +options { + directory "/var/bind"; + + forward first; + forwarders { + %(isp_dns1); + %(isp_dns2); + }; + + listen-on-v6 { none; }; + listen-on { + %(bind_addr1); + %(bind_addr2); + }; + + pid-file "/var/run/named/named.pid"; +}; + +zone "." IN { + type hint; + file "named.ca"; +}; + +zone "localhost" IN { + type master; + file "pri/localhost.zone"; + allow-update { none; }; + notify no; +}; + +zone "127.in-addr.arpa" IN { + type master; + file "pri/127.zone"; + allow-update { none; }; + notify no; +}; + +zone "%(zone1)" IN { + type master; + file "pri/%(zone1).zone"; + allow-update { none; }; + notify no; +}; + +zone "%(zone1)" IN { + type master; + file "pri/%(zone1).zone.ptr"; + allow-update { none; }; + notify no; +}; + +zone "%(zone2)" IN { + type master; + file "pri/%(zone2).zone"; + allow-update { none; }; + notify no; +}; + +zone "%(zone2)" IN { + type master; + file "pri/%(zone2).zone.ptr"; + allow-update { none; }; + notify no; +}; + diff --git a/dhcpd/dhcpd.conf b/dhcpd/dhcpd.conf new file mode 100644 index 0000000..7fe8d65 --- /dev/null +++ b/dhcpd/dhcpd.conf @@ -0,0 +1,23 @@ +ddns-update-style none; + +option domain-name baryon.com.ar; +option domain-name-servers my_ns1, my_ns2; + +authoritative; + +log-facility local7; + +subnet 192.168.0.0 netmask 255.255.255.0 { + range 192.168.0.100 192.168.0.200; + option routers 192.168.0.1; +} + +host my_name { + fixed-address 192.168.0.192; + hardware ethernet 00:12:ff:56; +} + +host nico { + fixed-address 192.168.0.188; + hardware ethernet 00:00:00:00; +} diff --git a/dhcpd/dhcpd.py b/dhcpd/dhcpd.py new file mode 100644 index 0000000..6846703 --- /dev/null +++ b/dhcpd/dhcpd.py @@ -0,0 +1,121 @@ + +import pickle + +class ParamsError(Exception): + def __init__(self,reason): + self.reason = reason + + def __str__(self): + return repr(reason) + +class dhcpd: + "class that handles dhcpd config" + + def __init__(self): + self.host_list = dict() + self.glob = { 'domain_name' : 'my_domain_name', + 'dns_1' : 'my_ns1', + 'dns_2' : 'my_ns2', + 'net_address' : '192.168.0.0', + 'net_mask' : '255.255.255.0', + 'net_start' : '192.168.0.100', + 'net_end' : '192.168.0.200', + 'net_gateway' : '192.168.0.1'} + + + def to_file_format(self): + #bajo los parametros globales + glob_file = open('dhcpd_global.template','r') + glob_tmp = glob_file.read() + glob_file.close() + conf = glob_tmp % self.glob + #bajo los hosts + host_file = open('dhcpd_host.template','r') + host_tmp = host_file.read() + host_file.close() + for h , v in self.host_list.iteritems(): + conf = conf + '\n' + (host_tmp % v) + return conf + + def add_host(self, args): + #deberia indexar por hostname o por ip? + if len(args) == 3: + self.host_list[args[0]] = {"host_name": args[0], "host_ip": args[1], "host_mac": args[2]} + else: + raise ParamsError('Wrong number of parameters') + + def mod_host(self, args): + #deberia indexar por hostname o por ip? + if len(args) == 3: + self.host_list[args[0]] = {"host_name": args[0], "host_ip": args[1], "host_mac": args[2]} + else: + raise ParamsError('Wrong number of parameters') + + def remove_host(self, hostname): + if hostname in self.host_list: + del(self.host_list[hostname]) + else: + raise ParamsError("No such host") + + def set(self, pair): + if pair[0] in self.glob: + self.glob[pair[0]] = pair[1] + else: + raise ParamsError("Parameter " + pair[0] + " not found") + + def start(self): + #esto seria para poner en una interfaz + #y seria el hook para arrancar el servicio + pass + + def stop(self): + #esto seria para poner en una interfaz + #y seria el hook para arrancar el servicio + pass + + def commit(self): + #esto seria para poner en una interfaz + #y seria que hace el pickle deberia llamarse + #al hacerse un commit + output = open('dhcpd_config.pkl', 'wb') + pickle.dump(config, output) + output.close() + + def show_params(self): + string = '' + for k , v in self.glob.iteritems(): + string = string + k + ' : ' + v + '\n' + return string + + def show_hosts(self): + string = '' + for k , v in self.host_list.iteritems(): + string = string + k + ' : ' + v["host_ip"] + ' : ' + v["host_mac"] + '\n' + return string + + +if __name__ == '__main__': + + config = dhcpd() + + try : + arguments = ('my_name','192.168.0.102','00:12:ff:56') + config.add_host(arguments) + + arguments = ('my_name','192.168.0.192','00:12:ff:56') + config.mod_host(arguments) + + arguments = ('nico','192.168.0.188','00:00:00:00') + config.add_host(arguments) + + config.set(('domain_name','baryon.com.ar')) + config.set(('sarasa','baryon.com.ar')) + + except ParamsError, inst: + print inst.reason + + config.commit() + + conf_file = open('dhcpd.conf','w') + conf_file.write(config.to_file_format()) + conf_file.close() diff --git a/dhcpd/dhcpd_config.pkl b/dhcpd/dhcpd_config.pkl new file mode 100644 index 0000000..57f614e --- /dev/null +++ b/dhcpd/dhcpd_config.pkl @@ -0,0 +1,68 @@ +(i__main__ +dhcpd +p0 +(dp1 +S'glob' +p2 +(dp3 +S'net_end' +p4 +S'192.168.0.200' +p5 +sS'net_mask' +p6 +S'255.255.255.0' +p7 +sS'domain_name' +p8 +S'baryon.com.ar' +p9 +sS'dns_1' +p10 +S'my_ns1' +p11 +sS'dns_2' +p12 +S'my_ns2' +p13 +sS'net_start' +p14 +S'192.168.0.100' +p15 +sS'net_gateway' +p16 +S'192.168.0.1' +p17 +sS'net_address' +p18 +S'192.168.0.0' +p19 +ssS'host_list' +p20 +(dp21 +S'my_name' +p22 +(dp23 +S'host_name' +p24 +g22 +sS'host_mac' +p25 +S'00:12:ff:56' +p26 +sS'host_ip' +p27 +S'192.168.0.192' +p28 +ssS'nico' +p29 +(dp30 +g24 +g29 +sg25 +S'00:00:00:00' +p31 +sg27 +S'192.168.0.188' +p32 +sssb. \ No newline at end of file diff --git a/dhcpd/dhcpd_global.template b/dhcpd/dhcpd_global.template new file mode 100644 index 0000000..6f1f2fd --- /dev/null +++ b/dhcpd/dhcpd_global.template @@ -0,0 +1,13 @@ +ddns-update-style none; + +option domain-name %(domain_name)s; +option domain-name-servers %(dns_1)s, %(dns_2)s; + +authoritative; + +log-facility local7; + +subnet %(net_address)s netmask %(net_mask)s { + range %(net_start)s %(net_end)s; + option routers %(net_gateway)s; +} diff --git a/dhcpd/dhcpd_host.template b/dhcpd/dhcpd_host.template new file mode 100644 index 0000000..edd99d9 --- /dev/null +++ b/dhcpd/dhcpd_host.template @@ -0,0 +1,4 @@ +host %(host_name)s { + fixed-address %(host_ip)s; + hardware ethernet %(host_mac)s; +} diff --git a/dispatcher.py b/dispatcher.py new file mode 100644 index 0000000..78ae246 --- /dev/null +++ b/dispatcher.py @@ -0,0 +1,89 @@ +# vim: set et sts=4 sw=4 encoding=utf-8 : + +class BadRouteError(Exception): + + def __init__(self,cmd): + self.cmd = cmd + + def __str__(self): + return repr(cmd) + +class CommandNotFoundError(Exception): + + def __init__(self,cmd): + self.cmd = cmd + + def __str__(self): + return repr(cmd) + +class Dispatcher: + + def __init__(self, routes=dict()): + self.routes = routes + + def dispatch(self, route): + route = route.split() # TODO considerar comillas + try: + handler = self.routes[route[0]] + route = route[1:] + while not callable(handler): + handler = getattr(handler, route[0]) + route = route[1:] + handler(*route) + + except KeyError: + raise CommandNotFoundError(route[0]) + except AttributeError: + raise BadRouteError(route[0]) + except IndexError: + pass + + +def test_func(*args): + print 'func:', args + + +class TestClassSubHandler: + + def subcmd(self, *args): + print 'class.subclass.subcmd:', args + + +class TestClass: + + def cmd1(self, *args): + print 'class.cmd1:', args + + def cmd2(self, *args): + print 'class.cmd2:', args + + subclass = TestClassSubHandler() + + +if __name__ == '__main__': + + d = Dispatcher(dict( + func=test_func, + inst=TestClass(), + )) + + d.dispatch('func arg1 arg2 arg3') + d.dispatch('inst cmd1 arg1 arg2 arg3 arg4') + d.dispatch('inst subclass subcmd arg1 arg2 arg3 arg4 arg5') + +# Ideas / TODO: +# +# * Soportar comillas para argumentos con espacios y otros caracteres, onda: +# 'misc set motd "Hola!\nEste es el servidor de garombia"' +# +# * Soportar keyword arguments, onda que: +# 'dns set pepe=10.10.10.1 juan=10.10.10.2' +# se mapee a algo como: dns.set(pepe='10.10.10.1', juan='10.10.10.2') +# +# Estas cosas quedan sujetas a necesitada y a definición del protocolo. +# Para mí lo ideal es que el protocolo de red sea igual que la consola del +# usuario, porque después de todo no va a ser más que eso, mandar comanditos. +# +# Por otro lado, el cliente de consola, por que no es el cliente web pero +# accedido via ssh usando un navegador de texto como w3m??? + diff --git a/pollserver.py b/pollserver.py new file mode 100644 index 0000000..886ef3a --- /dev/null +++ b/pollserver.py @@ -0,0 +1,39 @@ +# vim: set encoding=utf-8 et sw=4 sts=4 : + +import signal +import select +from sys import exit + +import dispatcher as dis +import udp_server as us + +def quit(signum, frame): + print "Shuting down ..." + exit(0) + +signal.signal(signal.SIGINT, quit) +signal.signal(signal.SIGTERM, quit) + +server = us.UDPServer(9999) + +poll = select.poll() +poll.register(server.sock.fileno(), select.POLLIN | select.POLLPRI) + +d = dis.Dispatcher(dict( + func=dis.test_func, + inst=dis.TestClass() + )) + +def handle_recv(sock): + (msg, addr) = sock.recvfrom(65535) + try: + d.dispatch(msg) + except dis.BadRouteError, inst: + sock.sendto('Bad route from : ' + inst.cmd + '\n', addr) + except dis.CommandNotFoundError, inst: + sock.sendto('Command not found : ' + inst.cmd + '\n', addr) + +while True: + l = poll.poll() + handle_recv(server.sock) + diff --git a/udp_server.py b/udp_server.py new file mode 100644 index 0000000..23248a8 --- /dev/null +++ b/udp_server.py @@ -0,0 +1,11 @@ +# vim: set encoding=utf-8 et sw=4 sts=4 : + +import socket as s + +class UDPServer: + "Udp server class" + + def __init__(self, port): + self.sock = s.socket(s.AF_INET, s.SOCK_DGRAM) + self.sock.setsockopt(s.SOL_SOCKET, s.SO_REUSEADDR, 1) + self.sock.bind(('', port)) \ No newline at end of file -- 2.43.0