1
0

dhcp_server_raw.c 24 KB

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