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