#!/usr/bin/env python # # Standard imports # import string import struct, socket, select # # Default variables # BOOTP_PORT = 67 BOOTP_PORT_MVP = 16867 # For MediaMVP BOOTREQUEST = 1 BOOTREPLY = 2 BOOTPFormat = "!4bIHH4s4s4s4s16s64s128s64s" BOOTPFormatSize = struct.calcsize(BOOTPFormat) DHCPFormat = "!4bIHH4s4s4s4s16s64s128s4s" DHCPFormatSize = struct.calcsize(DHCPFormat) COOKIE='\0x63\0x82\0x53\0x63' # # Errors # class BOOTPError(Exception): pass def getOutAddr(addr): """Return local IP address as decimal dotted string to send data to target addr (which is tuple) TODO: Cache the result.""" s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(addr) result = s.getsockname()[0] s.close() return result # # Simple BootP Server # class BOOTPServer: """BOOTP Server Implements bootstrap protocol """ def __init__(self): self.sock = [] # end __init__ def bind(self, host, port): print "binding to", port if not host and port==BOOTP_PORT: host = '10.0.0.153' sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.append(sock) sock.bind((host, port)) # end start def forever(self): while 1: r,w,e = select.select(self.sock, [], self.sock) for sock in r: data, addr = sock.recvfrom(556) self.handle(sock, addr, data) # end serve_forever def handle(self, sock, addr, data): print "Sender:", addr, " on socket ", sock.getsockname() if len(data) < DHCPFormatSize: print "Cannot be a DHCP or BOOTP request - too small!" tail = data[DHCPFormatSize:] buf = list(struct.unpack(DHCPFormat, data[:DHCPFormatSize])) if buf[0] == BOOTREQUEST: print " data:", buf # construct reply buf[0] = BOOTREPLY # "your" address print "Client IP ", socket.inet_ntoa(buf[7]) if buf[7] == '\x00\x00\x00\x00': #print "Cannot serve this client, it does not have an IP yet" #return # client needs its address? buf[8] = socket.inet_aton('10.0.0.155') addr = ('10.0.0.155', addr[1]) else: buf[8] = buf[7] # 0x0A00009BL # 10.0.0.155 # siaddr siaddr = socket.inet_aton(getOutAddr(addr)) buf[9] = siaddr # 10.0.0.153 buf[10] = siaddr # sname buf[12] = "milo.lan" # file buf[13] = "dongle.bin.mvpmc" # -1.2.0" #buf[13] = "dongle.bin" # Extras (DHCP options?) buf[14] = '' print "Sending reply:", buf pkt = struct.pack(BOOTPFormat, *buf) sock.sendto(pkt, addr) # end handle # end class TFTPServer if __name__ == "__main__": import sys if sys.argv[1:]: port = string.atoi(sys.argv[1]) try: serv = BOOTPServer() serv.bind("", BOOTP_PORT) serv.bind("", BOOTP_PORT_MVP) serv.forever() except KeyboardInterrupt, SystemExit: pass