dhcp_server_raw.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /*
  2. * File : dhcp_server_raw.c
  3. * A simple DHCP server implementation
  4. * COPYRIGHT (C) 2011-2018, Shanghai Real-Thread Technology Co., Ltd
  5. * http://www.rt-thread.com
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without modification,
  9. * are permitted provided that the following conditions are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright notice,
  12. * this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright notice,
  14. * this list of conditions and the following disclaimer in the documentation
  15. * and/or other materials provided with the distribution.
  16. * 3. The name of the author may not be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  22. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  23. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  24. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  27. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  28. * OF SUCH DAMAGE.
  29. *
  30. * Change Logs:
  31. * Date Author Notes
  32. * 2014-04-01 Ren.Haibo the first version
  33. * 2018-06-12 aozima ignore DHCP_OPTION_SERVER_ID.
  34. */
  35. #include <stdio.h>
  36. #include <stdint.h>
  37. #include <rtthread.h>
  38. #include <lwip/opt.h>
  39. #include <lwip/sockets.h>
  40. #include <lwip/inet_chksum.h>
  41. #include <netif/etharp.h>
  42. #include <netif/ethernetif.h>
  43. #include <lwip/ip.h>
  44. #include <lwip/init.h>
  45. #if (LWIP_VERSION) < 0x02000000U
  46. #error "not support old LWIP"
  47. #endif
  48. #if !LWIP_IPV4
  49. #error "must enable IPV4"
  50. #endif
  51. #if (LWIP_VERSION) >= 0x02000000U
  52. #include <lwip/prot/dhcp.h>
  53. #endif
  54. /* DHCP server option */
  55. /* allocated client ip range */
  56. #ifndef DHCPD_CLIENT_IP_MIN
  57. #define DHCPD_CLIENT_IP_MIN 2
  58. #endif
  59. #ifndef DHCPD_CLIENT_IP_MAX
  60. #define DHCPD_CLIENT_IP_MAX 254
  61. #endif
  62. /* the DHCP server address */
  63. #ifndef DHCPD_SERVER_IP
  64. #define DHCPD_SERVER_IP "192.168.169.1"
  65. #endif
  66. #define DHCP_DEBUG_PRINTF
  67. #ifdef DHCP_DEBUG_PRINTF
  68. #define DEBUG_PRINTF rt_kprintf("[DHCP] "); rt_kprintf
  69. #else
  70. #define DEBUG_PRINTF(...)
  71. #endif /* DHCP_DEBUG_PRINTF */
  72. /* we need some routines in the DHCP of lwIP */
  73. #undef LWIP_DHCP
  74. #define LWIP_DHCP 1
  75. #include <lwip/dhcp.h>
  76. /** Mac address length */
  77. #define DHCP_MAX_HLEN 6
  78. /** dhcp default live time */
  79. #define DHCP_DEFAULT_LIVE_TIME 0x80510100
  80. /** Minimum length for request before packet is parsed */
  81. #define DHCP_MIN_REQUEST_LEN 44
  82. #define LWIP_NETIF_LOCK(...)
  83. #define LWIP_NETIF_UNLOCK(...)
  84. /**
  85. * The dhcp client node struct.
  86. */
  87. struct dhcp_client_node
  88. {
  89. struct dhcp_client_node *next;
  90. u8_t chaddr[DHCP_MAX_HLEN];
  91. ip4_addr_t ipaddr;
  92. u32_t lease_end;
  93. };
  94. /**
  95. * The dhcp server struct.
  96. */
  97. struct dhcp_server
  98. {
  99. struct dhcp_server *next;
  100. struct netif *netif;
  101. struct udp_pcb *pcb;
  102. struct dhcp_client_node *node_list;
  103. ip4_addr_t start;
  104. ip4_addr_t end;
  105. ip4_addr_t current;
  106. };
  107. static u8_t *dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option);
  108. /**
  109. * The dhcp server struct list.
  110. */
  111. static struct dhcp_server *lw_dhcp_server;
  112. /**
  113. * Find a dhcp client node by mac address
  114. *
  115. * @param dhcpserver The dhcp server
  116. * @param chaddr Mac address
  117. * @param hlen Mac address length
  118. * @return dhcp client node
  119. */
  120. static struct dhcp_client_node *
  121. dhcp_client_find_by_mac(struct dhcp_server *dhcpserver, const u8_t *chaddr, u8_t hlen)
  122. {
  123. struct dhcp_client_node *node;
  124. for (node = dhcpserver->node_list; node != NULL; node = node->next)
  125. {
  126. if (memcmp(node->chaddr, chaddr, hlen) == 0)
  127. {
  128. return node;
  129. }
  130. }
  131. return NULL;
  132. }
  133. /**
  134. * Find a dhcp client node by ip address
  135. *
  136. * @param dhcpserver The dhcp server
  137. * @param chaddr Mac address
  138. * @param hlen Mac address length
  139. * @return dhcp client node
  140. */
  141. static struct dhcp_client_node *
  142. dhcp_client_find_by_ip(struct dhcp_server *dhcpserver, const ip4_addr_t *ip)
  143. {
  144. struct dhcp_client_node *node;
  145. for (node = dhcpserver->node_list; node != NULL; node = node->next)
  146. {
  147. if (ip4_addr_cmp(&node->ipaddr, ip))
  148. {
  149. return node;
  150. }
  151. }
  152. return NULL;
  153. }
  154. /**
  155. * Find a dhcp client node by ip address
  156. *
  157. * @param dhcpserver The dhcp server
  158. * @param chaddr Mac address
  159. * @param hlen Mac address length
  160. * @return dhcp client node
  161. */
  162. static struct dhcp_client_node *
  163. dhcp_client_find(struct dhcp_server *dhcpserver, struct dhcp_msg *msg,
  164. u8_t *opt_buf, u16_t len)
  165. {
  166. u8_t *opt;
  167. //u32_t ipaddr;
  168. struct dhcp_client_node *node;
  169. node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen);
  170. if (node != NULL)
  171. {
  172. return node;
  173. }
  174. opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP);
  175. if (opt != NULL)
  176. {
  177. node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2]));
  178. if (node != NULL)
  179. {
  180. return node;
  181. }
  182. }
  183. return NULL;
  184. }
  185. /**
  186. * Find a dhcp client node by ip address
  187. *
  188. * @param dhcpserver The dhcp server
  189. * @param chaddr Mac address
  190. * @param hlen Mac address length
  191. * @return dhcp client node
  192. */
  193. static struct dhcp_client_node *
  194. dhcp_client_alloc(struct dhcp_server *dhcpserver, struct dhcp_msg *msg,
  195. u8_t *opt_buf, u16_t len)
  196. {
  197. u8_t *opt;
  198. u32_t ipaddr;
  199. struct dhcp_client_node *node;
  200. node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen);
  201. if (node != NULL)
  202. {
  203. return node;
  204. }
  205. opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP);
  206. if (opt != NULL)
  207. {
  208. node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2]));
  209. if (node != NULL)
  210. {
  211. return node;
  212. }
  213. }
  214. dhcp_alloc_again:
  215. node = dhcp_client_find_by_ip(dhcpserver, &dhcpserver->current);
  216. if (node != NULL)
  217. {
  218. ipaddr = (ntohl(dhcpserver->current.addr) + 1);
  219. if (ipaddr > ntohl(dhcpserver->end.addr))
  220. {
  221. ipaddr = ntohl(dhcpserver->start.addr);
  222. }
  223. dhcpserver->current.addr = htonl(ipaddr);
  224. goto dhcp_alloc_again;
  225. }
  226. node = (struct dhcp_client_node *)mem_malloc(sizeof(struct dhcp_client_node));
  227. if (node == NULL)
  228. {
  229. return NULL;
  230. }
  231. SMEMCPY(node->chaddr, msg->chaddr, msg->hlen);
  232. node->ipaddr = dhcpserver->current;
  233. node->next = dhcpserver->node_list;
  234. dhcpserver->node_list = node;
  235. return node;
  236. }
  237. /**
  238. * find option from buffer.
  239. *
  240. * @param buf The buffer to find option
  241. * @param len The buffer length
  242. * @param option Which option to find
  243. * @return dhcp option buffer
  244. */
  245. static u8_t *
  246. dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option)
  247. {
  248. u8_t *end = buf + len;
  249. while ((buf < end) && (*buf != DHCP_OPTION_END))
  250. {
  251. if (*buf == option)
  252. {
  253. return buf;
  254. }
  255. buf += (buf[1] + 2);
  256. }
  257. return NULL;
  258. }
  259. /**
  260. * If an incoming DHCP message is in response to us, then trigger the state machine
  261. */
  262. static void
  263. dhcp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *recv_addr, u16_t port)
  264. {
  265. struct dhcp_server *dhcp_server = (struct dhcp_server *)arg;
  266. struct dhcp_msg *msg;
  267. struct pbuf *q;
  268. u8_t *opt_buf;
  269. u8_t *opt;
  270. struct dhcp_client_node *node;
  271. u8_t msg_type;
  272. u16_t length;
  273. ip_addr_t addr = *recv_addr;
  274. u32_t tmp;
  275. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("[%s:%d] %c%c recv %d\n", __FUNCTION__, __LINE__, dhcp_server->netif->name[0], dhcp_server->netif->name[1], p->tot_len));
  276. /* prevent warnings about unused arguments */
  277. LWIP_UNUSED_ARG(pcb);
  278. LWIP_UNUSED_ARG(addr);
  279. LWIP_UNUSED_ARG(port);
  280. if (p->len < DHCP_MIN_REQUEST_LEN)
  281. {
  282. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP request message or pbuf too short\n"));
  283. pbuf_free(p);
  284. return;
  285. }
  286. q = pbuf_alloc(PBUF_TRANSPORT, 1500, PBUF_RAM);
  287. if (q == NULL)
  288. {
  289. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloc dhcp_msg failed!\n"));
  290. pbuf_free(p);
  291. return;
  292. }
  293. if (q->tot_len < p->tot_len)
  294. {
  295. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloc dhcp_msg too small %d:%d\n", q->tot_len, p->tot_len));
  296. pbuf_free(p);
  297. return;
  298. }
  299. pbuf_copy(q, p);
  300. pbuf_free(p);
  301. msg = (struct dhcp_msg *)q->payload;
  302. if (msg->op != DHCP_BOOTREQUEST)
  303. {
  304. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP request message, but type %"U16_F"\n", (u16_t)msg->op));
  305. goto free_pbuf_and_return;
  306. }
  307. if (msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE))
  308. {
  309. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("bad DHCP_MAGIC_COOKIE!\n"));
  310. goto free_pbuf_and_return;
  311. }
  312. if (msg->hlen > DHCP_MAX_HLEN)
  313. {
  314. goto free_pbuf_and_return;
  315. }
  316. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  317. length = q->tot_len - DHCP_OPTIONS_OFS;
  318. opt = dhcp_server_option_find(opt_buf, length, DHCP_OPTION_MESSAGE_TYPE);
  319. if (opt)
  320. {
  321. msg_type = *(opt + 2);
  322. if (msg_type == DHCP_DISCOVER)
  323. {
  324. node = dhcp_client_alloc(dhcp_server, msg, opt_buf, length);
  325. if (node == NULL)
  326. {
  327. goto free_pbuf_and_return;
  328. }
  329. node->lease_end = DHCP_DEFAULT_LIVE_TIME;
  330. /* create dhcp offer and send */
  331. msg->op = DHCP_BOOTREPLY;
  332. msg->hops = 0;
  333. msg->secs = 0;
  334. SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
  335. msg->sname[0] = '\0';
  336. msg->file[0] = '\0';
  337. msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
  338. SMEMCPY(&msg->yiaddr, &node->ipaddr, 4);
  339. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  340. /* add msg type */
  341. *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
  342. *opt_buf++ = 1;
  343. *opt_buf++ = DHCP_OFFER;
  344. /* add server id */
  345. *opt_buf++ = DHCP_OPTION_SERVER_ID;
  346. *opt_buf++ = 4;
  347. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  348. opt_buf += 4;
  349. /* add_lease_time */
  350. *opt_buf++ = DHCP_OPTION_LEASE_TIME;
  351. *opt_buf++ = 4;
  352. tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME);
  353. SMEMCPY(opt_buf, &tmp, 4);
  354. opt_buf += 4;
  355. /* add config */
  356. *opt_buf++ = DHCP_OPTION_SUBNET_MASK;
  357. *opt_buf++ = 4;
  358. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4);
  359. opt_buf += 4;
  360. *opt_buf++ = DHCP_OPTION_DNS_SERVER;
  361. *opt_buf++ = 4;
  362. #ifdef DHCP_DNS_SERVER_IP
  363. {
  364. ip_addr_t dns_addr;
  365. ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr);
  366. SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4);
  367. }
  368. #else
  369. /* default use gatewary dns server */
  370. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  371. #endif /* DHCP_DNS_SERVER_IP */
  372. opt_buf += 4;
  373. *opt_buf++ = DHCP_OPTION_ROUTER;
  374. *opt_buf++ = 4;
  375. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4);
  376. opt_buf += 4;
  377. /* add option end */
  378. *opt_buf++ = DHCP_OPTION_END;
  379. length = (u32_t)opt_buf - (u32_t)msg;
  380. if (length < q->tot_len)
  381. {
  382. pbuf_realloc(q, length);
  383. }
  384. ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
  385. udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
  386. }
  387. else
  388. {
  389. if (1)
  390. {
  391. if (msg_type == DHCP_REQUEST)
  392. {
  393. node = dhcp_client_find(dhcp_server, msg, opt_buf, length);
  394. if (node != NULL)
  395. {
  396. /* Send ack */
  397. node->lease_end = DHCP_DEFAULT_LIVE_TIME;
  398. /* create dhcp offer and send */
  399. msg->op = DHCP_BOOTREPLY;
  400. msg->hops = 0;
  401. msg->secs = 0;
  402. SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
  403. msg->sname[0] = '\0';
  404. msg->file[0] = '\0';
  405. msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
  406. SMEMCPY(&msg->yiaddr, &node->ipaddr, 4);
  407. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  408. /* add msg type */
  409. *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
  410. *opt_buf++ = 1;
  411. *opt_buf++ = DHCP_ACK;
  412. /* add server id */
  413. *opt_buf++ = DHCP_OPTION_SERVER_ID;
  414. *opt_buf++ = 4;
  415. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  416. opt_buf += 4;
  417. /* add_lease_time */
  418. *opt_buf++ = DHCP_OPTION_LEASE_TIME;
  419. *opt_buf++ = 4;
  420. tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME);
  421. SMEMCPY(opt_buf, &tmp, 4);
  422. opt_buf += 4;
  423. /* add config */
  424. *opt_buf++ = DHCP_OPTION_SUBNET_MASK;
  425. *opt_buf++ = 4;
  426. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4);
  427. opt_buf += 4;
  428. *opt_buf++ = DHCP_OPTION_DNS_SERVER;
  429. *opt_buf++ = 4;
  430. #ifdef DHCP_DNS_SERVER_IP
  431. {
  432. ip_addr_t dns_addr;
  433. ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr);
  434. SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4);
  435. }
  436. #else
  437. /* default use gatewary dns server */
  438. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  439. #endif /* DHCP_DNS_SERVER_IP */
  440. opt_buf += 4;
  441. *opt_buf++ = DHCP_OPTION_ROUTER;
  442. *opt_buf++ = 4;
  443. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4);
  444. opt_buf += 4;
  445. /* add option end */
  446. *opt_buf++ = DHCP_OPTION_END;
  447. length = (u32_t)opt_buf - (u32_t)msg;
  448. if (length < q->tot_len)
  449. {
  450. pbuf_realloc(q, length);
  451. }
  452. ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
  453. udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
  454. }
  455. else
  456. {
  457. /* Send no ack */
  458. /* create dhcp offer and send */
  459. msg->op = DHCP_BOOTREPLY;
  460. msg->hops = 0;
  461. msg->secs = 0;
  462. SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
  463. msg->sname[0] = '\0';
  464. msg->file[0] = '\0';
  465. msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
  466. memset(&msg->yiaddr, 0, 4);
  467. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  468. /* add msg type */
  469. *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
  470. *opt_buf++ = 1;
  471. *opt_buf++ = DHCP_NAK;
  472. /* add server id */
  473. *opt_buf++ = DHCP_OPTION_SERVER_ID;
  474. *opt_buf++ = 4;
  475. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  476. opt_buf += 4;
  477. /* add option end */
  478. *opt_buf++ = DHCP_OPTION_END;
  479. length = (u32_t)opt_buf - (u32_t)msg;
  480. if (length < q->tot_len)
  481. {
  482. pbuf_realloc(q, length);
  483. }
  484. ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
  485. udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
  486. }
  487. }
  488. else if (msg_type == DHCP_RELEASE)
  489. {
  490. struct dhcp_client_node *node_prev = NULL;
  491. for (node = dhcp_server->node_list; node != NULL; node = node->next)
  492. {
  493. if (memcmp(node->chaddr, msg->chaddr, msg->hlen) == 0)
  494. {
  495. if (node == dhcp_server->node_list)
  496. {
  497. dhcp_server->node_list = node->next;
  498. }
  499. else
  500. {
  501. node_prev->next = node->next;
  502. }
  503. break;
  504. }
  505. node_prev = node;
  506. node = node->next;
  507. }
  508. if (node != NULL)
  509. {
  510. mem_free(node);
  511. }
  512. }
  513. else if (msg_type == DHCP_DECLINE)
  514. {
  515. ;
  516. }
  517. else if (msg_type == DHCP_INFORM)
  518. {
  519. ;
  520. }
  521. }
  522. }
  523. }
  524. free_pbuf_and_return:
  525. pbuf_free(q);
  526. }
  527. /**
  528. * start dhcp server for a netif
  529. *
  530. * @param netif The netif which use dhcp server
  531. * @param start The Start IP address
  532. * @param end The netif which use dhcp server
  533. * @return lwIP error code
  534. * - ERR_OK - No error
  535. * - ERR_MEM - Out of memory
  536. */
  537. err_t
  538. dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end)
  539. {
  540. struct dhcp_server *dhcp_server;
  541. /* If this netif alreday use the dhcp server. */
  542. for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next)
  543. {
  544. if (dhcp_server->netif == netif)
  545. {
  546. dhcp_server->start = *start;
  547. dhcp_server->end = *end;
  548. dhcp_server->current = *start;
  549. return ERR_OK;
  550. }
  551. }
  552. dhcp_server = NULL;
  553. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting new DHCP server\n"));
  554. dhcp_server = (struct dhcp_server *)mem_malloc(sizeof(struct dhcp_server));
  555. if (dhcp_server == NULL)
  556. {
  557. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not allocate dhcp\n"));
  558. return ERR_MEM;
  559. }
  560. /* clear data structure */
  561. memset(dhcp_server, 0, sizeof(struct dhcp_server));
  562. /* store this dhcp server to list */
  563. dhcp_server->next = lw_dhcp_server;
  564. lw_dhcp_server = dhcp_server;
  565. dhcp_server->netif = netif;
  566. dhcp_server->node_list = NULL;
  567. dhcp_server->start = *start;
  568. dhcp_server->end = *end;
  569. dhcp_server->current = *start;
  570. /* allocate UDP PCB */
  571. dhcp_server->pcb = udp_new();
  572. if (dhcp_server->pcb == NULL)
  573. {
  574. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not obtain pcb\n"));
  575. return ERR_MEM;
  576. }
  577. ip_set_option(dhcp_server->pcb, SOF_BROADCAST);
  578. /* set up local and remote port for the pcb */
  579. udp_bind(dhcp_server->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
  580. //udp_connect(dhcp_server->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
  581. /* set up the recv callback and argument */
  582. udp_recv(dhcp_server->pcb, dhcp_server_recv, dhcp_server);
  583. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting DHCP server\n"));
  584. return ERR_OK;
  585. }
  586. void dhcpd_start(const char *netif_name)
  587. {
  588. struct netif *netif = netif_list;
  589. err_t res;
  590. DEBUG_PRINTF("%s: %s\r\n", __FUNCTION__, netif_name);
  591. LWIP_NETIF_LOCK();
  592. if (strlen(netif_name) > sizeof(netif->name))
  593. {
  594. DEBUG_PRINTF("network interface name too long!\r\n");
  595. goto _exit;
  596. }
  597. while (netif != RT_NULL)
  598. {
  599. if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0)
  600. break;
  601. netif = netif->next;
  602. if (netif == RT_NULL)
  603. {
  604. DEBUG_PRINTF("network interface: %s not found!\r\n", netif_name);
  605. break;
  606. }
  607. }
  608. if (netif == RT_NULL)
  609. {
  610. goto _exit;
  611. }
  612. if (1)
  613. {
  614. extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr);
  615. dhcp_stop(netif);
  616. set_if(netif_name, DHCPD_SERVER_IP, "0.0.0.0", "255.255.255.0");
  617. netif_set_up(netif);
  618. }
  619. {
  620. char str_tmp[4 * 4 + 4] = DHCPD_SERVER_IP;
  621. char *p = str_tmp;
  622. ip4_addr_t ip_start, ip_end;
  623. p = strchr(str_tmp, '.');
  624. if (p)
  625. {
  626. p = strchr(p + 1, '.');
  627. if (p)
  628. {
  629. p = strchr(p + 1, '.');
  630. }
  631. }
  632. if (!p)
  633. {
  634. DEBUG_PRINTF("DHCPD_SERVER_IP: %s error!\r\n", str_tmp);
  635. goto _exit;
  636. }
  637. p = p + 1; /* move to xxx.xxx.xxx.^ */
  638. sprintf(p, "%d", DHCPD_CLIENT_IP_MIN);
  639. ip4addr_aton(str_tmp, &ip_start);
  640. DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp);
  641. sprintf(p, "%d", DHCPD_CLIENT_IP_MAX);
  642. ip4addr_aton(str_tmp, &ip_end);
  643. DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp);
  644. res = dhcp_server_start(netif, &ip_start, &ip_end);
  645. if (res != 0)
  646. {
  647. DEBUG_PRINTF("dhcp_server_start res: %s.\r\n", res);
  648. }
  649. }
  650. _exit:
  651. LWIP_NETIF_UNLOCK();
  652. return;
  653. }