dhcp.c 14 KB

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