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