1 /******************************************************************************
2 @file udhcpc.c
3 @brief call DHCP tools to obtain IP address.
4
5 DESCRIPTION
6 Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules.
7
8 INITIALIZATION AND SEQUENCING REQUIREMENTS
9 None.
10
11 ---------------------------------------------------------------------------
12 Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
13 Quectel Wireless Solution Proprietary and Confidential.
14 ---------------------------------------------------------------------------
15 ******************************************************************************/
16 #include <sys/socket.h>
17 #include <sys/select.h>
18 #include <sys/types.h>
19 #include <net/if.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <endian.h>
24
25 #include "util.h"
26 #include "QMIThread.h"
27
28 #define IFDOWN_SCRIPT "/etc/quectel/ifdown.sh"
29 #define IFUP_SCRIPT "/etc/quectel/ifup.sh"
30
ql_system(const char * shell_cmd)31 static int ql_system(const char *shell_cmd)
32 {
33 dbg_time("%s", shell_cmd);
34 return system(shell_cmd);
35 }
36
mask_to_prefix_v4(uint32_t mask)37 uint32_t mask_to_prefix_v4(uint32_t mask)
38 {
39 uint32_t prefix = 0;
40 while (mask)
41 {
42 mask = mask & (mask - 1);
43 prefix++;
44 }
45 return prefix;
46 }
47
mask_from_prefix_v4(uint32_t prefix)48 uint32_t mask_from_prefix_v4(uint32_t prefix)
49 {
50 return ~((1 << (32 - prefix)) - 1);
51 }
52
53 /* mask in int */
broadcast_from_mask(uint32_t ip,uint32_t mask)54 uint32_t broadcast_from_mask(uint32_t ip, uint32_t mask)
55 {
56 return (ip & mask) | (~mask);
57 }
58
ipaddr_to_string_v4(in_addr_t ipaddr,char * buf,size_t size)59 const char *ipaddr_to_string_v4(in_addr_t ipaddr, char *buf, size_t size)
60 {
61 // static char buf[INET6_ADDRSTRLEN] = {'\0'};
62 buf[0] = '\0';
63 uint32_t addr = ipaddr;
64 return inet_ntop(AF_INET, &addr, buf, size);
65 }
66
ipaddr_to_string_v6(uint8_t * ipaddr,char * buf,size_t size)67 const char *ipaddr_to_string_v6(uint8_t *ipaddr, char *buf, size_t size)
68 {
69 buf[0] = '\0';
70 return inet_ntop(AF_INET6, ipaddr, buf, size);
71 }
72
73 /**
74 * For more details see default.script
75 *
76 * The main aim of this function is offload ip management to script, CM has not interest in manage IP address.
77 * just tell script all the info about ip, mask, router, dns...
78 */
udhcpc_start(PROFILE_T * profile)79 void udhcpc_start(PROFILE_T *profile)
80 {
81 char shell_cmd[1024];
82 char ip[128];
83 char subnet[128];
84 char broadcast[128];
85 char router[128];
86 char domain1[128];
87 char domain2[128];
88
89 if (NULL == getenv(IFUP_SCRIPT))
90 return;
91
92 // manage IPv4???
93 // check rawip ???
94 snprintf(shell_cmd, sizeof(shell_cmd),
95 " netiface=%s interface=%s mtu=%u ip=%s subnet=%s broadcast=%s router=%s"
96 " domain=\"%s %s\" %s",
97 profile->usbnet_adapter,
98 profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter,
99 profile->ipv4.Mtu,
100 ipaddr_to_string_v4(ntohl(profile->ipv4.Address), ip, sizeof(ip)),
101 ipaddr_to_string_v4(ntohl(profile->ipv4.SubnetMask), subnet, sizeof(subnet)),
102 ipaddr_to_string_v4(ntohl(broadcast_from_mask(profile->ipv4.Address, profile->ipv4.SubnetMask)),
103 broadcast, sizeof(broadcast)),
104 ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway), router, sizeof(router)),
105 ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary), domain1, sizeof(domain1)),
106 ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary), domain2, sizeof(domain2)),
107 getenv(IFUP_SCRIPT));
108 ql_system(shell_cmd);
109
110 // manage IPv6???
111 }
112
113 /**
114 * For more details see default.script
115 *
116 * The main aim of this function is offload ip management to script, CM has not interest in manage IP address.
117 * just tell script all the info about ip, mask, router, dns...
118 */
udhcpc_stop(PROFILE_T * profile)119 void udhcpc_stop(PROFILE_T *profile)
120 {
121 char shell_cmd[1024];
122
123 if (NULL == getenv(IFDOWN_SCRIPT))
124 return;
125
126 snprintf(shell_cmd, sizeof(shell_cmd),
127 "netiface=%s interface=%s %s",
128 profile->usbnet_adapter,
129 profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter,
130 getenv(IFDOWN_SCRIPT));
131 ql_system(shell_cmd);
132 }
133