dhcp_server_raw.c 21 KB

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