• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include <arpa/inet.h>
18 #include <time.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <sys/socket.h>
25 #include <unistd.h>
26 #include <ifaddrs.h>
27 #include <netdb.h>
28 #include <net/if.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <netinet/in.h>
32 #include <sys/ioctl.h>
33 
34 #include "securec.h"
35 #include "dhcp_define.h"
36 
37 #undef LOG_TAG
38 #define LOG_TAG "WifiDhcpFunction"
39 
Ip4StrConToInt(const char * strIp,uint32_t * uIp,bool bHost)40 bool Ip4StrConToInt(const char *strIp, uint32_t *uIp, bool bHost)
41 {
42     if ((strIp == NULL) || (strlen(strIp) == 0)) {
43         LOGE("Ip4StrConToInt failed, strIp == NULL or \"\"!");
44         return false;
45     }
46 
47     struct in_addr addr4;
48     int nRet = inet_pton(AF_INET, strIp, &addr4);
49     if (nRet != 1) {
50         LOGE("Ip4StrConToInt strIp:%{private}s failed, inet_pton nRet:%{public}d!", strIp, nRet);
51         if (nRet == 0) {
52             LOGE("Ip4StrConToInt strIp:%{private}s not in presentation format!", strIp);
53         } else {
54             LOGE("Ip4StrConToInt strIp:%{private}s inet_pton does not contain a valid address family!", strIp);
55         }
56         return false;
57     }
58 
59     if (bHost) {
60         *uIp = ntohl(addr4.s_addr);
61     } else {
62         *uIp = addr4.s_addr;
63     }
64 
65     return true;
66 }
67 
Ip4IntConToStr(uint32_t uIp,bool bHost)68 char *Ip4IntConToStr(uint32_t uIp, bool bHost)
69 {
70     char bufIp4[INET_ADDRSTRLEN] = {0};
71     struct in_addr addr4;
72     if (bHost) {
73         addr4.s_addr = htonl(uIp);
74     } else {
75         addr4.s_addr = uIp;
76     }
77     const char *p = inet_ntop(AF_INET, &addr4, bufIp4, INET_ADDRSTRLEN);
78     if (p == NULL) {
79         LOGE("Ip4IntConToStr uIp:%{private}u failed, inet_ntop p == NULL!", uIp);
80         return NULL;
81     }
82 
83     char *strIp = (char *)malloc(INET_ADDRSTRLEN);
84     if (strIp == NULL) {
85         LOGE("Ip4IntConToStr uIp:%{private}u failed, strIp malloc failed!", uIp);
86         return NULL;
87     }
88     if (strncpy_s(strIp, INET_ADDRSTRLEN, bufIp4, strlen(bufIp4)) != EOK) {
89         LOGE("Ip4IntConToStr uIp:%{private}u failed, strIp strncpy_s failed!", uIp);
90         free(strIp);
91         strIp = NULL;
92         return NULL;
93     }
94 
95     return strIp;
96 }
97 
Ip6StrConToChar(const char * strIp,uint8_t chIp[],size_t chlen)98 bool Ip6StrConToChar(const char *strIp, uint8_t chIp[], size_t chlen)
99 {
100     if ((strIp == NULL) || (strlen(strIp) == 0)) {
101         LOGE("Ip6StrConToChar failed, strIp == NULL or \"\"!");
102         return false;
103     }
104 
105     struct in6_addr addr6;
106     if (memset_s(&addr6, sizeof(addr6), 0, sizeof(addr6)) != EOK) {
107         return false;
108     }
109     int nRet = inet_pton(AF_INET6, strIp, &addr6);
110     if (nRet != 1) {
111         LOGE("Ip6StrConToChar strIp:%{private}s failed, inet_pton nRet:%{public}d!", strIp, nRet);
112         if (nRet == 0) {
113             LOGE("Ip6StrConToChar strIp:%{private}s not in presentation format!", strIp);
114         } else {
115             LOGE("Ip6StrConToChar strIp:%{private}s inet_pton does not contain a valid address family!", strIp);
116         }
117         return false;
118     }
119 
120     LOGI("Ip6StrConToChar strIp:%{private}s -> ", strIp);
121     for (size_t i = 0; i < chlen; i++) {
122         LOGI("Ip6StrConToChar addr6.s6_addr: %{private}zu - %{private}02x", i, addr6.s6_addr[i]);
123         chIp[i] = addr6.s6_addr[i];
124     }
125 
126     return true;
127 }
128 
MacChConToMacStr(const unsigned char * pChMac,size_t chLen,char * pStrMac,size_t strLen)129 const char *MacChConToMacStr(const unsigned char *pChMac, size_t chLen, char *pStrMac, size_t strLen)
130 {
131     if ((pChMac == NULL) || (chLen == 0)) {
132         LOGE("MacChConToMacStr failed, pChMac == NULL or chLen == 0!");
133         return NULL;
134     }
135 
136     if ((pStrMac == NULL) || (strLen < (chLen * MAC_ADDR_CHAR_NUM))) {
137         LOGE("MacChConToMacStr failed, pStrMac == NULL or strLen:%{public}d error!", (int)strLen);
138         return NULL;
139     }
140 
141     const unsigned char *pSrc = pChMac;
142     const unsigned char *pSrcEnd = pSrc + chLen;
143     char *pDest = pStrMac;
144     for (; pSrc < pSrcEnd; pSrc++) {
145         /* The first character of pStrMac starts with a letter, not ':'. */
146         if (pSrc != pChMac) {
147             *(pDest++) = ':';
148         }
149         pDest += snprintf_s(pDest, MAC_ADDR_CHAR_NUM, MAC_ADDR_CHAR_NUM - 1, "%.2x", *pSrc);
150     }
151     /* The last character of pStrMac ends with '\0'. */
152     *(pDest++) = '\0';
153     return pStrMac;
154 }
155 
GetLocalInterface(const char * ifname,int * ifindex,unsigned char * hwaddr,uint32_t * ifaddr4)156 int GetLocalInterface(const char *ifname, int *ifindex, unsigned char *hwaddr, uint32_t *ifaddr4)
157 {
158     if ((ifname == NULL) || (strlen(ifname) == 0) || hwaddr == NULL) {
159         LOGE("GetLocalInterface() failed, ifname == NULL or hwaddr is NULL");
160         return DHCP_OPT_FAILED;
161     }
162 
163     int fd;
164     struct ifreq iface;
165     struct sockaddr_in *pSockIn = NULL;
166 
167     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
168         LOGE("GetLocalInterface() ifname:%{public}s failed, socket err:%{public}d!", ifname, errno);
169         return DHCP_OPT_FAILED;
170     }
171 
172     if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) {
173         LOGE("GetLocalInterface() ifname:%{public}s failed, memset_s error!", ifname);
174         close(fd);
175         return DHCP_OPT_FAILED;
176     }
177     if (strncpy_s(iface.ifr_name, sizeof(iface.ifr_name), ifname, strlen(ifname)) != EOK) {
178         LOGE("GetLocalInterface() ifname:%{public}s failed, strncpy_s error!", ifname);
179         close(fd);
180         return DHCP_OPT_FAILED;
181     }
182 
183     if (ioctl(fd, SIOCGIFINDEX, &iface) != 0) {
184         LOGE("GetLocalInterface() %{public}s failed, SIOCGIFINDEX err:%{public}d!", ifname, errno);
185         close(fd);
186         return DHCP_OPT_FAILED;
187     }
188     *ifindex = iface.ifr_ifindex;
189 
190     if (ioctl(fd, SIOCGIFHWADDR, &iface) != 0) {
191         LOGE("GetLocalInterface() %{public}s failed, SIOCGIFHWADDR err:%{public}d!", ifname, errno);
192         close(fd);
193         return DHCP_OPT_FAILED;
194     }
195     if (memcpy_s(hwaddr, MAC_ADDR_LEN, iface.ifr_hwaddr.sa_data, MAC_ADDR_LEN) != EOK) {
196         LOGE("GetLocalInterface() ifname:%{public}s failed, memcpy_s error!", ifname);
197         close(fd);
198         return DHCP_OPT_FAILED;
199     }
200 
201     if (ifaddr4 != NULL) {
202         if (ioctl(fd, SIOCGIFADDR, &iface) < 0) {
203             LOGE("GetLocalInterface() %{public}s failed, SIOCGIFADDR err:%{public}d!", ifname, errno);
204             close(fd);
205             return DHCP_OPT_FAILED;
206         }
207         pSockIn = (struct sockaddr_in *)&iface.ifr_addr;
208         *ifaddr4 = pSockIn->sin_addr.s_addr;
209     }
210 
211     close(fd);
212     return DHCP_OPT_SUCCESS;
213 }
214 
GetLocalIp(const char * ifname,uint32_t * ifaddr4)215 int GetLocalIp(const char *ifname, uint32_t *ifaddr4)
216 {
217     if ((ifname == NULL) || (strlen(ifname) == 0)) {
218         LOGE("GetLocalIp() failed, ifname == NULL or \"\"!");
219         return DHCP_OPT_FAILED;
220     }
221 
222     struct ifaddrs *ifaddr = NULL;
223     struct ifaddrs *ifa = NULL;
224     int family, s;
225     char strIp[NI_MAXHOST];
226 
227     if (getifaddrs(&ifaddr) == -1) {
228         LOGE("GetLocalIp() ifname:%{public}s failed, getifaddrs error:%{public}d!", ifname, errno);
229         return DHCP_OPT_FAILED;
230     }
231 
232     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
233         if (strcmp(ifa->ifa_name, ifname) != 0) {
234             continue;
235         }
236 
237         if (ifa->ifa_addr == NULL) {
238             LOGE("GetLocalIp() ifname:%{public}s failed, ifa->ifa_addr == NULL!", ifname);
239             continue;
240         }
241 
242         family = ifa->ifa_addr->sa_family;
243         if ((family != AF_INET) && (family != AF_INET6)) {
244             continue;
245         }
246 
247         if (memset_s(strIp, sizeof(strIp), 0, sizeof(strIp)) != EOK) {
248             return DHCP_OPT_FAILED;
249         }
250         s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
251             strIp, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
252         if (s != 0) {
253             LOGE("GetLocalIp() %{public}s failed, getnameinfo error:%{public}s!", ifname, gai_strerror(s));
254             return DHCP_OPT_FAILED;
255         }
256 
257         /* Output all ip with ifa_name is ifname and family is AF_INET or AF_INET6. */
258         if (family == AF_INET) {
259             uint32_t hostIp = 0;
260             if (!Ip4StrConToInt(strIp, &hostIp, true)) {
261                 LOGE("GetLocalIp() %{public}s failed, Ip4StrConToInt strIp:%{private}s error!", ifname, strIp);
262                 return DHCP_OPT_FAILED;
263             }
264             LOGI("GetLocalIp() %{public}s, AF_INET str:%{private}s -> host:%{private}u.", ifname, strIp, hostIp);
265             *ifaddr4 = hostIp;
266         } else {
267             LOGI("GetLocalIp() %{public}s, AF_INET6 strIp:%{private}s.", ifname, strIp);
268         }
269     }
270 
271     freeifaddrs(ifaddr);
272     return DHCP_OPT_SUCCESS;
273 }
274 
SetIpOrMask(const char * ifname,int fd,uint32_t netAddr,unsigned long cmd)275 int SetIpOrMask(const char *ifname, int fd, uint32_t netAddr, unsigned long cmd)
276 {
277     struct ifreq ifr;
278     struct sockaddr_in sin;
279     if (memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) {
280         LOGE("SetIpOrMask() failed, memset_s ifr error!");
281         return DHCP_OPT_FAILED;
282     }
283 
284     if (strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifname, strlen(ifname)) != EOK) {
285         LOGE("SetIpOrMask() %{public}s failed, , strncpy_s ifr.ifr_name error!", ifname);
286         return DHCP_OPT_FAILED;
287     }
288 
289     if (memset_s(&sin, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)) != EOK) {
290         LOGE("SetIpOrMask() failed, memset_s sin error!");
291         return DHCP_OPT_FAILED;
292     }
293     sin.sin_family = AF_INET;
294     sin.sin_addr.s_addr = netAddr;
295     if (memcpy_s(&ifr.ifr_addr, sizeof(ifr.ifr_addr), &sin, sizeof(struct sockaddr)) != EOK) {
296         LOGE("SetIpOrMask() failed, memcpy_s ifr.ifr_addr error!");
297         return DHCP_OPT_FAILED;
298     }
299 
300     if (ioctl(fd, cmd, &ifr) < 0) {
301         LOGE("SetIpOrMask() %{public}s failed, %{public}ld!", ifname, cmd);
302         return DHCP_OPT_FAILED;
303     }
304     return DHCP_OPT_SUCCESS;
305 }
306 
SetLocalInterface(const char * ifname,uint32_t ipAddr,uint32_t netMask)307 int SetLocalInterface(const char *ifname, uint32_t ipAddr, uint32_t netMask)
308 {
309     if ((ifname == NULL) || (strlen(ifname) == 0)) {
310         LOGE("SetLocalInterface() failed, ifname == NULL or \"\"!");
311         return DHCP_OPT_FAILED;
312     }
313     LOGI("SetLocalInterface() %{public}s, ipAddr:%{private}u mask %{private}u.", ifname, ipAddr, netMask);
314 
315     int fd = socket(AF_INET, SOCK_DGRAM, 0);
316     if (fd < 0) {
317         LOGE("SetLocalInterface() ifname:%{public}s failed, socket error:%{public}d!", ifname, errno);
318         return DHCP_OPT_FAILED;
319     }
320 
321     if (SetIpOrMask(ifname, fd, ipAddr, SIOCSIFADDR) != DHCP_OPT_SUCCESS) {
322         close(fd);
323         return DHCP_OPT_FAILED;
324     }
325 
326     if (SetIpOrMask(ifname, fd, netMask, SIOCSIFNETMASK) != DHCP_OPT_SUCCESS) {
327         close(fd);
328         return DHCP_OPT_FAILED;
329     }
330     close(fd);
331     return DHCP_OPT_SUCCESS;
332 }
333 
InitPidfile(const char * pidDir,const char * pidFile,pid_t pid)334 int InitPidfile(const char *pidDir, const char *pidFile, pid_t pid)
335 {
336     if ((pidDir == NULL) || (strlen(pidDir) == 0) || (pidFile == NULL) || (strlen(pidFile) == 0)) {
337         LOGE("InitPidfile() failed, pidDir or pidFile == NULL or \"\"!");
338         return DHCP_OPT_FAILED;
339     }
340     LOGI("InitPidfile() pidDir:%{public}s, pidFile:%{public}s.", pidDir, pidFile);
341     unlink(pidFile);
342 
343     int fd;
344     if ((fd = open(pidFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
345         LOGE("InitPidfile() failed, open pidFile:%{public}s error:%{public}d!", pidFile, errno);
346         return DHCP_OPT_FAILED;
347     }
348 
349     char buf[PID_MAX_LEN] = {0};
350     if (snprintf_s(buf, PID_MAX_LEN, PID_MAX_LEN - 1, "%d", pid) < 0) {
351         LOGE("InitPidfile() pidFile:%{public}s failed, snprintf_s error:%{public}d!", pidFile, errno);
352         close(fd);
353         return DHCP_OPT_FAILED;
354     }
355     ssize_t bytes;
356     if ((bytes = write(fd, buf, strlen(buf))) <= 0) {
357         LOGE("InitPidfile() failed, write pidFile:%{public}s error:%{public}d, bytes:%{public}zd!",
358             pidFile, errno, bytes);
359         close(fd);
360         return DHCP_OPT_FAILED;
361     }
362     LOGI("InitPidfile() buf:%{public}s write pidFile:%{public}s, bytes:%{public}zd!", buf, pidFile, bytes);
363     close(fd);
364 
365     if (chdir(pidDir) != 0) {
366         LOGE("InitPidfile() failed, chdir pidDir:%{public}s error:%{public}d!", pidDir, errno);
367         return DHCP_OPT_FAILED;
368     }
369 
370     /* Set default permissions for the specified client process id files and directories. */
371     umask(DEFAULT_UMASK);
372 
373     /* Change attribs to the specified client process id files: 644 (user=rw, group=r, other=r). */
374     chmod(pidFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
375 
376     return DHCP_OPT_SUCCESS;
377 }
378 
GetPID(const char * pidFile)379 pid_t GetPID(const char *pidFile)
380 {
381     /* Check pidFile is or not exists. */
382     struct stat sb;
383     if (stat(pidFile, &sb) != 0) {
384         LOGW("GetPID() pidFile:%{public}s stat error:%{public}d!", pidFile, errno);
385         return -1;
386     }
387     LOGI("GetPID() pidFile:%{public}s stat st_size:%{public}d.", pidFile, (int)sb.st_size);
388 
389     int fd;
390     if ((fd = open(pidFile, O_RDONLY)) < 0) {
391         LOGE("GetPID() failed, open pidFile:%{public}s error!", pidFile);
392         return -1;
393     }
394 
395     lseek(fd, 0, SEEK_SET);
396 
397     char buf[PID_MAX_LEN] = {0};
398     ssize_t bytes;
399     if ((bytes = read(fd, buf, sb.st_size)) < 0) {
400         LOGE("GetPID() failed, read pidFile:%{public}s error, bytes:%{public}zd!", pidFile, bytes);
401         close(fd);
402         return -1;
403     }
404     LOGI("GetPID() read pidFile:%{public}s, buf:%{public}s, bytes:%{public}zd.", pidFile, buf, bytes);
405     close(fd);
406 
407     return atoi(buf);
408 }
409 
CreateDirs(const char * dirs,int mode)410 int CreateDirs(const char *dirs, int mode)
411 {
412     if ((dirs == NULL) || (strlen(dirs) == 0) || (strlen(dirs) >= DIR_MAX_LEN)) {
413         LOGE("CreateDirs() dirs:%{public}s error!", dirs);
414         return DHCP_OPT_FAILED;
415     }
416 
417     int nSrcLen = (int)strlen(dirs);
418     char strDir[DIR_MAX_LEN] = {0};
419     if (strncpy_s(strDir, sizeof(strDir), dirs, strlen(dirs)) != EOK) {
420         LOGE("CreateDirs() strncpy_s dirs:%{public}s failed!", dirs);
421         return DHCP_OPT_FAILED;
422     }
423     if (strDir[nSrcLen - 1] != '/') {
424         if (nSrcLen == (DIR_MAX_LEN - 1)) {
425             LOGE("CreateDirs() dirs:%{public}s len:%{public}d error!", dirs, nSrcLen);
426             return DHCP_OPT_FAILED;
427         }
428         if (strcat_s(strDir, sizeof(strDir), "/") != EOK) {
429             LOGE("CreateDirs() strcat_s strDir:%{public}s failed!", strDir);
430             return DHCP_OPT_FAILED;
431         }
432         nSrcLen++;
433     }
434 
435     int i = (strDir[0] == '/') ? 1 : 0;
436     for (; i <= nSrcLen - 1; i++) {
437         if (strDir[i] == '/') {
438             strDir[i] = 0;
439             if ((access(strDir, F_OK) != 0) && (mkdir(strDir, mode) != 0)) {
440                 LOGE("CreateDirs() mkdir %{public}s %{public}.4o failed:%{public}d!", strDir, mode, errno);
441                 return DHCP_OPT_FAILED;
442             }
443             strDir[i] = '/';
444         }
445     }
446     LOGI("CreateDirs() %{public}s %{public}.4o success.", dirs, mode);
447     return DHCP_OPT_SUCCESS;
448 }
449