"""Dynamic Host Configuration Protocol.""" from pypacker import pypacker, triggerlist from pypacker.layer12 import arp import logging logger = logging.getLogger("pypacker") DHCP_OP_REQUEST = 1 DHCP_OP_REPLY = 2 DHCP_MAGIC = 0x63825363 # DHCP option codes DHCP_OPT_NETMASK = 1 # I: subnet mask DHCP_OPT_TIMEOFFSET = 2 DHCP_OPT_ROUTER = 3 # s: list of router ips DHCP_OPT_TIMESERVER = 4 DHCP_OPT_NAMESERVER = 5 DHCP_OPT_DNS_SVRS = 6 # s: list of DNS servers DHCP_OPT_LOGSERV = 7 DHCP_OPT_COOKIESERV = 8 DHCP_OPT_LPRSERV = 9 DHCP_OPT_IMPSERV = 10 DHCP_OPT_RESSERV = 11 DHCP_OPT_HOSTNAME = 12 # s: client hostname DHCP_OPT_BOOTFILESIZE = 13 DHCP_OPT_DUMPFILE = 14 DHCP_OPT_DOMAIN = 15 # s: domain name DHCP_OPT_SWAPSERV = 16 DHCP_OPT_ROOTPATH = 17 DHCP_OPT_EXTENPATH = 18 DHCP_OPT_IPFORWARD = 19 DHCP_OPT_SRCROUTE = 20 DHCP_OPT_POLICYFILTER = 21 DHCP_OPT_MAXASMSIZE = 22 DHCP_OPT_IPTTL = 23 DHCP_OPT_MTUTIMEOUT = 24 DHCP_OPT_MTUTABLE = 25 DHCP_OPT_MTUSIZE = 26 DHCP_OPT_LOCALSUBNETS = 27 DHCP_OPT_BROADCASTADDR = 28 DHCP_OPT_DOMASKDISCOV = 29 DHCP_OPT_MASKSUPPLY = 30 DHCP_OPT_DOROUTEDISC = 31 DHCP_OPT_ROUTERSOLICIT = 32 DHCP_OPT_STATICROUTE = 33 DHCP_OPT_TRAILERENCAP = 34 DHCP_OPT_ARPTIMEOUT = 35 DHCP_OPT_ETHERENCAP = 36 DHCP_OPT_TCPTTL = 37 DHCP_OPT_TCPKEEPALIVE = 38 DHCP_OPT_TCPALIVEGARBAGE = 39 DHCP_OPT_NISDOMAIN = 40 DHCP_OPT_NISSERVERS = 41 DHCP_OPT_NISTIMESERV = 42 DHCP_OPT_VENDSPECIFIC = 43 DHCP_OPT_NBNS = 44 DHCP_OPT_NBDD = 45 DHCP_OPT_NBTCPIP = 46 DHCP_OPT_NBTCPSCOPE = 47 DHCP_OPT_XFONT = 48 DHCP_OPT_XDISPLAYMGR = 49 DHCP_OPT_REQ_IP = 50 # I: IP address DHCP_OPT_LEASE_SEC = 51 # I: lease seconds DHCP_OPT_OPTIONOVERLOAD = 52 DHCP_OPT_MSGTYPE = 53 # B: message type DHCP_OPT_SERVER_ID = 54 # I: server IP address DHCP_OPT_PARAM_REQ = 55 # s: list of option codes DHCP_OPT_MESSAGE = 56 DHCP_OPT_MAXMSGSIZE = 57 DHCP_OPT_RENEWTIME = 58 DHCP_OPT_REBINDTIME = 59 DHCP_OPT_VENDOR_ID = 60 # s: vendor class id DHCP_OPT_CLIENT_ID = 61 # Bs: idtype, id (idtype 0: FQDN, idtype 1: M DHCP_OPT_NISPLUSDOMAIN = 64 DHCP_OPT_NISPLUSSERVERS = 65 DHCP_OPT_MOBILEIPAGENT = 68 DHCP_OPT_SMTPSERVER = 69 DHCP_OPT_POP3SERVER = 70 DHCP_OPT_NNTPSERVER = 71 DHCP_OPT_WWWSERVER = 72 DHCP_OPT_FINGERSERVER = 73 DHCP_OPT_IRCSERVER = 74 DHCP_OPT_STSERVER = 75 DHCP_OPT_STDASERVER = 76 # DHCP message type values DHCPDISCOVER = 1 DHCPOFFER = 2 DHCPREQUEST = 3 DHCPDECLINE = 4 DHCPACK = 5 DHCPNAK = 6 DHCPRELEASE = 7 DHCPINFORM = 8 class DHCP(pypacker.Packet): __hdr__ = ( ("op", "B", DHCP_OP_REQUEST), ("hrd", "B", arp.ARP_HRD_ETH), # just like ARP.hrd ("hln", "B", 6), # and ARP.hln ("hops", "B", 0), ("xid", "I", 0xdeadbeef), ("secs", "H", 0), ("flags", "H", 0), ("ciaddr", "I", 0), ("yiaddr", "I", 0), ("siaddr", "I", 0), ("giaddr", "I", 0), # MAC + padding ("chaddr", "16s", b"\x00" * 6 + b"\x00" * 10), ("sname", "64s", b"\x00" * 64), ("file", "128s", b"\x00" * 128), ("magic", "I", DHCP_MAGIC), ("opts", None, triggerlist.TriggerList) ) """ opts = ( (DHCP_OPT_MSGTYPE, chr(DHCPDISCOVER)), (DHCP_OPT_PARAM_REQ, "".join(map(chr, (DHCP_OPT_REQ_IP, DHCP_OPT_ROUTER, DHCP_OPT_NETMASK, DHCP_OPT_DNS_SVRS)))) ) # list of (type, data) tuples """ def _dissect(self, buf): # logger.debug("DHCP: parsing options, buflen: %d" % len(buf)) self._init_triggerlist("opts", buf[28 + 16 + 64 + 128 + 4:], self.__get_opts) # logger.debug(buf[28+16+64+128+4:]) # logger.debug("amount of options after parsing: %d" % len(self.opts)) return len(buf) def __get_opts(self, buf): # logger.debug("DHCP: parsing options from: %s" % buf) opts = [] i = 0 while i < len(buf): t = buf[i] p = None # logger.debug("DHCP: adding option type %d" % t) # last option if t in [0, 0xff]: p = DHCPOptSingle(type=t) i += 1 else: dlen = buf[i + 1] p = DHCPOptMulti(type=t, len=dlen, body_bytes=buf[i + 2: i + 2 + dlen]) i += 2 + dlen # logger.debug("new option: %s" % p) opts.append(p) if t == 0xff: if i < len(buf): # padding is part of the options opts.append(Padding(buf[i:])) break return opts class DHCPOptSingle(pypacker.Packet): __hdr__ = ( ("type", "B", 0), ) class DHCPOptMulti(pypacker.Packet): __hdr__ = ( ("type", "B", 0), ("len", "B", 0), ) class Padding(pypacker.Packet): pass