1*4882a593Smuzhiyun /******************************************************************************
2*4882a593Smuzhiyun @file udhcpc.c
3*4882a593Smuzhiyun @brief call DHCP tools to obtain IP address.
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun DESCRIPTION
6*4882a593Smuzhiyun Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules.
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun INITIALIZATION AND SEQUENCING REQUIREMENTS
9*4882a593Smuzhiyun None.
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun ---------------------------------------------------------------------------
12*4882a593Smuzhiyun Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
13*4882a593Smuzhiyun Quectel Wireless Solution Proprietary and Confidential.
14*4882a593Smuzhiyun ---------------------------------------------------------------------------
15*4882a593Smuzhiyun ******************************************************************************/
16*4882a593Smuzhiyun #include <sys/socket.h>
17*4882a593Smuzhiyun #include <sys/select.h>
18*4882a593Smuzhiyun #include <sys/types.h>
19*4882a593Smuzhiyun #include <net/if.h>
20*4882a593Smuzhiyun #include <sys/socket.h>
21*4882a593Smuzhiyun #include <netinet/in.h>
22*4882a593Smuzhiyun #include <arpa/inet.h>
23*4882a593Smuzhiyun #include <endian.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include "util.h"
26*4882a593Smuzhiyun #include "QMIThread.h"
27*4882a593Smuzhiyun
qmi2addr(uint32_t __x)28*4882a593Smuzhiyun static __inline in_addr_t qmi2addr(uint32_t __x) {
29*4882a593Smuzhiyun return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun
ql_system(const char * shell_cmd)32*4882a593Smuzhiyun static int ql_system(const char *shell_cmd) {
33*4882a593Smuzhiyun dbg_time("%s", shell_cmd);
34*4882a593Smuzhiyun return system(shell_cmd);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun
ifc_init_ifr(const char * name,struct ifreq * ifr)37*4882a593Smuzhiyun static void ifc_init_ifr(const char *name, struct ifreq *ifr)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun memset(ifr, 0, sizeof(struct ifreq));
40*4882a593Smuzhiyun strncpy(ifr->ifr_name, name, IFNAMSIZ);
41*4882a593Smuzhiyun ifr->ifr_name[IFNAMSIZ - 1] = 0;
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
ql_set_mtu(const char * ifname,int ifru_mtu)44*4882a593Smuzhiyun static void ql_set_mtu(const char *ifname, int ifru_mtu) {
45*4882a593Smuzhiyun int inet_sock;
46*4882a593Smuzhiyun struct ifreq ifr;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (inet_sock > 0) {
51*4882a593Smuzhiyun ifc_init_ifr(ifname, &ifr);
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) {
54*4882a593Smuzhiyun if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) {
55*4882a593Smuzhiyun dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu , ifru_mtu);
56*4882a593Smuzhiyun ifr.ifr_ifru.ifru_mtu = ifru_mtu;
57*4882a593Smuzhiyun ioctl(inet_sock, SIOCSIFMTU, &ifr);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun close(inet_sock);
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
ifc_get_addr(const char * name,in_addr_t * addr)65*4882a593Smuzhiyun static int ifc_get_addr(const char *name, in_addr_t *addr)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun int inet_sock;
68*4882a593Smuzhiyun struct ifreq ifr;
69*4882a593Smuzhiyun int ret = 0;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun ifc_init_ifr(name, &ifr);
74*4882a593Smuzhiyun if (addr != NULL) {
75*4882a593Smuzhiyun ret = ioctl(inet_sock, SIOCGIFADDR, &ifr);
76*4882a593Smuzhiyun if (ret < 0) {
77*4882a593Smuzhiyun *addr = 0;
78*4882a593Smuzhiyun } else {
79*4882a593Smuzhiyun *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun close(inet_sock);
83*4882a593Smuzhiyun return ret;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
ifc_get_flags(const char * ifname)86*4882a593Smuzhiyun static short ifc_get_flags(const char *ifname)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun int inet_sock;
89*4882a593Smuzhiyun struct ifreq ifr;
90*4882a593Smuzhiyun int ret = 0;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun inet_sock = socket(AF_INET, SOCK_DGRAM, 0);
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (inet_sock > 0) {
95*4882a593Smuzhiyun ifc_init_ifr(ifname, &ifr);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun if (!ioctl(inet_sock, SIOCGIFFLAGS, &ifr)) {
98*4882a593Smuzhiyun ret = ifr.ifr_ifru.ifru_flags;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun close(inet_sock);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun return ret;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
ql_netcard_ipv4_address_check(const char * ifname,in_addr_t ip)107*4882a593Smuzhiyun static int ql_netcard_ipv4_address_check(const char *ifname, in_addr_t ip) {
108*4882a593Smuzhiyun in_addr_t addr = 0;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun ifc_get_addr(ifname, &addr);
111*4882a593Smuzhiyun return addr == ip;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
ql_raw_ip_mode_check(const char * ifname,uint32_t ip)114*4882a593Smuzhiyun static int ql_raw_ip_mode_check(const char *ifname, uint32_t ip) {
115*4882a593Smuzhiyun int fd;
116*4882a593Smuzhiyun char raw_ip[128];
117*4882a593Smuzhiyun char shell_cmd[128];
118*4882a593Smuzhiyun char mode[2] = "X";
119*4882a593Smuzhiyun int mode_change = 0;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (ql_netcard_ipv4_address_check(ifname, qmi2addr(ip)))
122*4882a593Smuzhiyun return 0;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname);
125*4882a593Smuzhiyun if (access(raw_ip, F_OK))
126*4882a593Smuzhiyun return 0;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY);
129*4882a593Smuzhiyun if (fd < 0) {
130*4882a593Smuzhiyun dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno));
131*4882a593Smuzhiyun return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun if (read(fd, mode, 2) == -1) {};
135*4882a593Smuzhiyun if (mode[0] == '0' || mode[0] == 'N') {
136*4882a593Smuzhiyun dbg_time("File:%s Line:%d udhcpc fail to get ip address, try next:", __func__, __LINE__);
137*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname);
138*4882a593Smuzhiyun ql_system(shell_cmd);
139*4882a593Smuzhiyun dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
140*4882a593Smuzhiyun mode[0] = 'Y';
141*4882a593Smuzhiyun if (write(fd, mode, 2) == -1) {};
142*4882a593Smuzhiyun mode_change = 1;
143*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname);
144*4882a593Smuzhiyun ql_system(shell_cmd);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun close(fd);
148*4882a593Smuzhiyun return mode_change;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
udhcpc_thread_function(void * arg)151*4882a593Smuzhiyun static void* udhcpc_thread_function(void* arg) {
152*4882a593Smuzhiyun FILE * udhcpc_fp;
153*4882a593Smuzhiyun char *udhcpc_cmd = (char *)arg;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun if (udhcpc_cmd == NULL)
156*4882a593Smuzhiyun return NULL;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun dbg_time("%s", udhcpc_cmd);
159*4882a593Smuzhiyun udhcpc_fp = popen(udhcpc_cmd, "r");
160*4882a593Smuzhiyun free(udhcpc_cmd);
161*4882a593Smuzhiyun if (udhcpc_fp) {
162*4882a593Smuzhiyun char buf[0xff];
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun buf[sizeof(buf)-1] = '\0';
165*4882a593Smuzhiyun while((fgets(buf, sizeof(buf)-1, udhcpc_fp)) != NULL) {
166*4882a593Smuzhiyun if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n'))
167*4882a593Smuzhiyun buf[strlen(buf) - 1] = '\0';
168*4882a593Smuzhiyun dbg_time("%s", buf);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun pclose(udhcpc_fp);
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun return NULL;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun //#define USE_DHCLIENT
178*4882a593Smuzhiyun #ifdef USE_DHCLIENT
179*4882a593Smuzhiyun static int dhclient_alive = 0;
180*4882a593Smuzhiyun #endif
181*4882a593Smuzhiyun static int dibbler_client_alive = 0;
182*4882a593Smuzhiyun
ql_set_driver_link_state(PROFILE_T * profile,int link_state)183*4882a593Smuzhiyun void ql_set_driver_link_state(PROFILE_T *profile, int link_state) {
184*4882a593Smuzhiyun char link_file[128];
185*4882a593Smuzhiyun int fd;
186*4882a593Smuzhiyun int new_state = 0;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter);
189*4882a593Smuzhiyun fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY);
190*4882a593Smuzhiyun if (fd == -1) {
191*4882a593Smuzhiyun if (errno != ENOENT)
192*4882a593Smuzhiyun dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno));
193*4882a593Smuzhiyun return;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (profile->qmap_mode <= 1)
197*4882a593Smuzhiyun new_state = !!link_state;
198*4882a593Smuzhiyun else {
199*4882a593Smuzhiyun //0x80 means link off this pdp
200*4882a593Smuzhiyun new_state = (link_state ? 0x00 : 0x80) + (profile->muxid - 0x80);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun snprintf(link_file, sizeof(link_file), "%d\n", new_state);
204*4882a593Smuzhiyun if (write(fd, link_file, sizeof(link_file)) == -1) {};
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun if (link_state == 0 && profile->qmapnet_adapter[0]
207*4882a593Smuzhiyun && strcmp(profile->qmapnet_adapter, profile->usbnet_adapter)) {
208*4882a593Smuzhiyun size_t rc;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun lseek(fd, 0, SEEK_SET);
211*4882a593Smuzhiyun rc = read(fd, link_file, sizeof(link_file));
212*4882a593Smuzhiyun if (rc > 1 && (!strncasecmp(link_file, "0\n", 2) || !strncasecmp(link_file, "0x0\n", 4))) {
213*4882a593Smuzhiyun snprintf(link_file, sizeof(link_file), "ifconfig %s down", profile->usbnet_adapter);
214*4882a593Smuzhiyun ql_system(link_file);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun close(fd);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
ipv4Str(const uint32_t Address)221*4882a593Smuzhiyun static const char *ipv4Str(const uint32_t Address) {
222*4882a593Smuzhiyun static char str[] = {"255.225.255.255"};
223*4882a593Smuzhiyun uint8_t *ip = (uint8_t *)&Address;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun snprintf(str, sizeof(str), "%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]);
226*4882a593Smuzhiyun return str;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
ipv6Str(const UCHAR Address[16])229*4882a593Smuzhiyun static const char *ipv6Str(const UCHAR Address[16]) {
230*4882a593Smuzhiyun static char str[64];
231*4882a593Smuzhiyun uint16_t ip[8];
232*4882a593Smuzhiyun int i;
233*4882a593Smuzhiyun for (i = 0; i < 8; i++) {
234*4882a593Smuzhiyun ip[i] = (Address[i*2]<<8) + Address[i*2+1];
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x:%x:%x",
238*4882a593Smuzhiyun ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun return str;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
update_ipv4_address(const char * ifname,const char * ip,const char * gw,unsigned prefix)243*4882a593Smuzhiyun void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun char shell_cmd[128];
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun if (!ifname)
248*4882a593Smuzhiyun return;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun if (!access("/sbin/ip", X_OK)) {
251*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 4, ifname);
252*4882a593Smuzhiyun ql_system(shell_cmd);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 4, ip, prefix, ifname);
255*4882a593Smuzhiyun ql_system(shell_cmd);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun //ping6 www.qq.com
258*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default via %s dev %s", 4, gw, ifname);
259*4882a593Smuzhiyun ql_system(shell_cmd);
260*4882a593Smuzhiyun } else {
261*4882a593Smuzhiyun unsigned n = (0xFFFFFFFF >> (32 - prefix)) << (32 - prefix);
262*4882a593Smuzhiyun n = (n>>24) | (n>>8&0xff00) | (n<<8&0xff0000) | (n<<24);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s netmask %s", ifname, ip, ipv4Str(n));
265*4882a593Smuzhiyun ql_system(shell_cmd);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun //Resetting default routes
268*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "route del default dev %s", ifname);
269*4882a593Smuzhiyun while(!system(shell_cmd));
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "route add default gw %s dev %s", gw, ifname);
272*4882a593Smuzhiyun ql_system(shell_cmd);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
update_ipv6_address(const char * ifname,const char * ip,const char * gw,unsigned prefix)276*4882a593Smuzhiyun void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix) {
277*4882a593Smuzhiyun char shell_cmd[128];
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun (void)gw;
280*4882a593Smuzhiyun if (!access("/sbin/ip", X_OK)) {
281*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 6, ifname);
282*4882a593Smuzhiyun ql_system(shell_cmd);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 6, ip, prefix, ifname);
285*4882a593Smuzhiyun ql_system(shell_cmd);
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun //ping6 www.qq.com
288*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default dev %s", 6, ifname);
289*4882a593Smuzhiyun ql_system(shell_cmd);
290*4882a593Smuzhiyun } else {
291*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s/%d", ifname, ip, prefix);
292*4882a593Smuzhiyun ql_system(shell_cmd);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default dev %s", ifname);
295*4882a593Smuzhiyun ql_system(shell_cmd);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
update_ip_address_by_qmi(const char * ifname,const IPV4_T * ipv4,const IPV6_T * ipv6)299*4882a593Smuzhiyun static void update_ip_address_by_qmi(const char *ifname, const IPV4_T *ipv4, const IPV6_T *ipv6) {
300*4882a593Smuzhiyun char *d1, *d2;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun if (ipv4 && ipv4->Address) {
303*4882a593Smuzhiyun d1 = strdup(ipv4Str(ipv4->Address));
304*4882a593Smuzhiyun d2 = strdup(ipv4Str(ipv4->Gateway));
305*4882a593Smuzhiyun unsigned prefix = 0;
306*4882a593Smuzhiyun unsigned n = 0;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun for (n = 0; n < 32; n++) {
309*4882a593Smuzhiyun if (ipv4->SubnetMask&(1<<n)) {
310*4882a593Smuzhiyun prefix++;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun update_ipv4_address(ifname, d1, d2, prefix);
315*4882a593Smuzhiyun free(d1); free(d2);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun //Adding DNS
318*4882a593Smuzhiyun if (ipv4->DnsPrimary) {
319*4882a593Smuzhiyun d1 = strdup(ipv4Str(ipv4->DnsPrimary));
320*4882a593Smuzhiyun d2 = strdup(ipv4Str(ipv4->DnsSecondary ? ipv4->DnsSecondary : ipv4->DnsPrimary));
321*4882a593Smuzhiyun update_resolv_conf(4, ifname, d1, d2);
322*4882a593Smuzhiyun free(d1); free(d2);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun if (ipv6 && ipv6->Address[0] && ipv6->PrefixLengthIPAddr) {
327*4882a593Smuzhiyun d1 = strdup(ipv6Str(ipv6->Address));
328*4882a593Smuzhiyun d2 = strdup(ipv6Str(ipv6->Gateway));
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun update_ipv6_address(ifname, d1, d2, ipv6->PrefixLengthIPAddr);
331*4882a593Smuzhiyun free(d1); free(d2);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun //Adding DNS
334*4882a593Smuzhiyun if (ipv6->DnsPrimary[0]) {
335*4882a593Smuzhiyun d1 = strdup(ipv6Str(ipv6->DnsPrimary));
336*4882a593Smuzhiyun d2 = strdup(ipv6Str(ipv6->DnsSecondary[0] ? ipv6->DnsSecondary : ipv6->DnsPrimary));
337*4882a593Smuzhiyun update_resolv_conf(6, ifname, d1, d2);
338*4882a593Smuzhiyun free(d1); free(d2);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun //#define QL_OPENWER_NETWORK_SETUP
344*4882a593Smuzhiyun #ifdef QL_OPENWER_NETWORK_SETUP
345*4882a593Smuzhiyun static const char *openwrt_lan = "br-lan";
346*4882a593Smuzhiyun static const char *openwrt_wan = "wwan0";
347*4882a593Smuzhiyun
ql_openwrt_system(const char * cmd)348*4882a593Smuzhiyun static int ql_openwrt_system(const char *cmd) {
349*4882a593Smuzhiyun int i;
350*4882a593Smuzhiyun int ret = 1;
351*4882a593Smuzhiyun char shell_cmd[128];
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "%s 2>1 > /dev/null", cmd);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun for (i = 0; i < 15; i++) {
356*4882a593Smuzhiyun dbg_time("%s", cmd);
357*4882a593Smuzhiyun ret = system(shell_cmd);
358*4882a593Smuzhiyun if (!ret)
359*4882a593Smuzhiyun break;
360*4882a593Smuzhiyun sleep(1);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun return ret;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
ql_openwrt_is_wan(const char * ifname)366*4882a593Smuzhiyun static int ql_openwrt_is_wan(const char *ifname) {
367*4882a593Smuzhiyun if (openwrt_lan == NULL) {
368*4882a593Smuzhiyun system("uci show network.wan.ifname");
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun if (strcmp(ifname, openwrt_wan))
372*4882a593Smuzhiyun return 0;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun return 1;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
ql_openwrt_setup_wan(const char * ifname,const IPV4_T * ipv4)377*4882a593Smuzhiyun static void ql_openwrt_setup_wan(const char *ifname, const IPV4_T *ipv4) {
378*4882a593Smuzhiyun FILE *fp = NULL;
379*4882a593Smuzhiyun char config[64];
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv4config", ifname);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (ipv4 == NULL) {
384*4882a593Smuzhiyun if (ql_openwrt_is_wan(ifname))
385*4882a593Smuzhiyun ql_openwrt_system("ifdown wan");
386*4882a593Smuzhiyun return;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun fp = fopen(config, "w");
390*4882a593Smuzhiyun if (fp == NULL)
391*4882a593Smuzhiyun return;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun fprintf(fp, "IFNAME=\"%s\"\n", ifname);
394*4882a593Smuzhiyun fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv4Str(ipv4->Address));
395*4882a593Smuzhiyun fprintf(fp, "NETMASK=\"%s\"\n", ipv4Str(ipv4->SubnetMask));
396*4882a593Smuzhiyun fprintf(fp, "GATEWAY=\"%s\"\n", ipv4Str(ipv4->Gateway));
397*4882a593Smuzhiyun fprintf(fp, "DNSSERVERS=\"%s", ipv4Str(ipv4->DnsPrimary));
398*4882a593Smuzhiyun if (ipv4->DnsSecondary != 0)
399*4882a593Smuzhiyun fprintf(fp, " %s", ipv4Str(ipv4->DnsSecondary));
400*4882a593Smuzhiyun fprintf(fp, "\"\n");
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun fclose(fp);
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (!ql_openwrt_is_wan(ifname))
405*4882a593Smuzhiyun return;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun ql_openwrt_system("ifup wan");
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
ql_openwrt_setup_wan6(const char * ifname,const IPV6_T * ipv6)410*4882a593Smuzhiyun static void ql_openwrt_setup_wan6(const char *ifname, const IPV6_T *ipv6) {
411*4882a593Smuzhiyun FILE *fp = NULL;
412*4882a593Smuzhiyun char config[64];
413*4882a593Smuzhiyun int first_ifup;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv6config", ifname);
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (ipv6 == NULL) {
418*4882a593Smuzhiyun if (ql_openwrt_is_wan(ifname))
419*4882a593Smuzhiyun ql_openwrt_system("ifdown wan6");
420*4882a593Smuzhiyun return;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun first_ifup = (access(config, F_OK) != 0);
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun fp = fopen(config, "w");
426*4882a593Smuzhiyun if (fp == NULL)
427*4882a593Smuzhiyun return;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun fprintf(fp, "IFNAME=\"%s\"\n", ifname);
430*4882a593Smuzhiyun fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv6Str(ipv6->Address));
431*4882a593Smuzhiyun fprintf(fp, "NETMASK=\"%s\"\n", ipv6Str(ipv6->SubnetMask));
432*4882a593Smuzhiyun fprintf(fp, "GATEWAY=\"%s\"\n", ipv6Str(ipv6->Gateway));
433*4882a593Smuzhiyun fprintf(fp, "PrefixLength=\"%d\"\n", ipv6->PrefixLengthIPAddr);
434*4882a593Smuzhiyun fprintf(fp, "DNSSERVERS=\"%s", ipv6Str(ipv6->DnsPrimary));
435*4882a593Smuzhiyun if (ipv6->DnsSecondary[0])
436*4882a593Smuzhiyun fprintf(fp, " %s", ipv6Str(ipv6->DnsSecondary));
437*4882a593Smuzhiyun fprintf(fp, "\"\n");
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun fclose(fp);
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun if (!ql_openwrt_is_wan(ifname))
442*4882a593Smuzhiyun return;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (first_ifup)
445*4882a593Smuzhiyun ql_openwrt_system("ifup wan6");
446*4882a593Smuzhiyun else
447*4882a593Smuzhiyun ql_openwrt_system("/etc/init.d/network restart"); //make PC to release old IPV6 address, and RS new IPV6 address
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun #if 1 //TODO? why need this?
450*4882a593Smuzhiyun if (openwrt_lan) {
451*4882a593Smuzhiyun int i;
452*4882a593Smuzhiyun char shell_cmd[128];
453*4882a593Smuzhiyun UCHAR Address[16] = {0};
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun ql_openwrt_system(("ifstatus lan"));
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun for (i = 0; i < (ipv6->PrefixLengthIPAddr/8); i++)
458*4882a593Smuzhiyun Address[i] = ipv6->Address[i];
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip route del %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, ifname);
461*4882a593Smuzhiyun ql_openwrt_system(shell_cmd);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ip route add %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, openwrt_lan);
464*4882a593Smuzhiyun ql_system(shell_cmd);
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun #endif
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun #endif
469*4882a593Smuzhiyun
udhcpc_start(PROFILE_T * profile)470*4882a593Smuzhiyun void udhcpc_start(PROFILE_T *profile) {
471*4882a593Smuzhiyun char *ifname = profile->usbnet_adapter;
472*4882a593Smuzhiyun char shell_cmd[128];
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun ql_set_driver_link_state(profile, 1);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun if (profile->qmapnet_adapter[0]) {
477*4882a593Smuzhiyun ifname = profile->qmapnet_adapter;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) {
481*4882a593Smuzhiyun ql_set_mtu(ifname, (profile->ipv4.Mtu));
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun if (strcmp(ifname, profile->usbnet_adapter)) {
485*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", profile->usbnet_adapter);
486*4882a593Smuzhiyun ql_system(shell_cmd);
487*4882a593Smuzhiyun if (ifc_get_flags(ifname)&IFF_UP) {
488*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname);
489*4882a593Smuzhiyun ql_system(shell_cmd);
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname);
494*4882a593Smuzhiyun ql_system(shell_cmd);
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun if (profile->ipv4.Address) {
497*4882a593Smuzhiyun if (profile->PCSCFIpv4Addr1)
498*4882a593Smuzhiyun dbg_time("pcscf1: %s", ipv4Str(profile->PCSCFIpv4Addr1));
499*4882a593Smuzhiyun if (profile->PCSCFIpv4Addr2)
500*4882a593Smuzhiyun dbg_time("pcscf2: %s", ipv4Str(profile->PCSCFIpv4Addr2));
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) {
504*4882a593Smuzhiyun if (profile->PCSCFIpv6Addr1[0])
505*4882a593Smuzhiyun dbg_time("pcscf1: %s", ipv6Str(profile->PCSCFIpv6Addr1));
506*4882a593Smuzhiyun if (profile->PCSCFIpv6Addr2[0])
507*4882a593Smuzhiyun dbg_time("pcscf2: %s", ipv6Str(profile->PCSCFIpv6Addr2));
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun #if 1 //for bridge mode, only one public IP, so do udhcpc manually
511*4882a593Smuzhiyun if (ql_bridge_mode_detect(profile)) {
512*4882a593Smuzhiyun return;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun #endif
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun //because must use udhcpc to obtain IP when working on ETH mode,
517*4882a593Smuzhiyun //so it is better also use udhcpc to obtain IP when working on IP mode.
518*4882a593Smuzhiyun //use the same policy for all modules
519*4882a593Smuzhiyun #if 0
520*4882a593Smuzhiyun if (profile->rawIP != 0) //mdm9x07/ec25,ec20 R2.0
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun update_ip_address_by_qmi(ifname, &profile->ipv4, &profile->ipv6);
523*4882a593Smuzhiyun return;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun #endif
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (profile->ipv4.Address == 0)
528*4882a593Smuzhiyun goto set_ipv6;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun if (profile->request_ops == &mbim_request_ops) { //lots of mbim modem do not support DHCP
531*4882a593Smuzhiyun update_ip_address_by_qmi(ifname, &profile->ipv4, NULL);
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun else
534*4882a593Smuzhiyun /* Do DHCP using busybox tools */
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun char udhcpc_cmd[128];
537*4882a593Smuzhiyun pthread_attr_t udhcpc_thread_attr;
538*4882a593Smuzhiyun pthread_t udhcpc_thread_id;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun pthread_attr_init(&udhcpc_thread_attr);
541*4882a593Smuzhiyun pthread_attr_setdetachstate(&udhcpc_thread_attr, PTHREAD_CREATE_DETACHED);
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun #ifdef USE_DHCLIENT
544*4882a593Smuzhiyun snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -4 -d --no-pid %s", ifname);
545*4882a593Smuzhiyun dhclient_alive++;
546*4882a593Smuzhiyun #else
547*4882a593Smuzhiyun if (access("/usr/share/udhcpc/default.script", X_OK)
548*4882a593Smuzhiyun && access("/etc//udhcpc/default.script", X_OK)) {
549*4882a593Smuzhiyun dbg_time("No default.script found, it should be in '/usr/share/udhcpc/' or '/etc//udhcpc' depend on your udhcpc version!");
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun //-f,--foreground Run in foreground
553*4882a593Smuzhiyun //-b,--background Background if lease is not obtained
554*4882a593Smuzhiyun //-n,--now Exit if lease is not obtained
555*4882a593Smuzhiyun //-q,--quit Exit after obtaining lease
556*4882a593Smuzhiyun //-t,--retries N Send up to N discover packets (default 3)
557*4882a593Smuzhiyun snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "busybox udhcpc -f -n -q -t 5 -i %s", ifname);
558*4882a593Smuzhiyun #endif
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun #if 1 //for OpenWrt
561*4882a593Smuzhiyun if (!access("/lib/netifd/dhcp.script", X_OK) && !access("/sbin/ifup", X_OK) && !access("/sbin/ifstatus", X_OK)) {
562*4882a593Smuzhiyun dbg_time("you are use OpenWrt?");
563*4882a593Smuzhiyun dbg_time("should not calling udhcpc manually?");
564*4882a593Smuzhiyun dbg_time("should modify /etc/config/network as below?");
565*4882a593Smuzhiyun dbg_time("config interface wan");
566*4882a593Smuzhiyun dbg_time("\toption ifname %s", ifname);
567*4882a593Smuzhiyun dbg_time("\toption proto dhcp");
568*4882a593Smuzhiyun dbg_time("should use \"/sbin/ifstaus wan\" to check %s 's status?", ifname);
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun #endif
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun #ifdef USE_DHCLIENT
573*4882a593Smuzhiyun pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd));
574*4882a593Smuzhiyun sleep(1);
575*4882a593Smuzhiyun #else
576*4882a593Smuzhiyun pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd));
577*4882a593Smuzhiyun pthread_join(udhcpc_thread_id, NULL);
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun if (profile->request_ops != &qmi_request_ops) { //only QMI modem support next fixup!
580*4882a593Smuzhiyun goto set_ipv6;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun if (ql_raw_ip_mode_check(ifname, profile->ipv4.Address)) {
584*4882a593Smuzhiyun pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd));
585*4882a593Smuzhiyun pthread_join(udhcpc_thread_id, NULL);
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun if (!ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) {
589*4882a593Smuzhiyun //no udhcpc's default.script exist, directly set ip and dns
590*4882a593Smuzhiyun update_ip_address_by_qmi(ifname, &profile->ipv4, NULL);
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun #endif
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun #ifdef QL_OPENWER_NETWORK_SETUP
596*4882a593Smuzhiyun ql_openwrt_setup_wan(ifname, &profile->ipv4);
597*4882a593Smuzhiyun #endif
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun set_ipv6:
600*4882a593Smuzhiyun if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) {
601*4882a593Smuzhiyun #if 1
602*4882a593Smuzhiyun //module do not support DHCPv6, only support 'Router Solicit'
603*4882a593Smuzhiyun //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS
604*4882a593Smuzhiyun const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
605*4882a593Smuzhiyun int forward_fd = open(forward_file, O_RDONLY);
606*4882a593Smuzhiyun if (forward_fd > 0) {
607*4882a593Smuzhiyun char forward_state[2];
608*4882a593Smuzhiyun if (read(forward_fd, forward_state, 2) == -1) {};
609*4882a593Smuzhiyun if (forward_state[0] == '1') {
610*4882a593Smuzhiyun //dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun close(forward_fd);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun update_ip_address_by_qmi(ifname, NULL, &profile->ipv6);
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun if (profile->ipv6.DnsPrimary[0] || profile->ipv6.DnsSecondary[0]) {
618*4882a593Smuzhiyun char dns1str[64], dns2str[64];
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun if (profile->ipv6.DnsPrimary[0]) {
621*4882a593Smuzhiyun strcpy(dns1str, ipv6Str(profile->ipv6.DnsPrimary));
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun if (profile->ipv6.DnsSecondary[0]) {
625*4882a593Smuzhiyun strcpy(dns2str, ipv6Str(profile->ipv6.DnsSecondary));
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun update_resolv_conf(6, ifname, profile->ipv6.DnsPrimary[0] ? dns1str : NULL,
629*4882a593Smuzhiyun profile->ipv6.DnsSecondary[0] != '\0' ? dns2str : NULL);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun #ifdef QL_OPENWER_NETWORK_SETUP
633*4882a593Smuzhiyun ql_openwrt_setup_wan6(ifname, &profile->ipv6);
634*4882a593Smuzhiyun #endif
635*4882a593Smuzhiyun #else
636*4882a593Smuzhiyun #ifdef USE_DHCLIENT
637*4882a593Smuzhiyun snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -6 -d --no-pid %s", ifname);
638*4882a593Smuzhiyun dhclient_alive++;
639*4882a593Smuzhiyun #else
640*4882a593Smuzhiyun /*
641*4882a593Smuzhiyun DHCPv6: Dibbler - a portable DHCPv6
642*4882a593Smuzhiyun 1. download from http://klub.com.pl/dhcpv6/
643*4882a593Smuzhiyun 2. cross-compile
644*4882a593Smuzhiyun 2.1 ./configure --host=arm-linux-gnueabihf
645*4882a593Smuzhiyun 2.2 copy dibbler-client to your board
646*4882a593Smuzhiyun 3. mkdir -p /var/log/dibbler/ /var/lib/ on your board
647*4882a593Smuzhiyun 4. create /etc/dibbler/client.conf on your board, the content is
648*4882a593Smuzhiyun log-mode short
649*4882a593Smuzhiyun log-level 7
650*4882a593Smuzhiyun iface wwan0 {
651*4882a593Smuzhiyun ia
652*4882a593Smuzhiyun option dns-server
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun 5. run "dibbler-client start" to get ipV6 address
655*4882a593Smuzhiyun 6. run "route -A inet6 add default dev wwan0" to add default route
656*4882a593Smuzhiyun */
657*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default %s", ifname);
658*4882a593Smuzhiyun ql_system(shell_cmd);
659*4882a593Smuzhiyun snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dibbler-client run");
660*4882a593Smuzhiyun dibbler_client_alive++;
661*4882a593Smuzhiyun #endif
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd));
664*4882a593Smuzhiyun #endif
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun
udhcpc_stop(PROFILE_T * profile)668*4882a593Smuzhiyun void udhcpc_stop(PROFILE_T *profile) {
669*4882a593Smuzhiyun char *ifname = profile->usbnet_adapter;
670*4882a593Smuzhiyun char shell_cmd[128];
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun ql_set_driver_link_state(profile, 0);
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun if (profile->qmapnet_adapter[0]) {
675*4882a593Smuzhiyun ifname = profile->qmapnet_adapter;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun #ifdef USE_DHCLIENT
679*4882a593Smuzhiyun if (dhclient_alive) {
680*4882a593Smuzhiyun system("killall dhclient");
681*4882a593Smuzhiyun dhclient_alive = 0;
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun #endif
684*4882a593Smuzhiyun if (dibbler_client_alive) {
685*4882a593Smuzhiyun if (system("killall dibbler-client")) {};
686*4882a593Smuzhiyun dibbler_client_alive = 0;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun //it seems when call netif_carrier_on(), and netcard 's IP is "0.0.0.0", will cause netif_queue_stopped()
690*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s 0.0.0.0", ifname);
691*4882a593Smuzhiyun ql_system(shell_cmd);
692*4882a593Smuzhiyun snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname);
693*4882a593Smuzhiyun ql_system(shell_cmd);
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun #ifdef QL_OPENWER_NETWORK_SETUP
696*4882a593Smuzhiyun ql_openwrt_setup_wan(ifname, NULL);
697*4882a593Smuzhiyun ql_openwrt_setup_wan6(ifname, NULL);
698*4882a593Smuzhiyun #endif
699*4882a593Smuzhiyun }
700