Populate subnet_mask and router options from individual NIC parameters,
[invirt/packages/invirt-dhcp.git] / invirt-dhcpserver
index a1966d8..438d80d 100755 (executable)
@@ -7,7 +7,6 @@ from pydhcplib.type_hw_addr import hwmac
 from pydhcplib.type_ipv4 import ipv4
 from pydhcplib.type_strlist import strlist
 import socket
 from pydhcplib.type_ipv4 import ipv4
 from pydhcplib.type_strlist import strlist
 import socket
-import os
 import IN
 
 import syslog as s
 import IN
 
 import syslog as s
@@ -16,24 +15,21 @@ import time
 from invirt import database
 from invirt.config import structs as config
 
 from invirt import database
 from invirt.config import structs as config
 
-dhcp_options = {'subnet_mask': config.dhcp.netmask,
-                'router': config.dhcp.gateway,
-                'domain_name_server': ','.join(config.dhcp.dns),
-                'ip_address_lease_time': 60*60*24,
-                'server_identifier': socket.gethostbyname(os.uname()[1])}
+dhcp_options = {'domain_name_server': ','.join(config.dhcp.dns),
+                'ip_address_lease_time': config.dhcp.leasetime if config.dhcp.has_key('leasetime') else 60*60*24}
 
 class DhcpBackend:
     def __init__(self):
         database.connect()
     def findNIC(self, mac):
         database.clear_cache()
 
 class DhcpBackend:
     def __init__(self):
         database.connect()
     def findNIC(self, mac):
         database.clear_cache()
-        return database.NIC.query().filter_by(mac_addr=mac).first()
+        return database.NIC.query.filter_by(mac_addr=mac).first()
     def find_interface(self, packet):
         chaddr = hwmac(packet.GetHardwareAddress())
         nic = self.findNIC(str(chaddr))
         if nic is None or nic.ip is None:
             return None
     def find_interface(self, packet):
         chaddr = hwmac(packet.GetHardwareAddress())
         nic = self.findNIC(str(chaddr))
         if nic is None or nic.ip is None:
             return None
-        ipstr = ''.join(reversed(['%02X' % i for i in ipv4(nic.ip).list()]))
+        ipstr = ''.join(reversed(['%02X' % i for i in ipv4(nic.ip.encode("utf-8")).list()]))
         for line in open('/proc/net/route'):
             parts = line.split()
             if parts[1] == ipstr:
         for line in open('/proc/net/route'):
             parts = line.split()
             if parts[1] == ipstr:
@@ -99,15 +95,17 @@ class DhcpBackend:
         nic = self.findNIC(str(chaddr))
         if nic is None or nic.machine is None:
             return False
         nic = self.findNIC(str(chaddr))
         if nic is None or nic.machine is None:
             return False
-        ip = nic.ip
+        ip = nic.ip.encode("utf-8")
         if ip is None:  #Deactivated?
             return False
 
         options = {}
         if ip is None:  #Deactivated?
             return False
 
         options = {}
+        options['subnet_mask'] = nic.netmask.encode("utf-8")
+        options['router'] = nic.gateway.encode("utf-8")
         if nic.hostname and '.' in nic.hostname:
         if nic.hostname and '.' in nic.hostname:
-            options['host_name'], options['domain_name'] = nic.hostname.split('.', 1)
+            options['host_name'], options['domain_name'] = nic.hostname.encode('utf-8').split('.', 1)
         elif nic.machine.name:
         elif nic.machine.name:
-            options['host_name'] = nic.machine.name
+            options['host_name'] = nic.machine.name.encode('utf-8')
             options['domain_name'] = config.dns.domains[0]
         else:
             hostname = None
             options['domain_name'] = config.dns.domains[0]
         else:
             hostname = None
@@ -115,17 +113,15 @@ class DhcpBackend:
             options['host_name'] += '.' + options['domain_name']
             del options['domain_name']
             options['domain_search'] = [config.dhcp.search_domain]
             options['host_name'] += '.' + options['domain_name']
             del options['domain_name']
             options['domain_search'] = [config.dhcp.search_domain]
-        if ip is not None:
-            ip = ipv4(ip)
-            s.syslog(s.LOG_DEBUG,"dhcp_backend : Discover result = "+str(ip))
-            packet_parameters = self.getParameters(**options)
+        ip = ipv4(ip)
+        s.syslog(s.LOG_DEBUG,"dhcp_backend : Discover result = "+str(ip))
+        packet_parameters = self.getParameters(**options)
 
 
-            # FIXME: Other offer parameters go here
-            packet_parameters["yiaddr"] = ip.list()
-            
-            packet.SetMultipleOptions(packet_parameters)
-            return True
-        return False
+        # FIXME: Other offer parameters go here
+        packet_parameters["yiaddr"] = ip.list()
+
+        packet.SetMultipleOptions(packet_parameters)
+        return True
         
     def Request(self, packet):
         s.syslog(s.LOG_DEBUG, "dhcp_backend : Request")
         
     def Request(self, packet):
         s.syslog(s.LOG_DEBUG, "dhcp_backend : Request")
@@ -164,12 +160,9 @@ class DhcpServer(pydhcplib.dhcp_network.DhcpServer):
     def SendDhcpPacketTo(self, To, packet):
         intf = self.backend.find_interface(packet)
         if intf:
     def SendDhcpPacketTo(self, To, packet):
         intf = self.backend.find_interface(packet)
         if intf:
-            out_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-            out_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST,1)
-            out_socket.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, intf)
-            #out_socket.bind((ip, self.listen_port))
-            ret = out_socket.sendto(packet.EncodePacket(), (To,self.emit_port))
-            out_socket.close()
+            self.dhcp_socket.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, intf)
+            ret = self.dhcp_socket.sendto(packet.EncodePacket(), (To,self.emit_port))
+            self.dhcp_socket.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, '')
             return ret
         else:
             return self.dhcp_socket.sendto(packet.EncodePacket(),(To,self.emit_port))
             return ret
         else:
             return self.dhcp_socket.sendto(packet.EncodePacket(),(To,self.emit_port))
@@ -229,12 +222,14 @@ class DhcpServer(pydhcplib.dhcp_network.DhcpServer):
 
         else : s.syslog(s.LOG_INFO,"Get DHCPREQUEST_UNKNOWN_STATE packet : not implemented")
 
 
         else : s.syslog(s.LOG_INFO,"Get DHCPREQUEST_UNKNOWN_STATE packet : not implemented")
 
-        if self.backend.Request(packet) : packet.TransformToDhcpAckPacket()
-        else : packet.TransformToDhcpNackPacket()
-
-        self.SendPacket(packet)
-
-
+        if self.backend.Request(packet):
+            packet.TransformToDhcpAckPacket()
+            self.SendPacket(packet)
+        elif self.backend.Discover(packet):
+            packet.TransformToDhcpNackPacket()
+            self.SendPacket(packet)
+        else:
+            pass # We aren't authoritative, so don't reply if we don't know them.
 
     # FIXME: These are not yet implemented.
     def HandleDhcpDecline(self, packet):
 
     # FIXME: These are not yet implemented.
     def HandleDhcpDecline(self, packet):
@@ -259,6 +254,14 @@ if '__main__' == __name__:
     options = { "server_listen_port":67,
                 "client_listen_port":68,
                 "listen_address":"0.0.0.0"}
     options = { "server_listen_port":67,
                 "client_listen_port":68,
                 "listen_address":"0.0.0.0"}
+
+    myip = socket.gethostbyname(socket.gethostname())
+    if not myip:
+        print "invirt-dhcpserver: cannot determine local IP address by looking up %s" % socket.gethostname()
+        sys.exit(1)
+    
+    dhcp_options['server_identifier'] = ipv4(myip).int()
+
     backend = DhcpBackend()
     server = DhcpServer(backend, options)
 
     backend = DhcpBackend()
     server = DhcpServer(backend, options)