xref: /OK3568_Linux_fs/app/forlinx/quectelCM/udhcpc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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