1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //#include "esp_common.h"
15 #include <stdlib.h>
16 #include <string.h>
17 #include "lwip/inet.h"
18 #include "lwip/err.h"
19 #include "lwip/pbuf.h"
20 #include "lwip/udp.h"
21 #include "lwip/mem.h"
22 #include "lwip/ip_addr.h"
23 #include "esp_netif.h"
24 
25 #include "dhcpserver/dhcpserver.h"
26 #include "dhcpserver/dhcpserver_options.h"
27 
28 #if ESP_DHCP
29 
30 #define BOOTP_BROADCAST 0x8000
31 
32 #define DHCP_REQUEST        1
33 #define DHCP_REPLY          2
34 #define DHCP_HTYPE_ETHERNET 1
35 #define DHCP_HLEN_ETHERNET  6
36 #define DHCP_MSG_LEN      236
37 
38 #define DHCPS_SERVER_PORT  67
39 #define DHCPS_CLIENT_PORT  68
40 
41 #define DHCPDISCOVER  1
42 #define DHCPOFFER     2
43 #define DHCPREQUEST   3
44 #define DHCPDECLINE   4
45 #define DHCPACK       5
46 #define DHCPNAK       6
47 #define DHCPRELEASE   7
48 
49 #define DHCP_OPTION_SUBNET_MASK   1
50 #define DHCP_OPTION_ROUTER        3
51 #define DHCP_OPTION_DNS_SERVER    6
52 #define DHCP_OPTION_REQ_IPADDR   50
53 #define DHCP_OPTION_LEASE_TIME   51
54 #define DHCP_OPTION_MSG_TYPE     53
55 #define DHCP_OPTION_SERVER_ID    54
56 #define DHCP_OPTION_INTERFACE_MTU 26
57 #define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31
58 #define DHCP_OPTION_BROADCAST_ADDRESS 28
59 #define DHCP_OPTION_REQ_LIST     55
60 #define DHCP_OPTION_END         255
61 
62 //#define USE_CLASS_B_NET 1
63 #define DHCPS_DEBUG          0
64 #define DHCPS_LOG printf
65 
66 #define MAX_STATION_NUM CONFIG_LWIP_DHCPS_MAX_STATION_NUM
67 
68 #define DHCPS_STATE_OFFER 1
69 #define DHCPS_STATE_DECLINE 2
70 #define DHCPS_STATE_ACK 3
71 #define DHCPS_STATE_NAK 4
72 #define DHCPS_STATE_IDLE 5
73 #define DHCPS_STATE_RELEASE 6
74 
75 typedef struct _list_node {
76 	void *pnode;
77 	struct _list_node *pnext;
78 } list_node;
79 
80 ////////////////////////////////////////////////////////////////////////////////////
81 
82 static const u32_t magic_cookie  = 0x63538263;
83 
84 static struct netif   *dhcps_netif = NULL;
85 static ip4_addr_t  broadcast_dhcps;
86 static ip4_addr_t server_address;
87 static ip4_addr_t dns_server = {0};
88 static ip4_addr_t client_address;        //added
89 static ip4_addr_t client_address_plus;
90 static ip4_addr_t s_dhcps_mask = {
91 #ifdef USE_CLASS_B_NET
92         .addr = PP_HTONL(LWIP_MAKEU32(255, 240, 0, 0))
93 #else
94         .addr = PP_HTONL(LWIP_MAKEU32(255, 255, 255, 0))
95 #endif
96     };
97 
98 static list_node *plist = NULL;
99 static bool renew = false;
100 
101 static dhcps_lease_t dhcps_poll;
102 static dhcps_time_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF;  //minute
103 static dhcps_offer_t dhcps_offer = 0xFF;
104 static dhcps_offer_t dhcps_dns = 0x00;
105 static dhcps_cb_t dhcps_cb;
106 
107 /******************************************************************************
108  * FunctionName : dhcps_option_info
109  * Description  : get the DHCP message option info
110  * Parameters   : op_id -- DHCP message option id
111  *                opt_len -- DHCP message option length
112  * Returns      : DHCP message option addr
113 *******************************************************************************/
dhcps_option_info(u8_t op_id,u32_t opt_len)114 void *dhcps_option_info(u8_t op_id, u32_t opt_len)
115 {
116     void *option_arg = NULL;
117 
118     switch (op_id) {
119         case IP_ADDRESS_LEASE_TIME:
120             if (opt_len == sizeof(dhcps_time_t)) {
121                 option_arg = &dhcps_lease_time;
122             }
123 
124             break;
125 
126         case REQUESTED_IP_ADDRESS:
127             if (opt_len == sizeof(dhcps_lease_t)) {
128                 option_arg = &dhcps_poll;
129             }
130 
131             break;
132 
133         case ROUTER_SOLICITATION_ADDRESS:
134             if (opt_len == sizeof(dhcps_offer_t)) {
135                 option_arg = &dhcps_offer;
136             }
137 
138             break;
139 
140         case DOMAIN_NAME_SERVER:
141             if (opt_len == sizeof(dhcps_offer_t)) {
142                 option_arg = &dhcps_dns;
143             }
144 
145             break;
146         case SUBNET_MASK:
147             if (opt_len == sizeof(s_dhcps_mask)) {
148                 option_arg = &s_dhcps_mask;
149             }
150 
151             break;
152         default:
153             break;
154     }
155 
156     return option_arg;
157 }
158 
159 /******************************************************************************
160  * FunctionName : dhcps_set_option_info
161  * Description  : set the DHCP message option info
162  * Parameters   : op_id -- DHCP message option id
163  *                opt_info -- DHCP message option info
164  *                opt_len -- DHCP message option length
165  * Returns      : none
166 *******************************************************************************/
dhcps_set_option_info(u8_t op_id,void * opt_info,u32_t opt_len)167 void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len)
168 {
169     if (opt_info == NULL) {
170         return;
171     }
172     switch (op_id) {
173         case IP_ADDRESS_LEASE_TIME:
174             if (opt_len == sizeof(dhcps_time_t)) {
175                 dhcps_lease_time = *(dhcps_time_t *)opt_info;
176             }
177 
178             break;
179 
180         case REQUESTED_IP_ADDRESS:
181             if (opt_len == sizeof(dhcps_lease_t)) {
182                 dhcps_poll = *(dhcps_lease_t *)opt_info;
183             }
184 
185             break;
186 
187         case ROUTER_SOLICITATION_ADDRESS:
188             if (opt_len == sizeof(dhcps_offer_t)) {
189                 dhcps_offer = *(dhcps_offer_t *)opt_info;
190             }
191 
192             break;
193 
194         case DOMAIN_NAME_SERVER:
195             if (opt_len == sizeof(dhcps_offer_t)) {
196                 dhcps_dns = *(dhcps_offer_t *)opt_info;
197             }
198             break;
199 
200         case SUBNET_MASK:
201             if (opt_len == sizeof(s_dhcps_mask)) {
202                 s_dhcps_mask = *(ip4_addr_t *)opt_info;
203             }
204 
205 
206         default:
207             break;
208     }
209     return;
210 }
211 
212 /******************************************************************************
213  * FunctionName : node_insert_to_list
214  * Description  : insert the node to the list
215  * Parameters   : phead -- the head node of the list
216  *                pinsert -- the insert node of the list
217  * Returns      : none
218 *******************************************************************************/
node_insert_to_list(list_node ** phead,list_node * pinsert)219 static void node_insert_to_list(list_node **phead, list_node *pinsert)
220 {
221     list_node *plist = NULL;
222     struct dhcps_pool *pdhcps_pool = NULL;
223     struct dhcps_pool *pdhcps_node = NULL;
224 
225     if (*phead == NULL) {
226         *phead = pinsert;
227     } else {
228         plist = *phead;
229         pdhcps_node = pinsert->pnode;
230         pdhcps_pool = plist->pnode;
231 
232         if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
233             pinsert->pnext = plist;
234             *phead = pinsert;
235         } else {
236             while (plist->pnext != NULL) {
237                 pdhcps_pool = plist->pnext->pnode;
238 
239                 if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
240                     pinsert->pnext = plist->pnext;
241                     plist->pnext = pinsert;
242                     break;
243                 }
244 
245                 plist = plist->pnext;
246             }
247 
248             if (plist->pnext == NULL) {
249                 plist->pnext = pinsert;
250             }
251         }
252     }
253 
254 //	pinsert->pnext = NULL;
255 }
256 
257 /******************************************************************************
258  * FunctionName : node_delete_from_list
259  * Description  : remove the node from list
260  * Parameters   : phead -- the head node of the list
261  *                pdelete -- the remove node of the list
262  * Returns      : none
263 *******************************************************************************/
node_remove_from_list(list_node ** phead,list_node * pdelete)264 void node_remove_from_list(list_node **phead, list_node *pdelete)
265 {
266     list_node *plist = NULL;
267 
268     plist = *phead;
269 
270     if (plist == NULL) {
271         *phead = NULL;
272     } else {
273         if (plist == pdelete) {
274             // Note: Ignoring the "use after free" warnings, as it could only happen
275             // if the linked list contains loops
276             *phead = plist->pnext; // NOLINT(clang-analyzer-unix.Malloc)
277             pdelete->pnext = NULL;
278         } else {
279             while (plist != NULL) {
280                 if (plist->pnext == pdelete) { // NOLINT(clang-analyzer-unix.Malloc)
281                     plist->pnext = pdelete->pnext;
282                     pdelete->pnext = NULL;
283                 }
284 
285                 plist = plist->pnext;
286             }
287         }
288     }
289 }
290 
291 /******************************************************************************
292  * FunctionName : add_msg_type
293  * Description  : add TYPE option of DHCP message
294  * Parameters   : optptr -- the addr of DHCP message option
295  * Returns      : the addr of DHCP message option
296 *******************************************************************************/
add_msg_type(u8_t * optptr,u8_t type)297 static u8_t *add_msg_type(u8_t *optptr, u8_t type)
298 {
299     *optptr++ = DHCP_OPTION_MSG_TYPE;
300     *optptr++ = 1;
301     *optptr++ = type;
302     return optptr;
303 }
304 
305 /******************************************************************************
306  * FunctionName : add_offer_options
307  * Description  : add OFFER option of DHCP message
308  * Parameters   : optptr -- the addr of DHCP message option
309  * Returns      : the addr of DHCP message option
310 *******************************************************************************/
add_offer_options(u8_t * optptr)311 static u8_t *add_offer_options(u8_t *optptr)
312 {
313     ip4_addr_t ipadd;
314 
315     ipadd.addr = *((u32_t *) &server_address);
316 
317     *optptr++ = DHCP_OPTION_SUBNET_MASK;
318     *optptr++ = 4;
319     *optptr++ = ip4_addr1(&s_dhcps_mask);
320     *optptr++ = ip4_addr2(&s_dhcps_mask);
321     *optptr++ = ip4_addr3(&s_dhcps_mask);
322     *optptr++ = ip4_addr4(&s_dhcps_mask);
323 
324     *optptr++ = DHCP_OPTION_LEASE_TIME;
325     *optptr++ = 4;
326     *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 24) & 0xFF;
327     *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 16) & 0xFF;
328     *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 8) & 0xFF;
329     *optptr++ = ((dhcps_lease_time * DHCPS_LEASE_UNIT) >> 0) & 0xFF;
330 
331     *optptr++ = DHCP_OPTION_SERVER_ID;
332     *optptr++ = 4;
333     *optptr++ = ip4_addr1(&ipadd);
334     *optptr++ = ip4_addr2(&ipadd);
335     *optptr++ = ip4_addr3(&ipadd);
336     *optptr++ = ip4_addr4(&ipadd);
337 
338     if (dhcps_router_enabled(dhcps_offer)) {
339         esp_netif_ip_info_t if_ip;
340         memset(&if_ip , 0x00, sizeof(esp_netif_ip_info_t));
341         esp_netif_get_ip_info(dhcps_netif->state, &if_ip);
342 
343         ip4_addr_t* gw_ip = (ip4_addr_t*)&if_ip.gw;
344 
345         if (!ip4_addr_isany_val(*gw_ip)) {
346             *optptr++ = DHCP_OPTION_ROUTER;
347             *optptr++ = 4;
348             *optptr++ = ip4_addr1(gw_ip);
349             *optptr++ = ip4_addr2(gw_ip);
350             *optptr++ = ip4_addr3(gw_ip);
351             *optptr++ = ip4_addr4(gw_ip);
352         }
353     }
354 
355     *optptr++ = DHCP_OPTION_DNS_SERVER;
356     *optptr++ = 4;
357     if (dhcps_dns_enabled(dhcps_dns)) {
358         *optptr++ = ip4_addr1(&dns_server);
359         *optptr++ = ip4_addr2(&dns_server);
360         *optptr++ = ip4_addr3(&dns_server);
361         *optptr++ = ip4_addr4(&dns_server);
362     }else {
363         *optptr++ = ip4_addr1(&ipadd);
364         *optptr++ = ip4_addr2(&ipadd);
365         *optptr++ = ip4_addr3(&ipadd);
366         *optptr++ = ip4_addr4(&ipadd);
367     }
368 
369     ip4_addr_t broadcast_addr = { .addr = (ipadd.addr & s_dhcps_mask.addr) | ~s_dhcps_mask.addr };
370     *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
371     *optptr++ = 4;
372     *optptr++ = ip4_addr1(&broadcast_addr);
373     *optptr++ = ip4_addr2(&broadcast_addr);
374     *optptr++ = ip4_addr3(&broadcast_addr);
375     *optptr++ = ip4_addr4(&broadcast_addr);
376 
377     *optptr++ = DHCP_OPTION_INTERFACE_MTU;
378     *optptr++ = 2;
379     *optptr++ = 0x05;
380     *optptr++ = 0xdc;
381 
382     *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
383     *optptr++ = 1;
384     *optptr++ = 0x00;
385 
386     *optptr++ = 43;
387     *optptr++ = 6;
388 
389     *optptr++ = 0x01;
390     *optptr++ = 4;
391     *optptr++ = 0x00;
392     *optptr++ = 0x00;
393     *optptr++ = 0x00;
394     *optptr++ = 0x02;
395 
396     return optptr;
397 }
398 
399 /******************************************************************************
400  * FunctionName : add_end
401  * Description  : add end option of DHCP message
402  * Parameters   : optptr -- the addr of DHCP message option
403  * Returns      : the addr of DHCP message option
404 *******************************************************************************/
add_end(u8_t * optptr)405 static u8_t *add_end(u8_t *optptr)
406 {
407     *optptr++ = DHCP_OPTION_END;
408     return optptr;
409 }
410 
411 /******************************************************************************
412  * FunctionName : create_msg
413  * Description  : create response message
414  * Parameters   : m -- DHCP message info
415  * Returns      : none
416 *******************************************************************************/
create_msg(struct dhcps_msg * m)417 static void create_msg(struct dhcps_msg *m)
418 {
419     ip4_addr_t client;
420 
421 
422     client.addr = *((uint32_t *) &client_address);
423 
424     m->op = DHCP_REPLY;
425 
426     m->htype = DHCP_HTYPE_ETHERNET;
427 
428     m->hlen = 6;
429 
430     m->hops = 0;
431 //        os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
432     m->secs = 0;
433     m->flags = htons(BOOTP_BROADCAST);
434 
435     memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
436 
437     memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
438 
439     memset((char *) m->siaddr, 0, sizeof(m->siaddr));
440 
441     memset((char *) m->giaddr, 0, sizeof(m->giaddr));
442 
443     memset((char *) m->sname, 0, sizeof(m->sname));
444 
445     memset((char *) m->file, 0, sizeof(m->file));
446 
447     memset((char *) m->options, 0, sizeof(m->options));
448 
449     u32_t magic_cookie_temp = magic_cookie;
450 
451     memcpy((char *) m->options, &magic_cookie_temp, sizeof(magic_cookie_temp));
452 }
453 
dhcps_pbuf_alloc(u16_t len)454 struct pbuf * dhcps_pbuf_alloc(u16_t len)
455 {
456     u16_t mlen = sizeof(struct dhcps_msg);
457 
458     if (len > mlen) {
459 #if DHCPS_DEBUG
460         DHCPS_LOG("dhcps: len=%d mlen=%d", len, mlen);
461 #endif
462         mlen = len;
463     }
464 
465     return pbuf_alloc(PBUF_TRANSPORT, mlen, PBUF_RAM);
466 }
467 
468 /******************************************************************************
469  * FunctionName : send_offer
470  * Description  : DHCP message OFFER Response
471  * Parameters   : m -- DHCP message info
472  * Returns      : none
473 *******************************************************************************/
send_offer(struct dhcps_msg * m,u16_t len)474 static void send_offer(struct dhcps_msg *m, u16_t len)
475 {
476     u8_t *end;
477     struct pbuf *p, *q;
478     u8_t *data;
479     u16_t cnt = 0;
480     u16_t i;
481 #if DHCPS_DEBUG
482     err_t SendOffer_err_t;
483 #endif
484     create_msg(m);
485 
486     end = add_msg_type(&m->options[4], DHCPOFFER);
487     end = add_offer_options(end);
488     end = add_end(end);
489 
490     p = dhcps_pbuf_alloc(len);
491 #if DHCPS_DEBUG
492     DHCPS_LOG("udhcp: send_offer>>p->ref = %d\n", p->ref);
493 #endif
494 
495     if (p != NULL) {
496 
497 #if DHCPS_DEBUG
498         DHCPS_LOG("dhcps: send_offer>>pbuf_alloc succeed\n");
499         DHCPS_LOG("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
500         DHCPS_LOG("dhcps: send_offer>>p->len = %d\n", p->len);
501 #endif
502         q = p;
503 
504         while (q != NULL) {
505             data = (u8_t *)q->payload;
506 
507             for (i = 0; i < q->len; i++) {
508                 data[i] = ((u8_t *) m)[cnt++];
509 #if DHCPS_DEBUG
510                 DHCPS_LOG("%02x ", data[i]);
511 
512                 if ((i + 1) % 16 == 0) {
513                     DHCPS_LOG("\n");
514                 }
515 
516 #endif
517             }
518 
519             q = q->next;
520         }
521     } else {
522 
523 #if DHCPS_DEBUG
524         DHCPS_LOG("dhcps: send_offer>>pbuf_alloc failed\n");
525 #endif
526         return;
527     }
528 
529     ip_addr_t ip_temp = IPADDR4_INIT(0x0);
530     ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
531     struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb;
532 #if DHCPS_DEBUG
533     SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
534     DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t);
535 #else
536     udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
537 #endif
538 
539     if (p->ref != 0) {
540 #if DHCPS_DEBUG
541         DHCPS_LOG("udhcp: send_offer>>free pbuf\n");
542 #endif
543         pbuf_free(p);
544     }
545 }
546 
547 /******************************************************************************
548  * FunctionName : send_nak
549  * Description  : DHCP message NACK Response
550  * Parameters   : m -- DHCP message info
551  * Returns      : none
552 *******************************************************************************/
send_nak(struct dhcps_msg * m,u16_t len)553 static void send_nak(struct dhcps_msg *m, u16_t len)
554 {
555     u8_t *end;
556     struct pbuf *p, *q;
557     u8_t *data;
558     u16_t cnt = 0;
559     u16_t i;
560 #if DHCPS_DEBUG
561     err_t SendNak_err_t;
562 #endif
563     create_msg(m);
564 
565     end = add_msg_type(&m->options[4], DHCPNAK);
566     end = add_end(end);
567 
568     p = dhcps_pbuf_alloc(len);
569 #if DHCPS_DEBUG
570     DHCPS_LOG("udhcp: send_nak>>p->ref = %d\n", p->ref);
571 #endif
572 
573     if (p != NULL) {
574 
575 #if DHCPS_DEBUG
576         DHCPS_LOG("dhcps: send_nak>>pbuf_alloc succeed\n");
577         DHCPS_LOG("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
578         DHCPS_LOG("dhcps: send_nak>>p->len = %d\n", p->len);
579 #endif
580         q = p;
581 
582         while (q != NULL) {
583             data = (u8_t *)q->payload;
584 
585             for (i = 0; i < q->len; i++) {
586                 data[i] = ((u8_t *) m)[cnt++];
587 #if DHCPS_DEBUG
588                 DHCPS_LOG("%02x ", data[i]);
589 
590                 if ((i + 1) % 16 == 0) {
591                     DHCPS_LOG("\n");
592                 }
593 
594 #endif
595             }
596 
597             q = q->next;
598         }
599     } else {
600 
601 #if DHCPS_DEBUG
602         DHCPS_LOG("dhcps: send_nak>>pbuf_alloc failed\n");
603 #endif
604         return;
605     }
606 
607     ip_addr_t ip_temp = IPADDR4_INIT(0x0);
608     ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
609     struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb;
610 #if DHCPS_DEBUG
611     SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
612     DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t);
613 #else
614     udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
615 #endif
616 
617     if (p->ref != 0) {
618 #if DHCPS_DEBUG
619         DHCPS_LOG("udhcp: send_nak>>free pbuf\n");
620 #endif
621         pbuf_free(p);
622     }
623 }
624 
625 /******************************************************************************
626  * FunctionName : send_ack
627  * Description  : DHCP message ACK Response
628  * Parameters   : m -- DHCP message info
629  * Returns      : none
630 *******************************************************************************/
send_ack(struct dhcps_msg * m,u16_t len)631 static void send_ack(struct dhcps_msg *m, u16_t len)
632 {
633     u8_t *end;
634     struct pbuf *p, *q;
635     u8_t *data;
636     u16_t cnt = 0;
637     u16_t i;
638     err_t SendAck_err_t;
639     create_msg(m);
640 
641     end = add_msg_type(&m->options[4], DHCPACK);
642     end = add_offer_options(end);
643     end = add_end(end);
644 
645     p = dhcps_pbuf_alloc(len);
646 #if DHCPS_DEBUG
647     DHCPS_LOG("udhcp: send_ack>>p->ref = %d\n", p->ref);
648 #endif
649 
650     if (p != NULL) {
651 
652 #if DHCPS_DEBUG
653         DHCPS_LOG("dhcps: send_ack>>pbuf_alloc succeed\n");
654         DHCPS_LOG("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
655         DHCPS_LOG("dhcps: send_ack>>p->len = %d\n", p->len);
656 #endif
657         q = p;
658 
659         while (q != NULL) {
660             data = (u8_t *)q->payload;
661 
662             for (i = 0; i < q->len; i++) {
663                 data[i] = ((u8_t *) m)[cnt++];
664 #if DHCPS_DEBUG
665                 DHCPS_LOG("%02x ", data[i]);
666 
667                 if ((i + 1) % 16 == 0) {
668                     DHCPS_LOG("\n");
669                 }
670 
671 #endif
672             }
673 
674             q = q->next;
675         }
676     } else {
677 
678 #if DHCPS_DEBUG
679         DHCPS_LOG("dhcps: send_ack>>pbuf_alloc failed\n");
680 #endif
681         return;
682     }
683 
684     ip_addr_t ip_temp = IPADDR4_INIT(0x0);
685     ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
686     struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb;
687     SendAck_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
688 #if DHCPS_DEBUG
689     DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t);
690 #endif
691 
692     if (SendAck_err_t == ERR_OK) {
693         dhcps_cb(m->yiaddr);
694     }
695 
696     if (p->ref != 0) {
697 #if DHCPS_DEBUG
698         DHCPS_LOG("udhcp: send_ack>>free pbuf\n");
699 #endif
700         pbuf_free(p);
701     }
702 }
703 
704 /******************************************************************************
705  * FunctionName : parse_options
706  * Description  : parse DHCP message options
707  * Parameters   : optptr -- DHCP message option info
708  *                len -- DHCP message option length
709  * Returns      : none
710 *******************************************************************************/
parse_options(u8_t * optptr,s16_t len)711 static u8_t parse_options(u8_t *optptr, s16_t len)
712 {
713     ip4_addr_t client;
714     bool is_dhcp_parse_end = false;
715     struct dhcps_state s;
716 
717     client.addr = *((uint32_t *) &client_address);
718 
719     u8_t *end = optptr + len;
720     u16_t type = 0;
721 
722     s.state = DHCPS_STATE_IDLE;
723 
724     while (optptr < end) {
725 #if DHCPS_DEBUG
726         DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
727 #endif
728 
729         switch ((s16_t) *optptr) {
730 
731             case DHCP_OPTION_MSG_TYPE:	//53
732                 type = *(optptr + 2);
733                 break;
734 
735             case DHCP_OPTION_REQ_IPADDR://50
736                 if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
737 #if DHCPS_DEBUG
738                     DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
739 #endif
740                     s.state = DHCPS_STATE_ACK;
741                 } else {
742 #if DHCPS_DEBUG
743                     DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
744 #endif
745                     s.state = DHCPS_STATE_NAK;
746                 }
747 
748                 break;
749 
750             case DHCP_OPTION_END: {
751                 is_dhcp_parse_end = true;
752             }
753             break;
754         }
755 
756         if (is_dhcp_parse_end) {
757             break;
758         }
759 
760         optptr += optptr[1] + 2;
761     }
762 
763     switch (type) {
764 
765         case DHCPDISCOVER://1
766             s.state = DHCPS_STATE_OFFER;
767 #if DHCPS_DEBUG
768             DHCPS_LOG("dhcps: DHCPD_STATE_OFFER\n");
769 #endif
770             break;
771 
772         case DHCPREQUEST://3
773             if (!(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK)) {
774                 if (renew == true) {
775                     s.state = DHCPS_STATE_ACK;
776                 } else {
777                     s.state = DHCPS_STATE_NAK;
778                 }
779 
780 #if DHCPS_DEBUG
781                 DHCPS_LOG("dhcps: DHCPD_STATE_NAK\n");
782 #endif
783             }
784 
785             break;
786 
787         case DHCPDECLINE://4
788             s.state = DHCPS_STATE_IDLE;
789 #if DHCPS_DEBUG
790             DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
791 #endif
792             break;
793 
794         case DHCPRELEASE://7
795             s.state = DHCPS_STATE_RELEASE;
796 #if DHCPS_DEBUG
797             DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
798 #endif
799             break;
800     }
801 
802 #if DHCPS_DEBUG
803     DHCPS_LOG("dhcps: return s.state = %d\n", s.state);
804 #endif
805     return s.state;
806 }
807 
808 /******************************************************************************
809  * FunctionName : parse_msg
810  * Description  : parse DHCP message from netif
811  * Parameters   : m -- DHCP message info
812  *                len -- DHCP message length
813  * Returns      : DHCP message type
814 *******************************************************************************/
parse_msg(struct dhcps_msg * m,u16_t len)815 static s16_t parse_msg(struct dhcps_msg *m, u16_t len)
816 {
817     u32_t lease_timer = (dhcps_lease_time * DHCPS_LEASE_UNIT)/DHCPS_COARSE_TIMER_SECS;
818 
819     if (memcmp((char *)m->options, &magic_cookie, sizeof(magic_cookie)) == 0) {
820 #if DHCPS_DEBUG
821         DHCPS_LOG("dhcps: len = %d\n", len);
822 #endif
823         ip4_addr_t addr_tmp;
824 
825         struct dhcps_pool *pdhcps_pool = NULL;
826         list_node *pnode = NULL;
827         list_node *pback_node = NULL;
828         ip4_addr_t first_address;
829         bool flag = false;
830 
831         first_address.addr = dhcps_poll.start_ip.addr;
832         client_address.addr = client_address_plus.addr;
833         renew = false;
834 
835         if (plist != NULL) {
836             for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) {
837                 pdhcps_pool = pback_node->pnode;
838 
839                 if (memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0) {
840                     if (memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) {
841                         renew = true;
842                     }
843 
844                     client_address.addr = pdhcps_pool->ip.addr;
845                     pdhcps_pool->lease_timer = lease_timer;
846                     pnode = pback_node;
847                     goto POOL_CHECK;
848                 } else if (pdhcps_pool->ip.addr == client_address_plus.addr) {
849                     addr_tmp.addr = htonl(client_address_plus.addr);
850                     addr_tmp.addr++;
851                     client_address_plus.addr = htonl(addr_tmp.addr);
852                     client_address.addr = client_address_plus.addr;
853                 }
854 
855                 if (flag == false) { // search the fisrt unused ip
856                     if (first_address.addr < pdhcps_pool->ip.addr) {
857                         flag = true;
858                     } else {
859                         addr_tmp.addr = htonl(first_address.addr);
860                         addr_tmp.addr++;
861                         first_address.addr = htonl(addr_tmp.addr);
862                     }
863                 }
864             }
865         } else {
866             client_address.addr = dhcps_poll.start_ip.addr;
867         }
868 
869         if (client_address_plus.addr > dhcps_poll.end_ip.addr) {
870             client_address.addr = first_address.addr;
871         }
872 
873         if (client_address.addr > dhcps_poll.end_ip.addr) {
874             client_address_plus.addr = dhcps_poll.start_ip.addr;
875             pdhcps_pool = NULL;
876             pnode = NULL;
877         } else {
878             pdhcps_pool = (struct dhcps_pool *)mem_malloc(sizeof(struct dhcps_pool));
879             memset(pdhcps_pool , 0x00 , sizeof(struct dhcps_pool));
880 
881             pdhcps_pool->ip.addr = client_address.addr;
882             memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
883             pdhcps_pool->lease_timer = lease_timer;
884             pnode = (list_node *)mem_malloc(sizeof(list_node));
885             memset(pnode , 0x00 , sizeof(list_node));
886 
887             pnode->pnode = pdhcps_pool;
888             pnode->pnext = NULL;
889             node_insert_to_list(&plist, pnode);
890 
891             if (client_address.addr == dhcps_poll.end_ip.addr) {
892                 client_address_plus.addr = dhcps_poll.start_ip.addr;
893             } else {
894                 addr_tmp.addr = htonl(client_address.addr);
895                 addr_tmp.addr++;
896                 client_address_plus.addr = htonl(addr_tmp.addr);
897             }
898         }
899 
900 POOL_CHECK:
901 
902         if ((client_address.addr > dhcps_poll.end_ip.addr) || (ip4_addr_isany(&client_address))) {
903             if (pnode != NULL) {
904                 node_remove_from_list(&plist, pnode);
905                 free(pnode);
906                 pnode = NULL;
907             }
908 
909             if (pdhcps_pool != NULL) {
910                 free(pdhcps_pool);
911                 pdhcps_pool = NULL;
912             }
913 
914             return 4;
915         }
916 
917         s16_t ret = parse_options(&m->options[4], len);;
918 
919         if (ret == DHCPS_STATE_RELEASE || ret == DHCPS_STATE_NAK) {
920             if (pnode != NULL) {
921                 node_remove_from_list(&plist, pnode);
922                 free(pnode);
923                 pnode = NULL;
924             }
925 
926             if (pdhcps_pool != NULL) {
927                 free(pdhcps_pool);
928                 pdhcps_pool = NULL;
929             }
930 
931             memset(&client_address, 0x0, sizeof(client_address));
932         }
933 
934 #if DHCPS_DEBUG
935         DHCPS_LOG("dhcps: xid changed\n");
936         DHCPS_LOG("dhcps: client_address.addr = %x\n", client_address.addr);
937 #endif
938         return ret;
939     }
940 
941     return 0;
942 }
943 
944 /******************************************************************************
945  * FunctionName : handle_dhcp
946  * Description  : If an incoming DHCP message is in response to us, then trigger the state machine
947  * Parameters   : arg -- arg user supplied argument (udp_pcb.recv_arg)
948  * 				  pcb -- the udp_pcb which received data
949  * 			      p -- the packet buffer that was received
950  * 				  addr -- the remote IP address from which the packet was received
951  * 				  port -- the remote port from which the packet was received
952  * Returns      : none
953 *******************************************************************************/
handle_dhcp(void * arg,struct udp_pcb * pcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)954 static void handle_dhcp(void *arg,
955                         struct udp_pcb *pcb,
956                         struct pbuf *p,
957                         const ip_addr_t *addr,
958                         u16_t port)
959 {
960     struct dhcps_msg *pmsg_dhcps = NULL;
961     s16_t tlen, malloc_len;
962     u16_t i;
963     u16_t dhcps_msg_cnt = 0;
964     u8_t *p_dhcps_msg = NULL;
965     u8_t *data;
966 
967 #if DHCPS_DEBUG
968     DHCPS_LOG("dhcps: handle_dhcp-> receive a packet\n");
969 #endif
970 
971     if (p == NULL) {
972         return;
973     }
974 
975     malloc_len = sizeof(struct dhcps_msg);
976 #if DHCPS_DEBUG
977     DHCPS_LOG("dhcps: handle_dhcp malloc_len=%d rx_len=%d", malloc_len, p->tot_len);
978 #endif
979     if (malloc_len < p->tot_len) {
980         malloc_len = p->tot_len;
981     }
982 
983     pmsg_dhcps = (struct dhcps_msg *)mem_malloc(malloc_len);
984     if (NULL == pmsg_dhcps) {
985         pbuf_free(p);
986         return;
987     }
988 
989     memset(pmsg_dhcps , 0x00 , malloc_len);
990     p_dhcps_msg = (u8_t *)pmsg_dhcps;
991     tlen = p->tot_len;
992     data = p->payload;
993 
994 #if DHCPS_DEBUG
995     DHCPS_LOG("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
996     DHCPS_LOG("dhcps: handle_dhcp-> p->len = %d\n", p->len);
997 #endif
998 
999     for (i = 0; i < p->len; i++) {
1000         p_dhcps_msg[dhcps_msg_cnt++] = data[i];
1001 #if DHCPS_DEBUG
1002         DHCPS_LOG("%02x ", data[i]);
1003 
1004         if ((i + 1) % 16 == 0) {
1005             DHCPS_LOG("\n");
1006         }
1007 
1008 #endif
1009     }
1010 
1011     if (p->next != NULL) {
1012 #if DHCPS_DEBUG
1013         DHCPS_LOG("dhcps: handle_dhcp-> p->next != NULL\n");
1014         DHCPS_LOG("dhcps: handle_dhcp-> p->next->tot_len = %d\n", p->next->tot_len);
1015         DHCPS_LOG("dhcps: handle_dhcp-> p->next->len = %d\n", p->next->len);
1016 #endif
1017 
1018         data = p->next->payload;
1019 
1020         for (i = 0; i < p->next->len; i++) {
1021             p_dhcps_msg[dhcps_msg_cnt++] = data[i];
1022 #if DHCPS_DEBUG
1023             DHCPS_LOG("%02x ", data[i]);
1024 
1025             if ((i + 1) % 16 == 0) {
1026                 DHCPS_LOG("\n");
1027             }
1028 
1029 #endif
1030         }
1031     }
1032 
1033 #if DHCPS_DEBUG
1034     DHCPS_LOG("dhcps: handle_dhcp-> parse_msg(p)\n");
1035 #endif
1036 
1037     switch (parse_msg(pmsg_dhcps, tlen - 240)) {
1038         case DHCPS_STATE_OFFER://1
1039 #if DHCPS_DEBUG
1040             DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
1041 #endif
1042             send_offer(pmsg_dhcps, malloc_len);
1043             break;
1044 
1045         case DHCPS_STATE_ACK://3
1046 #if DHCPS_DEBUG
1047             DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
1048 #endif
1049             send_ack(pmsg_dhcps, malloc_len);
1050             break;
1051 
1052         case DHCPS_STATE_NAK://4
1053 #if DHCPS_DEBUG
1054             DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
1055 #endif
1056             send_nak(pmsg_dhcps, malloc_len);
1057             break;
1058 
1059         default :
1060             break;
1061     }
1062 
1063 #if DHCPS_DEBUG
1064     DHCPS_LOG("dhcps: handle_dhcp-> pbuf_free(p)\n");
1065 #endif
1066     pbuf_free(p);
1067     free(pmsg_dhcps);
1068     pmsg_dhcps = NULL;
1069 }
1070 
1071 /******************************************************************************
1072  * FunctionName : dhcps_poll_set
1073  * Description  : set ip poll from start to end for station
1074  * Parameters   : ip -- The current ip addr
1075  * Returns      : none
1076 *******************************************************************************/
dhcps_poll_set(u32_t ip)1077 static void dhcps_poll_set(u32_t ip)
1078 {
1079     u32_t softap_ip = 0, local_ip = 0;
1080     u32_t start_ip = 0;
1081     u32_t end_ip = 0;
1082 
1083     if (dhcps_poll.enable == true) {
1084         softap_ip = htonl(ip);
1085         start_ip = htonl(dhcps_poll.start_ip.addr);
1086         end_ip = htonl(dhcps_poll.end_ip.addr);
1087 
1088         /*config ip information can't contain local ip*/
1089         if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
1090             dhcps_poll.enable = false;
1091         } else {
1092             /*config ip information must be in the same segment as the local ip*/
1093             softap_ip >>= 8;
1094 
1095             if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
1096                     || (end_ip - start_ip > DHCPS_MAX_LEASE)) {
1097                 dhcps_poll.enable = false;
1098             }
1099         }
1100     }
1101 
1102     if (dhcps_poll.enable == false) {
1103         local_ip = softap_ip = htonl(ip);
1104         softap_ip &= 0xFFFFFF00;
1105         local_ip &= 0xFF;
1106 
1107         if (local_ip >= 0x80) {
1108             local_ip -= DHCPS_MAX_LEASE;
1109         } else {
1110             local_ip ++;
1111         }
1112 
1113         bzero(&dhcps_poll, sizeof(dhcps_poll));
1114         dhcps_poll.start_ip.addr = softap_ip | local_ip;
1115         dhcps_poll.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
1116         dhcps_poll.start_ip.addr = htonl(dhcps_poll.start_ip.addr);
1117         dhcps_poll.end_ip.addr = htonl(dhcps_poll.end_ip.addr);
1118     }
1119 
1120 }
1121 
1122 
1123 /******************************************************************************
1124  * FunctionName : dhcps_set_new_lease_cb
1125  * Description  : set callback for dhcp server when it assign an IP
1126  *                to the connected dhcp client
1127  * Parameters   : cb -- callback for dhcp server
1128  * Returns      : none
1129 *******************************************************************************/
dhcps_set_new_lease_cb(dhcps_cb_t cb)1130 void dhcps_set_new_lease_cb(dhcps_cb_t cb)
1131 {
1132     dhcps_cb = cb;
1133 }
1134 
1135 /******************************************************************************
1136  * FunctionName : dhcps_start
1137  * Description  : start dhcp server function
1138  * Parameters   : netif -- The current netif addr
1139  *              : info  -- The current ip info
1140  * Returns      : none
1141 *******************************************************************************/
dhcps_start(struct netif * netif,ip4_addr_t ip)1142 void dhcps_start(struct netif *netif, ip4_addr_t ip)
1143 {
1144     dhcps_netif = netif;
1145 
1146     if (dhcps_netif->dhcps_pcb != NULL) {
1147         udp_remove(dhcps_netif->dhcps_pcb);
1148     }
1149 
1150     dhcps_netif->dhcps_pcb = udp_new();
1151     struct udp_pcb *pcb_dhcps = dhcps_netif->dhcps_pcb;
1152 
1153     if (pcb_dhcps == NULL || ip4_addr_isany_val(ip)) {
1154         printf("dhcps_start(): could not obtain pcb\n");
1155     }
1156 
1157     dhcps_netif->dhcps_pcb = pcb_dhcps;
1158 
1159     IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
1160 
1161     server_address.addr = ip.addr;
1162     dhcps_poll_set(server_address.addr);
1163 
1164     client_address_plus.addr = dhcps_poll.start_ip.addr;
1165 
1166     udp_bind(pcb_dhcps, &netif->ip_addr, DHCPS_SERVER_PORT);
1167     udp_recv(pcb_dhcps, handle_dhcp, NULL);
1168 #if DHCPS_DEBUG
1169     DHCPS_LOG("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
1170 #endif
1171 
1172 }
1173 
1174 /******************************************************************************
1175  * FunctionName : dhcps_stop
1176  * Description  : stop dhcp server function
1177  * Parameters   : netif -- The current netif addr
1178  * Returns      : none
1179 *******************************************************************************/
dhcps_stop(struct netif * netif)1180 void dhcps_stop(struct netif *netif)
1181 {
1182     struct netif *apnetif = netif;
1183 
1184     if (apnetif == NULL) {
1185         printf("dhcps_stop: apnetif == NULL\n");
1186         return;
1187     }
1188 
1189     if (apnetif->dhcps_pcb != NULL) {
1190         udp_disconnect(apnetif->dhcps_pcb);
1191         udp_remove(apnetif->dhcps_pcb);
1192         apnetif->dhcps_pcb = NULL;
1193     }
1194 
1195     list_node *pnode = NULL;
1196     list_node *pback_node = NULL;
1197     pnode = plist;
1198 
1199     while (pnode != NULL) {
1200         pback_node = pnode;
1201         pnode = pback_node->pnext;
1202         node_remove_from_list(&plist, pback_node);
1203         free(pback_node->pnode);
1204         pback_node->pnode = NULL;
1205         free(pback_node);
1206         pback_node = NULL;
1207     }
1208 }
1209 
1210 /******************************************************************************
1211  * FunctionName : kill_oldest_dhcps_pool
1212  * Description  : remove the oldest node from list
1213  * Parameters   : none
1214  * Returns      : none
1215 *******************************************************************************/
kill_oldest_dhcps_pool(void)1216 static void kill_oldest_dhcps_pool(void)
1217 {
1218     list_node *pre = NULL, *p = NULL;
1219     list_node *minpre = NULL, *minp = NULL;
1220     struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
1221     pre = plist;
1222     assert(pre != NULL && pre->pnext != NULL); // Expect the list to have at least 2 nodes
1223     p = pre->pnext;
1224     minpre = pre;
1225     minp = p;
1226 
1227     while (p != NULL) {
1228         pdhcps_pool = p->pnode;
1229         pmin_pool = minp->pnode;
1230 
1231         if (pdhcps_pool->lease_timer < pmin_pool->lease_timer) {
1232             minp = p;
1233             minpre = pre;
1234         }
1235 
1236         pre = p;
1237         p = p->pnext;
1238     }
1239 
1240     minpre->pnext = minp->pnext;
1241     free(minp->pnode);
1242     minp->pnode = NULL;
1243     free(minp);
1244     minp = NULL;
1245 }
1246 
1247 /******************************************************************************
1248  * FunctionName : dhcps_coarse_tmr
1249  * Description  : the lease time count
1250  * Parameters   : none
1251  * Returns      : none
1252 *******************************************************************************/
dhcps_coarse_tmr(void)1253 void dhcps_coarse_tmr(void)
1254 {
1255     u8_t num_dhcps_pool = 0;
1256     list_node *pback_node = NULL;
1257     list_node *pnode = NULL;
1258     struct dhcps_pool *pdhcps_pool = NULL;
1259     pnode = plist;
1260 
1261     while (pnode != NULL) {
1262         pdhcps_pool = pnode->pnode;
1263         pdhcps_pool->lease_timer --;
1264 
1265         if (pdhcps_pool->lease_timer == 0) {
1266             pback_node = pnode;
1267             pnode = pback_node->pnext;
1268             node_remove_from_list(&plist, pback_node);
1269             free(pback_node->pnode);
1270             pback_node->pnode = NULL;
1271             free(pback_node);
1272             pback_node = NULL;
1273         } else {
1274             pnode = pnode ->pnext;
1275             num_dhcps_pool ++;
1276         }
1277     }
1278 
1279     if (num_dhcps_pool > MAX_STATION_NUM) {
1280         kill_oldest_dhcps_pool();
1281     }
1282 }
1283 
1284 /******************************************************************************
1285  * FunctionName : dhcp_search_ip_on_mac
1286  * Description  : Search ip address based on mac address
1287  * Parameters   : mac -- The MAC addr
1288  *				  ip  -- The IP info
1289  * Returns      : true or false
1290 *******************************************************************************/
dhcp_search_ip_on_mac(u8_t * mac,ip4_addr_t * ip)1291 bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip)
1292 {
1293     struct dhcps_pool *pdhcps_pool = NULL;
1294     list_node *pback_node = NULL;
1295     bool ret = false;
1296 
1297     for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) {
1298         pdhcps_pool = pback_node->pnode;
1299 
1300         if (memcmp(pdhcps_pool->mac, mac, sizeof(pdhcps_pool->mac)) == 0) {
1301             memcpy(&ip->addr, &pdhcps_pool->ip.addr, sizeof(pdhcps_pool->ip.addr));
1302             ret = true;
1303             break;
1304         }
1305     }
1306 
1307     return ret;
1308 }
1309 
1310 /******************************************************************************
1311  * FunctionName : dhcps_dns_setserver
1312  * Description  : set DNS server address for dhcpserver
1313  * Parameters   : dnsserver -- The DNS server address
1314  * Returns      : none
1315 *******************************************************************************/
1316 void
dhcps_dns_setserver(const ip_addr_t * dnsserver)1317 dhcps_dns_setserver(const ip_addr_t *dnsserver)
1318 {
1319     if (dnsserver != NULL) {
1320         dns_server = *(ip_2_ip4(dnsserver));
1321     } else {
1322         dns_server = *(ip_2_ip4(IP_ADDR_ANY));
1323     }
1324 }
1325 
1326 /******************************************************************************
1327  * FunctionName : dhcps_dns_getserver
1328  * Description  : get DNS server address for dhcpserver
1329  * Parameters   : none
1330  * Returns      : ip4_addr_t
1331 *******************************************************************************/
1332 ip4_addr_t
dhcps_dns_getserver(void)1333 dhcps_dns_getserver(void)
1334 {
1335     return dns_server;
1336 }
1337 #endif // ESP_DHCP
1338