Ignore:
Timestamp:
Oct 18, 2007, 9:49:09 PM (17 years ago)
Author:
quentin
Message:

Use correct dhcp options, and use SO_BINDTODEVICE to send out the right device

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/dhcp/dhcpserver.py

    r191 r202  
    88from pydhcplib.type_ipv4 import ipv4
    99from pydhcplib.type_strlist import strlist
     10import socket
     11import IN
    1012
    1113import event_logger
     
    1416from event_logger import Log
    1517
     18import psycopg2
     19import time
    1620import sipb_xen_database
     21from sqlalchemy import create_engine
    1722
    1823dhcp_options = {'subnet_mask': '255.255.0.0',
    1924                'router': '18.181.0.1',
    2025                'domain_name_server': '18.70.0.160,18.71.0.151,18.72.0.3',
    21                 'domain_name': 'mit.edu'}
    22    
     26                'domain_name': 'mit.edu',
     27                'ip_address_lease_time': 60*60*24}
    2328
    2429class DhcpBackend:
    2530    def __init__(self, database=None):
    2631        if database is not None:
    27             sipb_xen_database.connect(database)
    28     def findIP(self, mac):
    29         value = sipb_xen_database.NIC.get_by(mac_addr=mac)
    30         if value is None:
    31             return None
    32         ip = value.ip
    33         if ip is None:  #Deactivated?
    34             return None
    35         return ip
    36     def getParameters(self):
     32            self.database = database
     33            sipb_xen_database.connect(create_engine(database))
     34    def findNIC(self, mac):
     35        for i in range(3):
     36            try:
     37                value = sipb_xen_database.NIC.get_by(mac_addr=mac)
     38            except psycopg2.OperationalError:
     39                time.sleep(0.5)
     40                if i == 2:  #Try twice to reconnect.
     41                    raise
     42                #Sigh.  SQLAlchemy should do this itself.
     43                sipb_xen_database.connect(create_engine(self.database))
     44            else:
     45                break
     46        return value
     47    def find_interface(self, packet):
     48        chaddr = hwmac(packet.GetHardwareAddress())
     49        nic = self.findNIC(str(chaddr))
     50        if nic is None or nic.ip is None:
     51            return ("18.181.0.60", None)
     52        ipstr = ''.join(reversed(['%02X' % i for i in ipv4(nic.ip).list()]))
     53        for line in open('/proc/net/route'):
     54            parts = line.split()
     55            if parts[1] == ipstr:
     56                Log.Output(Log.debug, "find_interface found "+str(nic.ip)+" on "+parts[0])
     57                return ("18.181.0.60", parts[0])
     58        return ("18.181.0.60", None)
     59                           
     60    def getParameters(self, **extra):
     61        all_options=dict(dhcp_options)
     62        all_options.update(extra)
    3763        options = {}
    38         for parameter, value in dhcp_options.iteritems():
     64        for parameter, value in all_options.iteritems():
     65            if value is None:
     66                continue
    3967            option_type = DhcpOptionsTypes[DhcpOptions[parameter]]
    4068
     
    4775                opt = []
    4876                for single in iplist :
    49                     opt.append(ipv4(single).list())
     77                    opt.extend(ipv4(single).list())
    5078                options[parameter] = opt
    5179            elif option_type == "32-bits" :
     
    76104        Log.Output(Log.debug,"dhcp_backend : Discover ")
    77105        chaddr = hwmac(packet.GetHardwareAddress())
    78         ip = self.findIP(str(chaddr))
     106        nic = self.findNIC(str(chaddr))
     107        if nic is None:
     108            return False
     109        ip = nic.ip
     110        if ip is None:  #Deactivated?
     111            return False
     112        hostname = nic.hostname
     113        if hostname is not None:
     114            hostname += ".servers.csail.mit.edu"
    79115        if ip is not None:
    80116            ip = ipv4(ip)
    81117            Log.Output(Log.debug,"dhcp_backend : Discover result = "+str(ip))
    82             packet_parameters = self.getParameters()
     118            packet_parameters = self.getParameters(host_name=hostname)
    83119
    84120            # FIXME: Other offer parameters go here
     
    96132        chaddr = hwmac(packet.GetHardwareAddress())
    97133        request = packet.GetOption("request_ip_address")
     134        if not request:
     135            request = packet.GetOption("ciaddr")
    98136        yiaddr = packet.GetOption("yiaddr")
    99137
     
    121159        Log.Output(Log.debug, "__init__ DhcpServer")
    122160
     161    def SendDhcpPacketTo(self, To, packet):
     162        (ip, intf) = self.backend.find_interface(packet)
     163        if intf:
     164            out_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
     165            out_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST,1)
     166            out_socket.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, intf)
     167            #out_socket.bind((ip, self.listen_port))
     168            ret = out_socket.sendto(packet.EncodePacket(), (To,self.emit_port))
     169            out_socket.close()
     170            return ret
     171        else:
     172            return self.dhcp_socket.sendto(packet.EncodePacket(),(To,self.emit_port))
     173
    123174    def SendPacket(self, packet):
    124175        """Encode and send the packet."""
     
    162213        sid = packet.GetOption("server_identifier")
    163214        ciaddr = packet.GetOption("ciaddr")
     215        #packet.PrintHeaders()
     216        #packet.PrintOptions()
    164217
    165218        if sid != [0,0,0,0] and ciaddr == [0,0,0,0] :
Note: See TracChangeset for help on using the changeset viewer.