1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "dhcp_function.h"
16 #include <arpa/inet.h>
17 #include <sys/time.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <cstdlib>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 #include <ifaddrs.h>
26 #include <netdb.h>
27 #include <net/if.h>
28 #include <cstdio>
29 #include <cerrno>
30 #include <netinet/in.h>
31 #include <sys/ioctl.h>
32 #include "securec.h"
33 #include "dhcp_client_def.h"
34 #include "dhcp_logger.h"
35
36 DEFINE_DHCPLOG_DHCP_LABEL("DhcpFunction");
37
Ip4StrConToInt(const char * strIp,uint32_t * uIp,bool bHost)38 bool Ip4StrConToInt(const char *strIp, uint32_t *uIp, bool bHost)
39 {
40 if ((strIp == NULL) || (strlen(strIp) == 0)) {
41 DHCP_LOGE("Ip4StrConToInt failed, strIp == NULL or \"\"!");
42 return false;
43 }
44
45 struct in_addr addr4;
46 int nRet = inet_pton(AF_INET, strIp, &addr4);
47 if (nRet != 1) {
48 DHCP_LOGE("Ip4StrConToInt strIp:%{private}s failed, inet_pton nRet:%{public}d!", strIp, nRet);
49 if (nRet == 0) {
50 DHCP_LOGE("Ip4StrConToInt strIp:%{private}s not in presentation format!", strIp);
51 } else {
52 DHCP_LOGE("Ip4StrConToInt strIp:%{private}s inet_pton does not contain a valid address family!", strIp);
53 }
54 return false;
55 }
56
57 if (bHost) {
58 *uIp = ntohl(addr4.s_addr);
59 } else {
60 *uIp = addr4.s_addr;
61 }
62
63 return true;
64 }
65
Ip6StrConToChar(const char * strIp,uint8_t chIp[],size_t chlen)66 bool Ip6StrConToChar(const char *strIp, uint8_t chIp[], size_t chlen)
67 {
68 if ((strIp == NULL) || (strlen(strIp) == 0)) {
69 DHCP_LOGE("Ip6StrConToChar failed, strIp == NULL or \"\"!");
70 return false;
71 }
72
73 struct in6_addr addr6;
74 if (memset_s(&addr6, sizeof(addr6), 0, sizeof(addr6)) != EOK) {
75 return false;
76 }
77 int nRet = inet_pton(AF_INET6, strIp, &addr6);
78 if (nRet != 1) {
79 DHCP_LOGE("Ip6StrConToChar strIp:%{private}s failed, inet_pton nRet:%{public}d!", strIp, nRet);
80 if (nRet == 0) {
81 DHCP_LOGE("Ip6StrConToChar strIp:%{private}s not in presentation format!", strIp);
82 } else {
83 DHCP_LOGE("Ip6StrConToChar strIp:%{private}s inet_pton does not contain a valid address family!", strIp);
84 }
85 return false;
86 }
87
88 DHCP_LOGI("Ip6StrConToChar strIp:%{private}s -> ", strIp);
89 for (size_t i = 0; (i < chlen) && (i < sizeof(addr6.s6_addr)); i++) {
90 DHCP_LOGI("Ip6StrConToChar addr6.s6_addr: %{private}zu - %{private}02x", i, addr6.s6_addr[i]);
91 chIp[i] = addr6.s6_addr[i];
92 }
93
94 return true;
95 }
96
MacChConToMacStr(const unsigned char * pChMac,size_t chLen,char * pStrMac,size_t strLen)97 const char *MacChConToMacStr(const unsigned char *pChMac, size_t chLen, char *pStrMac, size_t strLen)
98 {
99 if ((pChMac == NULL) || (chLen == 0)) {
100 DHCP_LOGE("MacChConToMacStr failed, pChMac == NULL or chLen == 0!");
101 return NULL;
102 }
103
104 if ((pStrMac == NULL) || (strLen < (chLen * MAC_ADDR_CHAR_NUM))) {
105 DHCP_LOGE("MacChConToMacStr failed, pStrMac == NULL or strLen:%{public}d error!", (int)strLen);
106 return NULL;
107 }
108
109 const unsigned char *pSrc = pChMac;
110 const unsigned char *pSrcEnd = pSrc + chLen;
111 char *pDest = pStrMac;
112 for (; pSrc < pSrcEnd; pSrc++) {
113 /* The first character of pStrMac starts with a letter, not ':'. */
114 if (pSrc != pChMac) {
115 *(pDest++) = ':';
116 }
117 pDest += snprintf_s(pDest, MAC_ADDR_CHAR_NUM, MAC_ADDR_CHAR_NUM - 1, "%.2x", *pSrc);
118 }
119 /* The last character of pStrMac ends with '\0'. */
120 *(pDest++) = '\0';
121 return pStrMac;
122 }
123
GetLocalInterface(const char * ifname,int * ifindex,unsigned char * hwaddr,uint32_t * ifaddr4)124 int GetLocalInterface(const char *ifname, int *ifindex, unsigned char *hwaddr, uint32_t *ifaddr4)
125 {
126 if ((ifname == NULL) || (strlen(ifname) == 0) || hwaddr == NULL) {
127 DHCP_LOGE("GetLocalInterface() failed, ifname == NULL or hwaddr is NULL");
128 return DHCP_OPT_FAILED;
129 }
130
131 int fd;
132 struct ifreq iface;
133 struct sockaddr_in *pSockIn = NULL;
134
135 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
136 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, socket err:%{public}d!", ifname, errno);
137 return DHCP_OPT_FAILED;
138 }
139
140 if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) {
141 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, memset_s error!", ifname);
142 close(fd);
143 return DHCP_OPT_FAILED;
144 }
145 if (strncpy_s(iface.ifr_name, sizeof(iface.ifr_name), ifname, strlen(ifname)) != EOK) {
146 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, strncpy_s error!", ifname);
147 close(fd);
148 return DHCP_OPT_FAILED;
149 }
150
151 if (ioctl(fd, SIOCGIFINDEX, &iface) != 0) {
152 DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFINDEX err:%{public}d!", ifname, errno);
153 close(fd);
154 return DHCP_OPT_FAILED;
155 }
156 *ifindex = iface.ifr_ifindex;
157
158 if (ioctl(fd, SIOCGIFHWADDR, &iface) != 0) {
159 DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFHWADDR err:%{public}d!", ifname, errno);
160 close(fd);
161 return DHCP_OPT_FAILED;
162 }
163 if (memcpy_s(hwaddr, MAC_ADDR_LEN, iface.ifr_hwaddr.sa_data, MAC_ADDR_LEN) != EOK) {
164 DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, memcpy_s error!", ifname);
165 close(fd);
166 return DHCP_OPT_FAILED;
167 }
168
169 if (ifaddr4 != NULL) {
170 if (ioctl(fd, SIOCGIFADDR, &iface) < 0) {
171 DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFADDR err:%{public}d!", ifname, errno);
172 close(fd);
173 return DHCP_OPT_FAILED;
174 }
175 pSockIn = (struct sockaddr_in *)&iface.ifr_addr;
176 *ifaddr4 = pSockIn->sin_addr.s_addr;
177 }
178 close(fd);
179 return DHCP_OPT_SUCCESS;
180 }
181
GetLocalIp(const char * ifname,uint32_t * ifaddr4)182 int GetLocalIp(const char *ifname, uint32_t *ifaddr4)
183 {
184 if ((ifname == NULL) || (strlen(ifname) == 0)) {
185 DHCP_LOGE("GetLocalIp() failed, ifname == NULL or \"\"!");
186 return DHCP_OPT_FAILED;
187 }
188
189 struct ifaddrs *ifaddr = NULL;
190 struct ifaddrs *ifa = NULL;
191 int family, s;
192 char strIp[NI_MAXHOST];
193
194 if (getifaddrs(&ifaddr) == -1) {
195 DHCP_LOGE("GetLocalIp() ifname:%{public}s failed, getifaddrs error:%{public}d!", ifname, errno);
196 return DHCP_OPT_FAILED;
197 }
198
199 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
200 if (strcmp(ifa->ifa_name, ifname) != 0) {
201 continue;
202 }
203
204 if (ifa->ifa_addr == NULL) {
205 DHCP_LOGE("GetLocalIp() ifname:%{public}s failed, ifa->ifa_addr == NULL!", ifname);
206 continue;
207 }
208
209 family = ifa->ifa_addr->sa_family;
210 if ((family != AF_INET) && (family != AF_INET6)) {
211 continue;
212 }
213
214 if (memset_s(strIp, sizeof(strIp), 0, sizeof(strIp)) != EOK) {
215 return DHCP_OPT_FAILED;
216 }
217 s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
218 strIp, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
219 if (s != 0) {
220 DHCP_LOGE("GetLocalIp() %{public}s failed, getnameinfo error:%{public}s!", ifname, gai_strerror(s));
221 return DHCP_OPT_FAILED;
222 }
223
224 /* Output all ip with ifa_name is ifname and family is AF_INET or AF_INET6. */
225 if (family == AF_INET) {
226 uint32_t hostIp = 0;
227 if (!Ip4StrConToInt(strIp, &hostIp, true)) {
228 DHCP_LOGE("GetLocalIp() %{public}s failed, Ip4StrConToInt strIp:%{private}s error!", ifname, strIp);
229 return DHCP_OPT_FAILED;
230 }
231 DHCP_LOGI("GetLocalIp() %{public}s, AF_INET str:%{private}s -> host:%{private}u.", ifname, strIp, hostIp);
232 *ifaddr4 = hostIp;
233 } else {
234 DHCP_LOGI("GetLocalIp() %{public}s, AF_INET6 strIp:%{private}s.", ifname, strIp);
235 }
236 }
237
238 freeifaddrs(ifaddr);
239 return DHCP_OPT_SUCCESS;
240 }
241
SetIpOrMask(const char * ifname,int fd,uint32_t netAddr,unsigned long cmd)242 int SetIpOrMask(const char *ifname, int fd, uint32_t netAddr, unsigned long cmd)
243 {
244 struct ifreq ifr;
245 struct sockaddr_in sin;
246 if (memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) {
247 DHCP_LOGE("SetIpOrMask() failed, memset_s ifr error!");
248 return DHCP_OPT_FAILED;
249 }
250
251 if (strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifname, strlen(ifname)) != EOK) {
252 DHCP_LOGE("SetIpOrMask() %{public}s failed, , strncpy_s ifr.ifr_name error!", ifname);
253 return DHCP_OPT_FAILED;
254 }
255
256 if (memset_s(&sin, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)) != EOK) {
257 DHCP_LOGE("SetIpOrMask() failed, memset_s sin error!");
258 return DHCP_OPT_FAILED;
259 }
260 sin.sin_family = AF_INET;
261 sin.sin_addr.s_addr = netAddr;
262 if (memcpy_s(&ifr.ifr_addr, sizeof(ifr.ifr_addr), &sin, sizeof(struct sockaddr)) != EOK) {
263 DHCP_LOGE("SetIpOrMask() failed, memcpy_s ifr.ifr_addr error!");
264 return DHCP_OPT_FAILED;
265 }
266
267 if (ioctl(fd, cmd, &ifr) < 0) {
268 DHCP_LOGE("SetIpOrMask() %{public}s failed!", ifname);
269 return DHCP_OPT_FAILED;
270 }
271 return DHCP_OPT_SUCCESS;
272 }
273
SetLocalInterface(const char * ifname,uint32_t ipAddr,uint32_t netMask)274 int SetLocalInterface(const char *ifname, uint32_t ipAddr, uint32_t netMask)
275 {
276 if ((ifname == NULL) || (strlen(ifname) == 0)) {
277 DHCP_LOGE("SetLocalInterface() failed, ifname == NULL or \"\"!");
278 return DHCP_OPT_FAILED;
279 }
280
281 int fd = socket(AF_INET, SOCK_DGRAM, 0);
282 if (fd < 0) {
283 DHCP_LOGE("SetLocalInterface() ifname:%{public}s failed, socket error:%{public}d!", ifname, errno);
284 return DHCP_OPT_FAILED;
285 }
286
287 if (SetIpOrMask(ifname, fd, ipAddr, SIOCSIFADDR) != DHCP_OPT_SUCCESS) {
288 close(fd);
289 return DHCP_OPT_FAILED;
290 }
291
292 if (SetIpOrMask(ifname, fd, netMask, SIOCSIFNETMASK) != DHCP_OPT_SUCCESS) {
293 close(fd);
294 return DHCP_OPT_FAILED;
295 }
296 close(fd);
297 return DHCP_OPT_SUCCESS;
298 }
299
CreateDirs(const char * dirs,int mode)300 int CreateDirs(const char *dirs, int mode)
301 {
302 if ((dirs == NULL) || (strlen(dirs) == 0) || (strlen(dirs) >= DIR_MAX_LEN)) {
303 DHCP_LOGE("CreateDirs() dirs:%{public}s error!", dirs);
304 return DHCP_OPT_FAILED;
305 }
306
307 int nSrcLen = (int)strlen(dirs);
308 char strDir[DIR_MAX_LEN] = {0};
309 if (strncpy_s(strDir, sizeof(strDir), dirs, strlen(dirs)) != EOK) {
310 DHCP_LOGE("CreateDirs() strncpy_s dirs:%{public}s failed!", dirs);
311 return DHCP_OPT_FAILED;
312 }
313 if (strDir[nSrcLen - 1] != '/') {
314 if (nSrcLen == (DIR_MAX_LEN - 1)) {
315 DHCP_LOGE("CreateDirs() dirs:%{public}s len:%{public}d error!", dirs, nSrcLen);
316 return DHCP_OPT_FAILED;
317 }
318 if (strcat_s(strDir, sizeof(strDir), "/") != EOK) {
319 DHCP_LOGE("CreateDirs() strcat_s strDir:%{public}s failed!", strDir);
320 return DHCP_OPT_FAILED;
321 }
322 nSrcLen++;
323 }
324
325 int i = (strDir[0] == '/') ? 1 : 0;
326 for (; i <= nSrcLen - 1; i++) {
327 if (strDir[i] == '/') {
328 strDir[i] = 0;
329 if ((access(strDir, F_OK) != 0) && (mkdir(strDir, mode) != 0)) {
330 DHCP_LOGE("CreateDirs() mkdir %{public}s %{public}.4o failed:%{public}d!", strDir, mode, errno);
331 return DHCP_OPT_FAILED;
332 }
333 strDir[i] = '/';
334 }
335 }
336 DHCP_LOGI("CreateDirs() %{public}s %{public}.4o success.", dirs, mode);
337 return DHCP_OPT_SUCCESS;
338 }
339