dhcp.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. """Dynamic Host Configuration Protocol."""
  2. from pypacker import pypacker, triggerlist
  3. from pypacker.layer12 import arp
  4. import logging
  5. logger = logging.getLogger("pypacker")
  6. DHCP_OP_REQUEST = 1
  7. DHCP_OP_REPLY = 2
  8. DHCP_MAGIC = 0x63825363
  9. # DHCP option codes
  10. DHCP_OPT_NETMASK = 1 # I: subnet mask
  11. DHCP_OPT_TIMEOFFSET = 2
  12. DHCP_OPT_ROUTER = 3 # s: list of router ips
  13. DHCP_OPT_TIMESERVER = 4
  14. DHCP_OPT_NAMESERVER = 5
  15. DHCP_OPT_DNS_SVRS = 6 # s: list of DNS servers
  16. DHCP_OPT_LOGSERV = 7
  17. DHCP_OPT_COOKIESERV = 8
  18. DHCP_OPT_LPRSERV = 9
  19. DHCP_OPT_IMPSERV = 10
  20. DHCP_OPT_RESSERV = 11
  21. DHCP_OPT_HOSTNAME = 12 # s: client hostname
  22. DHCP_OPT_BOOTFILESIZE = 13
  23. DHCP_OPT_DUMPFILE = 14
  24. DHCP_OPT_DOMAIN = 15 # s: domain name
  25. DHCP_OPT_SWAPSERV = 16
  26. DHCP_OPT_ROOTPATH = 17
  27. DHCP_OPT_EXTENPATH = 18
  28. DHCP_OPT_IPFORWARD = 19
  29. DHCP_OPT_SRCROUTE = 20
  30. DHCP_OPT_POLICYFILTER = 21
  31. DHCP_OPT_MAXASMSIZE = 22
  32. DHCP_OPT_IPTTL = 23
  33. DHCP_OPT_MTUTIMEOUT = 24
  34. DHCP_OPT_MTUTABLE = 25
  35. DHCP_OPT_MTUSIZE = 26
  36. DHCP_OPT_LOCALSUBNETS = 27
  37. DHCP_OPT_BROADCASTADDR = 28
  38. DHCP_OPT_DOMASKDISCOV = 29
  39. DHCP_OPT_MASKSUPPLY = 30
  40. DHCP_OPT_DOROUTEDISC = 31
  41. DHCP_OPT_ROUTERSOLICIT = 32
  42. DHCP_OPT_STATICROUTE = 33
  43. DHCP_OPT_TRAILERENCAP = 34
  44. DHCP_OPT_ARPTIMEOUT = 35
  45. DHCP_OPT_ETHERENCAP = 36
  46. DHCP_OPT_TCPTTL = 37
  47. DHCP_OPT_TCPKEEPALIVE = 38
  48. DHCP_OPT_TCPALIVEGARBAGE = 39
  49. DHCP_OPT_NISDOMAIN = 40
  50. DHCP_OPT_NISSERVERS = 41
  51. DHCP_OPT_NISTIMESERV = 42
  52. DHCP_OPT_VENDSPECIFIC = 43
  53. DHCP_OPT_NBNS = 44
  54. DHCP_OPT_NBDD = 45
  55. DHCP_OPT_NBTCPIP = 46
  56. DHCP_OPT_NBTCPSCOPE = 47
  57. DHCP_OPT_XFONT = 48
  58. DHCP_OPT_XDISPLAYMGR = 49
  59. DHCP_OPT_REQ_IP = 50 # I: IP address
  60. DHCP_OPT_LEASE_SEC = 51 # I: lease seconds
  61. DHCP_OPT_OPTIONOVERLOAD = 52
  62. DHCP_OPT_MSGTYPE = 53 # B: message type
  63. DHCP_OPT_SERVER_ID = 54 # I: server IP address
  64. DHCP_OPT_PARAM_REQ = 55 # s: list of option codes
  65. DHCP_OPT_MESSAGE = 56
  66. DHCP_OPT_MAXMSGSIZE = 57
  67. DHCP_OPT_RENEWTIME = 58
  68. DHCP_OPT_REBINDTIME = 59
  69. DHCP_OPT_VENDOR_ID = 60 # s: vendor class id
  70. DHCP_OPT_CLIENT_ID = 61 # Bs: idtype, id (idtype 0: FQDN, idtype 1: M
  71. DHCP_OPT_NISPLUSDOMAIN = 64
  72. DHCP_OPT_NISPLUSSERVERS = 65
  73. DHCP_OPT_MOBILEIPAGENT = 68
  74. DHCP_OPT_SMTPSERVER = 69
  75. DHCP_OPT_POP3SERVER = 70
  76. DHCP_OPT_NNTPSERVER = 71
  77. DHCP_OPT_WWWSERVER = 72
  78. DHCP_OPT_FINGERSERVER = 73
  79. DHCP_OPT_IRCSERVER = 74
  80. DHCP_OPT_STSERVER = 75
  81. DHCP_OPT_STDASERVER = 76
  82. # DHCP message type values
  83. DHCPDISCOVER = 1
  84. DHCPOFFER = 2
  85. DHCPREQUEST = 3
  86. DHCPDECLINE = 4
  87. DHCPACK = 5
  88. DHCPNAK = 6
  89. DHCPRELEASE = 7
  90. DHCPINFORM = 8
  91. class DHCP(pypacker.Packet):
  92. __hdr__ = (
  93. ("op", "B", DHCP_OP_REQUEST),
  94. ("hrd", "B", arp.ARP_HRD_ETH), # just like ARP.hrd
  95. ("hln", "B", 6), # and ARP.hln
  96. ("hops", "B", 0),
  97. ("xid", "I", 0xdeadbeef),
  98. ("secs", "H", 0),
  99. ("flags", "H", 0),
  100. ("ciaddr", "I", 0),
  101. ("yiaddr", "I", 0),
  102. ("siaddr", "I", 0),
  103. ("giaddr", "I", 0),
  104. # MAC + padding
  105. ("chaddr", "16s", b"\x00" * 6 + b"\x00" * 10),
  106. ("sname", "64s", b"\x00" * 64),
  107. ("file", "128s", b"\x00" * 128),
  108. ("magic", "I", DHCP_MAGIC),
  109. ("opts", None, triggerlist.TriggerList)
  110. )
  111. """
  112. opts = (
  113. (DHCP_OPT_MSGTYPE, chr(DHCPDISCOVER)),
  114. (DHCP_OPT_PARAM_REQ, "".join(map(chr, (DHCP_OPT_REQ_IP,
  115. DHCP_OPT_ROUTER,
  116. DHCP_OPT_NETMASK,
  117. DHCP_OPT_DNS_SVRS))))
  118. ) # list of (type, data) tuples
  119. """
  120. def _dissect(self, buf):
  121. # logger.debug("DHCP: parsing options, buflen: %d" % len(buf))
  122. self._init_triggerlist("opts", buf[28 + 16 + 64 + 128 + 4:], self.__get_opts)
  123. # logger.debug(buf[28+16+64+128+4:])
  124. # logger.debug("amount of options after parsing: %d" % len(self.opts))
  125. return len(buf)
  126. def __get_opts(self, buf):
  127. # logger.debug("DHCP: parsing options from: %s" % buf)
  128. opts = []
  129. i = 0
  130. while i < len(buf):
  131. t = buf[i]
  132. p = None
  133. # logger.debug("DHCP: adding option type %d" % t)
  134. # last option
  135. if t in [0, 0xff]:
  136. p = DHCPOptSingle(type=t)
  137. i += 1
  138. else:
  139. dlen = buf[i + 1]
  140. p = DHCPOptMulti(type=t, len=dlen, body_bytes=buf[i + 2: i + 2 + dlen])
  141. i += 2 + dlen
  142. # logger.debug("new option: %s" % p)
  143. opts.append(p)
  144. if t == 0xff:
  145. if i < len(buf):
  146. # padding is part of the options
  147. opts.append(Padding(buf[i:]))
  148. break
  149. return opts
  150. class DHCPOptSingle(pypacker.Packet):
  151. __hdr__ = (
  152. ("type", "B", 0),
  153. )
  154. class DHCPOptMulti(pypacker.Packet):
  155. __hdr__ = (
  156. ("type", "B", 0),
  157. ("len", "B", 0),
  158. )
  159. class Padding(pypacker.Packet):
  160. pass