080424

本文提供多个C语言编程实例,包括学生信息管理系统、求六个数中最小数、华氏温度转摄氏温度等实用功能,适合初学者练习。

1. 使用printf() 函数显示下列菜单:
                    Menu
===================================
1. Input the students’ names and scores
2. Search scores of some students
3. Modify scores of some students
4. List all students’ scores
5. Quit the system
===================================
Please input your choise (1-5):


/*
本程序有问题,输入姓名和分数后提示有问题需关闭,估计问题在字符串的输入处
*/

#include <stdio.h>
#include <stdlib.h>

int select(int n);
 char name[10];
 float score;
void main(){
 int n;

    printf("/t/t/tmenu/n");
    printf("************************************************/n");
    printf("1. Input the students’ names and scores/n");
    printf("2. Search scores of some students/n");
    printf("3. Modify scores of some students/n");
    printf("4. List all students’ scores/n");
    printf("5. Quit the system/n");
    printf("************************************************/n");
       
    printf("Please input your choise (1-5): ");
 do{
  scanf("%d",&n);
 }while(n>5||n<1);
  select(n);
}
int select(int n){
 switch(n){
  case 1:{
    printf("please input the student's name and scores:");
    scanf("%s%f",name,score);
    printf("**************************************************/n");
    printf("name/t/tscore/t/n");
    printf("%s/t/t%f",name,score);
    printf("**************************************************/n");
    break;
  }
  case 2:{
    printf("please input the student's name:");
    scanf("%s",name);
    break;
     }
  case 3:{
    printf("please input the student's new name and new scores:");
    scanf("%s%f",name,score);
    break;
     }
  case 4:{
    printf("please input the student's new name and new scores:");
    scanf("%s%f",name,score);
    break;
     }
  case 5:{
    system("exit");
     }
 }
 return n;
}
2. 参照例1.7和例1.8,选择一种方法编写一个程序,实现输入
    六个数输出最小数。
#include <stdio.h>

void main(){
 int num1,num2,num3,num4,num5,num6;
 int min;
 printf("please input 6 number:");
 scanf("%d%d%d%d%d%d",&num1,&num2,&num3,&num4,&num5,&num6);
 min=num1;
 if(min>num2){
  min=num2;
 }
 if(min>num3){
  min=num3;
 }
 if(min>num4){
  min=num4;
 }
 if(min>num5){
  min=num5;
 }
 if(min>num6){
  min=num6;
 }
 printf("%d/n",min);
}
3. 编写一个程序,从键盘上输入华氏温度,屏幕显示对应的
摄氏温度。华氏温度和摄氏温度的转换公式为:
 c=(f-32)/1.8

#include <stdio.h>

int main(){

    float tem1,tem2;
    printf("Please input the temperature:");
    scanf("%f",&tem1);
    tem2=(tem1-32)/1.8;
    printf("the temperature is %f",tem2);
}
4. 编程输出字符0、9、A、Z、a、z的ACSII码的十进制、八进制和十六进制的表示形式。
#include <stdio.h>

int main(){
    int a=0;
    int b=9;
    char c='a';
    char d='A';
    char e='z';
    char f='Z';
    printf("0/t%o/t%d/t%x/n",a,a,a);
    printf("9/t%o/t%d/t%x/n",b,b,b);
    printf("a/t%o/t%d/t%x/n",c,c,c);
    printf("A/t%o/t%d/t%x/n",d,d,d);
    printf("z/t%o/t%d/t%x/n",e,e,e);
    printf("Z/t%o/t%d/t%x/n",f,f,f);


}
5. 参考例L2_6.C编写一个程序,从键盘输入字符(例如’1’),转换成十进制数(即1),并输出。
#include <stdio.h>
void main(){
    char a;
    int b;
    scanf("%c",&a);
    b= ((int)a) - 48;
    printf("the number is %d",b);

}
提示:“1”的ASCII码为十进制数49,将其减去一个数等于十进制1即可。
6. 已知a=3,b=2,c=2.5,计算(float)(a+b)/3+(int)c的值。
#include <stdio.h>
int main(){
    int a=3;
    int b=2;
    float c=2.5;
    float d;
    d=(float)(a+b)/3+(int)c;
    printf("the d is %f",d);
}
7. 编写一个程序输出5!、10!的结果。
#include <stdio.h>
void main(){
 int i;
 int n;
 int s=1;
 
 printf("please input a number:");
 scanf("%d",&n);
 for(i=1;i<=n;i++){
  s=i*s;
 }
 printf("%d/n",s);
}
8. 参考例L2_8.C编写一个程序,输入2个学生的姓名、学号、英语、数学、计算机成绩,输出这两个学生的姓名、学号和平均分。
#include<stdio.h>
void main()
{
 long num;
 char name[12];
 float math,english,computer;
 float average;
 int n;
 for(n=1;n<=2;n++)
 {
  printf("please input a student's number:");
  scanf("%ld",&num);
  printf("please input the student's name:");
  scanf("%s",name);
  
  do
  {
   printf("please input the student's score(math english computer):");
   scanf("%f%f%f",&math,&english,&computer);
  }while((math<0||math>100)||(english<0||english>100)||(computer<0||computer>100));
  average=(math+english+computer)/3;
  printf("the %s average is %f/n",name,average);
 }
}

给我每行的注释#include <netinet/if_ether.h> #include <linux/filter.h> #include <linux/if_packet.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <net/if.h> #include "options.h" #include "packet.h" #include "dhcp.h" #include "dhcpc.h" #include "nsd_common.h" #include "libdms.h" #include "libds.h" #define DHCPC_SOCKET_RECV_BUF_SIZE (32 * 1024) #define DHCPC_SOCKET_SEND_BUF_SIZE (32 * 1024) #define DHCPC_SERVER_DETECT_TIMEOUT 60000000 //us(1 min) #define DHCPC_SERVER_DETECT_FAILED_MAX_TIME 5 LOCAL S32 discovery_timeout[DISCOVERY_RETRY_TIMES] = {2, 2, 4, 2, 12, 2, 2, 4, 2, 20, 2, 2, 4, 2, 20, 2, 2, 4, 2, 2}; /* DISCOVERY超时时间。 */ LOCAL DHCPC_PARAMS dhcpc_params = {0}; LOCAL struct dhcp_packet packet = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT #define DHCP_4G_ROUTER_STR "4g router" #define DHCPC_4G_IPC_DEV_NAME "usb0" #define DHCPC_WIRED_INTERNET_MODE 0 #define DHCPC_4G_INTERNET_MODE 1 LTE_CONFIG_INFO_DATA g_lte_config_data = {0}; S32 g_sock_idx = -1; S32 get_lte_config_data_flag = 0; /* 是否已经读取了lte_config_info_data的配置,0:未读取 ,1:已读取 */ #endif LOCAL S32 dhcpc_ip_reset() { DHCPC_MSG msg; memset(&msg, 0, sizeof(DHCPC_MSG)); msg.status = LINK_IP_RESET; msg.code = LINK_CODE_NORMAL; NSD_SEND(NSD_DHCPC_STATUS, (U8*)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL S32 dhcpc_flush_net(U32 status, U32 code) { DHCPC_MSG msg; PHY_STATUS phy_status = {0}; memset(&msg, 0, sizeof(DHCPC_MSG)); /* Stopped by caller, no need to send message. */ if (-1 == dhcpc_params.call_bk_id) { return OK; } msg.call_bk_id = dhcpc_params.call_bk_id; msg.ctrl = 0; //memcpy(msg.dev_name, dhcpc_params[iface].dev_name, DEV_NAME_LEN); msg.status = status; msg.code = code; msg.ip = dhcpc_params.yiaddr; msg.mask = dhcpc_params.mask; msg.gateway = dhcpc_params.gateway; msg.mtu = dhcpc_params.mtu; /*msg.proto = PROTO_DHCP;*/ if (FALSE == dhcpc_params.manual_dns) { msg.dns[0] = dhcpc_params.dns[0]; msg.dns[1] = dhcpc_params.dns[1]; } memcpy(msg.mac, dhcpc_params.server_mac, MAC_ADDR_SIZE); ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG("DHCP success,clean tag"); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 *)&phy_status, sizeof(PHY_STATUS)); } NSD_SEND(NSD_DHCPC_STATUS, (U8*)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL void dhcpc_timeout_flush_net() { PHY_STATUS phy_status = {0}; EXCEPTION_STATUS_MSG msg = {0}; ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG("record wrong code"); msg.type = WLAN_GATEWAY_UNREACHABLE; msg.status = 1; msg_send(EXCEPTION_STATUS_MID, (U8 *)&msg, sizeof(msg)); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 *)&phy_status, sizeof(PHY_STATUS)); } if (dhcpc_params.dhcp_timeout == 1) { dhcpc_flush_net(LINK_UP, LINK_CODE_DHCP_TIMEOUT); dhcpc_params.dhcp_timeout = 0; } return; } /* Multi-wans support: add parameter S32 i for all function. By xcl, 2011-05-04.*/ /* initialize a packet with the proper defaults */ LOCAL void init_packet(char type) { struct vendor { char vendor, length; char str[sizeof("MSFT 5.0")]; } vendor_id = { DHCP_VENDOR, sizeof("MSFT 5.0") - 1, "MSFT 5.0"}; /* Changed by lsz 080424, cheat server:"I am Windows XP" */ /* vendor_id = { DHCP_VENDOR, sizeof("udhcp "VERSION) - 1, "udhcp "VERSION};*/ init_header(&packet, type); /* message type */ memcpy(packet.chaddr, dhcpc_params.mac, 6); /* moved by tiger 20090304, from send_discover, flags should be setting for all packet in that mode */ /* Modified by Li Shaozhang, 070707 */ /* Multi-wans support.*/ if (dhcpc_params.flags/*get_runtime_dhcp_flags()*/) /* server reply mode choose */ packet.flags &= htons(0x7FFF); /* set first bit to 0, just AND 0111 1111 1111 1111 */ else /* server reply in broadcast mode */ packet.flags |= htons(0x8000); /* set first bit to 1, just OR 1000 0000 0000 0000 */ /* Edited by xcl, 13Feb12. * According to rfc2131, release packet must include options 53、54 and may 61, must not others. * decline packet is most the same but must include options 50. */ if (DHCPRELEASE != type && DHCPDECLINE != type) { /* 080501, add maximum size option --- lsz */ /* Explicitly saying that we want RFC-compliant packets helps * some buggy DHCP servers to NOT send bigger packets */ add_simple_option(packet.options, DHCP_MAX_SIZE, htons(DHCP_MAX_MSG_SIZE)); } if (dhcpc_params.client[OPT_DATA]) add_option_string(packet.options, (uint8_t *)dhcpc_params.client);/* client id */ /* Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 12. */ if (DHCPRELEASE != type && DHCPDECLINE != type && dhcpc_params.name[OPT_DATA]) add_option_string(packet.options, (uint8_t *)dhcpc_params.name);/* hostname */ /* Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 60. */ if (DHCPRELEASE != type && DHCPDECLINE != type) add_option_string(packet.options, (uint8_t *) &vendor_id); /* vendor id */ } /* Add a parameter request list for stubborn DHCP servers. Pull the data * from the struct in options.c. Don't do bounds checking here because it * goes towards the head of the packet. */ LOCAL void add_requests() { S32 end = end_option(packet.options); S32 i, len = 0; packet.options[end + OPT_CODE] = DHCP_PARAM_REQ; for (i = 0; dhcp_options[i].code; i++) if (dhcp_options[i].flags & OPTION_REQ) packet.options[end + OPT_DATA + len++] = dhcp_options[i].code; packet.options[end + OPT_LEN] = len; packet.options[end + OPT_DATA + len] = DHCP_END; } /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ LOCAL S32 send_discover() { init_packet(DHCPDISCOVER); packet.xid = dhcpc_params.xid; /* 080424, del by lsz, cauz some server may ignore our request with an requested ip */ #if 0 if (requested) add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); #endif add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Broadcasts a DHCP request message */ LOCAL S32 send_selecting(U32 server, U32 requested) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Unicasts or broadcasts a DHCP renew message */ LOCAL S32 send_renew(U32 server, U32 ciaddr) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; packet.ciaddr = ciaddr; add_requests(&packet); /* 指定了server的,就单播发送 */ if (server) { return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } #if 0 /* Unicasts a DHCP release message */ LOCAL S32 send_release(U32 server, U32 ciaddr) { init_packet(DHCPRELEASE); packet.xid = random(); /* 使用新ID */ packet.ciaddr = ciaddr; /* Del by xcl, 13Feb12. According to rfc2131, release packet must not include option 50 */ /*add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr);*/ add_simple_option(packet.options, DHCP_SERVER_ID, server); return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } #endif /* send broadcast when GARP checking failed added by tiger 20090825 */ LOCAL S32 send_decline(U32 server, U32 requested) { init_packet(DHCPDECLINE); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } LOCAL void dhcpc_params_update() { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read dev_name:%s failed", dhcpc_params.dev_name); return; } dhcpc_params.code = LINK_CODE_NORMAL; if (NULL != dhcpc_params.path) { ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; } /* start dial */ LOCAL S32 link_up_inner() { U64 cur_time = NSD_TIMESTAMP(); LINK_STATUS link_status = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data failed"); return ERROR; } if(lte_config.internet_wired_enable == 0) { LTE_DHCP_IP dhcp_ip = {0}; if (0 == ds_read(LTE_DHCP_IP_PATH, &dhcp_ip, sizeof(LTE_DHCP_IP))) { DHCPC_ERROR("Read lte dhcp ip failed"); return ERROR; } /* 4G_IPC: 用当前生效的ip去尝试续约 */ if (dhcp_ip.ipaddr != 0) { dhcpc_params.yiaddr = dhcp_ip.ipaddr; if(dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } }else { if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } /* 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } } #else if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } /* 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } #endif if (DISCOVERY == dhcpc_params.state || RECONNECT_RENEWING == dhcpc_params.state) { DHCPC_DEBUG("dhcpc_ip_reset"); dhcpc_ip_reset(); } switch (dhcpc_params.state) { case DISCOVERY: dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; /* 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 */ break; case RECONNECT_REBINDING: dhcpc_params.timeout = 0; dhcpc_params.t2 = 60; dhcpc_params.start = cur_time - dhcpc_params.t2; dhcpc_params.lease = 120; break; case RECONNECT_RENEWING: dhcpc_params.timeout = 0; dhcpc_params.start = cur_time; dhcpc_params.lease = 120; dhcpc_params.t2 = 60; dhcpc_params.t1 = 0; break; } dhcpc_params.dhcp_timeout = 1; /* 重连才触发dhcp timeout*/ #if 0 /* 如果当前正处在释放IP状态。 */ if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { dhcpc_params.re_dial = TRUE; /* IP地址释放完毕之后会自动重拨。 */ return 0; } /* 如果已经拨上号了,断线重连。 */ if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { /* 断开DHCPC-LAN的连接时,不要释放租约,对外表现与SLP平台保持一致,详解见linkDownInner。 */ if (dhcpc_params.send_release) { DHCPC_DEBUG("Send RELEASE to server %.8x", ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ } dhcpc_params.timeout = 0; /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; dhcpc_params.re_dial = TRUE; /* IP地址释放完毕之后会自动重拨。 */ #endif return OK; } /* stop dial */ LOCAL S32 link_down_inner(U32 code) { /* 智能ip策略,不需要发送release包,直接停止状态机即可 */ if (INIT != dhcpc_params.state) { /* 保留已经获取的ip */ /*dhcpc_params.yiaddr = 0;*/ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); } dhcpc_flush_net(LINK_DOWN, code); #if 0 /* 如果已经拨上号了,需要发送release包。 */ if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { /* 修复Bug 185658 & 185215,由于桥接到rootAP使用的MAC与DHCPC-LAN使用的LAN MAC不同,因此重桥会出 * 现以下问题: * 如果发送DHCP RELEASE释放了原来的租约,那么重桥重新获取IP时,rootAP的DHCPS可能会发ARP Request * 来探测原来分配的IP是否被使用,因为此时LAN口已配置了该IP,因此会给rootAP ARP Reply,告知该IP对 * 应的是LAN MAC。 * 但在rootAP端来看,ARP reply的MAC与DHCPC DISCOVER里携带MAC不同,因此DHCPS会误判成IP已被另一个设 * 备使用,从而又分配了另一个可用的IP,导致重桥后的LAN IP改变。 * SLP平台机型在重桥时因为没有发DHCP RELEASE释放租约,因此在租约有效期间重桥能够保持LAN IP不变。 * 当租约被老化清理掉,重桥同样会导致LAN IP改变。 * 要完全修复此bug需要无线驱动与DHCPC-LAN互相配合着修改,现在先部分修复,断开DHCPC-LAN的连接时, * 不要发DHCP RELEASE释放租约,令SDMP平台的对外表现与SLP平台一致。 */ if (dhcpc_params.send_release) { /* 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP * 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 */ DHCPC_DEBUG("Send RELEASE to server %.8x", ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ } dhcpc_params.timeout = 0; /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; return 0; } /* 如果正在断开,保持当前的状态机即可。 */ if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { return 0; } /* 如果正在拨号,停止状态机即可。 */ if (INIT != dhcpc_params.state) { dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); } #endif return 0; } LOCAL void dhcpc_check_timer() { U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}; #if 0 NVR_STREAM_NUM stream_num = {0}; if(BOUND == dhcpc_params.state) { if(dhcpc_params.arp_failed_times > DHCPC_SERVER_DETECT_FAILED_MAX_TIME) { DHCPC_ERROR("detect server exceed maximum, failed times:%d", dhcpc_params.arp_failed_times); dhcpc_params.timeout = cur_time; dhcpc_params.state = RENEWING; dhcpc_params.t1 = dhcpc_params.t2; } else { if(0 == dhcpc_params.last_arp_timestamp || (dhcpc_params.last_arp_timestamp + DHCPC_SERVER_DETECT_TIMEOUT)< cur_time) { /* 对于VIGI NVR拉流中,则不进行DHCP的ARP探测 */ ds_read(TP_NVR_STREAM_NUM_PATH, &stream_num, sizeof(NVR_STREAM_NUM)); if(0 == stream_num.num) { if(arpping(dhcpc_params.server, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300)) { DHCPC_ERROR("can't find dhcp server %x",dhcpc_params.server); dhcpc_params.arp_failed_times++; } else { dhcpc_params.arp_failed_times = 0; } } else { dhcpc_params.arp_failed_times = 0; } dhcpc_params.last_arp_timestamp = cur_time; } } } #endif /* DHCPC_DEBUG("DHCP state is %d", dhcpc_params.state); */ if (cur_time < dhcpc_params.timeout) /* 暂不考虑溢出问题。 */ { return; } switch (dhcpc_params.state) { case INIT: /* just do nothing */ break; /* 和发REQUEST包行为统一,第一个包要在收包前一个状态发,避免还未发DISCOVER包,就开始收包。 */ case DISCOVERY: DHCPC_DEBUG("Send DISCOVER with unicast flag %d", dhcpc_params.flags); dhcpc_params.xid = random(); /* 每次重新拨号,每次续约时才更换xid,若没有得到响应,可以不更换xid。 */ send_discover(); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[0]); dhcpc_params.packet++; dhcpc_params.state = SELECTING; break; case SELECTING: if (dhcpc_params.packet >= DISCOVERY_RETRY_TIMES) { /* DHCPC fail, start in 2s again. */ DHCPC_DEBUG("Dhcpc failed, retry count = %d", dhcpc_params.packet); dhcpc_params.timeout = cur_time + 2; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } /* change runtime dhcp flags when exceed DISCOVER_INVERT_TIMES added by tiger 20090819 apply 11G and XP's option */ /* 修复Bug 40838:切换单/广播时需同步加/卸载filter(20130924) */ /* 在PNE2.2平台里,每5个包为一组,每组里第三个包开始切换 */ if ((dhcpc_params.support_un_cast) && (DISCOVERY_INVERT_TIMES == (dhcpc_params.packet % DISCOVERY_GROUP_TIMES))) { dhcpc_params.flags = !dhcpc_params.flags; } DHCPC_DEBUG("Send DISCOVER with unicast flag %d", dhcpc_params.flags); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[dhcpc_params.packet]); send_discover(); dhcpc_params.packet++; if (DISCOVERY_RETRY_TIMEOUT == dhcpc_params.packet) { dhcpc_timeout_flush_net(); } break; case REQUESTING: if (dhcpc_params.packet > REQUESTING_RETRY_TIMES) /* 当尝试超过一定次数,重新发DISCOVERY。*/ { DHCPC_DEBUG("Recv no ACK, restart"); dhcpc_params.timeout = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send REQUEST to server %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = /*time(0) + ((cur_client->packet_num == 2) ? 10 : 2)*/cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.packet++; break; case BOUND: case RENEWING: /* Either set a new T1, or enter REBINDING state */ if ((dhcpc_params.t2 - dhcpc_params.t1) <= (dhcpc_params.lease / 14400 + 1)) { /* timed out, enter rebinding state */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(dhcpc_params.t2 - dhcpc_params.t1); dhcpc_params.state = REBINDING; /* 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server */ dhcpc_params.server = 0; dhcpc_params.arp_failed_times = 0; DHCPC_DEBUG("Entering rebinding state"); break; } /* send a request packet */ DHCPC_DEBUG("Send REQUEST to server %.8x", dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.t1 = (dhcpc_params.t2 - dhcpc_params.t1) / 2 + dhcpc_params.t1; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + dhcpc_params.start; dhcpc_params.state = RENEWING; break; case REBINDING: /* Either set a new T2, or enter INIT state */ //DHCPC_ERROR("dhcpc_params.lease:%d, dhcpc_params.t2:%d, limit:%d", dhcpc_params.lease, dhcpc_params.t2, (dhcpc_params.lease / 14400 + 1)); if ((dhcpc_params.lease - dhcpc_params.t2) <= (dhcpc_params.lease / 14400 + 1)) { //dhcpc_flush_net(LINK_DOWN, LINK_CODE_NOECHO); DHCPC_DEBUG("Lease lost, entering DISCOVERY state"); /* timed out, enter init state */ dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); /* 智能ip:rebinding失败,视为之前的ip失效了 */ dhcpc_params.yiaddr = 0; break; } ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG("broadcast REQUEST with request ip %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.t2 = (dhcpc_params.lease - dhcpc_params.t2) / 2 + dhcpc_params.t2; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t2) + dhcpc_params.start; dhcpc_params.packet++; break; case RECONNECT_RENEWING: /* 每秒发一次包,等待 RECONNECT_RENEWING_TIMES 秒 */ if (dhcpc_params.packet > RECONNECT_RENEWING_TIMES) { /* timed out, enter rebinding state */ dhcpc_params.timeout = cur_time; dhcpc_params.state = RECONNECT_REBINDING; dhcpc_params.packet = 0; /* 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server */ dhcpc_params.server = 0; DHCPC_DEBUG("[RECONNECT]Entering reconect_rebinding state"); break; } /* send a request packet */ DHCPC_DEBUG("[RECONNECT]Send REQUEST to server %.8x", dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.packet++; dhcpc_params.timeout = 0; break; case RECONNECT_REBINDING: /* 每秒发一次包,等待 RECONNECT_REBINDING_TIMES 秒 */ if (dhcpc_params.packet > RECONNECT_REBINDING_TIMES) { /* timed out, enter init state */ dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; /* 智能ip:rebinding失败,视为之前的ip失效了 */ dhcpc_params.yiaddr = 0; DHCPC_DEBUG("[RECONNECT]Reconnect fail, Entering discovery state"); break; } /* send a request packet */ ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG("broadcast REQUEST with request ip %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = cur_time; dhcpc_params.packet++; break; #if 0 case RELEASED: /* 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP * 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 */ ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send RELEASE to server %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(1); /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; break; case IFDOWN: dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); /* 注释掉,保存上次获取的ip */ //dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; if (-1 != dhcpc_params.call_bk_id_new) { dhcpc_params.call_bk_id = dhcpc_params.call_bk_id_new; dhcpc_params.call_bk_id_new = -1; } memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); if (TRUE == dhcpc_params.re_dial) { dhcpc_params.re_dial = FALSE; dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; /* 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 */ dhcpc_params.state = DISCOVERY; } break; #endif } } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL void write_mobile_access(U8 val) { DEVICE_BASIC_INFO info = {0}; if (0 == ds_read(DEVICE_BASIC_INFO_PATH, &info, sizeof(info))) { DHCPC_ERROR("ds read device basic_info failed"); return; } else { info.mobile_access = val; ds_write(DEVICE_BASIC_INFO_PATH, &info, sizeof(info)); } } #endif #if 0 LOCAL S32 dhcp_renew_handle(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { /* 仅对处于BOUND状态的DHCP进行renew操作 */ DHCPC_ERROR("Recv DHCP Renew, state(%d)", dhcpc_params.state); if(BOUND == dhcpc_params.state) { dhcpc_params.arp_failed_times = (DHCPC_SERVER_DETECT_FAILED_MAX_TIME + 1); } return OK; } #endif LOCAL void dhcpc_handle(S32 sock) { S32 bytes = 0; U8 *message = NULL, *option = NULL; U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}, mask = {0}, gateway = {0}, server = {0}; U32 dns[2] = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config error"); return; } #endif /* 收到DHCP服务器的响应报文。 */ bytes = get_packet(&packet, sock); if (bytes < 0) { DHCPC_WARNING("Error on read, %m, reopening socket"); return; } /* Ignore packets that aren't for us */ if (memcmp(packet.chaddr, dhcpc_params.mac, sizeof(dhcpc_params.mac))) { DHCPC_DEBUG("Packet does not have our chaddr -- ignoring"); return; } if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DHCPC_WARNING("Couldnt get option from packet -- ignoring"); return; } if (packet.xid != dhcpc_params.xid) { DHCPC_WARNING("ignoring XID %lx (our xid is %lx)", packet.xid, dhcpc_params.xid); return; } switch (dhcpc_params.state) { case INIT: case DISCOVERY: /* just drop all message. */ break; case SELECTING: if ((DHCPOFFER != *message) || /* 在此处只能接收OFFER包,其它包丢弃 */ (NULL == (option = get_option(&packet, DHCP_SERVER_ID)))) /* 必须带有SERVER_ID。 */ { break; } memcpy(&dhcpc_params.server, option, 4); dhcpc_params.mask = inet_addr("255.255.255.255"); switch (ip_network_id(packet.yiaddr)) { case 'A': dhcpc_params.mask = inet_addr("255.0.0.0"); break; case 'B': dhcpc_params.mask = inet_addr("255.255.0.0"); break; case 'C': dhcpc_params.mask = inet_addr("255.255.255.0"); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } /*dhcpc_params[iface].xid = packet.xid;*/ /* 忽略? */ dhcpc_params.yiaddr = packet.yiaddr; ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Recv OFFER from server %d.%d.%d.%d with ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); /* 在此处验证获得的IP的合法性。这里DHCP不回MTU */ if ((OK != check_valid_param(dhcpc_params.mtu, dhcpc_params.yiaddr, dhcpc_params.mask, 0))) { DHCPC_DEBUG("check_valid_param failed."); break; /* 继续等待其它的服务器响应 */ } /* 合法性验证通过后,发送Request报文,跳转到REQUESTING状态。 */ ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send REQUEST to server %d.%d.%d.%d with request ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.state = REQUESTING; dhcpc_params.packet = 0; dhcpc_params.retry = 0; break; case RENEWING: case REBINDING: case REQUESTING: case RECONNECT_RENEWING: case RECONNECT_REBINDING: /* 是否要验证server id?这里暂且验证下,个人认为这样安全。 */ if (NULL == (option = get_option(&packet, DHCP_SERVER_ID))) { break; /* unknown dhcp server? */ } /* REBINDING阶段更新server */ if (dhcpc_params.state == REBINDING || dhcpc_params.state == RECONNECT_REBINDING) { memcpy(&dhcpc_params.server, option, 4); } /* REBINDING阶段可能会切换server,此时不可检查 */ #if 0 if (dhcpc_params[iface].server != *(U32 *)option) { break; /* invalid dhcp server? */ } #endif if (DHCPACK == *message) { dhcpc_params.lease = 60*60; /* 默认1小时。 */ if (NULL != (option = get_option(&packet, DHCP_LEASE_TIME))) { memcpy(&dhcpc_params.lease, option, 4); dhcpc_params.lease = ntohl(dhcpc_params.lease); } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { IF_CONF if_conf = {0}; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return; } char dev_name[32] = {0}; U8 dev_mac[6] = {0}; snprintf(dev_name, sizeof(dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dev_name, NULL, dev_mac)) { DHCPC_ERROR("read usb0 device info error"); return; } /* 发送GARP验证IP是否被占用。 */ if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && ((0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300)) || (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dev_mac, dev_name, 300)))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in use, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } }else #endif { /* 发送GARP验证IP是否被占用。 */ if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in use, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT /* 在有线上网模式下,dhcp server分配的IP不能为4G网关192.168.43.1 */ if(((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && packet.yiaddr == 0x012ba8c0) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in Gateway for 4G, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #endif } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if (NULL != (option = get_option(&packet, DHCP_4G_ROUTER))) { if(0 == memcmp(option, DHCP_4G_ROUTER_STR, strlen(DHCP_4G_ROUTER_STR))) { DHCPC_INFO("get option DHCP_4G_ROUTER"); write_mobile_access(1); } else { write_mobile_access(0); } } else { write_mobile_access(0); } #endif /* 分配的IP没有被占用,则使用该IP,并且进入bound状态。 */ dhcpc_params.t1 = dhcpc_params.lease/2; dhcpc_params.t2 = ((dhcpc_params.lease * 0x7) >> 3);/* little fixed point for n * .875 */ //DHCPC_ERROR("dhcpc_params.t1:%d, dhcpc_params.t2:%d", dhcpc_params.t1, dhcpc_params.t2); dhcpc_params.start = cur_time; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + cur_time; ip_addr.ipAddr = dhcpc_params.yiaddr; /* 保留原IP的值 */ dhcpc_params.yiaddr = packet.yiaddr; /* 获取网关。 */ gateway.ipAddr = dhcpc_params.gateway; dhcpc_params.gateway = 0; if (NULL != (option = get_option(&packet, DHCP_ROUTER))) { if(0 != *option) { memcpy(&dhcpc_params.gateway, option, 4); } else if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR("Received ACK but gateway option is zero, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]", dhcpc_params.gateway, dhcpc_params.server); } else { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { dhcpc_params.gateway = 0x012ba8c0; /* 4G上网模式下,无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.43.1 */ DHCPC_ERROR("Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.43.1", dhcpc_params.gateway); }else #endif { dhcpc_params.gateway = 0x0100a8c0; /* 无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.0.1 */ DHCPC_ERROR("Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1", dhcpc_params.gateway); } } } else { if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR("Received ACK but gateway option is empty, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]", dhcpc_params.gateway, dhcpc_params.server); } else { dhcpc_params.gateway = 0x0100a8c0; DHCPC_ERROR("Received ACK but the gateway and source IP are illegal, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1", dhcpc_params.gateway); } } /* 获取掩码。 */ mask.ipAddr = dhcpc_params.mask; dhcpc_params.mask = inet_addr("255.255.255.255"); switch (ip_network_id(packet.yiaddr)) { case 'A': dhcpc_params.mask = inet_addr("255.0.0.0"); break; case 'B': dhcpc_params.mask = inet_addr("255.255.0.0"); break; case 'C': dhcpc_params.mask = inet_addr("255.255.255.0"); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } /* 获取DNS. */ if (FALSE == dhcpc_params.manual_dns) { dns[0] = dhcpc_params.dns[0]; dns[1] = dhcpc_params.dns[1]; dhcpc_params.dns[0] = 0; dhcpc_params.dns[1] = 0; if (NULL != (option = get_option(&packet, DHCP_DNS_SERVER))) { S32 dnsNum = 0; S32 i = 0; dnsNum = (*(option - 1))/4; dnsNum = dnsNum > 2 ? 2 : dnsNum; for (i = 0; i < dnsNum; i++) { memcpy(dhcpc_params.dns + i, option + 4 * i, 4); } } } /* REQUESTING状态或者ip、gateway、mask有更新则刷新接口。 */ /* RECONNECT_RENEWING 和 RECONNECT_REBINDING状态可能是静态转为动态,因此也要进行设置 */ if ((REQUESTING == dhcpc_params.state) || dhcpc_params.state == RECONNECT_RENEWING || dhcpc_params.state == RECONNECT_REBINDING || (ip_addr.ipAddr != dhcpc_params.yiaddr) || (gateway.ipAddr != dhcpc_params.gateway) || (mask.ipAddr != dhcpc_params.mask)) { /* 根据获得的IP配置本地接口。 */ ip_addr.ipAddr = dhcpc_params.yiaddr; mask.ipAddr = dhcpc_params.mask; gateway.ipAddr = dhcpc_params.gateway; DHCPC_INFO("%s set ip %d.%d.%d.%d mask %d.%d.%d.%d gateway %d.%d.%d.%d lease time %ld", dhcpc_params.dev_name, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3], mask.ipAddrByteFormat[0], mask.ipAddrByteFormat[1], mask.ipAddrByteFormat[2], mask.ipAddrByteFormat[3], gateway.ipAddrByteFormat[0], gateway.ipAddrByteFormat[1], gateway.ipAddrByteFormat[2], gateway.ipAddrByteFormat[3], dhcpc_params.lease); dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } else if ((TRUE != dhcpc_params.manual_dns) && ((dns[0] != dhcpc_params.dns[0]) || (dns[1] != dhcpc_params.dns[1]))) { dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } DHCPC_DEBUG("Recv ACK from server %.8x with ip %.8x lease time %ld", dhcpc_params.server, dhcpc_params.yiaddr, dhcpc_params.lease); dhcpc_params.retry = 0; /* clear the retry counter */ dhcpc_params.packet = 0; dhcpc_params.state = BOUND; break; } if (DHCPNAK != *message) { break; } /* 这里需要考虑两种情况: */ /* 在未配置本地IP的情况(即REQUESTING状态),只需更新状态到INIT_SELECTING状态即可。 */ /* 其它状态则需要释放已配置的IP。 */ if (REQUESTING != dhcpc_params.state) { DHCPC_DEBUG("state [%d] receive NACK", dhcpc_params.state); dhcpc_flush_net(LINK_DOWN, LINK_CODE_DENY); } ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_INFO("Recv NAK from server %d.%d.%d.%d with ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); if (dhcpc_params.state != RECONNECT_RENEWING && dhcpc_params.state != RECONNECT_REBINDING) { dhcpc_timeout_flush_net(); } else { /* 收到NAK后重新开始DISCOVERY前刷新参数 */ dhcpc_params_update(); } dhcpc_params.timeout = 0; dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } } LOCAL S32 dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING("call back parameter error."); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { DHCPC_DEBUG("Now start dhcpc progress."); link_up_inner(); dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG("Now stop dhcpc progress."); link_down_inner(msg->code); return OK; } DHCPC_WARNING("Unknown command."); return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL S32 dhcpc_socket_reload() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR("client socket call failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR("client socket set reuseaddr option failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &option, sizeof(option))) { DHCPC_ERROR("client socket set broadcast option failed"); goto dhcpc_error_exit; } /* 设置缓存大小 */ buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } /* 绑定网卡 */ struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); IF_CONF if_conf = {0}; LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { strncpy(ifr.ifr_name, DHCPC_4G_IPC_DEV_NAME, strlen(DHCPC_4G_IPC_DEV_NAME) + 1); DHCPC_ERROR("ifr.ifr_name:%s", ifr.ifr_name); }else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); goto dhcpc_error_exit; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); goto dhcpc_error_exit; } strncpy(ifr.ifr_name, if_conf.ifname, strlen(if_conf.ifname)); } if(ERROR == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char*)&ifr, sizeof(ifr))) { DHCPC_ERROR("can't bind to interface :%s", ifr.ifr_name); } DHCPC_ERROR("ifr.ifr_name:%s", ifr.ifr_name); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR("server socket set broadcast option failed"); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL int dhcpc_param_reload(int flag) { IF_CONF if_conf = {0}; DHCPC dhcpc_data; dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; //dhcpc_params.call_bk_id = -1; dhcpc_params.path = DHCPC_PATH; if(flag == DHCPC_4G_INTERNET_MODE) { /* 4G_ICP使用usb0 */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", DHCPC_4G_IPC_DEV_NAME); if(0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } } else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return ERROR; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return ERROR; } /* IPC使用br-wan */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } } /* 智能ip,IPC断开dhcp时不释放租约 */ dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.flags = FALSE; /* 默认广播。 */ if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; dhcpc_params.last_arp_timestamp = 0; dhcpc_params.arp_failed_times = 0; if(dhcpc_params.sock) { inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; } dhcpc_params.sock = dhcpc_socket_reload(); g_sock_idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if(0 > g_sock_idx) { DHCPC_ERROR("add dhcp client socket to inetd failed"); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if(0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR("add dhcp timer to inetd failed"); inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } return OK; } LOCAL S32 lte_dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; U8 dev_mac[6] = {0}; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING("call back parameter error."); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { if(!strncmp(dhcpc_params.dev_name, DHCPC_4G_IPC_DEV_NAME, sizeof(dhcpc_params.dev_name))) { DHCPC_DEBUG("Now start dhcpc progress."); if(0 > read_interface_info(dhcpc_params.dev_name, NULL, dev_mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } if(memcmp(dhcpc_params.mac, dev_mac, sizeof(dhcpc_params.mac))) { DHCPC_ERROR("usb0 device mac change, reload dhcpc params."); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } link_up_inner(); }else { DHCPC_DEBUG("Change dhcpc device first"); DHCPC_DEBUG("Now start dhcpc progress."); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } link_up_inner(); } dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG("Now stop dhcpc progress."); link_down_inner(msg->code); return OK; } DHCPC_WARNING("Unknown command."); return ERROR; } #endif LOCAL S32 dhcpc_socket_init() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR("client socket call failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR("client socket set reuseaddr option failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &option, sizeof(option))) { DHCPC_ERROR("client socket set broadcast option failed"); goto dhcpc_error_exit; } /* 设置缓存大小 */ buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR("server socket set broadcast option failed"); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL void dhcpc_param_init() { IF_CONF if_conf = {0}; DHCPC dhcpc_data; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return; } memset(&dhcpc_params, 0, sizeof(DHCPC_PARAMS)); /* 智能ip,设置ip为0xFFFFFFFF 标记是开机后首次获取ip */ dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; dhcpc_params.call_bk_id = -1; dhcpc_params.mac[0] = 0x00; dhcpc_params.mac[1] = 0x11; dhcpc_params.mac[2] = 0x22; dhcpc_params.mac[3] = 0x33; dhcpc_params.mac[4] = 0x44; dhcpc_params.mac[5] = 0x55; dhcpc_params.path = DHCPC_PATH; /* IPC使用br-wan */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { return; } /* 智能ip,IPC断开dhcp时不释放租约 */ dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.state = INIT; dhcpc_params.flags = FALSE; /* 默认广播。 */ if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.packet = 0; /* start things over */ dhcpc_params.timeout = 0xFFFFFFFF; /* Kill any timeouts because the user wants this to hurry along */ dhcpc_params.retry = 0; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; dhcpc_params.last_arp_timestamp = 0; dhcpc_params.arp_failed_times = 0; dhcpc_params.sock = dhcpc_socket_init(); } LOCAL S32 dhcpc_init() { S32 idx = -1; dhcpc_param_init(); if (0 > dhcpc_params.sock) { DHCPC_ERROR("dhcp client socket init failed"); return ERROR; } idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if (0 > idx) { DHCPC_ERROR("add dhcp client socket to inetd failed"); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if (0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR("add dhcp timer to inetd failed"); inet_del_socket(idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } msg_attach_handler(NSD_DHCPC_CTRL, dhcpc_ctrl_callback); #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT g_sock_idx = idx; msg_attach_handler(LTE_DHCPC_CTRL, lte_dhcpc_ctrl_callback); #endif #if 0 ds_register_action("dhcpc", "renew", dhcp_renew_handle); #endif DHCPC_ERROR("DHCPC init over."); return OK; } LOCAL S32 dhcpc_reload(DS_MSG *msg) { if (NULL == msg) { return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(!get_lte_config_data_flag) { if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&g_lte_config_data, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("ds read path [%s] failed.", LTE_INFO_DATA_PATH); return ERROR; } get_lte_config_data_flag = 1; } #endif if (ds_path_id_exist(msg->id, msg->num, DHCPC_PATH)) { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 == ds_read(DHCPC_PATH, (U8 *)&dhcpc_data, sizeof(DHCPC))) { DHCPC_ERROR("Read dhcpc data ERROR"); return ERROR; } dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(ds_path_id_exist(msg->id, msg->num, INFO_INTERNET_PATH)) { INFO_INTERNET info_internet = {0}; if(0 == ds_read(INFO_INTERNET_PATH, (U8*)&info_internet, sizeof(INFO_INTERNET))) { DHCPC_ERROR("ds read path [%s] failed.", INFO_INTERNET_PATH); return ERROR; } LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(info_internet.link_status == INTERNET_4G_DISCONNECTED) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } }else if(info_internet.link_status == INTERNET_4G_CONNECTING) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } } } #endif return OK; } LOCAL void dhcpc_main() { DS_DAT_MON_DESC dhcpc_data_monitor[] = { DS_DAT_MON(DHCPC_PATH, DATA_ATTRI_NOTIFY), #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT DS_DAT_MON(INFO_INTERNET_PATH, DATA_ATTRI_NOTIFY), #endif }; DS_MOD_DESC dhcpc_module = DS_STRUCT_MOD("dhcpc", dhcpc_init, NULL, dhcpc_reload, NULL, NULL, NULL, dhcpc_data_monitor); MODULE *module_node = ds_register_module("dhcpc", &dhcpc_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(dhcpc_main);
09-23
帮我分析这个代码,他是一个nvmp管理ipc的nsd模块下dhcpc模块,我对平台,协议等都不是太熟悉,帮我尽量详细的分析,我要了解这个功能后为它添加新功能。 #ifndef _H_DHCPC #define _H_DHCPC #include "nsd_common.h" #include "dhcp.h" #define DHCPC_DEBUG(fmt, ...) NSD_DEBUG("[DHCPC]" fmt, ##__VA_ARGS__) #define DHCPC_INFO(fmt, ...) NSD_LOG(LOG_INFO, "[Network][DHCP]" fmt, ##__VA_ARGS__) #define DHCPC_WARNING(fmt, ...) NSD_WARN("[DHCPC]" fmt, ##__VA_ARGS__) #define DHCPC_ERROR(fmt, ...) NSD_ERROR("[DHCPC]" fmt, ##__VA_ARGS__) #define MAX_HOST_NAME_LEN 64 #define MAX_CLIENT_ID_LEN 64 #define INIT 0 /* 停止尝试获取动态IP状态 */ #define DISCOVERY 1 /* 开始尝试获取动态IP状态 */ #define SELECTING 2 #define REQUESTING 3 #define BOUND 4 #define RENEWING 5 #define REBINDING 6 #define RELEASED 7 /* 准备释放动态IP状态 */ #define IFDOWN 8 /* 释放接口IP */ #define RECONNECT_RENEWING 9 /* 重连renewing状态 */ #define RECONNECT_REBINDING 10 /* 重连rebounding状态 */ /* TODO: 待利用的状态,准备按照RFC把这些状态利用起来,设备重启后使用。 */ #define INIT_REBOOT 9 #define REBOOTING 10 #define DISCOVERY_RETRY_TIMES 20 /* 待定。 */ #define DISCOVERY_RETRY_TIMEOUT 3 /* 超过三次认为上层ap没开DHCP,使用静态ip连接且可被app发现。 */ #define DISCOVERY_INVERT_TIMES 3 #define DISCOVERY_GROUP_TIMES 5 #define REQUESTING_TIMEOUT 2 /* 待定。 */ #define REQUESTING_RETRY_TIMES 3 /* 待定。 */ #define RECONNECT_RENEWING_TIMES 5 /* 待定。 */ #define RECONNECT_REBINDING_TIMES 5 /* 待定。 */ /* * added by tiger 20090304, for reply mode setting */ typedef enum _DHCPC_FLAGS { DHCP_FLAGS_BROADCAST = 0, DHCP_FLAGS_UNICAST }DHCPC_FLAGS; typedef struct _DHCPC_PARAMS { S32 sock; char dev_name[32]; U32 call_bk_id_new; U32 call_bk_id; BOOL send_release; /* 链路断开时,知否需要释放租约。WAN需要,WDS桥接时不需要; */ BOOL support_un_cast; /* 支持发送单播Discovery; */ BOOL delay_set_ip; char *path; S32 dev; U8 mac[6]; U8 server_mac[6]; S32 state; BOOL flags; /* TRUE:单播,FALSE:广播。 */ U32 mtu; char name[MAX_HOST_NAME_LEN + 2]; char client[MAX_CLIENT_ID_LEN + 2]; U32 xid; U32 yiaddr; /* 服务器分配的IP。 */ U32 mask; /* 服务器分配的掩码。 */ U32 server; /* 服务器IP。 */ U32 gateway; /* 服务器分配的网关。 */ U32 dns[2]; /* 服务器分配的DNS服务器地址。 */ U32 lease; /* 地址租期。 */ U64 start; /* 地址生效时刻 */ U32 t1; /* 进入RENEWING时刻,与原服务器通信 */ U32 t2; /* 进入REBINDING时刻,与任意服务器通信 */ U64 timeout; BOOL re_dial; /* 断开後,是否需要重连。 */ BOOL manual_dns; /* 是否手动配置DNS */ S32 packet; S32 retry; /* 与packet不同,每发DISCOVERY_RETRY_TIMES个DISCOVER请求 * 得不到响应,retry才加一,LINUX的习惯是retry间隔越来越长。*/ U32 code; /* 错误码 */ U32 dhcp_timeout; U64 last_arp_timestamp; U32 arp_failed_times; }DHCPC_PARAMS; #endif #include <netinet/if_ether.h> #include <linux/filter.h> #include <linux/if_packet.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <net/if.h> #include "options.h" #include "packet.h" #include "dhcp.h" #include "dhcpc.h" #include "nsd_common.h" #include "libdms.h" #include "libds.h" #define DHCPC_SOCKET_RECV_BUF_SIZE (32 * 1024) #define DHCPC_SOCKET_SEND_BUF_SIZE (32 * 1024) #define DHCPC_SERVER_DETECT_TIMEOUT 60000000 //us(1 min) #define DHCPC_SERVER_DETECT_FAILED_MAX_TIME 5 LOCAL S32 discovery_timeout[DISCOVERY_RETRY_TIMES] = {2, 2, 4, 2, 12, 2, 2, 4, 2, 20, 2, 2, 4, 2, 20, 2, 2, 4, 2, 2}; /* DISCOVERY超时时间。 */ LOCAL DHCPC_PARAMS dhcpc_params = {0}; LOCAL struct dhcp_packet packet = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT #define DHCP_4G_ROUTER_STR "4g router" #define DHCPC_4G_IPC_DEV_NAME "usb0" #define DHCPC_WIRED_INTERNET_MODE 0 #define DHCPC_4G_INTERNET_MODE 1 LTE_CONFIG_INFO_DATA g_lte_config_data = {0}; S32 g_sock_idx = -1; S32 get_lte_config_data_flag = 0; /* 是否已经读取了lte_config_info_data的配置,0:未读取 ,1:已读取 */ #endif LOCAL S32 dhcpc_ip_reset() { DHCPC_MSG msg; memset(&msg, 0, sizeof(DHCPC_MSG)); msg.status = LINK_IP_RESET; msg.code = LINK_CODE_NORMAL; NSD_SEND(NSD_DHCPC_STATUS, (U8*)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL S32 dhcpc_flush_net(U32 status, U32 code) { DHCPC_MSG msg; PHY_STATUS phy_status = {0}; memset(&msg, 0, sizeof(DHCPC_MSG)); /* Stopped by caller, no need to send message. */ if (-1 == dhcpc_params.call_bk_id) { return OK; } msg.call_bk_id = dhcpc_params.call_bk_id; msg.ctrl = 0; //memcpy(msg.dev_name, dhcpc_params[iface].dev_name, DEV_NAME_LEN); msg.status = status; msg.code = code; msg.ip = dhcpc_params.yiaddr; msg.mask = dhcpc_params.mask; msg.gateway = dhcpc_params.gateway; msg.mtu = dhcpc_params.mtu; /*msg.proto = PROTO_DHCP;*/ if (FALSE == dhcpc_params.manual_dns) { msg.dns[0] = dhcpc_params.dns[0]; msg.dns[1] = dhcpc_params.dns[1]; } memcpy(msg.mac, dhcpc_params.server_mac, MAC_ADDR_SIZE); ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG("DHCP success,clean tag"); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 *)&phy_status, sizeof(PHY_STATUS)); } NSD_SEND(NSD_DHCPC_STATUS, (U8*)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL void dhcpc_timeout_flush_net() { PHY_STATUS phy_status = {0}; EXCEPTION_STATUS_MSG msg = {0}; ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG("record wrong code"); msg.type = WLAN_GATEWAY_UNREACHABLE; msg.status = 1; msg_send(EXCEPTION_STATUS_MID, (U8 *)&msg, sizeof(msg)); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 *)&phy_status, sizeof(PHY_STATUS)); } if (dhcpc_params.dhcp_timeout == 1) { dhcpc_flush_net(LINK_UP, LINK_CODE_DHCP_TIMEOUT); dhcpc_params.dhcp_timeout = 0; } return; } /* Multi-wans support: add parameter S32 i for all function. By xcl, 2011-05-04.*/ /* initialize a packet with the proper defaults */ LOCAL void init_packet(char type) { struct vendor { char vendor, length; char str[sizeof("MSFT 5.0")]; } vendor_id = { DHCP_VENDOR, sizeof("MSFT 5.0") - 1, "MSFT 5.0"}; /* Changed by lsz 080424, cheat server:"I am Windows XP" */ /* vendor_id = { DHCP_VENDOR, sizeof("udhcp "VERSION) - 1, "udhcp "VERSION};*/ init_header(&packet, type); /* message type */ memcpy(packet.chaddr, dhcpc_params.mac, 6); /* moved by tiger 20090304, from send_discover, flags should be setting for all packet in that mode */ /* Modified by Li Shaozhang, 070707 */ /* Multi-wans support.*/ if (dhcpc_params.flags/*get_runtime_dhcp_flags()*/) /* server reply mode choose */ packet.flags &= htons(0x7FFF); /* set first bit to 0, just AND 0111 1111 1111 1111 */ else /* server reply in broadcast mode */ packet.flags |= htons(0x8000); /* set first bit to 1, just OR 1000 0000 0000 0000 */ /* Edited by xcl, 13Feb12. * According to rfc2131, release packet must include options 53、54 and may 61, must not others. * decline packet is most the same but must include options 50. */ if (DHCPRELEASE != type && DHCPDECLINE != type) { /* 080501, add maximum size option --- lsz */ /* Explicitly saying that we want RFC-compliant packets helps * some buggy DHCP servers to NOT send bigger packets */ add_simple_option(packet.options, DHCP_MAX_SIZE, htons(DHCP_MAX_MSG_SIZE)); } if (dhcpc_params.client[OPT_DATA]) add_option_string(packet.options, (uint8_t *)dhcpc_params.client);/* client id */ /* Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 12. */ if (DHCPRELEASE != type && DHCPDECLINE != type && dhcpc_params.name[OPT_DATA]) add_option_string(packet.options, (uint8_t *)dhcpc_params.name);/* hostname */ /* Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 60. */ if (DHCPRELEASE != type && DHCPDECLINE != type) add_option_string(packet.options, (uint8_t *) &vendor_id); /* vendor id */ } /* Add a parameter request list for stubborn DHCP servers. Pull the data * from the struct in options.c. Don't do bounds checking here because it * goes towards the head of the packet. */ LOCAL void add_requests() { S32 end = end_option(packet.options); S32 i, len = 0; packet.options[end + OPT_CODE] = DHCP_PARAM_REQ; for (i = 0; dhcp_options[i].code; i++) if (dhcp_options[i].flags & OPTION_REQ) packet.options[end + OPT_DATA + len++] = dhcp_options[i].code; packet.options[end + OPT_LEN] = len; packet.options[end + OPT_DATA + len] = DHCP_END; } /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ LOCAL S32 send_discover() { init_packet(DHCPDISCOVER); packet.xid = dhcpc_params.xid; /* 080424, del by lsz, cauz some server may ignore our request with an requested ip */ #if 0 if (requested) add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); #endif add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Broadcasts a DHCP request message */ LOCAL S32 send_selecting(U32 server, U32 requested) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Unicasts or broadcasts a DHCP renew message */ LOCAL S32 send_renew(U32 server, U32 ciaddr) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; packet.ciaddr = ciaddr; add_requests(&packet); /* 指定了server的,就单播发送 */ if (server) { return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } #if 0 /* Unicasts a DHCP release message */ LOCAL S32 send_release(U32 server, U32 ciaddr) { init_packet(DHCPRELEASE); packet.xid = random(); /* 使用新ID */ packet.ciaddr = ciaddr; /* Del by xcl, 13Feb12. According to rfc2131, release packet must not include option 50 */ /*add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr);*/ add_simple_option(packet.options, DHCP_SERVER_ID, server); return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } #endif /* send broadcast when GARP checking failed added by tiger 20090825 */ LOCAL S32 send_decline(U32 server, U32 requested) { init_packet(DHCPDECLINE); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } LOCAL void dhcpc_params_update() { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read dev_name:%s failed", dhcpc_params.dev_name); return; } dhcpc_params.code = LINK_CODE_NORMAL; if (NULL != dhcpc_params.path) { ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; } /* start dial */ LOCAL S32 link_up_inner() { U64 cur_time = NSD_TIMESTAMP(); LINK_STATUS link_status = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data failed"); return ERROR; } if(lte_config.internet_wired_enable == 0) { LTE_DHCP_IP dhcp_ip = {0}; if (0 == ds_read(LTE_DHCP_IP_PATH, &dhcp_ip, sizeof(LTE_DHCP_IP))) { DHCPC_ERROR("Read lte dhcp ip failed"); return ERROR; } /* 4G_IPC: 用当前生效的ip去尝试续约 */ if (dhcp_ip.ipaddr != 0) { dhcpc_params.yiaddr = dhcp_ip.ipaddr; if(dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } }else { if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } /* 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } } #else if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } /* 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } #endif if (DISCOVERY == dhcpc_params.state || RECONNECT_RENEWING == dhcpc_params.state) { DHCPC_DEBUG("dhcpc_ip_reset"); dhcpc_ip_reset(); } switch (dhcpc_params.state) { case DISCOVERY: dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; /* 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 */ break; case RECONNECT_REBINDING: dhcpc_params.timeout = 0; dhcpc_params.t2 = 60; dhcpc_params.start = cur_time - dhcpc_params.t2; dhcpc_params.lease = 120; break; case RECONNECT_RENEWING: dhcpc_params.timeout = 0; dhcpc_params.start = cur_time; dhcpc_params.lease = 120; dhcpc_params.t2 = 60; dhcpc_params.t1 = 0; break; } dhcpc_params.dhcp_timeout = 1; /* 重连才触发dhcp timeout*/ #if 0 /* 如果当前正处在释放IP状态。 */ if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { dhcpc_params.re_dial = TRUE; /* IP地址释放完毕之后会自动重拨。 */ return 0; } /* 如果已经拨上号了,断线重连。 */ if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { /* 断开DHCPC-LAN的连接时,不要释放租约,对外表现与SLP平台保持一致,详解见linkDownInner。 */ if (dhcpc_params.send_release) { DHCPC_DEBUG("Send RELEASE to server %.8x", ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ } dhcpc_params.timeout = 0; /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; dhcpc_params.re_dial = TRUE; /* IP地址释放完毕之后会自动重拨。 */ #endif return OK; } /* stop dial */ LOCAL S32 link_down_inner(U32 code) { /* 智能ip策略,不需要发送release包,直接停止状态机即可 */ if (INIT != dhcpc_params.state) { /* 保留已经获取的ip */ /*dhcpc_params.yiaddr = 0;*/ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); } dhcpc_flush_net(LINK_DOWN, code); #if 0 /* 如果已经拨上号了,需要发送release包。 */ if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { /* 修复Bug 185658 & 185215,由于桥接到rootAP使用的MAC与DHCPC-LAN使用的LAN MAC不同,因此重桥会出 * 现以下问题: * 如果发送DHCP RELEASE释放了原来的租约,那么重桥重新获取IP时,rootAP的DHCPS可能会发ARP Request * 来探测原来分配的IP是否被使用,因为此时LAN口已配置了该IP,因此会给rootAP ARP Reply,告知该IP对 * 应的是LAN MAC。 * 但在rootAP端来看,ARP reply的MAC与DHCPC DISCOVER里携带MAC不同,因此DHCPS会误判成IP已被另一个设 * 备使用,从而又分配了另一个可用的IP,导致重桥后的LAN IP改变。 * SLP平台机型在重桥时因为没有发DHCP RELEASE释放租约,因此在租约有效期间重桥能够保持LAN IP不变。 * 当租约被老化清理掉,重桥同样会导致LAN IP改变。 * 要完全修复此bug需要无线驱动与DHCPC-LAN互相配合着修改,现在先部分修复,断开DHCPC-LAN的连接时, * 不要发DHCP RELEASE释放租约,令SDMP平台的对外表现与SLP平台一致。 */ if (dhcpc_params.send_release) { /* 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP * 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 */ DHCPC_DEBUG("Send RELEASE to server %.8x", ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ } dhcpc_params.timeout = 0; /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; return 0; } /* 如果正在断开,保持当前的状态机即可。 */ if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { return 0; } /* 如果正在拨号,停止状态机即可。 */ if (INIT != dhcpc_params.state) { dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); } #endif return 0; } LOCAL void dhcpc_check_timer() { U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}; #if 0 NVR_STREAM_NUM stream_num = {0}; if(BOUND == dhcpc_params.state) { if(dhcpc_params.arp_failed_times > DHCPC_SERVER_DETECT_FAILED_MAX_TIME) { DHCPC_ERROR("detect server exceed maximum, failed times:%d", dhcpc_params.arp_failed_times); dhcpc_params.timeout = cur_time; dhcpc_params.state = RENEWING; dhcpc_params.t1 = dhcpc_params.t2; } else { if(0 == dhcpc_params.last_arp_timestamp || (dhcpc_params.last_arp_timestamp + DHCPC_SERVER_DETECT_TIMEOUT)< cur_time) { /* 对于VIGI NVR拉流中,则不进行DHCP的ARP探测 */ ds_read(TP_NVR_STREAM_NUM_PATH, &stream_num, sizeof(NVR_STREAM_NUM)); if(0 == stream_num.num) { if(arpping(dhcpc_params.server, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300)) { DHCPC_ERROR("can't find dhcp server %x",dhcpc_params.server); dhcpc_params.arp_failed_times++; } else { dhcpc_params.arp_failed_times = 0; } } else { dhcpc_params.arp_failed_times = 0; } dhcpc_params.last_arp_timestamp = cur_time; } } } #endif /* DHCPC_DEBUG("DHCP state is %d", dhcpc_params.state); */ if (cur_time < dhcpc_params.timeout) /* 暂不考虑溢出问题。 */ { return; } switch (dhcpc_params.state) { case INIT: /* just do nothing */ break; /* 和发REQUEST包行为统一,第一个包要在收包前一个状态发,避免还未发DISCOVER包,就开始收包。 */ case DISCOVERY: DHCPC_DEBUG("Send DISCOVER with unicast flag %d", dhcpc_params.flags); dhcpc_params.xid = random(); /* 每次重新拨号,每次续约时才更换xid,若没有得到响应,可以不更换xid。 */ send_discover(); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[0]); dhcpc_params.packet++; dhcpc_params.state = SELECTING; break; case SELECTING: if (dhcpc_params.packet >= DISCOVERY_RETRY_TIMES) { /* DHCPC fail, start in 2s again. */ DHCPC_DEBUG("Dhcpc failed, retry count = %d", dhcpc_params.packet); dhcpc_params.timeout = cur_time + 2; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } /* change runtime dhcp flags when exceed DISCOVER_INVERT_TIMES added by tiger 20090819 apply 11G and XP's option */ /* 修复Bug 40838:切换单/广播时需同步加/卸载filter(20130924) */ /* 在PNE2.2平台里,每5个包为一组,每组里第三个包开始切换 */ if ((dhcpc_params.support_un_cast) && (DISCOVERY_INVERT_TIMES == (dhcpc_params.packet % DISCOVERY_GROUP_TIMES))) { dhcpc_params.flags = !dhcpc_params.flags; } DHCPC_DEBUG("Send DISCOVER with unicast flag %d", dhcpc_params.flags); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[dhcpc_params.packet]); send_discover(); dhcpc_params.packet++; if (DISCOVERY_RETRY_TIMEOUT == dhcpc_params.packet) { dhcpc_timeout_flush_net(); } break; case REQUESTING: if (dhcpc_params.packet > REQUESTING_RETRY_TIMES) /* 当尝试超过一定次数,重新发DISCOVERY。*/ { DHCPC_DEBUG("Recv no ACK, restart"); dhcpc_params.timeout = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send REQUEST to server %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = /*time(0) + ((cur_client->packet_num == 2) ? 10 : 2)*/cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.packet++; break; case BOUND: case RENEWING: /* Either set a new T1, or enter REBINDING state */ if ((dhcpc_params.t2 - dhcpc_params.t1) <= (dhcpc_params.lease / 14400 + 1)) { /* timed out, enter rebinding state */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(dhcpc_params.t2 - dhcpc_params.t1); dhcpc_params.state = REBINDING; /* 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server */ dhcpc_params.server = 0; dhcpc_params.arp_failed_times = 0; DHCPC_DEBUG("Entering rebinding state"); break; } /* send a request packet */ DHCPC_DEBUG("Send REQUEST to server %.8x", dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.t1 = (dhcpc_params.t2 - dhcpc_params.t1) / 2 + dhcpc_params.t1; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + dhcpc_params.start; dhcpc_params.state = RENEWING; break; case REBINDING: /* Either set a new T2, or enter INIT state */ //DHCPC_ERROR("dhcpc_params.lease:%d, dhcpc_params.t2:%d, limit:%d", dhcpc_params.lease, dhcpc_params.t2, (dhcpc_params.lease / 14400 + 1)); if ((dhcpc_params.lease - dhcpc_params.t2) <= (dhcpc_params.lease / 14400 + 1)) { //dhcpc_flush_net(LINK_DOWN, LINK_CODE_NOECHO); DHCPC_DEBUG("Lease lost, entering DISCOVERY state"); /* timed out, enter init state */ dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); /* 智能ip:rebinding失败,视为之前的ip失效了 */ dhcpc_params.yiaddr = 0; break; } ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG("broadcast REQUEST with request ip %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.t2 = (dhcpc_params.lease - dhcpc_params.t2) / 2 + dhcpc_params.t2; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t2) + dhcpc_params.start; dhcpc_params.packet++; break; case RECONNECT_RENEWING: /* 每秒发一次包,等待 RECONNECT_RENEWING_TIMES 秒 */ if (dhcpc_params.packet > RECONNECT_RENEWING_TIMES) { /* timed out, enter rebinding state */ dhcpc_params.timeout = cur_time; dhcpc_params.state = RECONNECT_REBINDING; dhcpc_params.packet = 0; /* 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server */ dhcpc_params.server = 0; DHCPC_DEBUG("[RECONNECT]Entering reconect_rebinding state"); break; } /* send a request packet */ DHCPC_DEBUG("[RECONNECT]Send REQUEST to server %.8x", dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.packet++; dhcpc_params.timeout = 0; break; case RECONNECT_REBINDING: /* 每秒发一次包,等待 RECONNECT_REBINDING_TIMES 秒 */ if (dhcpc_params.packet > RECONNECT_REBINDING_TIMES) { /* timed out, enter init state */ dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; /* 智能ip:rebinding失败,视为之前的ip失效了 */ dhcpc_params.yiaddr = 0; DHCPC_DEBUG("[RECONNECT]Reconnect fail, Entering discovery state"); break; } /* send a request packet */ ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG("broadcast REQUEST with request ip %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = cur_time; dhcpc_params.packet++; break; #if 0 case RELEASED: /* 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP * 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 */ ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send RELEASE to server %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(1); /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; break; case IFDOWN: dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); /* 注释掉,保存上次获取的ip */ //dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; if (-1 != dhcpc_params.call_bk_id_new) { dhcpc_params.call_bk_id = dhcpc_params.call_bk_id_new; dhcpc_params.call_bk_id_new = -1; } memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); if (TRUE == dhcpc_params.re_dial) { dhcpc_params.re_dial = FALSE; dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; /* 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 */ dhcpc_params.state = DISCOVERY; } break; #endif } } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL void write_mobile_access(U8 val) { DEVICE_BASIC_INFO info = {0}; if (0 == ds_read(DEVICE_BASIC_INFO_PATH, &info, sizeof(info))) { DHCPC_ERROR("ds read device basic_info failed"); return; } else { info.mobile_access = val; ds_write(DEVICE_BASIC_INFO_PATH, &info, sizeof(info)); } } #endif #if 0 LOCAL S32 dhcp_renew_handle(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { /* 仅对处于BOUND状态的DHCP进行renew操作 */ DHCPC_ERROR("Recv DHCP Renew, state(%d)", dhcpc_params.state); if(BOUND == dhcpc_params.state) { dhcpc_params.arp_failed_times = (DHCPC_SERVER_DETECT_FAILED_MAX_TIME + 1); } return OK; } #endif LOCAL void dhcpc_handle(S32 sock) { S32 bytes = 0; U8 *message = NULL, *option = NULL; U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}, mask = {0}, gateway = {0}, server = {0}; U32 dns[2] = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config error"); return; } #endif /* 收到DHCP服务器的响应报文。 */ bytes = get_packet(&packet, sock); if (bytes < 0) { DHCPC_WARNING("Error on read, %m, reopening socket"); return; } /* Ignore packets that aren't for us */ if (memcmp(packet.chaddr, dhcpc_params.mac, sizeof(dhcpc_params.mac))) { DHCPC_DEBUG("Packet does not have our chaddr -- ignoring"); return; } if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DHCPC_WARNING("Couldnt get option from packet -- ignoring"); return; } if (packet.xid != dhcpc_params.xid) { DHCPC_WARNING("ignoring XID %lx (our xid is %lx)", packet.xid, dhcpc_params.xid); return; } switch (dhcpc_params.state) { case INIT: case DISCOVERY: /* just drop all message. */ break; case SELECTING: if ((DHCPOFFER != *message) || /* 在此处只能接收OFFER包,其它包丢弃 */ (NULL == (option = get_option(&packet, DHCP_SERVER_ID)))) /* 必须带有SERVER_ID。 */ { break; } memcpy(&dhcpc_params.server, option, 4); dhcpc_params.mask = inet_addr("255.255.255.255"); switch (ip_network_id(packet.yiaddr)) { case 'A': dhcpc_params.mask = inet_addr("255.0.0.0"); break; case 'B': dhcpc_params.mask = inet_addr("255.255.0.0"); break; case 'C': dhcpc_params.mask = inet_addr("255.255.255.0"); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } /*dhcpc_params[iface].xid = packet.xid;*/ /* 忽略? */ dhcpc_params.yiaddr = packet.yiaddr; ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Recv OFFER from server %d.%d.%d.%d with ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); /* 在此处验证获得的IP的合法性。这里DHCP不回MTU */ if ((OK != check_valid_param(dhcpc_params.mtu, dhcpc_params.yiaddr, dhcpc_params.mask, 0))) { DHCPC_DEBUG("check_valid_param failed."); break; /* 继续等待其它的服务器响应 */ } /* 合法性验证通过后,发送Request报文,跳转到REQUESTING状态。 */ ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send REQUEST to server %d.%d.%d.%d with request ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.state = REQUESTING; dhcpc_params.packet = 0; dhcpc_params.retry = 0; break; case RENEWING: case REBINDING: case REQUESTING: case RECONNECT_RENEWING: case RECONNECT_REBINDING: /* 是否要验证server id?这里暂且验证下,个人认为这样安全。 */ if (NULL == (option = get_option(&packet, DHCP_SERVER_ID))) { break; /* unknown dhcp server? */ } /* REBINDING阶段更新server */ if (dhcpc_params.state == REBINDING || dhcpc_params.state == RECONNECT_REBINDING) { memcpy(&dhcpc_params.server, option, 4); } /* REBINDING阶段可能会切换server,此时不可检查 */ #if 0 if (dhcpc_params[iface].server != *(U32 *)option) { break; /* invalid dhcp server? */ } #endif if (DHCPACK == *message) { dhcpc_params.lease = 60*60; /* 默认1小时。 */ if (NULL != (option = get_option(&packet, DHCP_LEASE_TIME))) { memcpy(&dhcpc_params.lease, option, 4); dhcpc_params.lease = ntohl(dhcpc_params.lease); } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { IF_CONF if_conf = {0}; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return; } char dev_name[32] = {0}; U8 dev_mac[6] = {0}; snprintf(dev_name, sizeof(dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dev_name, NULL, dev_mac)) { DHCPC_ERROR("read usb0 device info error"); return; } /* 发送GARP验证IP是否被占用。 */ if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && ((0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300)) || (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dev_mac, dev_name, 300)))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in use, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } }else #endif { /* 发送GARP验证IP是否被占用。 */ if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in use, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT /* 在有线上网模式下,dhcp server分配的IP不能为4G网关192.168.43.1 */ if(((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && packet.yiaddr == 0x012ba8c0) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in Gateway for 4G, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #endif } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if (NULL != (option = get_option(&packet, DHCP_4G_ROUTER))) { if(0 == memcmp(option, DHCP_4G_ROUTER_STR, strlen(DHCP_4G_ROUTER_STR))) { DHCPC_INFO("get option DHCP_4G_ROUTER"); write_mobile_access(1); } else { write_mobile_access(0); } } else { write_mobile_access(0); } #endif /* 分配的IP没有被占用,则使用该IP,并且进入bound状态。 */ dhcpc_params.t1 = dhcpc_params.lease/2; dhcpc_params.t2 = ((dhcpc_params.lease * 0x7) >> 3);/* little fixed point for n * .875 */ //DHCPC_ERROR("dhcpc_params.t1:%d, dhcpc_params.t2:%d", dhcpc_params.t1, dhcpc_params.t2); dhcpc_params.start = cur_time; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + cur_time; ip_addr.ipAddr = dhcpc_params.yiaddr; /* 保留原IP的值 */ dhcpc_params.yiaddr = packet.yiaddr; /* 获取网关。 */ gateway.ipAddr = dhcpc_params.gateway; dhcpc_params.gateway = 0; if (NULL != (option = get_option(&packet, DHCP_ROUTER))) { if(0 != *option) { memcpy(&dhcpc_params.gateway, option, 4); } else if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR("Received ACK but gateway option is zero, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]", dhcpc_params.gateway, dhcpc_params.server); } else { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { dhcpc_params.gateway = 0x012ba8c0; /* 4G上网模式下,无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.43.1 */ DHCPC_ERROR("Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.43.1", dhcpc_params.gateway); }else #endif { dhcpc_params.gateway = 0x0100a8c0; /* 无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.0.1 */ DHCPC_ERROR("Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1", dhcpc_params.gateway); } } } else { if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR("Received ACK but gateway option is empty, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]", dhcpc_params.gateway, dhcpc_params.server); } else { dhcpc_params.gateway = 0x0100a8c0; DHCPC_ERROR("Received ACK but the gateway and source IP are illegal, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1", dhcpc_params.gateway); } } /* 获取掩码。 */ mask.ipAddr = dhcpc_params.mask; dhcpc_params.mask = inet_addr("255.255.255.255"); switch (ip_network_id(packet.yiaddr)) { case 'A': dhcpc_params.mask = inet_addr("255.0.0.0"); break; case 'B': dhcpc_params.mask = inet_addr("255.255.0.0"); break; case 'C': dhcpc_params.mask = inet_addr("255.255.255.0"); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } /* 获取DNS. */ if (FALSE == dhcpc_params.manual_dns) { dns[0] = dhcpc_params.dns[0]; dns[1] = dhcpc_params.dns[1]; dhcpc_params.dns[0] = 0; dhcpc_params.dns[1] = 0; if (NULL != (option = get_option(&packet, DHCP_DNS_SERVER))) { S32 dnsNum = 0; S32 i = 0; dnsNum = (*(option - 1))/4; dnsNum = dnsNum > 2 ? 2 : dnsNum; for (i = 0; i < dnsNum; i++) { memcpy(dhcpc_params.dns + i, option + 4 * i, 4); } } } /* REQUESTING状态或者ip、gateway、mask有更新则刷新接口。 */ /* RECONNECT_RENEWING 和 RECONNECT_REBINDING状态可能是静态转为动态,因此也要进行设置 */ if ((REQUESTING == dhcpc_params.state) || dhcpc_params.state == RECONNECT_RENEWING || dhcpc_params.state == RECONNECT_REBINDING || (ip_addr.ipAddr != dhcpc_params.yiaddr) || (gateway.ipAddr != dhcpc_params.gateway) || (mask.ipAddr != dhcpc_params.mask)) { /* 根据获得的IP配置本地接口。 */ ip_addr.ipAddr = dhcpc_params.yiaddr; mask.ipAddr = dhcpc_params.mask; gateway.ipAddr = dhcpc_params.gateway; DHCPC_INFO("%s set ip %d.%d.%d.%d mask %d.%d.%d.%d gateway %d.%d.%d.%d lease time %ld", dhcpc_params.dev_name, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3], mask.ipAddrByteFormat[0], mask.ipAddrByteFormat[1], mask.ipAddrByteFormat[2], mask.ipAddrByteFormat[3], gateway.ipAddrByteFormat[0], gateway.ipAddrByteFormat[1], gateway.ipAddrByteFormat[2], gateway.ipAddrByteFormat[3], dhcpc_params.lease); dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } else if ((TRUE != dhcpc_params.manual_dns) && ((dns[0] != dhcpc_params.dns[0]) || (dns[1] != dhcpc_params.dns[1]))) { dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } DHCPC_DEBUG("Recv ACK from server %.8x with ip %.8x lease time %ld", dhcpc_params.server, dhcpc_params.yiaddr, dhcpc_params.lease); dhcpc_params.retry = 0; /* clear the retry counter */ dhcpc_params.packet = 0; dhcpc_params.state = BOUND; break; } if (DHCPNAK != *message) { break; } /* 这里需要考虑两种情况: */ /* 在未配置本地IP的情况(即REQUESTING状态),只需更新状态到INIT_SELECTING状态即可。 */ /* 其它状态则需要释放已配置的IP。 */ if (REQUESTING != dhcpc_params.state) { DHCPC_DEBUG("state [%d] receive NACK", dhcpc_params.state); dhcpc_flush_net(LINK_DOWN, LINK_CODE_DENY); } ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_INFO("Recv NAK from server %d.%d.%d.%d with ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); if (dhcpc_params.state != RECONNECT_RENEWING && dhcpc_params.state != RECONNECT_REBINDING) { dhcpc_timeout_flush_net(); } else { /* 收到NAK后重新开始DISCOVERY前刷新参数 */ dhcpc_params_update(); } dhcpc_params.timeout = 0; dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } } LOCAL S32 dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING("call back parameter error."); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { DHCPC_DEBUG("Now start dhcpc progress."); link_up_inner(); dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG("Now stop dhcpc progress."); link_down_inner(msg->code); return OK; } DHCPC_WARNING("Unknown command."); return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL S32 dhcpc_socket_reload() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR("client socket call failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR("client socket set reuseaddr option failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &option, sizeof(option))) { DHCPC_ERROR("client socket set broadcast option failed"); goto dhcpc_error_exit; } /* 设置缓存大小 */ buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } /* 绑定网卡 */ struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); IF_CONF if_conf = {0}; LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { strncpy(ifr.ifr_name, DHCPC_4G_IPC_DEV_NAME, strlen(DHCPC_4G_IPC_DEV_NAME) + 1); DHCPC_ERROR("ifr.ifr_name:%s", ifr.ifr_name); }else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); goto dhcpc_error_exit; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); goto dhcpc_error_exit; } strncpy(ifr.ifr_name, if_conf.ifname, strlen(if_conf.ifname)); } if(ERROR == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char*)&ifr, sizeof(ifr))) { DHCPC_ERROR("can't bind to interface :%s", ifr.ifr_name); } DHCPC_ERROR("ifr.ifr_name:%s", ifr.ifr_name); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR("server socket set broadcast option failed"); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL int dhcpc_param_reload(int flag) { IF_CONF if_conf = {0}; DHCPC dhcpc_data; dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; //dhcpc_params.call_bk_id = -1; dhcpc_params.path = DHCPC_PATH; if(flag == DHCPC_4G_INTERNET_MODE) { /* 4G_ICP使用usb0 */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", DHCPC_4G_IPC_DEV_NAME); if(0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } } else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return ERROR; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return ERROR; } /* IPC使用br-wan */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } } /* 智能ip,IPC断开dhcp时不释放租约 */ dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.flags = FALSE; /* 默认广播。 */ if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; dhcpc_params.last_arp_timestamp = 0; dhcpc_params.arp_failed_times = 0; if(dhcpc_params.sock) { inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; } dhcpc_params.sock = dhcpc_socket_reload(); g_sock_idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if(0 > g_sock_idx) { DHCPC_ERROR("add dhcp client socket to inetd failed"); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if(0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR("add dhcp timer to inetd failed"); inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } return OK; } LOCAL S32 lte_dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; U8 dev_mac[6] = {0}; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING("call back parameter error."); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { if(!strncmp(dhcpc_params.dev_name, DHCPC_4G_IPC_DEV_NAME, sizeof(dhcpc_params.dev_name))) { DHCPC_DEBUG("Now start dhcpc progress."); if(0 > read_interface_info(dhcpc_params.dev_name, NULL, dev_mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } if(memcmp(dhcpc_params.mac, dev_mac, sizeof(dhcpc_params.mac))) { DHCPC_ERROR("usb0 device mac change, reload dhcpc params."); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } link_up_inner(); }else { DHCPC_DEBUG("Change dhcpc device first"); DHCPC_DEBUG("Now start dhcpc progress."); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } link_up_inner(); } dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG("Now stop dhcpc progress."); link_down_inner(msg->code); return OK; } DHCPC_WARNING("Unknown command."); return ERROR; } #endif LOCAL S32 dhcpc_socket_init() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR("client socket call failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR("client socket set reuseaddr option failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &option, sizeof(option))) { DHCPC_ERROR("client socket set broadcast option failed"); goto dhcpc_error_exit; } /* 设置缓存大小 */ buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR("server socket set broadcast option failed"); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL void dhcpc_param_init() { IF_CONF if_conf = {0}; DHCPC dhcpc_data; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return; } memset(&dhcpc_params, 0, sizeof(DHCPC_PARAMS)); /* 智能ip,设置ip为0xFFFFFFFF 标记是开机后首次获取ip */ dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; dhcpc_params.call_bk_id = -1; dhcpc_params.mac[0] = 0x00; dhcpc_params.mac[1] = 0x11; dhcpc_params.mac[2] = 0x22; dhcpc_params.mac[3] = 0x33; dhcpc_params.mac[4] = 0x44; dhcpc_params.mac[5] = 0x55; dhcpc_params.path = DHCPC_PATH; /* IPC使用br-wan */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { return; } /* 智能ip,IPC断开dhcp时不释放租约 */ dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.state = INIT; dhcpc_params.flags = FALSE; /* 默认广播。 */ if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.packet = 0; /* start things over */ dhcpc_params.timeout = 0xFFFFFFFF; /* Kill any timeouts because the user wants this to hurry along */ dhcpc_params.retry = 0; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; dhcpc_params.last_arp_timestamp = 0; dhcpc_params.arp_failed_times = 0; dhcpc_params.sock = dhcpc_socket_init(); } LOCAL S32 dhcpc_init() { S32 idx = -1; dhcpc_param_init(); if (0 > dhcpc_params.sock) { DHCPC_ERROR("dhcp client socket init failed"); return ERROR; } idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if (0 > idx) { DHCPC_ERROR("add dhcp client socket to inetd failed"); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if (0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR("add dhcp timer to inetd failed"); inet_del_socket(idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } msg_attach_handler(NSD_DHCPC_CTRL, dhcpc_ctrl_callback); #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT g_sock_idx = idx; msg_attach_handler(LTE_DHCPC_CTRL, lte_dhcpc_ctrl_callback); #endif #if 0 ds_register_action("dhcpc", "renew", dhcp_renew_handle); #endif DHCPC_ERROR("DHCPC init over."); return OK; } LOCAL S32 dhcpc_reload(DS_MSG *msg) { if (NULL == msg) { return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(!get_lte_config_data_flag) { if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&g_lte_config_data, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("ds read path [%s] failed.", LTE_INFO_DATA_PATH); return ERROR; } get_lte_config_data_flag = 1; } #endif if (ds_path_id_exist(msg->id, msg->num, DHCPC_PATH)) { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 == ds_read(DHCPC_PATH, (U8 *)&dhcpc_data, sizeof(DHCPC))) { DHCPC_ERROR("Read dhcpc data ERROR"); return ERROR; } dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(ds_path_id_exist(msg->id, msg->num, INFO_INTERNET_PATH)) { INFO_INTERNET info_internet = {0}; if(0 == ds_read(INFO_INTERNET_PATH, (U8*)&info_internet, sizeof(INFO_INTERNET))) { DHCPC_ERROR("ds read path [%s] failed.", INFO_INTERNET_PATH); return ERROR; } LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(info_internet.link_status == INTERNET_4G_DISCONNECTED) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } }else if(info_internet.link_status == INTERNET_4G_CONNECTING) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } } } #endif return OK; } LOCAL void dhcpc_main() { DS_DAT_MON_DESC dhcpc_data_monitor[] = { DS_DAT_MON(DHCPC_PATH, DATA_ATTRI_NOTIFY), #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT DS_DAT_MON(INFO_INTERNET_PATH, DATA_ATTRI_NOTIFY), #endif }; DS_MOD_DESC dhcpc_module = DS_STRUCT_MOD("dhcpc", dhcpc_init, NULL, dhcpc_reload, NULL, NULL, NULL, dhcpc_data_monitor); MODULE *module_node = ds_register_module("dhcpc", &dhcpc_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(dhcpc_main);
09-23
[ 116.079472][ C5] CPU#5 Utilization every 4s during lockup: [ 116.079475][ C5] #1: 100% system, 0% softirq, 0% hardirq, 0% idle [ 116.079479][ C5] #2: 100% system, 0% softirq, 1% hardirq, 0% idle [ 116.079482][ C5] #3: 100% system, 0% softirq, 1% hardirq, 0% idle [ 116.079485][ C5] #4: 100% system, 0% softirq, 0% hardirq, 0% idle [ 116.079489][ C5] #5: 100% system, 0% softirq, 1% hardirq, 0% idle [ 116.080193][ C5] Kernel panic - not syncing: softlockup: hung tasks [ 116.080196][ C5] CPU: 5 PID: 91 Comm: kswapd0 Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.080201][ C5] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.080204][ C5] Call trace: [ 116.080206][ C5] dump_backtrace+0xf0/0x140 [ 116.080210][ C5] show_stack+0x18/0x28 [ 116.080213][ C5] dump_stack_lvl+0x70/0xa4 [ 116.080218][ C5] panic+0x158/0x3e4 [ 116.080222][ C5] watchdog_timer_fn+0x394/0x494 [ 116.080227][ C5] __hrtimer_run_queues+0x1d8/0x40c [ 116.080232][ C5] hrtimer_interrupt+0xf4/0x3b8 [ 116.080237][ C5] arch_timer_handler_virt+0x50/0x64 [ 116.080241][ C5] handle_percpu_devid_irq+0x100/0x320 [ 116.080246][ C5] generic_handle_domain_irq+0x5c/0x88 [ 116.080251][ C5] gic_handle_irq+0x4c/0x114 [ 116.080255][ C5] call_on_irq_stack+0x3c/0x70 [ 116.080258][ C5] do_interrupt_handler+0x7c/0xe8 [ 116.080263][ C5] el1_interrupt+0x34/0x58 [ 116.080267][ C5] el1h_64_irq_handler+0x18/0x24 [ 116.080270][ C5] el1h_64_irq+0x68/0x6c [ 116.080273][ C5] queued_spin_lock_slowpath+0x9c/0x51c [ 116.080278][ C5] do_raw_spin_lock+0x104/0x120 [ 116.080282][ C5] _raw_spin_lock+0x74/0x98 [ 116.080286][ C5] __swap_duplicate+0xa4/0x1fc [ 116.080290][ C5] swap_duplicate+0x24/0x58 [ 116.080294][ C5] try_to_unmap_one+0x620/0xf40 [ 116.080299][ C5] rmap_walk_anon+0x1f8/0x294 [ 116.080304][ C5] try_to_unmap+0x5c/0x9c [ 116.080309][ C5] shrink_folio_list+0x7f8/0x15bc [ 116.080314][ C5] shrink_inactive_list+0x2a0/0x574 [ 116.080319][ C5] shrink_lruvec+0x54c/0xa1c [ 116.080323][ C5] shrink_node+0x270/0x11c4 [ 116.080327][ C5] balance_pgdat+0x8c0/0x1140 [ 116.080331][ C5] kswapd+0x35c/0x6cc [ 116.080335][ C5] kthread+0x118/0x158 [ 116.080340][ C5] ret_from_fork+0x10/0x20 [ 116.080344][ C5] SMP: stopping secondary CPUs [ 116.080355][ C6] VendorHooks: CPU6: stopping [ 116.080357][ C6] CPU: 6 PID: 3353 Comm: NetworkWatchlis Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.080360][ C6] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.080361][ C6] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 116.080363][ C6] pc : queued_spin_lock_slowpath+0x9c/0x51c [ 116.080367][ C6] lr : do_raw_spin_lock+0x104/0x120 [ 116.080370][ C6] sp : ffffffc0ae6232a0 [ 116.080371][ C6] x29: ffffffc0ae6232a0 x28: fffffffe207a46c8 x27: fffffffe207a46c0 [ 116.080374][ C6] x26: ffffffc0ae623628 x25: 0000000000000000 x24: 0000000000000040 [ 116.080376][ C6] x23: 0000000000000001 x22: 0000000000008000 x21: ffffffc0822e0008 [ 116.080378][ C6] x20: ffffff87f6f9a080 x19: ffffff87d6181800 x18: ffffffc098a3d0a8 [ 116.080380][ C6] x17: 00000000529c6ef0 x16: 00000000529c6ef0 x15: 0000000000000010 [ 116.080382][ C6] x14: 0000000000000040 x13: 0000000000000004 x12: 00000000655528d8 [ 116.080384][ C6] x11: 0000000000000015 x10: ffffffc082508730 x9 : 0000000000000000 [ 116.080386][ C6] x8 : 0000000000000001 x7 : 4040404040404040 x6 : ffffffc0803ef884 [ 116.080388][ C6] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000000000 [ 116.080390][ C6] x2 : 0000000000000000 x1 : 0000000000000001 x0 : ffffff87d6181800 [ 116.080392][ C6] Call trace: [ 116.080393][ C6] queued_spin_lock_slowpath+0x9c/0x51c [ 116.080395][ C6] do_raw_spin_lock+0x104/0x120 [ 116.080397][ C6] _raw_spin_lock+0x74/0x98 [ 116.080399][ C6] __swap_duplicate+0xa4/0x1fc [ 116.080401][ C6] shmem_writepage+0x35c/0x6a0 [ 116.080403][ C6] pageout+0xe8/0x440 [ 116.080406][ C6] shrink_folio_list+0xb38/0x15bc [ 116.080409][ C6] shrink_inactive_list+0x2a0/0x574 [ 116.080412][ C6] shrink_lruvec+0x54c/0xa1c [ 116.080415][ C6] shrink_node+0x270/0x11c4 [ 116.080416][ C6] do_try_to_free_pages+0x26c/0x6bc [ 116.080419][ C6] try_to_free_pages+0x460/0x994 [ 116.080422][ C6] __alloc_pages_slowpath+0x764/0x197c [ 116.080424][ C6] __alloc_pages+0x1f4/0x2cc [ 116.080426][ C6] vma_alloc_zeroed_movable_folio+0x38/0x5c [ 116.080429][ C6] handle_mm_fault+0xd94/0x20e8 [ 116.080432][ C6] do_page_fault+0x20c/0x4b0 [ 116.080435][ C6] do_translation_fault+0x38/0x54 [ 116.080437][ C6] do_mem_abort+0x58/0x118 [ 116.080438][ C6] el0_da+0x48/0x84 [ 116.080440][ C6] el0t_64_sync_handler+0x98/0xbc [ 116.080442][ C6] el0t_64_sync+0x1a8/0x1ac [ 116.080444][ C7] VendorHooks: CPU7: stopping [ 116.080446][ C7] CPU: 7 PID: 0 Comm: swapper/7 Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.080450][ C7] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.080451][ C7] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 116.080455][ C7] pc : arch_local_irq_enable+0x4/0xc [ 116.080461][ C7] lr : cpuidle_enter_state+0x180/0x31c [ 116.080465][ C7] sp : ffffffc0833e3d70 [ 116.080466][ C7] x29: ffffffc0833e3d80 x28: ffffffc082508000 x27: 0000000000000080 [ 116.080470][ C7] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000001 [ 116.080474][ C7] x23: 0000001b06ed9ded x22: 0000001b06e02aba x21: 0000000000000000 [ 116.080478][ C7] x20: ffffff8023ac6080 x19: ffffff88f5bf3bf8 x18: ffffffc08339d028 [ 116.080481][ C7] x17: 00000000d0c6e49b x16: 00000000d0c6e49b x15: 0000000000000000 [ 116.080485][ C7] x14: 000000000000002a x13: 0000000000000004 x12: 0000000084d6a034 [ 116.080487][ C7] x11: 0000000000000015 x10: ffffffc082508730 x9 : 0000000100000001 [ 116.080489][ C7] x8 : 0000000100000001 x7 : 0000000000000001 x6 : ffffffc07c86c18c [ 116.080491][ C7] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000071624 [ 116.080493][ C7] x2 : ffffff88f5bf3bf8 x1 : ffffffc081476e68 x0 : 0000000000000007 [ 116.080495][ C7] Call trace: [ 116.080496][ C7] arch_local_irq_enable+0x4/0xc [ 116.080499][ C7] cpuidle_enter+0x38/0x54 [ 116.080503][ C7] do_idle+0x1cc/0x2d8 [ 116.080506][ C7] cpu_startup_entry+0x34/0x3c [ 116.080509][ C7] secondary_start_kernel+0x138/0x160 [ 116.080512][ C7] __secondary_switched+0xc0/0xc4 [ 116.080515][ C4] VendorHooks: CPU4: stopping [ 116.080519][ C4] CPU: 4 PID: 0 Comm: swapper/4 Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.080523][ C4] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.080524][ C4] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 116.080527][ C4] pc : arch_local_irq_enable+0x4/0xc [ 116.080532][ C4] lr : cpuidle_enter_state+0x180/0x31c [ 116.080536][ C4] sp : ffffffc0833cbd70 [ 116.080537][ C4] x29: ffffffc0833cbd80 x28: ffffffc082508000 x27: 0000000000000010 [ 116.080541][ C4] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000001 [ 116.080544][ C4] x23: 0000001b06ed9a77 x22: 0000001b06b74a40 x21: 0000000000000000 [ 116.080547][ C4] x20: ffffff8023ac3080 x19: ffffff88f5620bf8 x18: ffffffc083385028 [ 116.080549][ C4] x17: 00000000d0c6e49b x16: 00000000d0c6e49b x15: 0000000000000000 [ 116.080551][ C4] x14: 000000000000002a x13: 0000000000000004 x12: 0000000084d6a023 [ 116.080553][ C4] x11: 0000000000000015 x10: ffffffc082508730 x9 : 0000000100000001 [ 116.080555][ C4] x8 : 0000000100000001 x7 : 0000000000000001 x6 : ffffffc07c86c18c [ 116.080558][ C4] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 000000000007216c [ 116.080559][ C4] x2 : ffffff88f5620bf8 x1 : ffffffc081476e68 x0 : 0000000000000004 [ 116.080562][ C4] Call trace: [ 116.080562][ C4] arch_local_irq_enable+0x4/0xc [ 116.080566][ C4] cpuidle_enter+0x38/0x54 [ 116.080569][ C4] do_idle+0x1cc/0x2d8 [ 116.080572][ C4] cpu_startup_entry+0x34/0x3c [ 116.080575][ C4] secondary_start_kernel+0x138/0x160 [ 116.080578][ C4] __secondary_switched+0xc0/0xc4 [ 116.080581][ C0] VendorHooks: CPU0: stopping [ 116.080588][ C0] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.080594][ C0] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.080596][ C0] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 116.080602][ C0] pc : arch_local_irq_enable+0x4/0xc [ 116.080609][ C0] lr : cpuidle_enter_state+0x180/0x31c [ 116.080615][ C0] sp : ffffffc0824e3d30 [ 116.080617][ C0] x29: ffffffc0824e3d40 x28: ffffffc082508000 x27: 0000000000000001 [ 116.080626][ C0] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000001 [ 116.080633][ C0] x23: 0000001b06ed9736 x22: 0000001b06a45795 x21: 0000000000000000 [ 116.080641][ C0] x20: ffffff8023ac1080 x19: ffffff88f4e5cbf8 x18: ffffffc08251a078 [ 116.080648][ C0] x17: 00000000d0c6e49b x16: 00000000d0c6e49b x15: 0000000000000000 [ 116.080656][ C0] x14: 000000000000002a x13: 0000000000000004 x12: 0000000084d6a013 [ 116.080663][ C0] x11: 0000000000000015 x10: ffffffc082508730 x9 : 0000000100000001 [ 116.080671][ C0] x8 : 0000000100000001 x7 : 0000000000000000 x6 : ffffffc07c86c18c [ 116.080678][ C0] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000079f5c [ 116.080685][ C0] x2 : ffffff88f4e5cbf8 x1 : ffffffc081476e68 x0 : 0000000000000000 [ 116.080692][ C0] Call trace: [ 116.080694][ C0] arch_local_irq_enable+0x4/0xc [ 116.080701][ C0] cpuidle_enter+0x38/0x54 [ 116.080707][ C0] do_idle+0x1cc/0x2d8 [ 116.080713][ C0] cpu_startup_entry+0x34/0x3c [ 116.080719][ C0] rest_init+0xe4/0xe8 [ 116.080724][ C0] arch_call_rest_init+0x10/0x14 [ 116.080731][ C0] start_kernel+0x39c/0x454 [ 116.080736][ C0] __primary_switched+0xc8/0x8c2c [ 116.080743][ C1] VendorHooks: CPU1: stopping [ 116.080749][ C1] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.080756][ C1] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.080758][ C1] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 116.080763][ C1] pc : arch_local_irq_enable+0x4/0xc [ 116.080771][ C1] lr : cpuidle_enter_state+0x180/0x31c [ 116.080777][ C1] sp : ffffffc0833b3d70 [ 116.080779][ C1] x29: ffffffc0833b3d80 x28: ffffffc082508000 x27: 0000000000000002 [ 116.080787][ C1] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000001 [ 116.080795][ C1] x23: 0000001b06ed9a0f x22: 0000001b05b05386 x21: 0000000000000000 [ 116.080802][ C1] x20: ffffff8023ac4880 x19: ffffff88f504dbf8 x18: ffffffc08336d028 [ 116.080810][ C1] x17: 00000000d0c6e49b x16: 00000000d0c6e49b x15: 0000000000000000 [ 116.080817][ C1] x14: 000000000000002a x13: 0000000000000004 x12: 0000000084d6a021 [ 116.080824][ C1] x11: 0000000000000015 x10: ffffffc082508730 x9 : 0000000100000001 [ 116.080831][ C1] x8 : 0000000100000001 x7 : 0000000000000001 x6 : ffffffc07c86c18c [ 116.080839][ C1] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 00000000000128ec [ 116.080846][ C1] x2 : ffffff88f504dbf8 x1 : ffffffc081476e68 x0 : 0000000000000001 [ 116.080853][ C1] Call trace: [ 116.080855][ C1] arch_local_irq_enable+0x4/0xc [ 116.080861][ C1] cpuidle_enter+0x38/0x54 [ 116.080868][ C1] do_idle+0x1cc/0x2d8 [ 116.080874][ C1] cpu_startup_entry+0x34/0x3c [ 116.080880][ C1] secondary_start_kernel+0x138/0x160 [ 116.080885][ C1] __secondary_switched+0xc0/0xc4 [ 116.080891][ C3] VendorHooks: CPU3: stopping [ 116.080898][ C3] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.080904][ C3] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.080906][ C3] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 116.080911][ C3] pc : arch_local_irq_enable+0x4/0xc [ 116.080919][ C3] lr : cpuidle_enter_state+0x180/0x31c [ 116.080925][ C3] sp : ffffffc0833c3d70 [ 116.080927][ C3] x29: ffffffc0833c3d80 x28: ffffffc082508000 x27: 0000000000000008 [ 116.080935][ C3] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000001 [ 116.080943][ C3] x23: 0000001b06ed9b7c x22: 0000001b062a6211 x21: 0000000000000000 [ 116.080950][ C3] x20: ffffff8023ac0080 x19: ffffff88f542fbf8 x18: ffffffc08337d028 [ 116.080958][ C3] x17: 00000000d0c6e49b x16: 00000000d0c6e49b x15: 0000000000000000 [ 116.080965][ C3] x14: 000000000000002a x13: 0000000000000004 x12: 0000000084d6a028 [ 116.080972][ C3] x11: 0000000000000015 x10: ffffffc082508730 x9 : 0000000100000001 [ 116.080980][ C3] x8 : 0000000100000001 x7 : 0000000000000001 x6 : ffffffc07c86c18c [ 116.080987][ C3] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000010824 [ 116.080994][ C3] x2 : ffffff88f542fbf8 x1 : ffffffc081476e68 x0 : 0000000000000003 [ 116.081001][ C3] Call trace: [ 116.081003][ C3] arch_local_irq_enable+0x4/0xc [ 116.081010][ C3] cpuidle_enter+0x38/0x54 [ 116.081016][ C3] do_idle+0x1cc/0x2d8 [ 116.081022][ C3] cpu_startup_entry+0x34/0x3c [ 116.081028][ C3] secondary_start_kernel+0x138/0x160 [ 116.081034][ C3] __secondary_switched+0xc0/0xc4 [ 116.081040][ C2] VendorHooks: CPU2: stopping [ 116.081047][ C2] CPU: 2 PID: 0 Comm: swapper/2 Tainted: G C OEL 6.6.77-android15-8-maybe-dirty-debug #1 87d0bdbac97ce09587b16630b722a5b52b4aa5e1 [ 116.081053][ C2] Hardware name: Qualcomm Technologies, Inc. Kunzite QRD (DT) [ 116.081055][ C2] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 116.081061][ C2] pc : arch_local_irq_enable+0x4/0xc [ 116.081068][ C2] lr : cpuidle_enter_state+0x180/0x31c [ 116.081074][ C2] sp : ffffffc0833bbd70 [ 116.081076][ C2] x29: ffffffc0833bbd80 x28: ffffffc082508000 x27: 0000000000000004 [ 116.081084][ C2] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000001 [ 116.081091][ C2] x23: 0000001b06ed9adf x22: 0000001b05ed5ec3 x21: 0000000000000000 [ 116.081099][ C2] x20: ffffff8023ac4080 x19: ffffff88f523ebf8 x18: ffffffc083375028 [ 116.081107][ C2] x17: 00000000d0c6e49b x16: 00000000d0c6e49b x15: 0000000000000000 [ 116.081114][ C2] x14: 000000000000002a x13: 0000000000000004 x12: 0000000084d6a025 [ 116.081122][ C2] x11: 0000000000000015 x10: ffffffc082508730 x9 : 0000000100000001 [ 116.081129][ C2] x8 : 0000000100000001 x7 : 0000000000000001 x6 : ffffffc07c86c18c [ 116.081137][ C2] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 00000000000111cc [ 116.081144][ C2] x2 : ffffff88f523ebf8 x1 : ffffffc081476e68 x0 : 0000000000000002 [ 116.081151][ C2] Call trace: [ 116.081153][ C2] arch_local_irq_enable+0x4/0xc [ 116.081159][ C2] cpuidle_enter+0x38/0x54 [ 116.081166][ C2] do_idle+0x1cc/0x2d8 [ 116.081172][ C2] cpu_startup_entry+0x34/0x3c [ 116.081178][ C2] secondary_start_kernel+0x138/0x160 [ 116.081184][ C2] __secondary_switched+0xc0/0xc4 [ 116.081458][ C5] ipa ipa_save_registers:1027 Commencing [ 116.081742][ C5] ipa ipa_save_registers:1039 reading 2728 registers [ 116.148620][ C5] ipa ipa_save_registers:1297 Completed [ 116.149022][ C5] ipa_wigig ipa_wigig_save_regs:992 wigig ctx is not initialized [ 116.149031][ C5] ipa ipa3_panic_notifier:7667 [ 116.149031][ C5] ---- Active Clients Table ---- [ 116.149031][ C5] PANIC_VOTE 1 SPECIAL [ 116.149031][ C5] USB DPL 1 SPECIAL [ 116.149031][ C5] IPA_CLIENT_APPS_LAN_COAL_CONS 13 ENDPOINT [ 116.149031][ C5] FREEZE_VOTE 1 SPECIAL [ 116.149031][ C5] USB 1 SPECIAL [ 116.149031][ C5] IPA_CLIENT_APPS_LAN_CONS -13 ENDPOINT [ 116.149031][ C5] TAG_PROCESS -13 SPECIAL [ 116.149031][ C5] [ 116.149031][ C5] Total active clients count: 4 [ 116.149031][ C5] [ 116.149041][ C5] Skip md ftrace buffer dump for: 0x1609e0 [ 116.149054][ C5] ufshcd-qcom 1d84000.ufshc: ......dumping ufs info ....... [ 116.149058][ C5] ufshcd-qcom 1d84000.ufshc: UFS Host state=1 [ 116.149061][ C5] ufshcd-qcom 1d84000.ufshc: outstanding reqs=0x0 tasks=0x0 [ 116.149064][ C5] ufshcd-qcom 1d84000.ufshc: saved_err=0x0, saved_uic_err=0x0 [ 116.149067][ C5] ufshcd-qcom 1d84000.ufshc: Device power mode=1, UIC link state=1 [ 116.149071][ C5] ufshcd-qcom 1d84000.ufshc: PM in progress=0, sys. suspended=0 [ 116.149074][ C5] ufshcd-qcom 1d84000.ufshc: Clk gate=1 [ 116.149077][ C5] ufshcd-qcom 1d84000.ufshc: last_hibern8_exit_tstamp at 0 us, hibern8_exit_cnt=7 [ 116.149080][ C5] ufshcd-qcom 1d84000.ufshc: last intr at 113647782 us, last intr status=0x1 [ 116.149083][ C5] ufshcd-qcom 1d84000.ufshc: error handling flags=0x0, req. abort count=0 [ 116.149086][ C5] ufshcd-qcom 1d84000.ufshc: hba->ufs_version=0x300, Host capabilities=0x1587031f, caps=0x138b [ 116.149090][ C5] ufshcd-qcom 1d84000.ufshc: quirks=0x0, dev. quirks=0x140 [ 116.149093][ C5] ufshcd-qcom 1d84000.ufshc: [RX, TX]: gear=[3, 3], lane[2, 2], rate = 2 [ 116.149096][ C5] ufshcd-qcom 1d84000.ufshc: UFS RPM level = 3 [ 116.149099][ C5] ufshcd-qcom 1d84000.ufshc: UFS SPM level = 3 [ 116.149102][ C5] ufshcd-qcom 1d84000.ufshc: host_blocked=0 [ 116.149102][ C5] host_failed =0 [ 116.149102][ C5] Host self-block=0 [ 116.149105][ C5] ufshcd-qcom 1d84000.ufshc: ............. ufs dump complete .......... [ 116.149110][ C5] CPU0 next event is 116104000000 [ 116.149113][ C5] CPU1 next event is 119004000000 [ 116.149116][ C5] CPU2 next event is 116523874903 [ 116.149118][ C5] CPU3 next event is 120048000000 [ 116.149121][ C5] CPU4 next event is 116088000000 [ 116.149127][ C5] CPU5 next event is 9223372036854775807 [ 116.149130][ C5] CPU6 next event is 116064000000 [ 116.149132][ C5] CPU7 next event is 116064000000 [ 116.261266][ C5] pageowner minidump region exhausted [ 116.263033][ C5] kgsl kgsl-3d0: snapshot: device is powered off [ 116.463067][ C5] Kernel Offset: disabled [ 116.463071][ C5] CPU features: 0x000002,c0000000,70020043,1001720b [ 116.463075][ C5] Memory Limit: 0 MB [ 116.463079][ C5] metis-doublecyc: cpu: 5 [ 116.463082][ C5] metis-doublecyc: cpu: 6 [ 116.466523][ C5] Triggering late bite [ 116.466652][ C5] Top irqs in last 8706 ms: [ 116.466656][ C5] IRQ 11 [GICv3:arch_timer] - 10646 times [ 116.466659][ C5] IRQ 271 [GICv3:msm_drm] - 139 times [ 116.466663][ C5] IRQ 276 [GICv3:kgsl_3d0_irq] - 42 times [ 116.466666][ C5] IRQ 28 [GICv3:apps_rsc-drv-2] - 136 times [ 116.466670][ C5] IRQ 211 [GICv3:dwc3] - 443 times [ 116.466675][ C5] gh-watchdog hypervisor:qcom,gh-watchdog: Causing a QCOM Apps Watchdog bite! [ 116.466683][ C5] gh-watchdog hypervisor:qcom,gh-watchdog: vWdog-CTL: 1, vWdog-time since last pet: 317, vWdog-expired status: cpu5是不是被cpu6上的进程卡住的?看堆栈其他的cpu在do_idle
10-27
#include <netinet/if_ether.h> #include <linux/filter.h> #include <linux/if_packet.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <net/if.h> #include “options.h” #include “packet.h” #include “dhcp.h” #include “dhcpc.h” #include “nsd_common.h” #include “libdms.h” #include “libds.h” #define DHCPC_SOCKET_RECV_BUF_SIZE (32 * 1024) #define DHCPC_SOCKET_SEND_BUF_SIZE (32 * 1024) LOCAL S32 discovery_timeout[DISCOVERY_RETRY_TIMES] = {2, 2, 4, 2, 12, 2, 2, 4, 2, 20, 2, 2, 4, 2, 20, 2, 2, 4, 2, 2}; /* DISCOVERY超时时间。 */ LOCAL DHCPC_PARAMS dhcpc_params = {0}; LOCAL struct dhcp_packet packet = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT #define DHCP_4G_ROUTER_STR “4g router” #define DHCPC_4G_IPC_DEV_NAME “usb0” #define DHCPC_WIRED_INTERNET_MODE 0 #define DHCPC_4G_INTERNET_MODE 1 LTE_CONFIG_INFO_DATA g_lte_config_data = {0}; S32 g_sock_idx = -1; S32 get_lte_config_data_flag = 0; /* 是否已经读取了lte_config_info_data的配置,0:未读取 ,1:已读取 */ #endif LOCAL S32 dhcpc_ip_reset() { DHCPC_MSG msg; memset(&msg, 0, sizeof(DHCPC_MSG)); msg.status = LINK_IP_RESET; msg.code = LINK_CODE_NORMAL; NSD_SEND(NSD_DHCPC_STATUS, (U8*)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL S32 dhcpc_flush_net(U32 status, U32 code) { DHCPC_MSG msg; PHY_STATUS phy_status = {0}; memset(&msg, 0, sizeof(DHCPC_MSG)); /* Stopped by caller, no need to send message. */ if (-1 == dhcpc_params.call_bk_id) { return OK; } msg.call_bk_id = dhcpc_params.call_bk_id; msg.ctrl = 0; //memcpy(msg.dev_name, dhcpc_params[iface].dev_name, DEV_NAME_LEN); msg.status = status; msg.code = code; msg.ip = dhcpc_params.yiaddr; msg.mask = dhcpc_params.mask; msg.gateway = dhcpc_params.gateway; msg.mtu = dhcpc_params.mtu; /msg.proto = PROTO_DHCP;/ if (FALSE == dhcpc_params.manual_dns) { msg.dns[0] = dhcpc_params.dns[0]; msg.dns[1] = dhcpc_params.dns[1]; } memcpy(msg.mac, dhcpc_params.server_mac, MAC_ADDR_SIZE); ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG(“DHCP success,clean tag”); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 )&phy_status, sizeof(PHY_STATUS)); } NSD_SEND(NSD_DHCPC_STATUS, (U8)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL void dhcpc_timeout_flush_net() { PHY_STATUS phy_status = {0}; EXCEPTION_STATUS_MSG msg = {0}; ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG(“record wrong code”); msg.type = WLAN_GATEWAY_UNREACHABLE; msg.status = 1; msg_send(EXCEPTION_STATUS_MID, (U8 *)&msg, sizeof(msg)); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 *)&phy_status, sizeof(PHY_STATUS)); } if (dhcpc_params.dhcp_timeout == 1) { dhcpc_flush_net(LINK_UP, LINK_CODE_DHCP_TIMEOUT); dhcpc_params.dhcp_timeout = 0; } return; } /* Multi-wans support: add parameter S32 i for all function. By xcl, 2011-05-04./ / initialize a packet with the proper defaults / LOCAL void init_packet(char type) { struct vendor { char vendor, length; char str[sizeof(“MSFT 5.0”)]; } vendor_id = { DHCP_VENDOR, sizeof(“MSFT 5.0”) - 1, “MSFT 5.0”}; / Changed by lsz 080424, cheat server:“I am Windows XP” / / vendor_id = { DHCP_VENDOR, sizeof("udhcp "VERSION) - 1, "udhcp "VERSION};*/ init_header(&packet, type); /* message type / memcpy(packet.chaddr, dhcpc_params.mac, 6); / moved by tiger 20090304, from send_discover, flags should be setting for all packet in that mode / / Modified by Li Shaozhang, 070707 / / Multi-wans support./ if (dhcpc_params.flags/get_runtime_dhcp_flags()/) / server reply mode choose / packet.flags &= htons(0x7FFF); / set first bit to 0, just AND 0111 1111 1111 1111 / else / server reply in broadcast mode / packet.flags |= htons(0x8000); / set first bit to 1, just OR 1000 0000 0000 0000 / / Edited by xcl, 13Feb12. * According to rfc2131, release packet must include options 53、54 and may 61, must not others. * decline packet is most the same but must include options 50. / if (DHCPRELEASE != type && DHCPDECLINE != type) { / 080501, add maximum size option — lsz / / Explicitly saying that we want RFC-compliant packets helps * some buggy DHCP servers to NOT send bigger packets */ add_simple_option(packet.options, DHCP_MAX_SIZE, htons(DHCP_MAX_MSG_SIZE)); } if (dhcpc_params.client[OPT_DATA]) add_option_string(packet.options, (uint8_t )dhcpc_params.client);/ client id / / Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 12. */ if (DHCPRELEASE != type && DHCPDECLINE != type && dhcpc_params.name[OPT_DATA]) add_option_string(packet.options, (uint8_t )dhcpc_params.name);/ hostname / / Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 60. */ if (DHCPRELEASE != type && DHCPDECLINE != type) add_option_string(packet.options, (uint8_t ) &vendor_id); / vendor id */ } /* Add a parameter request list for stubborn DHCP servers. Pull the data from the struct in options.c. Don’t do bounds checking here because it goes towards the head of the packet. */ LOCAL void add_requests() { S32 end = end_option(packet.options); S32 i, len = 0; packet.options[end + OPT_CODE] = DHCP_PARAM_REQ; for (i = 0; dhcp_options[i].code; i++) if (dhcp_options[i].flags & OPTION_REQ) packet.options[end + OPT_DATA + len++] = dhcp_options[i].code; packet.options[end + OPT_LEN] = len; packet.options[end + OPT_DATA + len] = DHCP_END; } /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ LOCAL S32 send_discover() { init_packet(DHCPDISCOVER); packet.xid = dhcpc_params.xid; /* 080424, del by lsz, cauz some server may ignore our request with an requested ip */ #if 0 if (requested) add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); #endif add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Broadcasts a DHCP request message */ LOCAL S32 send_selecting(U32 server, U32 requested) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Unicasts or broadcasts a DHCP renew message */ LOCAL S32 send_renew(U32 server, U32 ciaddr) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; packet.ciaddr = ciaddr; add_requests(&packet); /* 指定了server的,就单播发送 */ if (server) { return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } #if 0 /* Unicasts a DHCP release message / LOCAL S32 send_release(U32 server, U32 ciaddr) { init_packet(DHCPRELEASE); packet.xid = random(); / 使用新ID */ packet.ciaddr = ciaddr; /* Del by xcl, 13Feb12. According to rfc2131, release packet must not include option 50 / /add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr);/ add_simple_option(packet.options, DHCP_SERVER_ID, server); return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } #endif / send broadcast when GARP checking failed added by tiger 20090825 */ LOCAL S32 send_decline(U32 server, U32 requested) { init_packet(DHCPDECLINE); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } LOCAL void dhcpc_params_update() { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR(“read dev_name:%s failed”, dhcpc_params.dev_name); return; } dhcpc_params.code = LINK_CODE_NORMAL; if (NULL != dhcpc_params.path) { ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = ‘\0’; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = ‘\0’; } /* start dial */ LOCAL S32 link_up_inner() { U64 cur_time = NSD_TIMESTAMP(); LINK_STATUS link_status = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR(“Read lte config data failed”); return ERROR; } if(lte_config.internet_wired_enable == 0) { LTE_DHCP_IP dhcp_ip = {0}; if (0 == ds_read(LTE_DHCP_IP_PATH, &dhcp_ip, sizeof(LTE_DHCP_IP))) { DHCPC_ERROR(“Read lte dhcp ip failed”); return ERROR; } /* 4G_IPC: 用当前生效的ip去尝试续约 / if (dhcp_ip.ipaddr != 0) { dhcpc_params.yiaddr = dhcp_ip.ipaddr; if(dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG(“Use ip %x server %x to renewing.”, dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG(“Use ip %x to rebinding.”, dhcpc_params.yiaddr); } } else { DHCPC_DEBUG(“No old ip, try discovery.”); dhcpc_params.state = DISCOVERY; } }else { if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } / 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG(“Use ip %x server %x to renewing.”, dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG(“Use ip %x to rebinding.”, dhcpc_params.yiaddr); } } else { DHCPC_DEBUG(“No old ip, try discovery.”); dhcpc_params.state = DISCOVERY; } } #else if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } /* 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG(“Use ip %x server %x to renewing.”, dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG(“Use ip %x to rebinding.”, dhcpc_params.yiaddr); } } else { DHCPC_DEBUG(“No old ip, try discovery.”); dhcpc_params.state = DISCOVERY; } #endif if (DISCOVERY == dhcpc_params.state || RECONNECT_RENEWING == dhcpc_params.state) { DHCPC_DEBUG(“dhcpc_ip_reset”); dhcpc_ip_reset(); } switch (dhcpc_params.state) { case DISCOVERY: dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; /* 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 / break; case RECONNECT_REBINDING: dhcpc_params.timeout = 0; dhcpc_params.t2 = 60; dhcpc_params.start = cur_time - dhcpc_params.t2; dhcpc_params.lease = 120; break; case RECONNECT_RENEWING: dhcpc_params.timeout = 0; dhcpc_params.start = cur_time; dhcpc_params.lease = 120; dhcpc_params.t2 = 60; dhcpc_params.t1 = 0; break; } dhcpc_params.dhcp_timeout = 1; / 重连才触发dhcp timeout*/ #if 0 /* 如果当前正处在释放IP状态。 / if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { dhcpc_params.re_dial = TRUE; / IP地址释放完毕之后会自动重拨。 */ return 0; } /* 如果已经拨上号了,断线重连。 / if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { / 断开DHCPC-LAN的连接时,不要释放租约,对外表现与SLP平台保持一致,详解见linkDownInner。 / if (dhcpc_params.send_release) { DHCPC_DEBUG(“Send RELEASE to server %.8x”, ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); / unicast / } dhcpc_params.timeout = 0; / 确保release包发出之后再释放接口IP / dhcpc_params.state = IFDOWN; dhcpc_params.re_dial = TRUE; / IP地址释放完毕之后会自动重拨。 */ #endif return OK; } /* stop dial / LOCAL S32 link_down_inner(U32 code) { / 智能ip策略,不需要发送release包,直接停止状态机即可 / if (INIT != dhcpc_params.state) { / 保留已经获取的ip */ /dhcpc_params.yiaddr = 0;/ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); } dhcpc_flush_net(LINK_DOWN, code); #if 0 /* 如果已经拨上号了,需要发送release包。 / if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { / 修复Bug 185658 & 185215,由于桥接到rootAP使用的MAC与DHCPC-LAN使用的LAN MAC不同,因此重桥会出 现以下问题: 如果发送DHCP RELEASE释放了原来的租约,那么重桥重新获取IP时,rootAP的DHCPS可能会发ARP Request 来探测原来分配的IP是否被使用,因为此时LAN口已配置了该IP,因此会给rootAP ARP Reply,告知该IP对 应的是LAN MAC。 但在rootAP端来看,ARP reply的MAC与DHCPC DISCOVER里携带MAC不同,因此DHCPS会误判成IP已被另一个设 备使用,从而又分配了另一个可用的IP,导致重桥后的LAN IP改变。 SLP平台机型在重桥时因为没有发DHCP RELEASE释放租约,因此在租约有效期间重桥能够保持LAN IP不变。 当租约被老化清理掉,重桥同样会导致LAN IP改变。 要完全修复此bug需要无线驱动与DHCPC-LAN互相配合着修改,现在先部分修复,断开DHCPC-LAN的连接时, 不要发DHCP RELEASE释放租约,令SDMP平台的对外表现与SLP平台一致。 / if (dhcpc_params.send_release) { / 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 / DHCPC_DEBUG(“Send RELEASE to server %.8x”, ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); / unicast */ } dhcpc_params.timeout = 0; /* 确保release包发出之后再释放接口IP / dhcpc_params.state = IFDOWN; return 0; } / 如果正在断开,保持当前的状态机即可。 / if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { return 0; } / 如果正在拨号,停止状态机即可。 */ if (INIT != dhcpc_params.state) { dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); } #endif return 0; } LOCAL void dhcpc_check_timer() { U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}; /* DHCPC_DEBUG(“DHCP state is %d”, dhcpc_params.state); / if (cur_time < dhcpc_params.timeout) / 暂不考虑溢出问题。 / { return; } switch (dhcpc_params.state) { case INIT: / just do nothing / break; / 和发REQUEST包行为统一,第一个包要在收包前一个状态发,避免还未发DISCOVER包,就开始收包。 / case DISCOVERY: DHCPC_DEBUG(“Send DISCOVER with unicast flag %d”, dhcpc_params.flags); dhcpc_params.xid = random(); / 每次重新拨号,每次续约时才更换xid,若没有得到响应,可以不更换xid。 / send_discover(); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[0]); dhcpc_params.packet++; dhcpc_params.state = SELECTING; break; case SELECTING: if (dhcpc_params.packet >= DISCOVERY_RETRY_TIMES) { / DHCPC fail, start in 2s again. / DHCPC_DEBUG(“Dhcpc failed, retry count = %d”, dhcpc_params.packet); dhcpc_params.timeout = cur_time + 2; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } / change runtime dhcp flags when exceed DISCOVER_INVERT_TIMES added by tiger 20090819 apply 11G and XP’s option / / 修复Bug 40838:切换单/广播时需同步加/卸载filter(20130924) / / 在PNE2.2平台里,每5个包为一组,每组里第三个包开始切换 / if ((dhcpc_params.support_un_cast) && (DISCOVERY_INVERT_TIMES == (dhcpc_params.packet % DISCOVERY_GROUP_TIMES))) { dhcpc_params.flags = !dhcpc_params.flags; } DHCPC_DEBUG(“Send DISCOVER with unicast flag %d”, dhcpc_params.flags); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[dhcpc_params.packet]); send_discover(); dhcpc_params.packet++; if (DISCOVERY_RETRY_TIMEOUT == dhcpc_params.packet) { dhcpc_timeout_flush_net(); } break; case REQUESTING: if (dhcpc_params.packet > REQUESTING_RETRY_TIMES) / 当尝试超过一定次数,重新发DISCOVERY。/ { DHCPC_DEBUG(“Recv no ACK, restart”); dhcpc_params.timeout = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG(“Send REQUEST to server %d.%d.%d.%d”, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); / broadcast / dhcpc_params.timeout = /time(0) + ((cur_client->packet_num == 2) ? 10 : 2)/cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.packet++; break; case BOUND: case RENEWING: / Either set a new T1, or enter REBINDING state / if ((dhcpc_params.t2 - dhcpc_params.t1) <= (dhcpc_params.lease / 14400 + 1)) { / timed out, enter rebinding state / dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(dhcpc_params.t2 - dhcpc_params.t1); dhcpc_params.state = REBINDING; / 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server / dhcpc_params.server = 0; DHCPC_DEBUG(“Entering rebinding state”); break; } / send a request packet / DHCPC_DEBUG(“Send REQUEST to server %.8x”, dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); / unicast / dhcpc_params.t1 = (dhcpc_params.t2 - dhcpc_params.t1) / 2 + dhcpc_params.t1; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + dhcpc_params.start; dhcpc_params.state = RENEWING; break; case REBINDING: / Either set a new T2, or enter INIT state / if ((dhcpc_params.lease - dhcpc_params.t2) <= (dhcpc_params.lease / 14400 + 1)) { //dhcpc_flush_net(LINK_DOWN, LINK_CODE_NOECHO); DHCPC_DEBUG(“Lease lost, entering DISCOVERY state”); / timed out, enter init state / dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); / 智能ip:rebinding失败,视为之前的ip失效了 / dhcpc_params.yiaddr = 0; break; } ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG(“broadcast REQUEST with request ip %d.%d.%d.%d”, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); / broadcast / dhcpc_params.t2 = (dhcpc_params.lease - dhcpc_params.t2) / 2 + dhcpc_params.t2; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t2) + dhcpc_params.start; dhcpc_params.packet++; break; case RECONNECT_RENEWING: / 每秒发一次包,等待 RECONNECT_RENEWING_TIMES 秒 / if (dhcpc_params.packet > RECONNECT_RENEWING_TIMES) { / timed out, enter rebinding state / dhcpc_params.timeout = cur_time; dhcpc_params.state = RECONNECT_REBINDING; dhcpc_params.packet = 0; / 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server / dhcpc_params.server = 0; DHCPC_DEBUG(“[RECONNECT]Entering reconect_rebinding state”); break; } / send a request packet / DHCPC_DEBUG(“[RECONNECT]Send REQUEST to server %.8x”, dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); / unicast / dhcpc_params.packet++; dhcpc_params.timeout = 0; break; case RECONNECT_REBINDING: / 每秒发一次包,等待 RECONNECT_REBINDING_TIMES 秒 / if (dhcpc_params.packet > RECONNECT_REBINDING_TIMES) { / timed out, enter init state / dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; / 智能ip:rebinding失败,视为之前的ip失效了 / dhcpc_params.yiaddr = 0; DHCPC_DEBUG(“[RECONNECT]Reconnect fail, Entering discovery state”); break; } / send a request packet / ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG(“broadcast REQUEST with request ip %d.%d.%d.%d”, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); / broadcast / dhcpc_params.timeout = cur_time; dhcpc_params.packet++; break; #if 0 case RELEASED: / 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 / ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG(“Send RELEASE to server %d.%d.%d.%d”, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_release(dhcpc_params.server, dhcpc_params.yiaddr); / unicast / dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(1); / 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; break; case IFDOWN: dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); /* 注释掉,保存上次获取的ip / //dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; if (-1 != dhcpc_params.call_bk_id_new) { dhcpc_params.call_bk_id = dhcpc_params.call_bk_id_new; dhcpc_params.call_bk_id_new = -1; } memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); if (TRUE == dhcpc_params.re_dial) { dhcpc_params.re_dial = FALSE; dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; / 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 */ dhcpc_params.state = DISCOVERY; } break; #endif } } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL void write_mobile_access(U8 val) { DEVICE_BASIC_INFO info = {0}; if (0 == ds_read(DEVICE_BASIC_INFO_PATH, &info, sizeof(info))) { DHCPC_ERROR(“ds read device basic_info failed”); return; } else { info.mobile_access = val; ds_write(DEVICE_BASIC_INFO_PATH, &info, sizeof(info)); } } #endif LOCAL void dhcpc_handle(S32 sock) { S32 bytes = 0; U8 *message = NULL, *option = NULL; U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}, mask = {0}, gateway = {0}, server = {0}; U32 dns[2] = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR(“Read lte config error”); return; } #endif /* 收到DHCP服务器的响应报文。 / bytes = get_packet(&packet, sock); if (bytes < 0) { DHCPC_WARNING(“Error on read, %m, reopening socket”); return; } / Ignore packets that aren’t for us / if (memcmp(packet.chaddr, dhcpc_params.mac, sizeof(dhcpc_params.mac))) { DHCPC_DEBUG(“Packet does not have our chaddr – ignoring”); return; } if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DHCPC_WARNING(“Couldnt get option from packet – ignoring”); return; } if (packet.xid != dhcpc_params.xid) { DHCPC_WARNING(“ignoring XID %lx (our xid is %lx)”, packet.xid, dhcpc_params.xid); return; } switch (dhcpc_params.state) { case INIT: case DISCOVERY: / just drop all message. */ break; case SELECTING: if ((DHCPOFFER != message) || / 在此处只能接收OFFER包,其它包丢弃 / (NULL == (option = get_option(&packet, DHCP_SERVER_ID)))) / 必须带有SERVER_ID。 / { break; } memcpy(&dhcpc_params.server, option, 4); dhcpc_params.mask = inet_addr(“255.255.255.255”); switch (ip_network_id(packet.yiaddr)) { case ‘A’: dhcpc_params.mask = inet_addr(“255.0.0.0”); break; case ‘B’: dhcpc_params.mask = inet_addr(“255.255.0.0”); break; case ‘C’: dhcpc_params.mask = inet_addr(“255.255.255.0”); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } /dhcpc_params[iface].xid = packet.xid;/ / 忽略? / dhcpc_params.yiaddr = packet.yiaddr; ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG(“Recv OFFER from server %d.%d.%d.%d with ip %d.%d.%d.%d”, server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); / 在此处验证获得的IP的合法性。这里DHCP不回MTU / if ((OK != check_valid_param(dhcpc_params.mtu, dhcpc_params.yiaddr, dhcpc_params.mask, 0))) { DHCPC_DEBUG(“check_valid_param failed.”); break; / 继续等待其它的服务器响应 / } / 合法性验证通过后,发送Request报文,跳转到REQUESTING状态。 / ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG(“Send REQUEST to server %d.%d.%d.%d with request ip %d.%d.%d.%d”, server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); / broadcast / dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.state = REQUESTING; dhcpc_params.packet = 0; dhcpc_params.retry = 0; break; case RENEWING: case REBINDING: case REQUESTING: case RECONNECT_RENEWING: case RECONNECT_REBINDING: / 是否要验证server id?这里暂且验证下,个人认为这样安全。 / if (NULL == (option = get_option(&packet, DHCP_SERVER_ID))) { break; / unknown dhcp server? / } / REBINDING阶段更新server / if (dhcpc_params.state == REBINDING || dhcpc_params.state == RECONNECT_REBINDING) { memcpy(&dhcpc_params.server, option, 4); } / REBINDING阶段可能会切换server,此时不可检查 */ #if 0 if (dhcpc_params[iface].server != *(U32 )option) { break; / invalid dhcp server? */ } #endif if (DHCPACK == message) { dhcpc_params.lease = 6060; /* 默认1小时。 */ if (NULL != (option = get_option(&packet, DHCP_LEASE_TIME))) { memcpy(&dhcpc_params.lease, option, 4); dhcpc_params.lease = ntohl(dhcpc_params.lease); } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { IF_CONF if_conf = {0}; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR(“Read wan config error”); return; } /* 无论是否为bridge ifname都存放我们需要的值 / if (0 == if_conf.ifname[0]) { DHCPC_ERROR(“Get ifname failed.”); return; } char dev_name[32] = {0}; U8 dev_mac[6] = {0}; snprintf(dev_name, sizeof(dev_name), “%s”, if_conf.ifname); if (0 > read_interface_info(dev_name, NULL, dev_mac)) { DHCPC_ERROR(“read usb0 device info error”); return; } / 发送GARP验证IP是否被占用。 / if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && ((0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300)) || (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dev_mac, dev_name, 300)))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING(“Offered address is in use, send DECLINE to server %d.%d.%d.%d”, server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); / 推迟一段时间再重新申请。 / dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } }else #endif { / 发送GARP验证IP是否被占用。 / if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING(“Offered address is in use, send DECLINE to server %d.%d.%d.%d”, server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); / 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT /* 在有线上网模式下,dhcp server分配的IP不能为4G网关192.168.43.1 / if(((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && packet.yiaddr == 0x012ba8c0) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING(“Offered address is in Gateway for 4G, send DECLINE to server %d.%d.%d.%d”, server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); / 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #endif } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if (NULL != (option = get_option(&packet, DHCP_4G_ROUTER))) { if(0 == memcmp(option, DHCP_4G_ROUTER_STR, strlen(DHCP_4G_ROUTER_STR))) { DHCPC_INFO(“get option DHCP_4G_ROUTER”); write_mobile_access(1); } else { write_mobile_access(0); } } else { write_mobile_access(0); } #endif /* 分配的IP没有被占用,则使用该IP,并且进入bound状态。 / dhcpc_params.t1 = dhcpc_params.lease/2; dhcpc_params.t2 = ((dhcpc_params.lease * 0x7) >> 3);/ little fixed point for n * .875 / dhcpc_params.start = cur_time; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + cur_time; ip_addr.ipAddr = dhcpc_params.yiaddr; / 保留原IP的值 / dhcpc_params.yiaddr = packet.yiaddr; / 获取网关。 */ gateway.ipAddr = dhcpc_params.gateway; dhcpc_params.gateway = 0; if (NULL != (option = get_option(&packet, DHCP_ROUTER))) { if(0 != option) { memcpy(&dhcpc_params.gateway, option, 4); } else if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR(“Received ACK but gateway option is zero, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]”, dhcpc_params.gateway, dhcpc_params.server); } else { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { dhcpc_params.gateway = 0x012ba8c0; / 4G上网模式下,无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.43.1 / DHCPC_ERROR(“Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.43.1”, dhcpc_params.gateway); }else #endif { dhcpc_params.gateway = 0x0100a8c0; / 无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.0.1 */ DHCPC_ERROR(“Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1”, dhcpc_params.gateway); } } } else { if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR(“Received ACK but gateway option is empty, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]”, dhcpc_params.gateway, dhcpc_params.server); } else { dhcpc_params.gateway = 0x0100a8c0; DHCPC_ERROR(“Received ACK but the gateway and source IP are illegal, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1”, dhcpc_params.gateway); } } /* 获取掩码。 / mask.ipAddr = dhcpc_params.mask; dhcpc_params.mask = inet_addr(“255.255.255.255”); switch (ip_network_id(packet.yiaddr)) { case ‘A’: dhcpc_params.mask = inet_addr(“255.0.0.0”); break; case ‘B’: dhcpc_params.mask = inet_addr(“255.255.0.0”); break; case ‘C’: dhcpc_params.mask = inet_addr(“255.255.255.0”); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } / 获取DNS. / if (FALSE == dhcpc_params.manual_dns) { dns[0] = dhcpc_params.dns[0]; dns[1] = dhcpc_params.dns[1]; dhcpc_params.dns[0] = 0; dhcpc_params.dns[1] = 0; if (NULL != (option = get_option(&packet, DHCP_DNS_SERVER))) { S32 dnsNum = 0; S32 i = 0; dnsNum = ((option - 1))/4; dnsNum = dnsNum > 2 ? 2 : dnsNum; for (i = 0; i < dnsNum; i++) { memcpy(dhcpc_params.dns + i, option + 4 * i, 4); } } } /* REQUESTING状态或者ip、gateway、mask有更新则刷新接口。 / / RECONNECT_RENEWING 和 RECONNECT_REBINDING状态可能是静态转为动态,因此也要进行设置 / if ((REQUESTING == dhcpc_params.state) || dhcpc_params.state == RECONNECT_RENEWING || dhcpc_params.state == RECONNECT_REBINDING || (ip_addr.ipAddr != dhcpc_params.yiaddr) || (gateway.ipAddr != dhcpc_params.gateway) || (mask.ipAddr != dhcpc_params.mask)) { / 根据获得的IP配置本地接口。 / ip_addr.ipAddr = dhcpc_params.yiaddr; mask.ipAddr = dhcpc_params.mask; gateway.ipAddr = dhcpc_params.gateway; DHCPC_INFO(“%s set ip %d.%d.%d.%d mask %d.%d.%d.%d gateway %d.%d.%d.%d lease time %ld”, dhcpc_params.dev_name, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3], mask.ipAddrByteFormat[0], mask.ipAddrByteFormat[1], mask.ipAddrByteFormat[2], mask.ipAddrByteFormat[3], gateway.ipAddrByteFormat[0], gateway.ipAddrByteFormat[1], gateway.ipAddrByteFormat[2], gateway.ipAddrByteFormat[3], dhcpc_params.lease); dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } else if ((TRUE != dhcpc_params.manual_dns) && ((dns[0] != dhcpc_params.dns[0]) || (dns[1] != dhcpc_params.dns[1]))) { dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } DHCPC_DEBUG(“Recv ACK from server %.8x with ip %.8x lease time %ld”, dhcpc_params.server, dhcpc_params.yiaddr, dhcpc_params.lease); dhcpc_params.retry = 0; / clear the retry counter */ dhcpc_params.packet = 0; dhcpc_params.state = BOUND; break; } if (DHCPNAK != message) { break; } / 这里需要考虑两种情况: / / 在未配置本地IP的情况(即REQUESTING状态),只需更新状态到INIT_SELECTING状态即可。 / / 其它状态则需要释放已配置的IP。 / if (REQUESTING != dhcpc_params.state) { DHCPC_DEBUG(“state [%d] receive NACK”, dhcpc_params.state); dhcpc_flush_net(LINK_DOWN, LINK_CODE_DENY); } ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_INFO(“Recv NAK from server %d.%d.%d.%d with ip %d.%d.%d.%d”, server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); if (dhcpc_params.state != RECONNECT_RENEWING && dhcpc_params.state != RECONNECT_REBINDING) { dhcpc_timeout_flush_net(); } else { / 收到NAK后重新开始DISCOVERY前刷新参数 */ dhcpc_params_update(); } dhcpc_params.timeout = 0; dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } } LOCAL S32 dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING(“call back parameter error.”); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { DHCPC_DEBUG(“Now start dhcpc progress.”); link_up_inner(); dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG(“Now stop dhcpc progress.”); link_down_inner(msg->code); return OK; } DHCPC_WARNING(“Unknown command.”); return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL S32 dhcpc_socket_reload() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR(“client socket call failed”); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR(“client socket set reuseaddr option failed”); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char ) &option, sizeof(option))) { DHCPC_ERROR(“client socket set broadcast option failed”); goto dhcpc_error_exit; } / 设置缓存大小 / buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR(“Set sock rcv buf error.”); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR(“Set sock rcv buf error.”); } / 绑定网卡 / struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); IF_CONF if_conf = {0}; LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR(“Read lte config data ERROR”); return ERROR; } if(lte_config.internet_wired_enable == 0) { strncpy(ifr.ifr_name, DHCPC_4G_IPC_DEV_NAME, strlen(DHCPC_4G_IPC_DEV_NAME) + 1); DHCPC_ERROR(“ifr.ifr_name:%s”, ifr.ifr_name); }else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR(“Read wan config error”); goto dhcpc_error_exit; } / 无论是否为bridge ifname都存放我们需要的值 / if (0 == if_conf.ifname[0]) { DHCPC_ERROR(“Get ifname failed.”); goto dhcpc_error_exit; } strncpy(ifr.ifr_name, if_conf.ifname, strlen(if_conf.ifname)); } if(ERROR == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char)&ifr, sizeof(ifr))) { DHCPC_ERROR(“can’t bind to interface :%s”, ifr.ifr_name); } DHCPC_ERROR(“ifr.ifr_name:%s”, ifr.ifr_name); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR(“server socket set broadcast option failed”); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL int dhcpc_param_reload(int flag) { IF_CONF if_conf = {0}; DHCPC dhcpc_data; dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; //dhcpc_params.call_bk_id = -1; dhcpc_params.path = DHCPC_PATH; if(flag == DHCPC_4G_INTERNET_MODE) { /* 4G_ICP使用usb0 / snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), “%s”, DHCPC_4G_IPC_DEV_NAME); if(0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR(“read usb0 device info error”); return ERROR; } } else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR(“Read wan config error”); return ERROR; } / 无论是否为bridge ifname都存放我们需要的值 / if (0 == if_conf.ifname[0]) { DHCPC_ERROR(“Get ifname failed.”); return ERROR; } / IPC使用br-wan / snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), “%s”, if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR(“read usb0 device info error”); return ERROR; } } / 智能ip,IPC断开dhcp时不释放租约 / dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.flags = FALSE; / 默认广播。 / if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = ‘\0’; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = ‘\0’; dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = ‘\0’; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; if(dhcpc_params.sock) { inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; } dhcpc_params.sock = dhcpc_socket_reload(); g_sock_idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if(0 > g_sock_idx) { DHCPC_ERROR(“add dhcp client socket to inetd failed”); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if(0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR(“add dhcp timer to inetd failed”); inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } return OK; } LOCAL S32 lte_dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; U8 dev_mac[6] = {0}; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING(“call back parameter error.”); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { if(!strncmp(dhcpc_params.dev_name, DHCPC_4G_IPC_DEV_NAME, sizeof(dhcpc_params.dev_name))) { DHCPC_DEBUG(“Now start dhcpc progress.”); if(0 > read_interface_info(dhcpc_params.dev_name, NULL, dev_mac)) { DHCPC_ERROR(“read usb0 device info error”); return ERROR; } if(memcmp(dhcpc_params.mac, dev_mac, sizeof(dhcpc_params.mac))) { DHCPC_ERROR(“usb0 device mac change, reload dhcpc params.”); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR(“reload dhcpc param failed”); return ERROR; } } link_up_inner(); }else { DHCPC_DEBUG(“Change dhcpc device first”); DHCPC_DEBUG(“Now start dhcpc progress.”); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR(“reload dhcpc param failed”); return ERROR; } link_up_inner(); } dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG(“Now stop dhcpc progress.”); link_down_inner(msg->code); return OK; } DHCPC_WARNING(“Unknown command.”); return ERROR; } #endif LOCAL S32 dhcpc_socket_init() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR(“client socket call failed”); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR(“client socket set reuseaddr option failed”); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char ) &option, sizeof(option))) { DHCPC_ERROR(“client socket set broadcast option failed”); goto dhcpc_error_exit; } / 设置缓存大小 */ buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR(“Set sock rcv buf error.”); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR(“Set sock rcv buf error.”); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR(“server socket set broadcast option failed”); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL void dhcpc_param_init() { IF_CONF if_conf = {0}; DHCPC dhcpc_data; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR(“Read wan config error”); return; } /* 无论是否为bridge ifname都存放我们需要的值 / if (0 == if_conf.ifname[0]) { DHCPC_ERROR(“Get ifname failed.”); return; } memset(&dhcpc_params, 0, sizeof(DHCPC_PARAMS)); / 智能ip,设置ip为0xFFFFFFFF 标记是开机后首次获取ip / dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; dhcpc_params.call_bk_id = -1; dhcpc_params.mac[0] = 0x00; dhcpc_params.mac[1] = 0x11; dhcpc_params.mac[2] = 0x22; dhcpc_params.mac[3] = 0x33; dhcpc_params.mac[4] = 0x44; dhcpc_params.mac[5] = 0x55; dhcpc_params.path = DHCPC_PATH; / IPC使用br-wan / snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), “%s”, if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { return; } / 智能ip,IPC断开dhcp时不释放租约 / dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.state = INIT; dhcpc_params.flags = FALSE; / 默认广播。 / if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = ‘\0’; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = ‘\0’; dhcpc_params.packet = 0; /* start things over / dhcpc_params.timeout = 0xFFFFFFFF; / Kill any timeouts because the user wants this to hurry along */ dhcpc_params.retry = 0; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; dhcpc_params.sock = dhcpc_socket_init(); } LOCAL S32 dhcpc_init() { S32 idx = -1; dhcpc_param_init(); if (0 > dhcpc_params.sock) { DHCPC_ERROR(“dhcp client socket init failed”); return ERROR; } idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if (0 > idx) { DHCPC_ERROR(“add dhcp client socket to inetd failed”); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if (0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR(“add dhcp timer to inetd failed”); inet_del_socket(idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } msg_attach_handler(NSD_DHCPC_CTRL, dhcpc_ctrl_callback); #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT g_sock_idx = idx; msg_attach_handler(LTE_DHCPC_CTRL, lte_dhcpc_ctrl_callback); #endif DHCPC_ERROR(“DHCPC init over.”); return OK; } LOCAL S32 dhcpc_reload(DS_MSG *msg) { if (NULL == msg) { return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(!get_lte_config_data_flag) { if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&g_lte_config_data, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR(“ds read path [%s] failed.”, LTE_INFO_DATA_PATH); return ERROR; } get_lte_config_data_flag = 1; } #endif if (ds_path_id_exist(msg->id, msg->num, DHCPC_PATH)) { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 == ds_read(DHCPC_PATH, (U8 *)&dhcpc_data, sizeof(DHCPC))) { DHCPC_ERROR(“Read dhcpc data ERROR”); return ERROR; } dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = ‘\0’; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(ds_path_id_exist(msg->id, msg->num, INFO_INTERNET_PATH)) { INFO_INTERNET info_internet = {0}; if(0 == ds_read(INFO_INTERNET_PATH, (U8*)&info_internet, sizeof(INFO_INTERNET))) { DHCPC_ERROR(“ds read path [%s] failed.”, INFO_INTERNET_PATH); return ERROR; } LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(info_internet.link_status == INTERNET_4G_DISCONNECTED) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR(“Read lte config data ERROR”); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR(“reload dhcpc param failed”); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR(“reload dhcpc param failed”); return ERROR; } } } }else if(info_internet.link_status == INTERNET_4G_CONNECTING) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR(“Read lte config data ERROR”); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR(“reload dhcpc param failed”); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR(“reload dhcpc param failed”); return ERROR; } } } } } #endif return OK; } LOCAL void dhcpc_main() { DS_DAT_MON_DESC dhcpc_data_monitor[] = { DS_DAT_MON(DHCPC_PATH, DATA_ATTRI_NOTIFY), #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT DS_DAT_MON(INFO_INTERNET_PATH, DATA_ATTRI_NOTIFY), #endif }; DS_MOD_DESC dhcpc_module = DS_STRUCT_MOD(“dhcpc”, dhcpc_init, NULL, dhcpc_reload, NULL, NULL, NULL, dhcpc_data_monitor); MODULE *module_node = ds_register_module(“dhcpc”, &dhcpc_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(dhcpc_main); 学习一下上面这个dhcp.c的代码,帮我完成下面的作业,arp和dhcp是同一级文件夹,你可以参考一下DHCP的,并且把arp这个也写成一个文件,源文件和头文件分开。 实验题 课题:ARP扫描功能 要求: 1、基于NVMP平台,为NSD模块添加一个用于定时扫描指定网段的主机的arp子模块。arp子模块的扫描需要通过socket编程收发ARP报文来实现。 2、arp子模块使用DS来保存用户配置,用户配置参数包括:功能开关、扫描周期(秒)、有效期(秒)、发包间隔(毫秒)、起始IP、结束IP。 例如可以指定192.168.1.100-192.168.1.200,每格60秒扫描一遍,发包间隔100毫秒,如果网络中有192.168.1.101和192.168.1.102两台主机,则扫描结果就是这两个IP地址及对应的MAC地址。扫描功能需在开关开启对情况下才进行; 扫描的结果需要在内存中管理维护,一个ARP条目如果超过有效期时间都未被再次扫描到则删除掉该条目。 3、arp子模块需要提供基于DMS的ubus服务接口,至少提供以下接口用于客户端调用,使用TDCP协议: set_arp_config(设置功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) get_arp_config(获取功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) start_scan(开始一次扫描) stop_scan(停止扫描) get_scan_status(扫描状态) get_scan_result(获取最近一次的扫描结果) clear_result(清除历史结果) 其次需要提供基于ubus工具的调测命令,用于在串口执行扫描,停止扫描,获取扫描结果,获取扫描状态,清除历史扫描结果等。 4、每次发现一台新的主机(之前扫描时未发现的),将主机信息打印到串口,同时在内存中进行存储。 5、写一个测试程序test_arpsd,通过C代码调用DMS/DS库API的方式(不能直接调用ubus命令),对各部分功能和接口进行测试。 6、在Network标签下添加一个子页面,标题为ARP Scanner。可以在该web页面上进行以下操作: 修改上述配置参数并生效、执行或终止一次扫描、获取并显示上一次扫描结果。 7、编写为NVMP平台NSD的一个子模块软件包,包含所有的c、shell、html代码及Makefile文件。 备注:WEB部分(上述第6点)是可选的,请先完成与web无关的部分。
08-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值