• 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 <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 bool 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 false;
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 false;
107     }
108 
109     if (chLen > MAC_ADDR_LEN) {
110         DHCP_LOGE("MacChConToMacStr failed, chLen:%{public}zu error!", chLen);
111         return false;
112     }
113 
114     const unsigned char *pSrc = pChMac;
115     const unsigned char *pSrcEnd = pSrc + chLen;
116     char *pDest = pStrMac;
117     for (; pSrc < pSrcEnd; pSrc++) {
118         /* The first character of pStrMac starts with a letter, not ':'. */
119         if (pSrc != pChMac) {
120             *(pDest++) = ':';
121         }
122         int ret = snprintf_s(pDest, MAC_ADDR_CHAR_NUM, MAC_ADDR_CHAR_NUM - 1, "%.2x", *pSrc);
123         if (ret < 0) {
124             DHCP_LOGE("snprintf_s failed!");
125             return false;
126         }
127         pDest += ret;
128     }
129     /* The last character of pStrMac ends with '\0'. */
130     *(pDest++) = '\0';
131     return true;
132 }
133 
GetLocalInterface(const char * ifname,int * ifindex,unsigned char * hwaddr,uint32_t * ifaddr4)134 int GetLocalInterface(const char *ifname, int *ifindex, unsigned char *hwaddr, uint32_t *ifaddr4)
135 {
136     if ((ifname == NULL) || (strlen(ifname) == 0) || hwaddr == NULL) {
137         DHCP_LOGE("GetLocalInterface() failed, ifname == NULL or hwaddr is NULL");
138         return DHCP_OPT_FAILED;
139     }
140 
141     int fd;
142     struct ifreq iface;
143     struct sockaddr_in *pSockIn = NULL;
144 
145     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
146         DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, socket err:%{public}d!", ifname, errno);
147         return DHCP_OPT_FAILED;
148     }
149 
150     if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) {
151         DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, memset_s error!", ifname);
152         close(fd);
153         return DHCP_OPT_FAILED;
154     }
155     if (strncpy_s(iface.ifr_name, sizeof(iface.ifr_name), ifname, strlen(ifname)) != EOK) {
156         DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, strncpy_s error!", ifname);
157         close(fd);
158         return DHCP_OPT_FAILED;
159     }
160 
161     if (ioctl(fd, SIOCGIFINDEX, &iface) != 0) {
162         DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFINDEX err:%{public}d!", ifname, errno);
163         close(fd);
164         return DHCP_OPT_FAILED;
165     }
166     *ifindex = iface.ifr_ifindex;
167 
168     if (ioctl(fd, SIOCGIFHWADDR, &iface) != 0) {
169         DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFHWADDR err:%{public}d!", ifname, errno);
170         close(fd);
171         return DHCP_OPT_FAILED;
172     }
173     if (memcpy_s(hwaddr, MAC_ADDR_LEN, iface.ifr_hwaddr.sa_data, MAC_ADDR_LEN) != EOK) {
174         DHCP_LOGE("GetLocalInterface() ifname:%{public}s failed, memcpy_s error!", ifname);
175         close(fd);
176         return DHCP_OPT_FAILED;
177     }
178 
179     if (ifaddr4 != NULL) {
180         if (ioctl(fd, SIOCGIFADDR, &iface) < 0) {
181             DHCP_LOGE("GetLocalInterface() %{public}s failed, SIOCGIFADDR err:%{public}d!", ifname, errno);
182             close(fd);
183             return DHCP_OPT_FAILED;
184         }
185         pSockIn = (struct sockaddr_in *)&iface.ifr_addr;
186         *ifaddr4 = pSockIn->sin_addr.s_addr;
187     }
188     close(fd);
189     return DHCP_OPT_SUCCESS;
190 }
191 
GetLocalIp(const char * ifname,uint32_t * ifaddr4)192 int GetLocalIp(const char *ifname, uint32_t *ifaddr4)
193 {
194     if ((ifname == NULL) || (strlen(ifname) == 0)) {
195         DHCP_LOGE("GetLocalIp() failed, ifname == NULL or \"\"!");
196         return DHCP_OPT_FAILED;
197     }
198 
199     struct ifaddrs *ifaddr = NULL;
200     struct ifaddrs *ifa = NULL;
201     int family, s;
202     char strIp[NI_MAXHOST];
203 
204     if (getifaddrs(&ifaddr) == -1) {
205         DHCP_LOGE("GetLocalIp() ifname:%{public}s failed, getifaddrs error:%{public}d!", ifname, errno);
206         return DHCP_OPT_FAILED;
207     }
208 
209     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
210         if (strcmp(ifa->ifa_name, ifname) != 0) {
211             continue;
212         }
213 
214         if (ifa->ifa_addr == NULL) {
215             DHCP_LOGE("GetLocalIp() ifname:%{public}s failed, ifa->ifa_addr == NULL!", ifname);
216             continue;
217         }
218 
219         family = ifa->ifa_addr->sa_family;
220         if ((family != AF_INET) && (family != AF_INET6)) {
221             continue;
222         }
223 
224         if (memset_s(strIp, sizeof(strIp), 0, sizeof(strIp)) != EOK) {
225             return DHCP_OPT_FAILED;
226         }
227         s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
228             strIp, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
229         if (s != 0) {
230             DHCP_LOGE("GetLocalIp() %{public}s failed, getnameinfo error:%{public}s!", ifname, gai_strerror(s));
231             return DHCP_OPT_FAILED;
232         }
233 
234         /* Output all ip with ifa_name is ifname and family is AF_INET or AF_INET6. */
235         if (family == AF_INET) {
236             uint32_t hostIp = 0;
237             if (!Ip4StrConToInt(strIp, &hostIp, true)) {
238                 DHCP_LOGE("GetLocalIp() %{public}s failed, Ip4StrConToInt strIp:%{private}s error!", ifname, strIp);
239                 return DHCP_OPT_FAILED;
240             }
241             DHCP_LOGI("GetLocalIp() %{public}s, AF_INET str:%{private}s -> host:%{private}u.", ifname, strIp, hostIp);
242             *ifaddr4 = hostIp;
243         } else {
244             DHCP_LOGI("GetLocalIp() %{public}s, AF_INET6 strIp:%{private}s.", ifname, strIp);
245         }
246     }
247 
248     freeifaddrs(ifaddr);
249     return DHCP_OPT_SUCCESS;
250 }
251 
SetIpOrMask(const char * ifname,int fd,uint32_t netAddr,unsigned long cmd)252 int SetIpOrMask(const char *ifname, int fd, uint32_t netAddr, unsigned long cmd)
253 {
254     struct ifreq ifr;
255     struct sockaddr_in sin;
256     if (memset_s(&ifr, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) {
257         DHCP_LOGE("SetIpOrMask() failed, memset_s ifr error!");
258         return DHCP_OPT_FAILED;
259     }
260 
261     if (strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifname, strlen(ifname)) != EOK) {
262         DHCP_LOGE("SetIpOrMask() %{public}s failed, , strncpy_s ifr.ifr_name error!", ifname);
263         return DHCP_OPT_FAILED;
264     }
265 
266     if (memset_s(&sin, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in)) != EOK) {
267         DHCP_LOGE("SetIpOrMask() failed, memset_s sin error!");
268         return DHCP_OPT_FAILED;
269     }
270     sin.sin_family = AF_INET;
271     sin.sin_addr.s_addr = netAddr;
272     if (memcpy_s(&ifr.ifr_addr, sizeof(ifr.ifr_addr), &sin, sizeof(struct sockaddr)) != EOK) {
273         DHCP_LOGE("SetIpOrMask() failed, memcpy_s ifr.ifr_addr error!");
274         return DHCP_OPT_FAILED;
275     }
276 
277     if (ioctl(fd, cmd, &ifr) < 0) {
278         DHCP_LOGE("SetIpOrMask() %{public}s failed!", ifname);
279         return DHCP_OPT_FAILED;
280     }
281     return DHCP_OPT_SUCCESS;
282 }
283 
SetLocalInterface(const char * ifname,uint32_t ipAddr,uint32_t netMask)284 int SetLocalInterface(const char *ifname, uint32_t ipAddr, uint32_t netMask)
285 {
286     if ((ifname == NULL) || (strlen(ifname) == 0)) {
287         DHCP_LOGE("SetLocalInterface() failed, ifname == NULL or \"\"!");
288         return DHCP_OPT_FAILED;
289     }
290 
291     int fd = socket(AF_INET, SOCK_DGRAM, 0);
292     if (fd < 0) {
293         DHCP_LOGE("SetLocalInterface() ifname:%{public}s failed, socket error:%{public}d!", ifname, errno);
294         return DHCP_OPT_FAILED;
295     }
296 
297     if (SetIpOrMask(ifname, fd, ipAddr, SIOCSIFADDR) != DHCP_OPT_SUCCESS) {
298         close(fd);
299         return DHCP_OPT_FAILED;
300     }
301 
302     if (SetIpOrMask(ifname, fd, netMask, SIOCSIFNETMASK) != DHCP_OPT_SUCCESS) {
303         close(fd);
304         return DHCP_OPT_FAILED;
305     }
306     close(fd);
307     return DHCP_OPT_SUCCESS;
308 }
309 
CreateDirs(const char * dirs,int mode)310 int CreateDirs(const char *dirs, int mode)
311 {
312     if ((dirs == NULL) || (strlen(dirs) == 0) || (strlen(dirs) >= DIR_MAX_LEN)) {
313         DHCP_LOGE("CreateDirs() dirs:%{public}s error!", dirs);
314         return DHCP_OPT_FAILED;
315     }
316 
317     int nSrcLen = (int)strlen(dirs);
318     char strDir[DIR_MAX_LEN] = {0};
319     if (strncpy_s(strDir, sizeof(strDir), dirs, strlen(dirs)) != EOK) {
320         DHCP_LOGE("CreateDirs() strncpy_s dirs:%{public}s failed!", dirs);
321         return DHCP_OPT_FAILED;
322     }
323     if (strDir[nSrcLen - 1] != '/') {
324         if (nSrcLen == (DIR_MAX_LEN - 1)) {
325             DHCP_LOGE("CreateDirs() dirs:%{public}s len:%{public}d error!", dirs, nSrcLen);
326             return DHCP_OPT_FAILED;
327         }
328         if (strcat_s(strDir, sizeof(strDir), "/") != EOK) {
329             DHCP_LOGE("CreateDirs() strcat_s strDir:%{public}s failed!", strDir);
330             return DHCP_OPT_FAILED;
331         }
332         nSrcLen++;
333     }
334 
335     int i = (strDir[0] == '/') ? 1 : 0;
336     for (; i <= nSrcLen - 1; i++) {
337         if (strDir[i] == '/') {
338             strDir[i] = 0;
339             if ((access(strDir, F_OK) != 0) && (mkdir(strDir, mode) != 0)) {
340                 DHCP_LOGE("CreateDirs() mkdir %{public}s %{public}.4o failed:%{public}d!", strDir, mode, errno);
341                 return DHCP_OPT_FAILED;
342             }
343             strDir[i] = '/';
344         }
345     }
346     DHCP_LOGI("CreateDirs() %{public}s %{public}.4o success.", dirs, mode);
347     return DHCP_OPT_SUCCESS;
348 }
349