dhcp_server_raw.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. /*
  2. * File : dhcp_server_raw.c
  3. * A simple DHCP server implementation
  4. * COPYRIGHT (C) 2011-2021, 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. #ifndef DHCP_SERVER_PORT
  85. #define DHCP_SERVER_PORT 67
  86. #endif
  87. /**
  88. * The dhcp client node struct.
  89. */
  90. struct dhcp_client_node
  91. {
  92. struct dhcp_client_node *next;
  93. u8_t chaddr[DHCP_MAX_HLEN];
  94. ip4_addr_t ipaddr;
  95. u32_t lease_end;
  96. };
  97. /**
  98. * The dhcp server struct.
  99. */
  100. struct dhcp_server
  101. {
  102. struct dhcp_server *next;
  103. struct netif *netif;
  104. struct udp_pcb *pcb;
  105. struct dhcp_client_node *node_list;
  106. ip4_addr_t start;
  107. ip4_addr_t end;
  108. ip4_addr_t current;
  109. };
  110. static u8_t *dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option);
  111. /**
  112. * The dhcp server struct list.
  113. */
  114. static struct dhcp_server *lw_dhcp_server;
  115. /**
  116. * Find a dhcp client node by mac address
  117. *
  118. * @param dhcpserver The dhcp server
  119. * @param chaddr Mac address
  120. * @param hlen Mac address length
  121. * @return dhcp client node
  122. */
  123. static struct dhcp_client_node *
  124. dhcp_client_find_by_mac(struct dhcp_server *dhcpserver, const u8_t *chaddr, u8_t hlen)
  125. {
  126. struct dhcp_client_node *node;
  127. for (node = dhcpserver->node_list; node != NULL; node = node->next)
  128. {
  129. if (memcmp(node->chaddr, chaddr, hlen) == 0)
  130. {
  131. return node;
  132. }
  133. }
  134. return NULL;
  135. }
  136. /**
  137. * Find a dhcp client node by ip address
  138. *
  139. * @param dhcpserver The dhcp server
  140. * @param chaddr Mac address
  141. * @param hlen Mac address length
  142. * @return dhcp client node
  143. */
  144. static struct dhcp_client_node *
  145. dhcp_client_find_by_ip(struct dhcp_server *dhcpserver, const ip4_addr_t *ip)
  146. {
  147. struct dhcp_client_node *node;
  148. for (node = dhcpserver->node_list; node != NULL; node = node->next)
  149. {
  150. if (ip4_addr_cmp(&node->ipaddr, ip))
  151. {
  152. return node;
  153. }
  154. }
  155. return NULL;
  156. }
  157. /**
  158. * Find a dhcp client node by ip address
  159. *
  160. * @param dhcpserver The dhcp server
  161. * @param chaddr Mac address
  162. * @param hlen Mac address length
  163. * @return dhcp client node
  164. */
  165. static struct dhcp_client_node *
  166. dhcp_client_find(struct dhcp_server *dhcpserver, struct dhcp_msg *msg,
  167. u8_t *opt_buf, u16_t len)
  168. {
  169. u8_t *opt;
  170. //u32_t ipaddr;
  171. struct dhcp_client_node *node;
  172. node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen);
  173. if (node != NULL)
  174. {
  175. return node;
  176. }
  177. opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP);
  178. if (opt != NULL)
  179. {
  180. node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2]));
  181. if (node != NULL)
  182. {
  183. return node;
  184. }
  185. }
  186. return NULL;
  187. }
  188. /**
  189. * Find a dhcp client node by ip address
  190. *
  191. * @param dhcpserver The dhcp server
  192. * @param chaddr Mac address
  193. * @param hlen Mac address length
  194. * @return dhcp client node
  195. */
  196. static struct dhcp_client_node *
  197. dhcp_client_alloc(struct dhcp_server *dhcpserver, struct dhcp_msg *msg,
  198. u8_t *opt_buf, u16_t len)
  199. {
  200. u8_t *opt;
  201. u32_t ipaddr;
  202. struct dhcp_client_node *node;
  203. node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen);
  204. if (node != NULL)
  205. {
  206. return node;
  207. }
  208. opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP);
  209. if (opt != NULL)
  210. {
  211. node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2]));
  212. if (node != NULL)
  213. {
  214. return node;
  215. }
  216. }
  217. dhcp_alloc_again:
  218. node = dhcp_client_find_by_ip(dhcpserver, &dhcpserver->current);
  219. if (node != NULL)
  220. {
  221. ipaddr = (ntohl(dhcpserver->current.addr) + 1);
  222. if (ipaddr > ntohl(dhcpserver->end.addr))
  223. {
  224. ipaddr = ntohl(dhcpserver->start.addr);
  225. }
  226. dhcpserver->current.addr = htonl(ipaddr);
  227. goto dhcp_alloc_again;
  228. }
  229. node = (struct dhcp_client_node *)mem_malloc(sizeof(struct dhcp_client_node));
  230. if (node == NULL)
  231. {
  232. return NULL;
  233. }
  234. SMEMCPY(node->chaddr, msg->chaddr, msg->hlen);
  235. node->ipaddr = dhcpserver->current;
  236. node->next = dhcpserver->node_list;
  237. dhcpserver->node_list = node;
  238. return node;
  239. }
  240. /**
  241. * find option from buffer.
  242. *
  243. * @param buf The buffer to find option
  244. * @param len The buffer length
  245. * @param option Which option to find
  246. * @return dhcp option buffer
  247. */
  248. static u8_t *
  249. dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option)
  250. {
  251. u8_t *end = buf + len;
  252. while ((buf < end) && (*buf != DHCP_OPTION_END))
  253. {
  254. if (*buf == option)
  255. {
  256. return buf;
  257. }
  258. buf += (buf[1] + 2);
  259. }
  260. return NULL;
  261. }
  262. /**
  263. * If an incoming DHCP message is in response to us, then trigger the state machine
  264. */
  265. static void
  266. dhcp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *recv_addr, u16_t port)
  267. {
  268. struct dhcp_server *dhcp_server = (struct dhcp_server *)arg;
  269. struct dhcp_msg *msg;
  270. struct pbuf *q;
  271. u8_t *opt_buf;
  272. u8_t *opt;
  273. struct dhcp_client_node *node;
  274. u8_t msg_type;
  275. u16_t length;
  276. ip_addr_t addr = *recv_addr;
  277. u32_t tmp;
  278. 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));
  279. /* prevent warnings about unused arguments */
  280. LWIP_UNUSED_ARG(pcb);
  281. LWIP_UNUSED_ARG(addr);
  282. LWIP_UNUSED_ARG(port);
  283. if (p->len < DHCP_MIN_REQUEST_LEN)
  284. {
  285. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP request message or pbuf too short\n"));
  286. pbuf_free(p);
  287. return;
  288. }
  289. q = pbuf_alloc(PBUF_TRANSPORT, 1500, PBUF_RAM);
  290. if (q == NULL)
  291. {
  292. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloc dhcp_msg failed!\n"));
  293. pbuf_free(p);
  294. return;
  295. }
  296. if (q->tot_len < p->tot_len)
  297. {
  298. 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));
  299. pbuf_free(p);
  300. return;
  301. }
  302. pbuf_copy(q, p);
  303. pbuf_free(p);
  304. msg = (struct dhcp_msg *)q->payload;
  305. if (msg->op != DHCP_BOOTREQUEST)
  306. {
  307. 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));
  308. goto free_pbuf_and_return;
  309. }
  310. if (msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE))
  311. {
  312. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("bad DHCP_MAGIC_COOKIE!\n"));
  313. goto free_pbuf_and_return;
  314. }
  315. if (msg->hlen > DHCP_MAX_HLEN)
  316. {
  317. goto free_pbuf_and_return;
  318. }
  319. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  320. length = q->tot_len - DHCP_OPTIONS_OFS;
  321. opt = dhcp_server_option_find(opt_buf, length, DHCP_OPTION_MESSAGE_TYPE);
  322. if (opt)
  323. {
  324. msg_type = *(opt + 2);
  325. if (msg_type == DHCP_DISCOVER)
  326. {
  327. node = dhcp_client_alloc(dhcp_server, msg, opt_buf, length);
  328. if (node == NULL)
  329. {
  330. goto free_pbuf_and_return;
  331. }
  332. node->lease_end = DHCP_DEFAULT_LIVE_TIME;
  333. /* create dhcp offer and send */
  334. msg->op = DHCP_BOOTREPLY;
  335. msg->hops = 0;
  336. msg->secs = 0;
  337. SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
  338. msg->sname[0] = '\0';
  339. msg->file[0] = '\0';
  340. msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
  341. SMEMCPY(&msg->yiaddr, &node->ipaddr, 4);
  342. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  343. /* add msg type */
  344. *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
  345. *opt_buf++ = 1;
  346. *opt_buf++ = DHCP_OFFER;
  347. /* add server id */
  348. *opt_buf++ = DHCP_OPTION_SERVER_ID;
  349. *opt_buf++ = 4;
  350. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  351. opt_buf += 4;
  352. /* add_lease_time */
  353. *opt_buf++ = DHCP_OPTION_LEASE_TIME;
  354. *opt_buf++ = 4;
  355. tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME);
  356. SMEMCPY(opt_buf, &tmp, 4);
  357. opt_buf += 4;
  358. /* add config */
  359. *opt_buf++ = DHCP_OPTION_SUBNET_MASK;
  360. *opt_buf++ = 4;
  361. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4);
  362. opt_buf += 4;
  363. *opt_buf++ = DHCP_OPTION_DNS_SERVER;
  364. *opt_buf++ = 4;
  365. #ifdef DHCP_DNS_SERVER_IP
  366. {
  367. ip_addr_t dns_addr;
  368. ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr);
  369. SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4);
  370. }
  371. #else
  372. /* default use gatewary dns server */
  373. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  374. #endif /* DHCP_DNS_SERVER_IP */
  375. opt_buf += 4;
  376. *opt_buf++ = DHCP_OPTION_ROUTER;
  377. *opt_buf++ = 4;
  378. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4);
  379. opt_buf += 4;
  380. /* add option end */
  381. *opt_buf++ = DHCP_OPTION_END;
  382. length = (u32_t)opt_buf - (u32_t)msg;
  383. if (length < q->tot_len)
  384. {
  385. pbuf_realloc(q, length);
  386. }
  387. ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
  388. udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
  389. }
  390. else
  391. {
  392. if (1)
  393. {
  394. if (msg_type == DHCP_REQUEST)
  395. {
  396. node = dhcp_client_find(dhcp_server, msg, opt_buf, length);
  397. if (node != NULL)
  398. {
  399. /* Send ack */
  400. node->lease_end = DHCP_DEFAULT_LIVE_TIME;
  401. /* create dhcp offer and send */
  402. msg->op = DHCP_BOOTREPLY;
  403. msg->hops = 0;
  404. msg->secs = 0;
  405. SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
  406. msg->sname[0] = '\0';
  407. msg->file[0] = '\0';
  408. msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
  409. SMEMCPY(&msg->yiaddr, &node->ipaddr, 4);
  410. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  411. /* add msg type */
  412. *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
  413. *opt_buf++ = 1;
  414. *opt_buf++ = DHCP_ACK;
  415. /* add server id */
  416. *opt_buf++ = DHCP_OPTION_SERVER_ID;
  417. *opt_buf++ = 4;
  418. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  419. opt_buf += 4;
  420. /* add_lease_time */
  421. *opt_buf++ = DHCP_OPTION_LEASE_TIME;
  422. *opt_buf++ = 4;
  423. tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME);
  424. SMEMCPY(opt_buf, &tmp, 4);
  425. opt_buf += 4;
  426. /* add config */
  427. *opt_buf++ = DHCP_OPTION_SUBNET_MASK;
  428. *opt_buf++ = 4;
  429. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4);
  430. opt_buf += 4;
  431. *opt_buf++ = DHCP_OPTION_DNS_SERVER;
  432. *opt_buf++ = 4;
  433. #ifdef DHCP_DNS_SERVER_IP
  434. {
  435. ip_addr_t dns_addr;
  436. ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr);
  437. SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4);
  438. }
  439. #else
  440. /* default use gatewary dns server */
  441. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  442. #endif /* DHCP_DNS_SERVER_IP */
  443. opt_buf += 4;
  444. *opt_buf++ = DHCP_OPTION_ROUTER;
  445. *opt_buf++ = 4;
  446. SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4);
  447. opt_buf += 4;
  448. /* add option end */
  449. *opt_buf++ = DHCP_OPTION_END;
  450. length = (u32_t)opt_buf - (u32_t)msg;
  451. if (length < q->tot_len)
  452. {
  453. pbuf_realloc(q, length);
  454. }
  455. ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
  456. udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
  457. }
  458. else
  459. {
  460. /* Send no ack */
  461. /* create dhcp offer and send */
  462. msg->op = DHCP_BOOTREPLY;
  463. msg->hops = 0;
  464. msg->secs = 0;
  465. SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4);
  466. msg->sname[0] = '\0';
  467. msg->file[0] = '\0';
  468. msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE);
  469. memset(&msg->yiaddr, 0, 4);
  470. opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS;
  471. /* add msg type */
  472. *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE;
  473. *opt_buf++ = 1;
  474. *opt_buf++ = DHCP_NAK;
  475. /* add server id */
  476. *opt_buf++ = DHCP_OPTION_SERVER_ID;
  477. *opt_buf++ = 4;
  478. SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4);
  479. opt_buf += 4;
  480. /* add option end */
  481. *opt_buf++ = DHCP_OPTION_END;
  482. length = (u32_t)opt_buf - (u32_t)msg;
  483. if (length < q->tot_len)
  484. {
  485. pbuf_realloc(q, length);
  486. }
  487. ip_2_ip4(&addr)->addr = INADDR_BROADCAST;
  488. udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif);
  489. }
  490. }
  491. else if (msg_type == DHCP_RELEASE)
  492. {
  493. struct dhcp_client_node *node_prev = NULL;
  494. for (node = dhcp_server->node_list; node != NULL; node = node->next)
  495. {
  496. if (memcmp(node->chaddr, msg->chaddr, msg->hlen) == 0)
  497. {
  498. if (node == dhcp_server->node_list)
  499. {
  500. dhcp_server->node_list = node->next;
  501. }
  502. else
  503. {
  504. node_prev->next = node->next;
  505. }
  506. break;
  507. }
  508. node_prev = node;
  509. node = node->next;
  510. }
  511. if (node != NULL)
  512. {
  513. mem_free(node);
  514. }
  515. }
  516. else if (msg_type == DHCP_DECLINE)
  517. {
  518. ;
  519. }
  520. else if (msg_type == DHCP_INFORM)
  521. {
  522. ;
  523. }
  524. }
  525. }
  526. }
  527. free_pbuf_and_return:
  528. pbuf_free(q);
  529. }
  530. /**
  531. * start dhcp server for a netif
  532. *
  533. * @param netif The netif which use dhcp server
  534. * @param start The Start IP address
  535. * @param end The netif which use dhcp server
  536. * @return lwIP error code
  537. * - ERR_OK - No error
  538. * - ERR_MEM - Out of memory
  539. */
  540. err_t
  541. dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end)
  542. {
  543. struct dhcp_server *dhcp_server;
  544. /* If this netif alreday use the dhcp server. */
  545. for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next)
  546. {
  547. if (dhcp_server->netif == netif)
  548. {
  549. dhcp_server->start = *start;
  550. dhcp_server->end = *end;
  551. dhcp_server->current = *start;
  552. return ERR_OK;
  553. }
  554. }
  555. dhcp_server = NULL;
  556. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting new DHCP server\n"));
  557. dhcp_server = (struct dhcp_server *)mem_malloc(sizeof(struct dhcp_server));
  558. if (dhcp_server == NULL)
  559. {
  560. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not allocate dhcp\n"));
  561. return ERR_MEM;
  562. }
  563. /* clear data structure */
  564. memset(dhcp_server, 0, sizeof(struct dhcp_server));
  565. /* store this dhcp server to list */
  566. dhcp_server->next = lw_dhcp_server;
  567. lw_dhcp_server = dhcp_server;
  568. dhcp_server->netif = netif;
  569. dhcp_server->node_list = NULL;
  570. dhcp_server->start = *start;
  571. dhcp_server->end = *end;
  572. dhcp_server->current = *start;
  573. /* allocate UDP PCB */
  574. dhcp_server->pcb = udp_new();
  575. if (dhcp_server->pcb == NULL)
  576. {
  577. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not obtain pcb\n"));
  578. return ERR_MEM;
  579. }
  580. ip_set_option(dhcp_server->pcb, SOF_BROADCAST);
  581. /* set up local and remote port for the pcb */
  582. udp_bind(dhcp_server->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT);
  583. //udp_connect(dhcp_server->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT);
  584. /* set up the recv callback and argument */
  585. udp_recv(dhcp_server->pcb, dhcp_server_recv, dhcp_server);
  586. LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting DHCP server\n"));
  587. return ERR_OK;
  588. }
  589. extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr);
  590. void dhcpd_start(const char *netif_name)
  591. {
  592. struct netif *netif = netif_list;
  593. err_t res;
  594. DEBUG_PRINTF("%s: %s\r\n", __FUNCTION__, netif_name);
  595. LWIP_NETIF_LOCK();
  596. if (strlen(netif_name) > sizeof(netif->name))
  597. {
  598. DEBUG_PRINTF("network interface name too long!\r\n");
  599. goto _exit;
  600. }
  601. while (netif != RT_NULL)
  602. {
  603. if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0)
  604. break;
  605. netif = netif->next;
  606. if (netif == RT_NULL)
  607. {
  608. DEBUG_PRINTF("network interface: %s not found!\r\n", netif_name);
  609. break;
  610. }
  611. }
  612. if (netif == RT_NULL)
  613. {
  614. goto _exit;
  615. }
  616. if (1)
  617. {
  618. dhcp_stop(netif);
  619. set_if(netif_name, DHCPD_SERVER_IP, "0.0.0.0", "255.255.255.0");
  620. netif_set_up(netif);
  621. }
  622. {
  623. char str_tmp[4 * 4 + 4] = DHCPD_SERVER_IP;
  624. char *p = str_tmp;
  625. ip4_addr_t ip_start, ip_end;
  626. p = strchr(str_tmp, '.');
  627. if (p)
  628. {
  629. p = strchr(p + 1, '.');
  630. if (p)
  631. {
  632. p = strchr(p + 1, '.');
  633. }
  634. }
  635. if (!p)
  636. {
  637. DEBUG_PRINTF("DHCPD_SERVER_IP: %s error!\r\n", str_tmp);
  638. goto _exit;
  639. }
  640. p = p + 1; /* move to xxx.xxx.xxx.^ */
  641. sprintf(p, "%d", DHCPD_CLIENT_IP_MIN);
  642. ip4addr_aton(str_tmp, &ip_start);
  643. DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp);
  644. sprintf(p, "%d", DHCPD_CLIENT_IP_MAX);
  645. ip4addr_aton(str_tmp, &ip_end);
  646. DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp);
  647. res = dhcp_server_start(netif, &ip_start, &ip_end);
  648. if (res != 0)
  649. {
  650. DEBUG_PRINTF("dhcp_server_start res: %s.\r\n", res);
  651. }
  652. }
  653. _exit:
  654. LWIP_NETIF_UNLOCK();
  655. return;
  656. }
  657. void dhcpd_stop(const char *netif_name)
  658. {
  659. struct dhcp_server *dhcp_server, *server_node;
  660. struct netif *netif = netif_list;
  661. struct dhcp_client_node *node, *next;
  662. DEBUG_PRINTF("%s: %s\r\n", __FUNCTION__, netif_name);
  663. LWIP_NETIF_LOCK();
  664. if (strlen(netif_name) > sizeof(netif->name))
  665. {
  666. DEBUG_PRINTF("network interface name too long!\r\n");
  667. goto _exit;
  668. }
  669. while (netif != RT_NULL)
  670. {
  671. if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0)
  672. break;
  673. netif = netif->next;
  674. if (netif == RT_NULL)
  675. {
  676. DEBUG_PRINTF("network interface: %s not found!\r\n", netif_name);
  677. break;
  678. }
  679. }
  680. if (netif == RT_NULL)
  681. {
  682. goto _exit;
  683. }
  684. /* If this netif alreday use the dhcp server. */
  685. for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next)
  686. {
  687. if (dhcp_server->netif == netif)
  688. {
  689. break;
  690. }
  691. }
  692. if (dhcp_server == RT_NULL)
  693. {
  694. goto _exit;
  695. }
  696. /* remove dhcp server */
  697. if (dhcp_server == lw_dhcp_server)
  698. {
  699. lw_dhcp_server = lw_dhcp_server->next;
  700. }
  701. else
  702. {
  703. server_node = lw_dhcp_server;
  704. while (server_node->next && server_node->next != dhcp_server)
  705. {
  706. server_node = server_node->next;
  707. }
  708. if (server_node->next != RT_NULL)
  709. {
  710. server_node->next = server_node->next->next;
  711. }
  712. }
  713. udp_disconnect(dhcp_server->pcb);
  714. udp_remove(dhcp_server->pcb);
  715. /* remove all client node */
  716. for (node = dhcp_server->node_list; node != NULL; node = next)
  717. {
  718. next = node->next;
  719. mem_free(node);
  720. }
  721. mem_free(dhcp_server);
  722. set_if(netif_name, "0.0.0.0", "0.0.0.0", "0.0.0.0");
  723. _exit:
  724. LWIP_NETIF_UNLOCK();
  725. }