12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205 |
- #include "lwip/inet.h"
- #include "lwip/err.h"
- #include "lwip/pbuf.h"
- #include "lwip/udp.h"
- #include "lwip/mem.h"
- //#include "crypto/common.h"
- #include "osapi.h"
- #include "lwip/app/dhcpserver.h"
- #ifndef LWIP_OPEN_SRC
- #include "net80211/ieee80211_var.h"
- #endif
- #include "user_interface.h"
- #ifdef MEMLEAK_DEBUG
- static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
- #endif
- ////////////////////////////////////////////////////////////////////////////////////
- //static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
- //static u8_t old_xid[4] = {0};
- static const uint32 magic_cookie ICACHE_RODATA_ATTR = 0x63538263;
- static struct udp_pcb *pcb_dhcps = NULL;
- static struct ip_addr broadcast_dhcps;
- static struct ip_addr server_address;
- static struct ip_addr client_address;//added
- static struct dhcps_lease dhcps_lease;
- //static bool dhcps_lease_flag = true;
- static list_node *plist = NULL;
- static uint8 offer = 0xFF;
- static bool renew = false;
- #define DHCPS_LEASE_TIME_DEF (120)
- uint32 dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute
- void wifi_softap_dhcps_client_leave(u8 *bssid, struct ip_addr *ip,bool force);
- uint32 wifi_softap_dhcps_client_update(u8 *bssid, struct ip_addr *ip);
- /******************************************************************************
- * FunctionName : node_insert_to_list
- * Description : insert the node to the list
- * Parameters : arg -- Additional argument to pass to the callback function
- * Returns : none
- *******************************************************************************/
- void ICACHE_FLASH_ATTR node_insert_to_list(list_node **phead, list_node* pinsert)
- {
- list_node *plist = NULL;
- struct dhcps_pool *pdhcps_pool = NULL;
- struct dhcps_pool *pdhcps_node = NULL;
- if (*phead == NULL)
- *phead = pinsert;
- else {
- plist = *phead;
- pdhcps_node = pinsert->pnode;
- pdhcps_pool = plist->pnode;
- if(pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
- pinsert->pnext = plist;
- *phead = pinsert;
- } else {
- while (plist->pnext != NULL) {
- pdhcps_pool = plist->pnext->pnode;
- if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
- pinsert->pnext = plist->pnext;
- plist->pnext = pinsert;
- break;
- }
- plist = plist->pnext;
- }
- if(plist->pnext == NULL) {
- plist->pnext = pinsert;
- }
- }
- }
- // pinsert->pnext = NULL;
- }
- /******************************************************************************
- * FunctionName : node_delete_from_list
- * Description : remove the node from list
- * Parameters : arg -- Additional argument to pass to the callback function
- * Returns : none
- *******************************************************************************/
- void ICACHE_FLASH_ATTR node_remove_from_list(list_node **phead, list_node* pdelete)
- {
- list_node *plist = NULL;
- plist = *phead;
- if (plist == NULL){
- *phead = NULL;
- } else {
- if (plist == pdelete){
- *phead = plist->pnext;
- pdelete->pnext = NULL;
- } else {
- while (plist != NULL) {
- if (plist->pnext == pdelete){
- plist->pnext = pdelete->pnext;
- pdelete->pnext = NULL;
- }
- plist = plist->pnext;
- }
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * ��DHCP msg��Ϣ�ṹ����������
- *
- * @param optptr -- DHCP msg��Ϣλ��
- * @param type -- Ҫ��ӵ�����option
- *
- * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static uint8_t* ICACHE_FLASH_ATTR add_msg_type(uint8_t *optptr, uint8_t type)
- {
- *optptr++ = DHCP_OPTION_MSG_TYPE;
- *optptr++ = 1;
- *optptr++ = type;
- return optptr;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * ��DHCP msg�ṹ������offerӦ������
- *
- * @param optptr -- DHCP msg��Ϣλ��
- *
- * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
- {
- struct ip_addr ipadd;
- ipadd.addr = *( (uint32_t *) &server_address);
- #ifdef USE_CLASS_B_NET
- *optptr++ = DHCP_OPTION_SUBNET_MASK;
- *optptr++ = 4; //length
- *optptr++ = 255;
- *optptr++ = 240;
- *optptr++ = 0;
- *optptr++ = 0;
- #else
- *optptr++ = DHCP_OPTION_SUBNET_MASK;
- *optptr++ = 4;
- *optptr++ = 255;
- *optptr++ = 255;
- *optptr++ = 255;
- *optptr++ = 0;
- #endif
- *optptr++ = DHCP_OPTION_LEASE_TIME;
- *optptr++ = 4;
- *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 24) & 0xFF;
- *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 16) & 0xFF;
- *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 8) & 0xFF;
- *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 0) & 0xFF;
- *optptr++ = DHCP_OPTION_SERVER_ID;
- *optptr++ = 4;
- *optptr++ = ip4_addr1( &ipadd);
- *optptr++ = ip4_addr2( &ipadd);
- *optptr++ = ip4_addr3( &ipadd);
- *optptr++ = ip4_addr4( &ipadd);
- if (dhcps_router_enabled(offer)){
- struct ip_info if_ip;
- os_bzero(&if_ip, sizeof(struct ip_info));
- wifi_get_ip_info(SOFTAP_IF, &if_ip);
- *optptr++ = DHCP_OPTION_ROUTER;
- *optptr++ = 4;
- *optptr++ = ip4_addr1( &if_ip.gw);
- *optptr++ = ip4_addr2( &if_ip.gw);
- *optptr++ = ip4_addr3( &if_ip.gw);
- *optptr++ = ip4_addr4( &if_ip.gw);
- }
- #ifdef USE_DNS
- *optptr++ = DHCP_OPTION_DNS_SERVER;
- *optptr++ = 4;
- *optptr++ = ip4_addr1( &ipadd);
- *optptr++ = ip4_addr2( &ipadd);
- *optptr++ = ip4_addr3( &ipadd);
- *optptr++ = ip4_addr4( &ipadd);
- #endif
- #ifdef CLASS_B_NET
- *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
- *optptr++ = 4;
- *optptr++ = ip4_addr1( &ipadd);
- *optptr++ = 255;
- *optptr++ = 255;
- *optptr++ = 255;
- #else
- *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
- *optptr++ = 4;
- *optptr++ = ip4_addr1( &ipadd);
- *optptr++ = ip4_addr2( &ipadd);
- *optptr++ = ip4_addr3( &ipadd);
- *optptr++ = 255;
- #endif
- *optptr++ = DHCP_OPTION_INTERFACE_MTU;
- *optptr++ = 2;
- #ifdef CLASS_B_NET
- *optptr++ = 0x05;
- *optptr++ = 0xdc;
- #else
- *optptr++ = 0x02;
- *optptr++ = 0x40;
- #endif
- *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
- *optptr++ = 1;
- *optptr++ = 0x00;
- *optptr++ = 43;
- *optptr++ = 6;
- *optptr++ = 0x01;
- *optptr++ = 4;
- *optptr++ = 0x00;
- *optptr++ = 0x00;
- *optptr++ = 0x00;
- *optptr++ = 0x02;
- return optptr;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * ��DHCP msg�ṹ����ӽ����־����
- *
- * @param optptr -- DHCP msg��Ϣλ��
- *
- * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr)
- {
- *optptr++ = DHCP_OPTION_END;
- return optptr;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////
- static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
- {
- struct ip_addr client;
- client.addr = client_address.addr;
- m->op = DHCP_REPLY;
- m->htype = DHCP_HTYPE_ETHERNET;
- m->hlen = 6;
- m->hops = 0;
- // os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
- m->secs = 0;
- m->flags = htons(BOOTP_BROADCAST);
- os_memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
- os_memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
- os_memset((char *) m->siaddr, 0, sizeof(m->siaddr));
- os_memset((char *) m->giaddr, 0, sizeof(m->giaddr));
- os_memset((char *) m->sname, 0, sizeof(m->sname));
- os_memset((char *) m->file, 0, sizeof(m->file));
- os_memset((char *) m->options, 0, sizeof(m->options));
- //For xiaomi crash bug
- uint32 magic_cookie1 = magic_cookie;
- os_memcpy((char *) m->options, &magic_cookie1, sizeof(magic_cookie1));
- }
- struct pbuf * dhcps_pbuf_alloc(u16_t len)
- {
- u16_t mlen = sizeof(struct dhcps_msg);
- if (len > mlen) {
- #if DHCPS_DEBUG
- DHCPS_LOG("dhcps: len=%d mlen=%d", len, mlen);
- #endif
- mlen = len;
- }
- return pbuf_alloc(PBUF_TRANSPORT, mlen, PBUF_RAM);
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * ����һ��OFFER
- *
- * @param -- m ָ����Ҫ���͵�DHCP msg����
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static void ICACHE_FLASH_ATTR send_offer(struct dhcps_msg *m, u16_t len)
- {
- uint8_t *end;
- struct pbuf *p, *q;
- u8_t *data;
- u16_t cnt=0;
- u16_t i;
- err_t SendOffer_err_t;
- create_msg(m);
- end = add_msg_type(&m->options[4], DHCPOFFER);
- end = add_offer_options(end);
- end = add_end(end);
- p = dhcps_pbuf_alloc(len);
- #if DHCPS_DEBUG
- os_printf("udhcp: send_offer>>p->ref = %d\n", p->ref);
- #endif
- if(p != NULL){
-
- #if DHCPS_DEBUG
- os_printf("dhcps: send_offer>>pbuf_alloc succeed\n");
- os_printf("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
- os_printf("dhcps: send_offer>>p->len = %d\n", p->len);
- #endif
- q = p;
- while(q != NULL){
- data = (u8_t *)q->payload;
- for(i=0; i<q->len; i++)
- {
- data[i] = ((u8_t *) m)[cnt++];
- }
- q = q->next;
- }
- }else{
-
- #if DHCPS_DEBUG
- os_printf("dhcps: send_offer>>pbuf_alloc failed\n");
- #endif
- return;
- }
- SendOffer_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
- #if DHCPS_DEBUG
- os_printf("dhcps: send_offer>>udp_sendto result %x\n",SendOffer_err_t);
- #endif
- if(p->ref != 0){
- #if DHCPS_DEBUG
- os_printf("udhcp: send_offer>>free pbuf\n");
- #endif
- pbuf_free(p);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * ����һ��NAK��Ϣ
- *
- * @param m ָ����Ҫ���͵�DHCP msg����
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static void ICACHE_FLASH_ATTR send_nak(struct dhcps_msg *m, u16_t len)
- {
- u8_t *end;
- struct pbuf *p, *q;
- u8_t *data;
- u16_t cnt=0;
- u16_t i;
- err_t SendNak_err_t;
- create_msg(m);
- end = add_msg_type(&m->options[4], DHCPNAK);
- end = add_end(end);
- p = dhcps_pbuf_alloc(len);
- #if DHCPS_DEBUG
- os_printf("udhcp: send_nak>>p->ref = %d\n", p->ref);
- #endif
- if(p != NULL){
-
- #if DHCPS_DEBUG
- os_printf("dhcps: send_nak>>pbuf_alloc succeed\n");
- os_printf("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
- os_printf("dhcps: send_nak>>p->len = %d\n", p->len);
- #endif
- q = p;
- while(q != NULL){
- data = (u8_t *)q->payload;
- for(i=0; i<q->len; i++)
- {
- data[i] = ((u8_t *) m)[cnt++];
- }
- q = q->next;
- }
- }else{
-
- #if DHCPS_DEBUG
- os_printf("dhcps: send_nak>>pbuf_alloc failed\n");
- #endif
- return;
- }
- SendNak_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
- #if DHCPS_DEBUG
- os_printf("dhcps: send_nak>>udp_sendto result %x\n",SendNak_err_t);
- #endif
- if(p->ref != 0){
- #if DHCPS_DEBUG
- os_printf("udhcp: send_nak>>free pbuf\n");
- #endif
- pbuf_free(p);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * ����һ��ACK��DHCP�ͻ���
- *
- * @param m ָ����Ҫ���͵�DHCP msg����
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static void ICACHE_FLASH_ATTR send_ack(struct dhcps_msg *m, u16_t len)
- {
- u8_t *end;
- struct pbuf *p, *q;
- u8_t *data;
- u16_t cnt=0;
- u16_t i;
- err_t SendAck_err_t;
- create_msg(m);
- end = add_msg_type(&m->options[4], DHCPACK);
- end = add_offer_options(end);
- end = add_end(end);
- p = dhcps_pbuf_alloc(len);
- #if DHCPS_DEBUG
- os_printf("udhcp: send_ack>>p->ref = %d\n", p->ref);
- #endif
- if(p != NULL){
-
- #if DHCPS_DEBUG
- os_printf("dhcps: send_ack>>pbuf_alloc succeed\n");
- os_printf("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
- os_printf("dhcps: send_ack>>p->len = %d\n", p->len);
- #endif
- q = p;
- while(q != NULL){
- data = (u8_t *)q->payload;
- for(i=0; i<q->len; i++)
- {
- data[i] = ((u8_t *) m)[cnt++];
- }
- q = q->next;
- }
- }else{
-
- #if DHCPS_DEBUG
- os_printf("dhcps: send_ack>>pbuf_alloc failed\n");
- #endif
- return;
- }
- SendAck_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
- #if DHCPS_DEBUG
- os_printf("dhcps: send_ack>>udp_sendto result %x\n",SendAck_err_t);
- #endif
-
- if(p->ref != 0){
- #if DHCPS_DEBUG
- os_printf("udhcp: send_ack>>free pbuf\n");
- #endif
- pbuf_free(p);
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * ����DHCP�ͻ��˷�����DHCP����������Ϣ�����Բ�ͬ��DHCP��������������Ӧ��Ӧ��
- *
- * @param optptr DHCP msg���������
- * @param len ��������Ĵ��?(byte)
- *
- * @return uint8_t ���ش�����DHCP Server״ֵ̬
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
- {
- struct ip_addr client;
- bool is_dhcp_parse_end = false;
- struct dhcps_state s;
- client.addr = *( (uint32_t *) &client_address);// Ҫ�����DHCP�ͻ��˵�IP
- u8_t *end = optptr + len;
- u16_t type = 0;
- s.state = DHCPS_STATE_IDLE;
- while (optptr < end) {
- #if DHCPS_DEBUG
- os_printf("dhcps: (sint16_t)*optptr = %d\n", (sint16_t)*optptr);
- #endif
- switch ((sint16_t) *optptr) {
- case DHCP_OPTION_MSG_TYPE: //53
- type = *(optptr + 2);
- break;
- case DHCP_OPTION_REQ_IPADDR://50
- //os_printf("dhcps:0x%08x,0x%08x\n",client.addr,*(uint32*)(optptr+2));
- if( os_memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) {
- #if DHCPS_DEBUG
- os_printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
- #endif
- s.state = DHCPS_STATE_ACK;
- }else {
- #if DHCPS_DEBUG
- os_printf("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
- #endif
- s.state = DHCPS_STATE_NAK;
- }
- break;
- case DHCP_OPTION_END:
- {
- is_dhcp_parse_end = true;
- }
- break;
- }
- if(is_dhcp_parse_end){
- break;
- }
- optptr += optptr[1] + 2;
- }
- switch (type){
-
- case DHCPDISCOVER://1
- s.state = DHCPS_STATE_OFFER;
- #if DHCPS_DEBUG
- os_printf("dhcps: DHCPD_STATE_OFFER\n");
- #endif
- break;
- case DHCPREQUEST://3
- if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) {
- if(renew == true) {
- s.state = DHCPS_STATE_ACK;
- } else {
- s.state = DHCPS_STATE_NAK;
- }
- #if DHCPS_DEBUG
- os_printf("dhcps: DHCPD_STATE_NAK\n");
- #endif
- }
- break;
- case DHCPDECLINE://4
- s.state = DHCPS_STATE_IDLE;
- #if DHCPS_DEBUG
- os_printf("dhcps: DHCPD_STATE_IDLE\n");
- #endif
- break;
- case DHCPRELEASE://7
- s.state = DHCPS_STATE_RELEASE;
- #if DHCPS_DEBUG
- os_printf("dhcps: DHCPD_STATE_IDLE\n");
- #endif
- break;
- }
- #if DHCPS_DEBUG
- os_printf("dhcps: return s.state = %d\n", s.state);
- #endif
- return s.state;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////
- static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
- {
- if(os_memcmp((char *)m->options,
- &magic_cookie,
- sizeof(magic_cookie)) == 0){
- struct ip_addr ip;
- os_memcpy(&ip.addr,m->ciaddr,sizeof(ip.addr));
- client_address.addr = wifi_softap_dhcps_client_update(m->chaddr,&ip);
- sint16_t ret = parse_options(&m->options[4], len);
- if(ret == DHCPS_STATE_RELEASE) {
- wifi_softap_dhcps_client_leave(m->chaddr,&ip,TRUE); // force to delete
- client_address.addr = ip.addr;
- }
- return ret;
- }
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- /*
- * DHCP ��������ݰ���մ���ص�����˺�����LWIP UDPģ������ʱ������
- * ��Ҫ����udp_recv()������LWIP����ע��.
- *
- * @param arg
- * @param pcb ���յ�UDP��Ŀ��ƿ�?
- * @param p ���յ���UDP�е��������?
- * @param addr ���ʹ�UDP���Դ�����IP��ַ
- * @param port ���ʹ�UDP���Դ�����UDPͨ���˿ں�
- */
- ///////////////////////////////////////////////////////////////////////////////////
- static void ICACHE_FLASH_ATTR handle_dhcp(void *arg,
- struct udp_pcb *pcb,
- struct pbuf *p,
- struct ip_addr *addr,
- uint16_t port)
- {
- struct dhcps_msg *pmsg_dhcps = NULL;
- sint16_t tlen = 0, malloc_len;
- u16_t i = 0;
- u16_t dhcps_msg_cnt = 0;
- u8_t *p_dhcps_msg = NULL;
- u8_t *data = NULL;
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> receive a packet\n");
- #endif
- if (p==NULL) return;
- malloc_len = sizeof(struct dhcps_msg);
- #if DHCPS_DEBUG
- DHCPS_LOG("dhcps: handle_dhcp malloc_len=%d rx_len=%d", malloc_len, p->tot_len);
- #endif
- if (malloc_len < p->tot_len) {
- malloc_len = p->tot_len;
- }
- pmsg_dhcps = (struct dhcps_msg *)os_malloc(malloc_len);
- if (NULL == pmsg_dhcps){
- pbuf_free(p);
- return;
- }
- memset(pmsg_dhcps , 0x00 , malloc_len);
- p_dhcps_msg = (u8_t *)pmsg_dhcps;
- tlen = p->tot_len;
- data = p->payload;
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
- os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len);
- #endif
- for(i=0; i<p->len; i++){
- p_dhcps_msg[dhcps_msg_cnt++] = data[i];
- }
-
- if(p->next != NULL) {
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> p->next != NULL\n");
- os_printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len);
- os_printf("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len);
- #endif
-
- data = p->next->payload;
- for(i=0; i<p->next->len; i++){
- p_dhcps_msg[dhcps_msg_cnt++] = data[i];
- }
- }
- /*
- * DHCP �ͻ���������Ϣ����
- */
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
- #endif
-
- switch(parse_msg(pmsg_dhcps, tlen - 240)) {
- case DHCPS_STATE_OFFER://1
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
- #endif
- send_offer(pmsg_dhcps, malloc_len);
- break;
- case DHCPS_STATE_ACK://3
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
- #endif
- send_ack(pmsg_dhcps, malloc_len);
- wifi_softap_set_station_info(pmsg_dhcps->chaddr, &client_address.addr);
- break;
- case DHCPS_STATE_NAK://4
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
- #endif
- send_nak(pmsg_dhcps, malloc_len);
- break;
- default :
- break;
- }
- #if DHCPS_DEBUG
- os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
- #endif
- pbuf_free(p);
- os_free(pmsg_dhcps);
- pmsg_dhcps = NULL;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
- {
- uint32 softap_ip = 0,local_ip = 0;
- uint32 start_ip = 0;
- uint32 end_ip = 0;
- // if (dhcps_lease_flag) {
- if (dhcps_lease.enable == TRUE) {
- softap_ip = htonl(ip);
- start_ip = htonl(dhcps_lease.start_ip.addr);
- end_ip = htonl(dhcps_lease.end_ip.addr);
- /*config ip information can't contain local ip*/
- if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
- dhcps_lease.enable = FALSE;
- } else {
- /*config ip information must be in the same segment as the local ip*/
- softap_ip >>= 8;
- if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
- || (end_ip - start_ip > DHCPS_MAX_LEASE)) {
- dhcps_lease.enable = FALSE;
- }
- }
- }
- if (dhcps_lease.enable == FALSE) {
- local_ip = softap_ip = htonl(ip);
- softap_ip &= 0xFFFFFF00;
- local_ip &= 0xFF;
- if (local_ip >= 0x80)
- local_ip -= DHCPS_MAX_LEASE;
- else
- local_ip ++;
- os_bzero(&dhcps_lease, sizeof(dhcps_lease));
- dhcps_lease.start_ip.addr = softap_ip | local_ip;
- dhcps_lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
- dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
- dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
- }
- // dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
- // dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
- // os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip);
- }
- ///////////////////////////////////////////////////////////////////////////////////
- void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
- {
- struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
-
- if(apnetif->dhcps_pcb != NULL) {
- udp_remove(apnetif->dhcps_pcb);
- }
- pcb_dhcps = udp_new();
- if (pcb_dhcps == NULL || info ==NULL) {
- os_printf("dhcps_start(): could not obtain pcb\n");
- }
- apnetif->dhcps_pcb = pcb_dhcps;
- IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
- server_address = info->ip;
- wifi_softap_init_dhcps_lease(server_address.addr);
- udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
- udp_recv(pcb_dhcps, handle_dhcp, NULL);
- #if DHCPS_DEBUG
- os_printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
- #endif
-
- }
- void ICACHE_FLASH_ATTR dhcps_stop(void)
- {
- struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
- udp_disconnect(pcb_dhcps);
- // dhcps_lease_flag = true;
- if(apnetif->dhcps_pcb != NULL) {
- udp_remove(apnetif->dhcps_pcb);
- apnetif->dhcps_pcb = NULL;
- }
- //udp_remove(pcb_dhcps);
- list_node *pnode = NULL;
- list_node *pback_node = NULL;
- struct dhcps_pool* dhcp_node = NULL;
- struct ip_addr ip_zero;
- os_memset(&ip_zero,0x0,sizeof(ip_zero));
- pnode = plist;
- while (pnode != NULL) {
- pback_node = pnode;
- pnode = pback_node->pnext;
- node_remove_from_list(&plist, pback_node);
- dhcp_node = (struct dhcps_pool*)pback_node->pnode;
- //wifi_softap_dhcps_client_leave(dhcp_node->mac,&dhcp_node->ip,TRUE); // force to delete
- wifi_softap_set_station_info(dhcp_node->mac, &ip_zero);
- os_free(pback_node->pnode);
- pback_node->pnode = NULL;
- os_free(pback_node);
- pback_node = NULL;
- }
- }
- /******************************************************************************
- * FunctionName : wifi_softap_set_dhcps_lease
- * Description : set the lease information of DHCP server
- * Parameters : please -- Additional argument to set the lease information,
- * Little-Endian.
- * Returns : true or false
- *******************************************************************************/
- bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
- {
- struct ip_info info;
- uint32 softap_ip = 0;
- uint32 start_ip = 0;
- uint32 end_ip = 0;
- uint8 opmode = wifi_get_opmode();
- if (opmode == STATION_MODE || opmode == NULL_MODE) {
- return false;
- }
- if (please == NULL || wifi_softap_dhcps_status() == DHCP_STARTED)
- return false;
- if(please->enable) {
- os_bzero(&info, sizeof(struct ip_info));
- wifi_get_ip_info(SOFTAP_IF, &info);
- softap_ip = htonl(info.ip.addr);
- start_ip = htonl(please->start_ip.addr);
- end_ip = htonl(please->end_ip.addr);
- /*config ip information can't contain local ip*/
- if ((start_ip <= softap_ip) && (softap_ip <= end_ip))
- return false;
- /*config ip information must be in the same segment as the local ip*/
- softap_ip >>= 8;
- if ((start_ip >> 8 != softap_ip)
- || (end_ip >> 8 != softap_ip)) {
- return false;
- }
- if (end_ip - start_ip > DHCPS_MAX_LEASE)
- return false;
- os_bzero(&dhcps_lease, sizeof(dhcps_lease));
- // dhcps_lease.start_ip.addr = start_ip;
- // dhcps_lease.end_ip.addr = end_ip;
- dhcps_lease.start_ip.addr = please->start_ip.addr;
- dhcps_lease.end_ip.addr = please->end_ip.addr;
- }
- dhcps_lease.enable = please->enable;
- // dhcps_lease_flag = false;
- return true;
- }
- /******************************************************************************
- * FunctionName : wifi_softap_get_dhcps_lease
- * Description : get the lease information of DHCP server
- * Parameters : please -- Additional argument to get the lease information,
- * Little-Endian.
- * Returns : true or false
- *******************************************************************************/
- bool ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease(struct dhcps_lease *please)
- {
- uint8 opmode = wifi_get_opmode();
- if (opmode == STATION_MODE || opmode == NULL_MODE) {
- return false;
- }
- if (NULL == please)
- return false;
- // if (dhcps_lease_flag){
- if (dhcps_lease.enable == FALSE){
- if (wifi_softap_dhcps_status() == DHCP_STOPPED)
- return false;
- } else {
- // os_bzero(please, sizeof(dhcps_lease));
- // if (wifi_softap_dhcps_status() == DHCP_STOPPED){
- // please->start_ip.addr = htonl(dhcps_lease.start_ip.addr);
- // please->end_ip.addr = htonl(dhcps_lease.end_ip.addr);
- // }
- }
- // if (wifi_softap_dhcps_status() == DHCP_STARTED){
- // os_bzero(please, sizeof(dhcps_lease));
- // please->start_ip.addr = dhcps_lease.start_ip.addr;
- // please->end_ip.addr = dhcps_lease.end_ip.addr;
- // }
- please->start_ip.addr = dhcps_lease.start_ip.addr;
- please->end_ip.addr = dhcps_lease.end_ip.addr;
- return true;
- }
- static void ICACHE_FLASH_ATTR kill_oldest_dhcps_pool(void)
- {
- list_node *pre = NULL, *p = NULL;
- list_node *minpre = NULL, *minp = NULL;
- struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
- pre = plist;
- p = pre->pnext;
- minpre = pre;
- minp = p;
- while (p != NULL){
- pdhcps_pool = p->pnode;
- pmin_pool = minp->pnode;
- if (pdhcps_pool->lease_timer < pmin_pool->lease_timer){
- minp = p;
- minpre = pre;
- }
- pre = p;
- p = p->pnext;
- }
- minpre->pnext = minp->pnext;
- os_free(minp->pnode);
- minp->pnode = NULL;
- os_free(minp);
- minp = NULL;
- }
- void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
- {
- uint8 num_dhcps_pool = 0;
- list_node *pback_node = NULL;
- list_node *pnode = NULL;
- struct dhcps_pool *pdhcps_pool = NULL;
- pnode = plist;
- while (pnode != NULL) {
- pdhcps_pool = pnode->pnode;
- if ( pdhcps_pool->type == DHCPS_TYPE_DYNAMIC) {
- pdhcps_pool->lease_timer --;
- }
- if (pdhcps_pool->lease_timer == 0){
- pback_node = pnode;
- pnode = pback_node->pnext;
- node_remove_from_list(&plist,pback_node);
- os_free(pback_node->pnode);
- pback_node->pnode = NULL;
- os_free(pback_node);
- pback_node = NULL;
- } else {
- pnode = pnode ->pnext;
- num_dhcps_pool ++;
- }
- }
- if (num_dhcps_pool >= MAX_STATION_NUM)
- kill_oldest_dhcps_pool();
- }
- bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
- {
- bool offer_flag = true;
- uint8 option = 0;
- if (optarg == NULL && wifi_softap_dhcps_status() == false)
- return false;
- if (level <= OFFER_START || level >= OFFER_END)
- return false;
- switch (level){
- case OFFER_ROUTER:
- offer = (*(uint8 *)optarg) & 0x01;
- offer_flag = true;
- break;
- default :
- offer_flag = false;
- break;
- }
- return offer_flag;
- }
- bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease_time(uint32 minute)
- {
- uint8 opmode = wifi_get_opmode();
- if (opmode == STATION_MODE || opmode == NULL_MODE) {
- return false;
- }
- if (wifi_softap_dhcps_status() == DHCP_STARTED) {
- return false;
- }
- if(minute == 0) {
- return false;
- }
- dhcps_lease_time = minute;
- return true;
- }
- bool ICACHE_FLASH_ATTR wifi_softap_reset_dhcps_lease_time(void)
- {
- uint8 opmode = wifi_get_opmode();
- if (opmode == STATION_MODE || opmode == NULL_MODE) {
- return false;
- }
- if (wifi_softap_dhcps_status() == DHCP_STARTED) {
- return false;
- }
- dhcps_lease_time = DHCPS_LEASE_TIME_DEF;
- return true;
- }
- uint32 ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease_time(void) // minute
- {
- return dhcps_lease_time;
- }
- void ICACHE_FLASH_ATTR wifi_softap_dhcps_client_leave(u8 *bssid, struct ip_addr *ip,bool force)
- {
- struct dhcps_pool *pdhcps_pool = NULL;
- list_node *pback_node = NULL;
- if ((bssid == NULL) || (ip == NULL)) {
- return;
- }
- for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
- pdhcps_pool = pback_node->pnode;
- if (os_memcmp(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac)) == 0){
- if (os_memcmp(&pdhcps_pool->ip.addr, &ip->addr, sizeof(pdhcps_pool->ip.addr)) == 0) {
- if ((pdhcps_pool->type == DHCPS_TYPE_STATIC) || (force)) {
- if(pback_node != NULL) {
- node_remove_from_list(&plist,pback_node);
- os_free(pback_node);
- pback_node = NULL;
- }
- if (pdhcps_pool != NULL) {
- os_free(pdhcps_pool);
- pdhcps_pool = NULL;
- }
- } else {
- pdhcps_pool->state = DHCPS_STATE_OFFLINE;
- }
- struct ip_addr ip_zero;
- os_memset(&ip_zero,0x0,sizeof(ip_zero));
- wifi_softap_set_station_info(bssid, &ip_zero);
- break;
- }
- }
- }
- }
- uint32 ICACHE_FLASH_ATTR wifi_softap_dhcps_client_update(u8 *bssid, struct ip_addr *ip)
- {
- struct dhcps_pool *pdhcps_pool = NULL;
- list_node *pback_node = NULL;
- list_node *pmac_node = NULL;
- list_node *pip_node = NULL;
- bool flag = FALSE;
- uint32 start_ip = dhcps_lease.start_ip.addr;
- uint32 end_ip = dhcps_lease.end_ip.addr;
- dhcps_type_t type = DHCPS_TYPE_DYNAMIC;
- if (bssid == NULL) {
- return IPADDR_ANY;
- }
- if (ip) {
- if (IPADDR_BROADCAST == ip->addr) {
- return IPADDR_ANY;
- } else if (IPADDR_ANY == ip->addr) {
- ip = NULL;
- } else {
- type = DHCPS_TYPE_STATIC;
- }
- }
- renew = FALSE;
- for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
- pdhcps_pool = pback_node->pnode;
- //os_printf("mac:"MACSTR"bssid:"MACSTR"\r\n",MAC2STR(pdhcps_pool->mac),MAC2STR(bssid));
- if (os_memcmp(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac)) == 0){
- pmac_node = pback_node;
- if (ip == NULL) {
- flag = TRUE;
- break;
- }
- }
- if (ip != NULL) {
- if (os_memcmp(&pdhcps_pool->ip.addr, &ip->addr, sizeof(pdhcps_pool->ip.addr)) == 0) {
- pip_node = pback_node;
- }
- } else if (flag == FALSE){
- if (os_memcmp(&pdhcps_pool->ip.addr, &start_ip, sizeof(pdhcps_pool->ip.addr)) != 0) {
- flag = TRUE;
- } else {
- start_ip = htonl((ntohl(start_ip) + 1));
- }
- }
- }
- if ((ip == NULL) && (flag == FALSE)) {
- if (plist == NULL) {
- if (start_ip <= end_ip) {
- flag = TRUE;
- } else {
- return IPADDR_ANY;
- }
- } else {
- if (start_ip > end_ip) {
- return IPADDR_ANY;
- }
- //start_ip = htonl((ntohl(start_ip) + 1));
- flag = TRUE;
- }
- }
- if (pmac_node != NULL) { // update new ip
- if (pip_node != NULL){
- pdhcps_pool = pip_node->pnode;
- if (pip_node != pmac_node) {
- if(pdhcps_pool->state != DHCPS_STATE_OFFLINE) { // ip is used
- return IPADDR_ANY;
- }
- // mac exists and ip exists in other node,delete mac
- node_remove_from_list(&plist,pmac_node);
- os_free(pmac_node->pnode);
- pmac_node->pnode = NULL;
- os_free(pmac_node);
- pmac_node = pip_node;
- os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
- } else {
- renew = true;
- type = DHCPS_TYPE_DYNAMIC;
- }
- pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
- pdhcps_pool->type = type;
- pdhcps_pool->state = DHCPS_STATE_ONLINE;
- } else {
- pdhcps_pool = pmac_node->pnode;
- if (ip != NULL) {
- pdhcps_pool->ip.addr = ip->addr;
- } else if (flag == TRUE) {
- pdhcps_pool->ip.addr = start_ip;
- } else { // no ip to distribute
- return IPADDR_ANY;
- }
- node_remove_from_list(&plist,pmac_node);
- pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
- pdhcps_pool->type = type;
- pdhcps_pool->state = DHCPS_STATE_ONLINE;
- node_insert_to_list(&plist,pmac_node);
- }
- } else { // new station
- if (pip_node != NULL) { // maybe ip has used
- pdhcps_pool = pip_node->pnode;
- if (pdhcps_pool->state != DHCPS_STATE_OFFLINE) {
- return IPADDR_ANY;
- }
- os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
- pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
- pdhcps_pool->type = type;
- pdhcps_pool->state = DHCPS_STATE_ONLINE;
- } else {
- pdhcps_pool = (struct dhcps_pool *)os_zalloc(sizeof(struct dhcps_pool));
- if (ip != NULL) {
- pdhcps_pool->ip.addr = ip->addr;
- } else if (flag == TRUE) {
- pdhcps_pool->ip.addr = start_ip;
- } else { // no ip to distribute
- os_free(pdhcps_pool);
- return IPADDR_ANY;
- }
- if (pdhcps_pool->ip.addr > end_ip) {
- os_free(pdhcps_pool);
- return IPADDR_ANY;
- }
- os_memcpy(pdhcps_pool->mac, bssid, sizeof(pdhcps_pool->mac));
- pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
- pdhcps_pool->type = type;
- pdhcps_pool->state = DHCPS_STATE_ONLINE;
- pback_node = (list_node *)os_zalloc(sizeof(list_node ));
- pback_node->pnode = pdhcps_pool;
- pback_node->pnext = NULL;
- node_insert_to_list(&plist,pback_node);
- }
- }
- return pdhcps_pool->ip.addr;
- }
|