dhcp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * TAP-Windows -- A kernel driver to provide virtual tap
  3. * device functionality on Windows.
  4. *
  5. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
  6. *
  7. * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
  8. * and is released under the GPL version 2 (see below).
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program (see the file COPYING included with this
  21. * distribution); if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. //=========================
  25. // Code to set DHCP options
  26. //=========================
  27. VOID
  28. SetDHCPOpt (DHCPMsg *m, void *data, unsigned int len)
  29. {
  30. if (!m->overflow)
  31. {
  32. if (m->optlen + len <= DHCP_OPTIONS_BUFFER_SIZE)
  33. {
  34. if (len)
  35. {
  36. NdisMoveMemory (m->msg.options + m->optlen, data, len);
  37. m->optlen += len;
  38. }
  39. }
  40. else
  41. {
  42. m->overflow = TRUE;
  43. }
  44. }
  45. }
  46. VOID
  47. SetDHCPOpt0 (DHCPMsg *msg, int type)
  48. {
  49. DHCPOPT0 opt;
  50. opt.type = (UCHAR) type;
  51. SetDHCPOpt (msg, &opt, sizeof (opt));
  52. }
  53. VOID
  54. SetDHCPOpt8 (DHCPMsg *msg, int type, ULONG data)
  55. {
  56. DHCPOPT8 opt;
  57. opt.type = (UCHAR) type;
  58. opt.len = sizeof (opt.data);
  59. opt.data = (UCHAR) data;
  60. SetDHCPOpt (msg, &opt, sizeof (opt));
  61. }
  62. VOID
  63. SetDHCPOpt32 (DHCPMsg *msg, int type, ULONG data)
  64. {
  65. DHCPOPT32 opt;
  66. opt.type = (UCHAR) type;
  67. opt.len = sizeof (opt.data);
  68. opt.data = data;
  69. SetDHCPOpt (msg, &opt, sizeof (opt));
  70. }
  71. //==============
  72. // Checksum code
  73. //==============
  74. USHORT
  75. ip_checksum (const UCHAR *buf, const int len_ip_header)
  76. {
  77. USHORT word16;
  78. ULONG sum = 0;
  79. int i;
  80. // make 16 bit words out of every two adjacent 8 bit words in the packet
  81. // and add them up
  82. for (i = 0; i < len_ip_header - 1; i += 2) {
  83. word16 = ((buf[i] << 8) & 0xFF00) + (buf[i+1] & 0xFF);
  84. sum += (ULONG) word16;
  85. }
  86. // take only 16 bits out of the 32 bit sum and add up the carries
  87. while (sum >> 16)
  88. sum = (sum & 0xFFFF) + (sum >> 16);
  89. // one's complement the result
  90. return ((USHORT) ~sum);
  91. }
  92. USHORT
  93. udp_checksum (const UCHAR *buf,
  94. const int len_udp,
  95. const UCHAR *src_addr,
  96. const UCHAR *dest_addr)
  97. {
  98. USHORT word16;
  99. ULONG sum = 0;
  100. int i;
  101. // make 16 bit words out of every two adjacent 8 bit words and
  102. // calculate the sum of all 16 bit words
  103. for (i = 0; i < len_udp; i += 2){
  104. word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0);
  105. sum += word16;
  106. }
  107. // add the UDP pseudo header which contains the IP source and destination addresses
  108. for (i = 0; i < 4; i += 2){
  109. word16 =((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF);
  110. sum += word16;
  111. }
  112. for (i = 0; i < 4; i += 2){
  113. word16 =((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF);
  114. sum += word16;
  115. }
  116. // the protocol number and the length of the UDP packet
  117. sum += (USHORT) IPPROTO_UDP + (USHORT) len_udp;
  118. // keep only the last 16 bits of the 32 bit calculated sum and add the carries
  119. while (sum >> 16)
  120. sum = (sum & 0xFFFF) + (sum >> 16);
  121. // Take the one's complement of sum
  122. return ((USHORT) ~sum);
  123. }
  124. //================================
  125. // Set IP and UDP packet checksums
  126. //================================
  127. VOID
  128. SetChecksumDHCPMsg (DHCPMsg *m)
  129. {
  130. // Set IP checksum
  131. m->msg.pre.ip.check = htons (ip_checksum ((UCHAR *) &m->msg.pre.ip, sizeof (IPHDR)));
  132. // Set UDP Checksum
  133. m->msg.pre.udp.check = htons (udp_checksum ((UCHAR *) &m->msg.pre.udp,
  134. sizeof (UDPHDR) + sizeof (DHCP) + m->optlen,
  135. (UCHAR *)&m->msg.pre.ip.saddr,
  136. (UCHAR *)&m->msg.pre.ip.daddr));
  137. }
  138. //===================
  139. // DHCP message tests
  140. //===================
  141. int
  142. GetDHCPMessageType (const DHCP *dhcp, const int optlen)
  143. {
  144. const UCHAR *p = (UCHAR *) (dhcp + 1);
  145. int i;
  146. for (i = 0; i < optlen; ++i)
  147. {
  148. const UCHAR type = p[i];
  149. const int room = optlen - i - 1;
  150. if (type == DHCP_END) // didn't find what we were looking for
  151. return -1;
  152. else if (type == DHCP_PAD) // no-operation
  153. ;
  154. else if (type == DHCP_MSG_TYPE) // what we are looking for
  155. {
  156. if (room >= 2)
  157. {
  158. if (p[i+1] == 1) // message length should be 1
  159. return p[i+2]; // return message type
  160. }
  161. return -1;
  162. }
  163. else // some other message
  164. {
  165. if (room >= 1)
  166. {
  167. const int len = p[i+1]; // get message length
  168. i += (len + 1); // advance to next message
  169. }
  170. }
  171. }
  172. return -1;
  173. }
  174. BOOLEAN
  175. DHCPMessageOurs (const TapAdapterPointer p_Adapter,
  176. const ETH_HEADER *eth,
  177. const IPHDR *ip,
  178. const UDPHDR *udp,
  179. const DHCP *dhcp)
  180. {
  181. // Must be UDPv4 protocol
  182. if (!(eth->proto == htons (ETH_P_IP) && ip->protocol == IPPROTO_UDP))
  183. return FALSE;
  184. // Source MAC must be our adapter
  185. if (!MAC_EQUAL (eth->src, p_Adapter->m_MAC))
  186. return FALSE;
  187. // Dest MAC must be either broadcast or our virtual DHCP server
  188. if (!(MAC_EQUAL (eth->dest, p_Adapter->m_MAC_Broadcast)
  189. || MAC_EQUAL (eth->dest, p_Adapter->m_dhcp_server_mac)))
  190. return FALSE;
  191. // Port numbers must be correct
  192. if (!(udp->dest == htons (BOOTPS_PORT)
  193. && udp->source == htons (BOOTPC_PORT)))
  194. return FALSE;
  195. // Hardware address must be MAC addr sized
  196. if (!(dhcp->hlen == sizeof (MACADDR)))
  197. return FALSE;
  198. // Hardware address must match our adapter
  199. if (!MAC_EQUAL (eth->src, dhcp->chaddr))
  200. return FALSE;
  201. return TRUE;
  202. }
  203. //=====================================================
  204. // Build all of DHCP packet except for DHCP options.
  205. // Assume that *p has been zeroed before we are called.
  206. //=====================================================
  207. VOID
  208. BuildDHCPPre (const TapAdapterPointer a,
  209. DHCPPre *p,
  210. const ETH_HEADER *eth,
  211. const IPHDR *ip,
  212. const UDPHDR *udp,
  213. const DHCP *dhcp,
  214. const int optlen,
  215. const int type)
  216. {
  217. // Should we broadcast or direct to a specific MAC / IP address?
  218. const BOOLEAN broadcast = (type == DHCPNAK
  219. || MAC_EQUAL (eth->dest, a->m_MAC_Broadcast));
  220. // Build ethernet header
  221. COPY_MAC (p->eth.src, a->m_dhcp_server_mac);
  222. if (broadcast)
  223. COPY_MAC (p->eth.dest, a->m_MAC_Broadcast);
  224. else
  225. COPY_MAC (p->eth.dest, eth->src);
  226. p->eth.proto = htons (ETH_P_IP);
  227. // Build IP header
  228. p->ip.version_len = (4 << 4) | (sizeof (IPHDR) >> 2);
  229. p->ip.tos = 0;
  230. p->ip.tot_len = htons (sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen);
  231. p->ip.id = 0;
  232. p->ip.frag_off = 0;
  233. p->ip.ttl = 16;
  234. p->ip.protocol = IPPROTO_UDP;
  235. p->ip.check = 0;
  236. p->ip.saddr = a->m_dhcp_server_ip;
  237. if (broadcast)
  238. p->ip.daddr = ~0;
  239. else
  240. p->ip.daddr = a->m_dhcp_addr;
  241. // Build UDP header
  242. p->udp.source = htons (BOOTPS_PORT);
  243. p->udp.dest = htons (BOOTPC_PORT);
  244. p->udp.len = htons (sizeof (UDPHDR) + sizeof (DHCP) + optlen);
  245. p->udp.check = 0;
  246. // Build DHCP response
  247. p->dhcp.op = BOOTREPLY;
  248. p->dhcp.htype = 1;
  249. p->dhcp.hlen = sizeof (MACADDR);
  250. p->dhcp.hops = 0;
  251. p->dhcp.xid = dhcp->xid;
  252. p->dhcp.secs = 0;
  253. p->dhcp.flags = 0;
  254. p->dhcp.ciaddr = 0;
  255. if (type == DHCPNAK)
  256. p->dhcp.yiaddr = 0;
  257. else
  258. p->dhcp.yiaddr = a->m_dhcp_addr;
  259. p->dhcp.siaddr = a->m_dhcp_server_ip;
  260. p->dhcp.giaddr = 0;
  261. COPY_MAC (p->dhcp.chaddr, eth->src);
  262. p->dhcp.magic = htonl (0x63825363);
  263. }
  264. //=============================
  265. // Build specific DHCP messages
  266. //=============================
  267. VOID
  268. SendDHCPMsg (const TapAdapterPointer a,
  269. const int type,
  270. const ETH_HEADER *eth,
  271. const IPHDR *ip,
  272. const UDPHDR *udp,
  273. const DHCP *dhcp)
  274. {
  275. DHCPMsg *pkt;
  276. if (!(type == DHCPOFFER || type == DHCPACK || type == DHCPNAK))
  277. {
  278. DEBUGP (("[TAP] SendDHCPMsg: Bad DHCP type: %d\n", type));
  279. return;
  280. }
  281. pkt = (DHCPMsg *) MemAlloc (sizeof (DHCPMsg), TRUE);
  282. if (pkt)
  283. {
  284. //-----------------------
  285. // Build DHCP options
  286. //-----------------------
  287. // Message Type
  288. SetDHCPOpt8 (pkt, DHCP_MSG_TYPE, type);
  289. // Server ID
  290. SetDHCPOpt32 (pkt, DHCP_SERVER_ID, a->m_dhcp_server_ip);
  291. if (type == DHCPOFFER || type == DHCPACK)
  292. {
  293. // Lease Time
  294. SetDHCPOpt32 (pkt, DHCP_LEASE_TIME, htonl (a->m_dhcp_lease_time));
  295. // Netmask
  296. SetDHCPOpt32 (pkt, DHCP_NETMASK, a->m_dhcp_netmask);
  297. // Other user-defined options
  298. SetDHCPOpt (pkt,
  299. a->m_dhcp_user_supplied_options_buffer,
  300. a->m_dhcp_user_supplied_options_buffer_len);
  301. }
  302. // End
  303. SetDHCPOpt0 (pkt, DHCP_END);
  304. if (!DHCPMSG_OVERFLOW (pkt))
  305. {
  306. // The initial part of the DHCP message (not including options) gets built here
  307. BuildDHCPPre (a,
  308. &pkt->msg.pre,
  309. eth,
  310. ip,
  311. udp,
  312. dhcp,
  313. DHCPMSG_LEN_OPT (pkt),
  314. type);
  315. SetChecksumDHCPMsg (pkt);
  316. DUMP_PACKET ("DHCPMsg",
  317. DHCPMSG_BUF (pkt),
  318. DHCPMSG_LEN_FULL (pkt));
  319. // Return DHCP response to kernel
  320. InjectPacketDeferred (a,
  321. DHCPMSG_BUF (pkt),
  322. DHCPMSG_LEN_FULL (pkt));
  323. }
  324. else
  325. {
  326. DEBUGP (("[TAP] SendDHCPMsg: DHCP buffer overflow\n"));
  327. }
  328. MemFree (pkt, sizeof (DHCPMsg));
  329. }
  330. }
  331. //===================================================================
  332. // Handle a BOOTPS packet produced by the local system to
  333. // resolve the address/netmask of this adapter.
  334. // If we are in TAP_WIN_IOCTL_CONFIG_DHCP_MASQ mode, reply
  335. // to the message. Return TRUE if we processed the passed
  336. // message, so that downstream stages can ignore it.
  337. //===================================================================
  338. BOOLEAN
  339. ProcessDHCP (TapAdapterPointer p_Adapter,
  340. const ETH_HEADER *eth,
  341. const IPHDR *ip,
  342. const UDPHDR *udp,
  343. const DHCP *dhcp,
  344. int optlen)
  345. {
  346. int msg_type;
  347. // Sanity check IP header
  348. if (!(ntohs (ip->tot_len) == sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen
  349. && (ntohs (ip->frag_off) & IP_OFFMASK) == 0))
  350. return TRUE;
  351. // Does this message belong to us?
  352. if (!DHCPMessageOurs (p_Adapter, eth, ip, udp, dhcp))
  353. return FALSE;
  354. msg_type = GetDHCPMessageType (dhcp, optlen);
  355. // Drop non-BOOTREQUEST messages
  356. if (dhcp->op != BOOTREQUEST)
  357. return TRUE;
  358. // Drop any messages except DHCPDISCOVER or DHCPREQUEST
  359. if (!(msg_type == DHCPDISCOVER || msg_type == DHCPREQUEST))
  360. return TRUE;
  361. // Should we reply with DHCPOFFER, DHCPACK, or DHCPNAK?
  362. if (msg_type == DHCPREQUEST
  363. && ((dhcp->ciaddr && dhcp->ciaddr != p_Adapter->m_dhcp_addr)
  364. || !p_Adapter->m_dhcp_received_discover
  365. || p_Adapter->m_dhcp_bad_requests >= BAD_DHCPREQUEST_NAK_THRESHOLD))
  366. SendDHCPMsg (p_Adapter,
  367. DHCPNAK,
  368. eth, ip, udp, dhcp);
  369. else
  370. SendDHCPMsg (p_Adapter,
  371. (msg_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK),
  372. eth, ip, udp, dhcp);
  373. // Remember if we received a DHCPDISCOVER
  374. if (msg_type == DHCPDISCOVER)
  375. p_Adapter->m_dhcp_received_discover = TRUE;
  376. // Is this a bad DHCPREQUEST?
  377. if (msg_type == DHCPREQUEST && dhcp->ciaddr && dhcp->ciaddr != p_Adapter->m_dhcp_addr)
  378. ++p_Adapter->m_dhcp_bad_requests;
  379. return TRUE;
  380. }
  381. #if DBG
  382. const char *
  383. message_op_text (int op)
  384. {
  385. switch (op)
  386. {
  387. case BOOTREQUEST:
  388. return "BOOTREQUEST";
  389. case BOOTREPLY:
  390. return "BOOTREPLY";
  391. default:
  392. return "???";
  393. }
  394. }
  395. const char *
  396. message_type_text (int type)
  397. {
  398. switch (type)
  399. {
  400. case DHCPDISCOVER:
  401. return "DHCPDISCOVER";
  402. case DHCPOFFER:
  403. return "DHCPOFFER";
  404. case DHCPREQUEST:
  405. return "DHCPREQUEST";
  406. case DHCPDECLINE:
  407. return "DHCPDECLINE";
  408. case DHCPACK:
  409. return "DHCPACK";
  410. case DHCPNAK:
  411. return "DHCPNAK";
  412. case DHCPRELEASE:
  413. return "DHCPRELEASE";
  414. case DHCPINFORM:
  415. return "DHCPINFORM";
  416. default:
  417. return "???";
  418. }
  419. }
  420. const char *
  421. port_name (int port)
  422. {
  423. switch (port)
  424. {
  425. case BOOTPS_PORT:
  426. return "BOOTPS";
  427. case BOOTPC_PORT:
  428. return "BOOTPC";
  429. default:
  430. return "unknown";
  431. }
  432. }
  433. VOID
  434. DumpDHCP (const ETH_HEADER *eth,
  435. const IPHDR *ip,
  436. const UDPHDR *udp,
  437. const DHCP *dhcp,
  438. const int optlen)
  439. {
  440. DEBUGP ((" %s", message_op_text (dhcp->op)));
  441. DEBUGP ((" %s ", message_type_text (GetDHCPMessageType (dhcp, optlen))));
  442. PrIP (ip->saddr);
  443. DEBUGP ((":%s[", port_name (ntohs (udp->source))));
  444. PrMac (eth->src);
  445. DEBUGP (("] -> "));
  446. PrIP (ip->daddr);
  447. DEBUGP ((":%s[", port_name (ntohs (udp->dest))));
  448. PrMac (eth->dest);
  449. DEBUGP (("]"));
  450. if (dhcp->ciaddr)
  451. {
  452. DEBUGP ((" ci="));
  453. PrIP (dhcp->ciaddr);
  454. }
  455. if (dhcp->yiaddr)
  456. {
  457. DEBUGP ((" yi="));
  458. PrIP (dhcp->yiaddr);
  459. }
  460. if (dhcp->siaddr)
  461. {
  462. DEBUGP ((" si="));
  463. PrIP (dhcp->siaddr);
  464. }
  465. if (dhcp->hlen == sizeof (MACADDR))
  466. {
  467. DEBUGP ((" ch="));
  468. PrMac (dhcp->chaddr);
  469. }
  470. DEBUGP ((" xid=0x%08x", ntohl (dhcp->xid)));
  471. if (ntohl (dhcp->magic) != 0x63825363)
  472. DEBUGP ((" ma=0x%08x", ntohl (dhcp->magic)));
  473. if (dhcp->htype != 1)
  474. DEBUGP ((" htype=%d", dhcp->htype));
  475. if (dhcp->hops)
  476. DEBUGP ((" hops=%d", dhcp->hops));
  477. if (ntohs (dhcp->secs))
  478. DEBUGP ((" secs=%d", ntohs (dhcp->secs)));
  479. if (ntohs (dhcp->flags))
  480. DEBUGP ((" flags=0x%04x", ntohs (dhcp->flags)));
  481. // extra stuff
  482. if (ip->version_len != 0x45)
  483. DEBUGP ((" vl=0x%02x", ip->version_len));
  484. if (ntohs (ip->tot_len) != sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen)
  485. DEBUGP ((" tl=%d", ntohs (ip->tot_len)));
  486. if (ntohs (udp->len) != sizeof (UDPHDR) + sizeof (DHCP) + optlen)
  487. DEBUGP ((" ul=%d", ntohs (udp->len)));
  488. if (ip->tos)
  489. DEBUGP ((" tos=0x%02x", ip->tos));
  490. if (ntohs (ip->id))
  491. DEBUGP ((" id=0x%04x", ntohs (ip->id)));
  492. if (ntohs (ip->frag_off))
  493. DEBUGP ((" frag_off=0x%04x", ntohs (ip->frag_off)));
  494. DEBUGP ((" ttl=%d", ip->ttl));
  495. DEBUGP ((" ic=0x%04x [0x%04x]", ntohs (ip->check),
  496. ip_checksum ((UCHAR*)ip, sizeof (IPHDR))));
  497. DEBUGP ((" uc=0x%04x [0x%04x/%d]", ntohs (udp->check),
  498. udp_checksum ((UCHAR *) udp,
  499. sizeof (UDPHDR) + sizeof (DHCP) + optlen,
  500. (UCHAR *) &ip->saddr,
  501. (UCHAR *) &ip->daddr),
  502. optlen));
  503. // Options
  504. {
  505. const UCHAR *opt = (UCHAR *) (dhcp + 1);
  506. int i;
  507. DEBUGP ((" OPT"));
  508. for (i = 0; i < optlen; ++i)
  509. {
  510. const UCHAR data = opt[i];
  511. DEBUGP ((".%d", data));
  512. }
  513. }
  514. }
  515. #endif /* DBG */