1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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"
17 #include "lwip/inet.h"
19 #include "lwip/pbuf.h"
22 #include "lwip/ip_addr.h"
23 #include "tcpip_adapter.h"
25 #include "apps/dhcpserver.h"
26 #include "apps/dhcpserver_options.h"
30 #define BOOTP_BROADCAST 0x8000
32 #define DHCP_REQUEST 1
34 #define DHCP_HTYPE_ETHERNET 1
35 #define DHCP_HLEN_ETHERNET 6
36 #define DHCP_MSG_LEN 236
38 #define DHCPS_SERVER_PORT 67
39 #define DHCPS_CLIENT_PORT 68
41 #define DHCPDISCOVER 1
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
62 //#define USE_CLASS_B_NET 1
64 #define DHCPS_LOG printf
66 #define MAX_STATION_NUM 8
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
75 typedef struct _list_node {
77 struct _list_node *pnext;
80 ////////////////////////////////////////////////////////////////////////////////////
82 static const u32_t magic_cookie = 0x63538263;
84 static struct udp_pcb *pcb_dhcps = 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;
91 static list_node *plist = NULL;
92 static bool renew = false;
94 static dhcps_lease_t dhcps_poll;
95 static dhcps_time_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute
96 static dhcps_offer_t dhcps_offer = 0xFF;
97 static dhcps_offer_t dhcps_dns = 0xFF;
99 /******************************************************************************
100 * FunctionName : dhcps_option_info
101 * Description : get the DHCP message option info
102 * Parameters : op_id -- DHCP message option id
103 * opt_len -- DHCP message option length
104 * Returns : DHCP message option addr
105 *******************************************************************************/
106 void *dhcps_option_info(u8_t op_id, u32_t opt_len)
108 void *option_arg = NULL;
111 case IP_ADDRESS_LEASE_TIME:
112 if (opt_len == sizeof(dhcps_time_t)) {
113 option_arg = &dhcps_lease_time;
118 case REQUESTED_IP_ADDRESS:
119 if (opt_len == sizeof(dhcps_lease_t)) {
120 option_arg = &dhcps_poll;
125 case ROUTER_SOLICITATION_ADDRESS:
126 if (opt_len == sizeof(dhcps_offer_t)) {
127 option_arg = &dhcps_offer;
132 case DOMAIN_NAME_SERVER:
133 if (opt_len == sizeof(dhcps_offer_t)) {
134 option_arg = &dhcps_dns;
146 /******************************************************************************
147 * FunctionName : dhcps_set_option_info
148 * Description : set the DHCP message option info
149 * Parameters : op_id -- DHCP message option id
150 * opt_info -- DHCP message option info
151 * opt_len -- DHCP message option length
153 *******************************************************************************/
154 void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len)
156 if (opt_info == NULL) {
160 case IP_ADDRESS_LEASE_TIME:
161 if (opt_len == sizeof(dhcps_time_t)) {
162 dhcps_lease_time = *(dhcps_time_t *)opt_info;
167 case REQUESTED_IP_ADDRESS:
168 if (opt_len == sizeof(dhcps_lease_t)) {
169 dhcps_poll = *(dhcps_lease_t *)opt_info;
174 case ROUTER_SOLICITATION_ADDRESS:
175 if (opt_len == sizeof(dhcps_offer_t)) {
176 dhcps_offer = *(dhcps_offer_t *)opt_info;
181 case DOMAIN_NAME_SERVER:
182 if (opt_len == sizeof(dhcps_offer_t)) {
183 dhcps_dns = *(dhcps_offer_t *)opt_info;
193 /******************************************************************************
194 * FunctionName : node_insert_to_list
195 * Description : insert the node to the list
196 * Parameters : phead -- the head node of the list
197 * pinsert -- the insert node of the list
199 *******************************************************************************/
200 static void node_insert_to_list(list_node **phead, list_node *pinsert)
202 list_node *plist = NULL;
203 struct dhcps_pool *pdhcps_pool = NULL;
204 struct dhcps_pool *pdhcps_node = NULL;
206 if (*phead == NULL) {
210 pdhcps_node = pinsert->pnode;
211 pdhcps_pool = plist->pnode;
213 if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
214 pinsert->pnext = plist;
217 while (plist->pnext != NULL) {
218 pdhcps_pool = plist->pnext->pnode;
220 if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
221 pinsert->pnext = plist->pnext;
222 plist->pnext = pinsert;
226 plist = plist->pnext;
229 if (plist->pnext == NULL) {
230 plist->pnext = pinsert;
235 // pinsert->pnext = NULL;
238 /******************************************************************************
239 * FunctionName : node_delete_from_list
240 * Description : remove the node from list
241 * Parameters : phead -- the head node of the list
242 * pdelete -- the remove node of the list
244 *******************************************************************************/
245 void node_remove_from_list(list_node **phead, list_node *pdelete)
247 list_node *plist = NULL;
254 if (plist == pdelete) {
255 *phead = plist->pnext;
256 pdelete->pnext = NULL;
258 while (plist != NULL) {
259 if (plist->pnext == pdelete) {
260 plist->pnext = pdelete->pnext;
261 pdelete->pnext = NULL;
264 plist = plist->pnext;
270 /******************************************************************************
271 * FunctionName : add_msg_type
272 * Description : add TYPE option of DHCP message
273 * Parameters : optptr -- the addr of DHCP message option
274 * Returns : the addr of DHCP message option
275 *******************************************************************************/
276 static u8_t *add_msg_type(u8_t *optptr, u8_t type)
278 *optptr++ = DHCP_OPTION_MSG_TYPE;
284 /******************************************************************************
285 * FunctionName : add_offer_options
286 * Description : add OFFER option of DHCP message
287 * Parameters : optptr -- the addr of DHCP message option
288 * Returns : the addr of DHCP message option
289 *******************************************************************************/
290 static u8_t *add_offer_options(u8_t *optptr)
294 ipadd.addr = *((u32_t *) &server_address);
296 #ifdef USE_CLASS_B_NET
297 *optptr++ = DHCP_OPTION_SUBNET_MASK;
298 *optptr++ = 4; //length
304 *optptr++ = DHCP_OPTION_SUBNET_MASK;
312 *optptr++ = DHCP_OPTION_LEASE_TIME;
314 *optptr++ = ((dhcps_lease_time * 60) >> 24) & 0xFF;
315 *optptr++ = ((dhcps_lease_time * 60) >> 16) & 0xFF;
316 *optptr++ = ((dhcps_lease_time * 60) >> 8) & 0xFF;
317 *optptr++ = ((dhcps_lease_time * 60) >> 0) & 0xFF;
319 *optptr++ = DHCP_OPTION_SERVER_ID;
321 *optptr++ = ip4_addr1(&ipadd);
322 *optptr++ = ip4_addr2(&ipadd);
323 *optptr++ = ip4_addr3(&ipadd);
324 *optptr++ = ip4_addr4(&ipadd);
326 if (dhcps_router_enabled(dhcps_offer)) {
327 tcpip_adapter_ip_info_t if_ip;
328 //bzero(&if_ip, sizeof(struct ip_info));
329 memset(&if_ip , 0x00, sizeof(tcpip_adapter_ip_info_t));
331 tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &if_ip);
333 if (!ip4_addr_isany_val(if_ip.gw)) {
334 *optptr++ = DHCP_OPTION_ROUTER;
336 *optptr++ = ip4_addr1(&if_ip.gw);
337 *optptr++ = ip4_addr2(&if_ip.gw);
338 *optptr++ = ip4_addr3(&if_ip.gw);
339 *optptr++ = ip4_addr4(&if_ip.gw);
343 *optptr++ = DHCP_OPTION_DNS_SERVER;
345 if (dhcps_dns_enabled(dhcps_dns)) {
346 *optptr++ = ip4_addr1(&dns_server);
347 *optptr++ = ip4_addr2(&dns_server);
348 *optptr++ = ip4_addr3(&dns_server);
349 *optptr++ = ip4_addr4(&dns_server);
351 *optptr++ = ip4_addr1(&ipadd);
352 *optptr++ = ip4_addr2(&ipadd);
353 *optptr++ = ip4_addr3(&ipadd);
354 *optptr++ = ip4_addr4(&ipadd);
358 *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
360 *optptr++ = ip4_addr1(&ipadd);
365 *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
367 *optptr++ = ip4_addr1(&ipadd);
368 *optptr++ = ip4_addr2(&ipadd);
369 *optptr++ = ip4_addr3(&ipadd);
373 *optptr++ = DHCP_OPTION_INTERFACE_MTU;
383 *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
400 /******************************************************************************
401 * FunctionName : add_end
402 * Description : add end option of DHCP message
403 * Parameters : optptr -- the addr of DHCP message option
404 * Returns : the addr of DHCP message option
405 *******************************************************************************/
406 static u8_t *add_end(u8_t *optptr)
408 *optptr++ = DHCP_OPTION_END;
412 /******************************************************************************
413 * FunctionName : create_msg
414 * Description : create response message
415 * Parameters : m -- DHCP message info
417 *******************************************************************************/
418 static void create_msg(struct dhcps_msg *m)
423 client.addr = *((uint32_t *) &client_address);
427 m->htype = DHCP_HTYPE_ETHERNET;
432 // os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
434 m->flags = htons(BOOTP_BROADCAST);
436 memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
438 memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
440 memset((char *) m->siaddr, 0, sizeof(m->siaddr));
442 memset((char *) m->giaddr, 0, sizeof(m->giaddr));
444 memset((char *) m->sname, 0, sizeof(m->sname));
446 memset((char *) m->file, 0, sizeof(m->file));
448 memset((char *) m->options, 0, sizeof(m->options));
450 u32_t magic_cookie_temp = magic_cookie;
452 memcpy((char *) m->options, &magic_cookie_temp, sizeof(magic_cookie_temp));
455 struct pbuf * dhcps_pbuf_alloc(u16_t len)
457 u16_t mlen = sizeof(struct dhcps_msg);
461 DHCPS_LOG("dhcps: len=%d mlen=%d", len, mlen);
466 return pbuf_alloc(PBUF_TRANSPORT, mlen, PBUF_RAM);
469 /******************************************************************************
470 * FunctionName : send_offer
471 * Description : DHCP message OFFER Response
472 * Parameters : m -- DHCP message info
474 *******************************************************************************/
475 static void send_offer(struct dhcps_msg *m, u16_t len)
482 err_t SendOffer_err_t;
485 end = add_msg_type(&m->options[4], DHCPOFFER);
486 end = add_offer_options(end);
489 p = dhcps_pbuf_alloc(len);
491 DHCPS_LOG("udhcp: send_offer>>p->ref = %d\n", p->ref);
497 DHCPS_LOG("dhcps: send_offer>>pbuf_alloc succeed\n");
498 DHCPS_LOG("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
499 DHCPS_LOG("dhcps: send_offer>>p->len = %d\n", p->len);
504 data = (u8_t *)q->payload;
506 for (i = 0; i < q->len; i++) {
507 data[i] = ((u8_t *) m)[cnt++];
509 DHCPS_LOG("%02x ", data[i]);
511 if ((i + 1) % 16 == 0) {
523 DHCPS_LOG("dhcps: send_offer>>pbuf_alloc failed\n");
528 ip_addr_t ip_temp = IPADDR4_INIT(0x0);
529 ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
530 SendOffer_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
532 DHCPS_LOG("dhcps: send_offer>>udp_sendto result %x\n", SendOffer_err_t);
537 DHCPS_LOG("udhcp: send_offer>>free pbuf\n");
543 /******************************************************************************
544 * FunctionName : send_nak
545 * Description : DHCP message NACK Response
546 * Parameters : m -- DHCP message info
548 *******************************************************************************/
549 static void send_nak(struct dhcps_msg *m, u16_t len)
559 end = add_msg_type(&m->options[4], DHCPNAK);
562 p = dhcps_pbuf_alloc(len);
564 DHCPS_LOG("udhcp: send_nak>>p->ref = %d\n", p->ref);
570 DHCPS_LOG("dhcps: send_nak>>pbuf_alloc succeed\n");
571 DHCPS_LOG("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
572 DHCPS_LOG("dhcps: send_nak>>p->len = %d\n", p->len);
577 data = (u8_t *)q->payload;
579 for (i = 0; i < q->len; i++) {
580 data[i] = ((u8_t *) m)[cnt++];
582 DHCPS_LOG("%02x ", data[i]);
584 if ((i + 1) % 16 == 0) {
596 DHCPS_LOG("dhcps: send_nak>>pbuf_alloc failed\n");
601 ip_addr_t ip_temp = IPADDR4_INIT(0x0);
602 ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
603 SendNak_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
605 DHCPS_LOG("dhcps: send_nak>>udp_sendto result %x\n", SendNak_err_t);
610 DHCPS_LOG("udhcp: send_nak>>free pbuf\n");
616 /******************************************************************************
617 * FunctionName : send_ack
618 * Description : DHCP message ACK Response
619 * Parameters : m -- DHCP message info
621 *******************************************************************************/
622 static void send_ack(struct dhcps_msg *m, u16_t len)
632 end = add_msg_type(&m->options[4], DHCPACK);
633 end = add_offer_options(end);
636 p = dhcps_pbuf_alloc(len);
638 DHCPS_LOG("udhcp: send_ack>>p->ref = %d\n", p->ref);
644 DHCPS_LOG("dhcps: send_ack>>pbuf_alloc succeed\n");
645 DHCPS_LOG("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
646 DHCPS_LOG("dhcps: send_ack>>p->len = %d\n", p->len);
651 data = (u8_t *)q->payload;
653 for (i = 0; i < q->len; i++) {
654 data[i] = ((u8_t *) m)[cnt++];
656 DHCPS_LOG("%02x ", data[i]);
658 if ((i + 1) % 16 == 0) {
670 DHCPS_LOG("dhcps: send_ack>>pbuf_alloc failed\n");
675 ip_addr_t ip_temp = IPADDR4_INIT(0x0);
676 ip4_addr_set(ip_2_ip4(&ip_temp), &broadcast_dhcps);
677 SendAck_err_t = udp_sendto(pcb_dhcps, p, &ip_temp, DHCPS_CLIENT_PORT);
679 DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t);
684 DHCPS_LOG("udhcp: send_ack>>free pbuf\n");
690 /******************************************************************************
691 * FunctionName : parse_options
692 * Description : parse DHCP message options
693 * Parameters : optptr -- DHCP message option info
694 * len -- DHCP message option length
696 *******************************************************************************/
697 static u8_t parse_options(u8_t *optptr, s16_t len)
700 bool is_dhcp_parse_end = false;
701 struct dhcps_state s;
703 client.addr = *((uint32_t *) &client_address);
705 u8_t *end = optptr + len;
708 s.state = DHCPS_STATE_IDLE;
710 while (optptr < end) {
712 DHCPS_LOG("dhcps: (s16_t)*optptr = %d\n", (s16_t)*optptr);
715 switch ((s16_t) *optptr) {
717 case DHCP_OPTION_MSG_TYPE: //53
718 type = *(optptr + 2);
721 case DHCP_OPTION_REQ_IPADDR://50
722 if (memcmp((char *) &client.addr, (char *) optptr + 2, 4) == 0) {
724 DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
726 s.state = DHCPS_STATE_ACK;
729 DHCPS_LOG("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
731 s.state = DHCPS_STATE_NAK;
736 case DHCP_OPTION_END: {
737 is_dhcp_parse_end = true;
742 if (is_dhcp_parse_end) {
746 optptr += optptr[1] + 2;
751 case DHCPDISCOVER://1
752 s.state = DHCPS_STATE_OFFER;
754 DHCPS_LOG("dhcps: DHCPD_STATE_OFFER\n");
759 if (!(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK)) {
761 s.state = DHCPS_STATE_ACK;
763 s.state = DHCPS_STATE_NAK;
767 DHCPS_LOG("dhcps: DHCPD_STATE_NAK\n");
774 s.state = DHCPS_STATE_IDLE;
776 DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
781 s.state = DHCPS_STATE_RELEASE;
783 DHCPS_LOG("dhcps: DHCPD_STATE_IDLE\n");
789 DHCPS_LOG("dhcps: return s.state = %d\n", s.state);
794 /******************************************************************************
795 * FunctionName : parse_msg
796 * Description : parse DHCP message from netif
797 * Parameters : m -- DHCP message info
798 * len -- DHCP message length
799 * Returns : DHCP message type
800 *******************************************************************************/
801 static s16_t parse_msg(struct dhcps_msg *m, u16_t len)
803 u32_t lease_timer = (dhcps_lease_time * 60)/DHCPS_COARSE_TIMER_SECS;
805 if (memcmp((char *)m->options, &magic_cookie, sizeof(magic_cookie)) == 0) {
807 DHCPS_LOG("dhcps: len = %d\n", len);
811 struct dhcps_pool *pdhcps_pool = NULL;
812 list_node *pnode = NULL;
813 list_node *pback_node = NULL;
814 ip4_addr_t first_address;
817 first_address.addr = dhcps_poll.start_ip.addr;
818 client_address.addr = client_address_plus.addr;
822 for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) {
823 pdhcps_pool = pback_node->pnode;
825 if (memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0) {
826 if (memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) {
830 client_address.addr = pdhcps_pool->ip.addr;
831 pdhcps_pool->lease_timer = lease_timer;
834 } else if (pdhcps_pool->ip.addr == client_address_plus.addr) {
835 addr_tmp.addr = htonl(client_address_plus.addr);
837 client_address_plus.addr = htonl(addr_tmp.addr);
838 client_address.addr = client_address_plus.addr;
841 if (flag == false) { // search the fisrt unused ip
842 if (first_address.addr < pdhcps_pool->ip.addr) {
845 addr_tmp.addr = htonl(first_address.addr);
847 first_address.addr = htonl(addr_tmp.addr);
852 client_address.addr = dhcps_poll.start_ip.addr;
855 if (client_address_plus.addr > dhcps_poll.end_ip.addr) {
856 client_address.addr = first_address.addr;
859 if (client_address.addr > dhcps_poll.end_ip.addr) {
860 client_address_plus.addr = dhcps_poll.start_ip.addr;
864 pdhcps_pool = (struct dhcps_pool *)mem_malloc(sizeof(struct dhcps_pool));
865 memset(pdhcps_pool , 0x00 , sizeof(struct dhcps_pool));
867 pdhcps_pool->ip.addr = client_address.addr;
868 memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
869 pdhcps_pool->lease_timer = lease_timer;
870 pnode = (list_node *)mem_malloc(sizeof(list_node));
871 memset(pnode , 0x00 , sizeof(list_node));
873 pnode->pnode = pdhcps_pool;
875 node_insert_to_list(&plist, pnode);
877 if (client_address.addr == dhcps_poll.end_ip.addr) {
878 client_address_plus.addr = dhcps_poll.start_ip.addr;
880 addr_tmp.addr = htonl(client_address.addr);
882 client_address_plus.addr = htonl(addr_tmp.addr);
888 if ((client_address.addr > dhcps_poll.end_ip.addr) || (ip4_addr_isany(&client_address))) {
890 node_remove_from_list(&plist, pnode);
895 if (pdhcps_pool != NULL) {
903 s16_t ret = parse_options(&m->options[4], len);;
905 if (ret == DHCPS_STATE_RELEASE) {
907 node_remove_from_list(&plist, pnode);
912 if (pdhcps_pool != NULL) {
917 memset(&client_address, 0x0, sizeof(client_address));
921 DHCPS_LOG("dhcps: xid changed\n");
922 DHCPS_LOG("dhcps: client_address.addr = %x\n", client_address.addr);
930 /******************************************************************************
931 * FunctionName : handle_dhcp
932 * Description : If an incoming DHCP message is in response to us, then trigger the state machine
933 * Parameters : arg -- arg user supplied argument (udp_pcb.recv_arg)
934 * pcb -- the udp_pcb which received data
935 * p -- the packet buffer that was received
936 * addr -- the remote IP address from which the packet was received
937 * port -- the remote port from which the packet was received
939 *******************************************************************************/
940 static void handle_dhcp(void *arg,
943 const ip_addr_t *addr,
946 struct dhcps_msg *pmsg_dhcps = NULL;
947 s16_t tlen, malloc_len;
949 u16_t dhcps_msg_cnt = 0;
950 u8_t *p_dhcps_msg = NULL;
954 DHCPS_LOG("dhcps: handle_dhcp-> receive a packet\n");
961 malloc_len = sizeof(struct dhcps_msg);
963 DHCPS_LOG("dhcps: handle_dhcp malloc_len=%d rx_len=%d", malloc_len, p->tot_len);
965 if (malloc_len < p->tot_len) {
966 malloc_len = p->tot_len;
969 pmsg_dhcps = (struct dhcps_msg *)mem_malloc(malloc_len);
970 if (NULL == pmsg_dhcps) {
975 memset(pmsg_dhcps , 0x00 , malloc_len);
976 p_dhcps_msg = (u8_t *)pmsg_dhcps;
981 DHCPS_LOG("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
982 DHCPS_LOG("dhcps: handle_dhcp-> p->len = %d\n", p->len);
985 for (i = 0; i < p->len; i++) {
986 p_dhcps_msg[dhcps_msg_cnt++] = data[i];
988 DHCPS_LOG("%02x ", data[i]);
990 if ((i + 1) % 16 == 0) {
997 if (p->next != NULL) {
999 DHCPS_LOG("dhcps: handle_dhcp-> p->next != NULL\n");
1000 DHCPS_LOG("dhcps: handle_dhcp-> p->next->tot_len = %d\n", p->next->tot_len);
1001 DHCPS_LOG("dhcps: handle_dhcp-> p->next->len = %d\n", p->next->len);
1004 data = p->next->payload;
1006 for (i = 0; i < p->next->len; i++) {
1007 p_dhcps_msg[dhcps_msg_cnt++] = data[i];
1009 DHCPS_LOG("%02x ", data[i]);
1011 if ((i + 1) % 16 == 0) {
1020 DHCPS_LOG("dhcps: handle_dhcp-> parse_msg(p)\n");
1023 switch (parse_msg(pmsg_dhcps, tlen - 240)) {
1024 case DHCPS_STATE_OFFER://1
1026 DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
1028 send_offer(pmsg_dhcps, malloc_len);
1031 case DHCPS_STATE_ACK://3
1033 DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
1035 send_ack(pmsg_dhcps, malloc_len);
1038 case DHCPS_STATE_NAK://4
1040 DHCPS_LOG("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
1042 send_nak(pmsg_dhcps, malloc_len);
1050 DHCPS_LOG("dhcps: handle_dhcp-> pbuf_free(p)\n");
1057 /******************************************************************************
1058 * FunctionName : dhcps_poll_set
1059 * Description : set ip poll from start to end for station
1060 * Parameters : ip -- The current ip addr
1062 *******************************************************************************/
1063 static void dhcps_poll_set(u32_t ip)
1065 u32_t softap_ip = 0, local_ip = 0;
1069 if (dhcps_poll.enable == true) {
1070 softap_ip = htonl(ip);
1071 start_ip = htonl(dhcps_poll.start_ip.addr);
1072 end_ip = htonl(dhcps_poll.end_ip.addr);
1074 /*config ip information can't contain local ip*/
1075 if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
1076 dhcps_poll.enable = false;
1078 /*config ip information must be in the same segment as the local ip*/
1081 if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
1082 || (end_ip - start_ip > DHCPS_MAX_LEASE)) {
1083 dhcps_poll.enable = false;
1088 if (dhcps_poll.enable == false) {
1089 local_ip = softap_ip = htonl(ip);
1090 softap_ip &= 0xFFFFFF00;
1093 if (local_ip >= 0x80) {
1094 local_ip -= DHCPS_MAX_LEASE;
1099 bzero(&dhcps_poll, sizeof(dhcps_poll));
1100 dhcps_poll.start_ip.addr = softap_ip | local_ip;
1101 dhcps_poll.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
1102 dhcps_poll.start_ip.addr = htonl(dhcps_poll.start_ip.addr);
1103 dhcps_poll.end_ip.addr = htonl(dhcps_poll.end_ip.addr);
1108 /******************************************************************************
1109 * FunctionName : dhcps_start
1110 * Description : start dhcp server function
1111 * Parameters : netif -- The current netif addr
1112 * : info -- The current ip info
1114 *******************************************************************************/
1115 void dhcps_start(struct netif *netif, ip4_addr_t ip)
1117 struct netif *apnetif = netif;
1119 if (apnetif->dhcps_pcb != NULL) {
1120 udp_remove(apnetif->dhcps_pcb);
1123 pcb_dhcps = udp_new();
1125 if (pcb_dhcps == NULL || ip4_addr_isany_val(ip)) {
1126 printf("dhcps_start(): could not obtain pcb\n");
1129 apnetif->dhcps_pcb = pcb_dhcps;
1131 IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
1133 server_address.addr = ip.addr;
1134 dhcps_poll_set(server_address.addr);
1136 client_address_plus.addr = dhcps_poll.start_ip.addr;
1138 udp_bind(pcb_dhcps, &netif->ip_addr, DHCPS_SERVER_PORT);
1139 udp_recv(pcb_dhcps, handle_dhcp, NULL);
1141 DHCPS_LOG("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
1146 /******************************************************************************
1147 * FunctionName : dhcps_stop
1148 * Description : stop dhcp server function
1149 * Parameters : netif -- The current netif addr
1151 *******************************************************************************/
1152 void dhcps_stop(struct netif *netif)
1154 struct netif *apnetif = netif;
1156 if (apnetif == NULL) {
1157 printf("dhcps_stop: apnetif == NULL\n");
1161 if (apnetif->dhcps_pcb != NULL) {
1162 udp_disconnect(apnetif->dhcps_pcb);
1163 udp_remove(apnetif->dhcps_pcb);
1164 apnetif->dhcps_pcb = NULL;
1167 list_node *pnode = NULL;
1168 list_node *pback_node = NULL;
1171 while (pnode != NULL) {
1173 pnode = pback_node->pnext;
1174 node_remove_from_list(&plist, pback_node);
1175 free(pback_node->pnode);
1176 pback_node->pnode = NULL;
1182 /******************************************************************************
1183 * FunctionName : kill_oldest_dhcps_pool
1184 * Description : remove the oldest node from list
1187 *******************************************************************************/
1188 static void kill_oldest_dhcps_pool(void)
1190 list_node *pre = NULL, *p = NULL;
1191 list_node *minpre = NULL, *minp = NULL;
1192 struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
1199 pdhcps_pool = p->pnode;
1200 pmin_pool = minp->pnode;
1202 if (pdhcps_pool->lease_timer < pmin_pool->lease_timer) {
1211 minpre->pnext = minp->pnext;
1218 /******************************************************************************
1219 * FunctionName : dhcps_coarse_tmr
1220 * Description : the lease time count
1223 *******************************************************************************/
1224 void dhcps_coarse_tmr(void)
1226 u8_t num_dhcps_pool = 0;
1227 list_node *pback_node = NULL;
1228 list_node *pnode = NULL;
1229 struct dhcps_pool *pdhcps_pool = NULL;
1232 while (pnode != NULL) {
1233 pdhcps_pool = pnode->pnode;
1234 pdhcps_pool->lease_timer --;
1236 if (pdhcps_pool->lease_timer == 0) {
1238 pnode = pback_node->pnext;
1239 node_remove_from_list(&plist, pback_node);
1240 free(pback_node->pnode);
1241 pback_node->pnode = NULL;
1245 pnode = pnode ->pnext;
1250 if (num_dhcps_pool >= MAX_STATION_NUM) {
1251 kill_oldest_dhcps_pool();
1255 /******************************************************************************
1256 * FunctionName : dhcp_search_ip_on_mac
1257 * Description : Search ip address based on mac address
1258 * Parameters : mac -- The MAC addr
1260 * Returns : true or false
1261 *******************************************************************************/
1262 bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip)
1264 struct dhcps_pool *pdhcps_pool = NULL;
1265 list_node *pback_node = NULL;
1268 for (pback_node = plist; pback_node != NULL; pback_node = pback_node->pnext) {
1269 pdhcps_pool = pback_node->pnode;
1271 if (memcmp(pdhcps_pool->mac, mac, sizeof(pdhcps_pool->mac)) == 0) {
1272 memcpy(&ip->addr, &pdhcps_pool->ip.addr, sizeof(pdhcps_pool->ip.addr));
1281 /******************************************************************************
1282 * FunctionName : dhcps_dns_setserver
1283 * Description : set DNS server address for dhcpserver
1284 * Parameters : dnsserver -- The DNS server address
1286 *******************************************************************************/
1288 dhcps_dns_setserver(const ip_addr_t *dnsserver)
1290 if (dnsserver != NULL) {
1291 dns_server = *(ip_2_ip4(dnsserver));
1293 dns_server = *(ip_2_ip4(IP_ADDR_ANY));
1297 /******************************************************************************
1298 * FunctionName : dhcps_dns_getserver
1299 * Description : get DNS server address for dhcpserver
1301 * Returns : ip4_addr_t
1302 *******************************************************************************/
1304 dhcps_dns_getserver()