帮我分析这个代码,他是一个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, <e_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*)<e_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(<e_config, 0, sizeof(LTE_CONFIG_INFO_DATA));
if(0 == ds_read(LTE_INFO_DATA_PATH, <e_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(<e_config, 0, sizeof(LTE_CONFIG_INFO_DATA));
if(info_internet.link_status == INTERNET_4G_DISCONNECTED)
{
if(0 == ds_read(LTE_INFO_DATA_PATH, <e_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, <e_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);