Source code for dpkt.dhcp

# $Id: dhcp.py 23 2006-11-08 15:45:33Z dugsong $
# -*- coding: utf-8 -*-
"""Dynamic Host Configuration Protocol."""
from __future__ import print_function
from __future__ import absolute_import

import struct

from . import arp
from . import dpkt
from .compat import compat_ord

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: MAC)
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


[docs]class DHCP(dpkt.Packet): """Dynamic Host Configuration Protocol. TODO: Longer class information.... Attributes: __hdr__: Header fields of DHCP. TODO. """ __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), ('chaddr', '16s', 16 * b'\x00'), ('sname', '64s', 64 * b'\x00'), ('file', '128s', 128 * b'\x00'), ('magic', 'I', DHCP_MAGIC), ) 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 __len__(self): return self.__hdr_len__ + \ sum([2 + len(o[1]) for o in self.opts]) + 1 + len(self.data) def __bytes__(self): return self.pack_hdr() + self.pack_opts() + bytes(self.data)
[docs] def pack_opts(self): """Return packed options string.""" if not self.opts: return b'' l = [] for t, data in self.opts: l.append(struct.pack("BB%is"%len(data), t, len(data), data)) l.append(b'\xff') return b''.join(l)
[docs] def unpack(self, buf): dpkt.Packet.unpack(self, buf) self.chaddr = self.chaddr[:self.hln] buf = self.data l = [] while buf: t = compat_ord(buf[0]) if t == 0xff: buf = buf[1:] break elif t == 0: buf = buf[1:] else: n = compat_ord(buf[1]) l.append((t, buf[2:2 + n])) buf = buf[2 + n:] self.opts = l self.data = buf
[docs]def test_dhcp(): s = b'\x01\x01\x06\x00\xadS\xc8c\xb8\x87\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02U\x82\xf3\xa6\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5\x01\x01\xfb\x01\x01=\x07\x01\x00\x02U\x82\xf3\xa62\x04\n\x00\x01e\x0c\tGuinevere<\x08MSFT 5.07\n\x01\x0f\x03\x06,./\x1f!+\xff\x00\x00\x00\x00\x00' dhcp = DHCP(s) assert (s == bytes(dhcp)) assert isinstance(dhcp.chaddr, bytes) assert isinstance(dhcp.sname, bytes) assert isinstance(dhcp.file, bytes) # Test default construction dhcp = DHCP() assert isinstance(dhcp.chaddr, bytes) assert isinstance(dhcp.sname, bytes) assert isinstance(dhcp.file, bytes)
if __name__ == '__main__': test_dhcp() print('Tests Successful...')