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