xref: /OK3568_Linux_fs/app/forlinx/quectelCM/udhcpc_netlink.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun #include <sys/socket.h>
2*4882a593Smuzhiyun #include <sys/select.h>
3*4882a593Smuzhiyun #include <sys/types.h>
4*4882a593Smuzhiyun #include <net/if.h>
5*4882a593Smuzhiyun #include <sys/socket.h>
6*4882a593Smuzhiyun #include <netinet/in.h>
7*4882a593Smuzhiyun #include <arpa/inet.h>
8*4882a593Smuzhiyun #include <endian.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include "libmnl/ifutils.h"
11*4882a593Smuzhiyun #include "libmnl/dhcp/dhcp.h"
12*4882a593Smuzhiyun #include "util.h"
13*4882a593Smuzhiyun #include "QMIThread.h"
14*4882a593Smuzhiyun 
ql_raw_ip_mode_check(const char * ifname)15*4882a593Smuzhiyun static int ql_raw_ip_mode_check(const char *ifname)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun     int fd;
18*4882a593Smuzhiyun     char raw_ip[128];
19*4882a593Smuzhiyun     char mode[2] = "X";
20*4882a593Smuzhiyun     int mode_change = 0;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun     snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname);
23*4882a593Smuzhiyun     if (access(raw_ip, F_OK))
24*4882a593Smuzhiyun         return 0;
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun     fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY);
27*4882a593Smuzhiyun     if (fd < 0)
28*4882a593Smuzhiyun     {
29*4882a593Smuzhiyun         dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno));
30*4882a593Smuzhiyun         return 0;
31*4882a593Smuzhiyun     }
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun     read(fd, mode, 2);
34*4882a593Smuzhiyun     if (mode[0] == '0' || mode[0] == 'N')
35*4882a593Smuzhiyun     {
36*4882a593Smuzhiyun         if_link_down(ifname);
37*4882a593Smuzhiyun         dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
38*4882a593Smuzhiyun         mode[0] = 'Y';
39*4882a593Smuzhiyun         write(fd, mode, 2);
40*4882a593Smuzhiyun         mode_change = 1;
41*4882a593Smuzhiyun         if_link_up(ifname);
42*4882a593Smuzhiyun     }
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun     close(fd);
45*4882a593Smuzhiyun     return mode_change;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
ql_set_driver_link_state(PROFILE_T * profile,int link_state)48*4882a593Smuzhiyun void ql_set_driver_link_state(PROFILE_T *profile, int link_state)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun     char link_file[128];
51*4882a593Smuzhiyun     int fd;
52*4882a593Smuzhiyun     int new_state = 0;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun     snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter);
55*4882a593Smuzhiyun     fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY);
56*4882a593Smuzhiyun     if (fd == -1)
57*4882a593Smuzhiyun     {
58*4882a593Smuzhiyun         if (errno != ENOENT)
59*4882a593Smuzhiyun             dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno));
60*4882a593Smuzhiyun         return;
61*4882a593Smuzhiyun     }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun     if (profile->qmap_mode <= 1)
64*4882a593Smuzhiyun         new_state = !!link_state;
65*4882a593Smuzhiyun     else
66*4882a593Smuzhiyun     {
67*4882a593Smuzhiyun         //0x80 means link off this pdp
68*4882a593Smuzhiyun         new_state = (link_state ? 0x00 : 0x80) + profile->pdp;
69*4882a593Smuzhiyun     }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun     snprintf(link_file, sizeof(link_file), "%d\n", new_state);
72*4882a593Smuzhiyun     write(fd, link_file, sizeof(link_file));
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun     if (link_state == 0 && profile->qmap_mode > 1)
75*4882a593Smuzhiyun     {
76*4882a593Smuzhiyun         size_t rc;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun         lseek(fd, 0, SEEK_SET);
79*4882a593Smuzhiyun         rc = read(fd, link_file, sizeof(link_file));
80*4882a593Smuzhiyun         if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n")))
81*4882a593Smuzhiyun         {
82*4882a593Smuzhiyun             if_link_down(profile->usbnet_adapter);
83*4882a593Smuzhiyun         }
84*4882a593Smuzhiyun     }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun     close(fd);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
udhcpc_start(PROFILE_T * profile)89*4882a593Smuzhiyun void udhcpc_start(PROFILE_T *profile)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun     char *ifname = profile->usbnet_adapter;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun     ql_set_driver_link_state(profile, 1);
94*4882a593Smuzhiyun     ql_raw_ip_mode_check(ifname);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     if (profile->qmapnet_adapter)
97*4882a593Smuzhiyun     {
98*4882a593Smuzhiyun         ifname = profile->qmapnet_adapter;
99*4882a593Smuzhiyun     }
100*4882a593Smuzhiyun     if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu)
101*4882a593Smuzhiyun     {
102*4882a593Smuzhiyun         if_set_mtu(ifname, (profile->ipv4.Mtu));
103*4882a593Smuzhiyun     }
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     if (strcmp(ifname, profile->usbnet_adapter))
106*4882a593Smuzhiyun     {
107*4882a593Smuzhiyun         if_link_up(profile->usbnet_adapter);
108*4882a593Smuzhiyun     }
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun     if_link_up(ifname);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun #if 1 //for bridge mode, only one public IP, so do udhcpc manually
113*4882a593Smuzhiyun     if (ql_bridge_mode_detect(profile))
114*4882a593Smuzhiyun     {
115*4882a593Smuzhiyun         return;
116*4882a593Smuzhiyun     }
117*4882a593Smuzhiyun #endif
118*4882a593Smuzhiyun     // if use DHCP(should make with ${DHCP} src files)
119*4882a593Smuzhiyun     // do_dhcp(ifname);
120*4882a593Smuzhiyun     // return 0;
121*4882a593Smuzhiyun     /* IPv4 Addr Info */
122*4882a593Smuzhiyun     if (profile->ipv4.Address)
123*4882a593Smuzhiyun     {
124*4882a593Smuzhiyun         dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu);
125*4882a593Smuzhiyun         dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address)));
126*4882a593Smuzhiyun         dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask)));
127*4882a593Smuzhiyun         dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway)));
128*4882a593Smuzhiyun         dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary)));
129*4882a593Smuzhiyun         dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary)));
130*4882a593Smuzhiyun         if_set_network_v4(ifname, ntohl(profile->ipv4.Address),
131*4882a593Smuzhiyun                        mask_to_prefix_v4(profile->ipv4.SubnetMask),
132*4882a593Smuzhiyun                        ntohl(profile->ipv4.Gateway),
133*4882a593Smuzhiyun                        ntohl(profile->ipv4.DnsPrimary),
134*4882a593Smuzhiyun                        ntohl(profile->ipv4.DnsSecondary));
135*4882a593Smuzhiyun     }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr)
138*4882a593Smuzhiyun     {
139*4882a593Smuzhiyun         //module do not support DHCPv6, only support 'Router Solicit'
140*4882a593Smuzhiyun         //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS
141*4882a593Smuzhiyun         const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
142*4882a593Smuzhiyun         int forward_fd = open(forward_file, O_RDONLY);
143*4882a593Smuzhiyun         if (forward_fd > 0)
144*4882a593Smuzhiyun         {
145*4882a593Smuzhiyun             char forward_state[2];
146*4882a593Smuzhiyun             read(forward_fd, forward_state, 2);
147*4882a593Smuzhiyun             if (forward_state[0] == '1')
148*4882a593Smuzhiyun             {
149*4882a593Smuzhiyun                 dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file);
150*4882a593Smuzhiyun             }
151*4882a593Smuzhiyun             close(forward_fd);
152*4882a593Smuzhiyun         }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun         dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu);
155*4882a593Smuzhiyun         dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address));
156*4882a593Smuzhiyun         dbg_time("IPv6 Netmask: %d", profile->ipv6.PrefixLengthIPAddr);
157*4882a593Smuzhiyun         dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway));
158*4882a593Smuzhiyun         dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary));
159*4882a593Smuzhiyun         dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary));
160*4882a593Smuzhiyun         if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr,
161*4882a593Smuzhiyun                        profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary);
162*4882a593Smuzhiyun     }
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
udhcpc_stop(PROFILE_T * profile)165*4882a593Smuzhiyun void udhcpc_stop(PROFILE_T *profile)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun     char *ifname = profile->usbnet_adapter;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     ql_set_driver_link_state(profile, 0);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     if (profile->qmapnet_adapter)
172*4882a593Smuzhiyun     {
173*4882a593Smuzhiyun         ifname = profile->qmapnet_adapter;
174*4882a593Smuzhiyun     }
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun     if_link_down(ifname);
177*4882a593Smuzhiyun     if_flush_v4_addr(ifname);
178*4882a593Smuzhiyun     if_flush_v6_addr(ifname);
179*4882a593Smuzhiyun }
180