• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2022 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 <unistd.h>
18 #include <net/if.h>
19 #include <sys/ioctl.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <vector>
24 #include <sys/wait.h>
25 
26 #include "securec.h"
27 #include "dhcp_logger.h"
28 #include "dhcp_common_utils.h"
29 
30 namespace OHOS {
31 namespace DHCP {
32 DEFINE_DHCPLOG_DHCP_LABEL("DhcpFunction");
33 
Ip4StrConToInt(const std::string & strIp,uint32_t & uIp,bool bHost)34 bool DhcpFunction::Ip4StrConToInt(const std::string& strIp, uint32_t& uIp, bool bHost)
35 {
36     if (strIp.empty()) {
37         DHCP_LOGE("Ip4StrConToInt error, strIp is empty()!");
38         return false;
39     }
40 
41     struct in_addr addr4;
42     int nRet = inet_pton(AF_INET, strIp.c_str(), &addr4);
43     if (nRet != 1) {
44         DHCP_LOGE("Ip4StrConToInt strIp:%{private}s failed, nRet:%{public}d!", strIp.c_str(), nRet);
45         if (nRet == 0) {
46             DHCP_LOGE("Ip4StrConToInt strIp:%{private}s not in presentation format!", strIp.c_str());
47         } else {
48             DHCP_LOGE("Ip4StrConToInt strIp:%{private}s inet_pton not contain a valid address!", strIp.c_str());
49         }
50         return false;
51     }
52 
53     if (bHost) {
54         uIp = ntohl(addr4.s_addr);
55     } else {
56         uIp = addr4.s_addr;
57     }
58 
59     return true;
60 }
61 
Ip6StrConToChar(const std::string & strIp,uint8_t chIp[],size_t uSize)62 bool DhcpFunction::Ip6StrConToChar(const std::string& strIp, uint8_t chIp[], size_t uSize)
63 {
64     if (strIp.empty()) {
65         DHCP_LOGE("Ip6StrConToChar param error, strIp is empty()!");
66         return false;
67     }
68 
69     struct in6_addr addr6;
70     if (memset_s(&addr6, sizeof(addr6), 0, sizeof(addr6)) != EOK) {
71         return false;
72     }
73     int nRet = inet_pton(AF_INET6, strIp.c_str(), &addr6);
74     if (nRet != 1) {
75         DHCP_LOGE("Ip6StrConToChar inet_pton strIp:%{private}s failed, nRet:%{public}d!", strIp.c_str(), nRet);
76         if (nRet == 0) {
77             DHCP_LOGE("Ip6StrConToChar strIp:%{private}s not in presentation format!", strIp.c_str());
78         } else {
79             DHCP_LOGE("Ip6StrConToChar strIp:%{private}s inet_pton not contain a valid address!", strIp.c_str());
80         }
81         return false;
82     }
83 
84     for (size_t i = 0; i < uSize; i++) {
85         chIp[i] = addr6.s6_addr[i];
86     }
87 
88     return true;
89 }
90 
Ip6CharConToStr(uint8_t chIp[],int size)91 std::string DhcpFunction::Ip6CharConToStr(uint8_t chIp[], int size)
92 {
93     if (size <= 0) {
94         DHCP_LOGE("Ip6CharConToStr param error, size:%{public}d!", size);
95         return "";
96     }
97 
98     std::string strIp = "";
99     char bufIp6[INET6_ADDRSTRLEN] = {0};
100     struct in6_addr addr6;
101     if (memcpy_s(addr6.s6_addr, sizeof(addr6.s6_addr), &chIp, size) != EOK) {
102         return "";
103     }
104     if (inet_ntop(AF_INET6, &addr6, bufIp6, INET6_ADDRSTRLEN) == nullptr) {
105         DHCP_LOGE("Ip6CharConToStr chIp failed, inet_ntop nullptr!");
106     } else {
107         strIp = bufIp6;
108         DHCP_LOGI("Ip6CharConToStr chIp -> strIp:%{private}s.", strIp.c_str());
109     }
110 
111     return strIp;
112 }
113 
CheckIpStr(const std::string & strIp)114 bool DhcpFunction::CheckIpStr(const std::string& strIp)
115 {
116     if (strIp.empty()) {
117         DHCP_LOGE("CheckIpStr param error, strIp is empty()!");
118         return false;
119     }
120 
121     bool bIp4 = false;
122     bool bIp6 = false;
123     std::string::size_type idx = strIp.find(IP4_SEPARATOR);
124     if (idx != std::string::npos) {
125         bIp4 = true;
126     }
127     idx = strIp.find(IP6_SEPARATOR);
128     if (idx != std::string::npos) {
129         bIp6 = true;
130     }
131     if ((!bIp4 && !bIp6) || (bIp4 && bIp6)) {
132         DHCP_LOGE("CheckIpStr strIp:%{private}s error, bIp4:%{public}d,bIp6:%{public}d!", strIp.c_str(), bIp4, bIp6);
133         return false;
134     }
135 
136     if (bIp4) {
137         uint32_t uIp = 0;
138         if (!Ip4StrConToInt(strIp, uIp)) {
139             DHCP_LOGE("CheckIpStr Ip4StrConToInt failed, strIp:%{private}s.", strIp.c_str());
140             return false;
141         }
142     } else {
143         uint8_t	addr6[sizeof(struct in6_addr)] = {0};
144         if (!Ip6StrConToChar(strIp, addr6, sizeof(struct in6_addr))) {
145             DHCP_LOGE("CheckIpStr Ip6StrConToChar failed, strIp:%{private}s.", strIp.c_str());
146             return false;
147         }
148     }
149 
150     return true;
151 }
152 
GetLocalIp(const std::string strInf,std::string & strIp,std::string & strMask)153 int DhcpFunction::GetLocalIp(const std::string strInf, std::string& strIp, std::string& strMask)
154 {
155     if (strInf.empty()) {
156         DHCP_LOGE("GetLocalIp param error, strInf is empty!");
157         return DHCP_OPT_ERROR;
158     }
159 
160     int fd;
161     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
162         DHCP_LOGE("GetLocalIp strInf:%{public}s failed, socket err:%{public}d!", strInf.c_str(), errno);
163         return DHCP_OPT_FAILED;
164     }
165 
166     struct ifreq iface;
167     if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) {
168         close(fd);
169         return DHCP_OPT_FAILED;
170     }
171     if (strncpy_s(iface.ifr_name, IFNAMSIZ, strInf.c_str(), IFNAMSIZ - 1) != EOK) {
172         close(fd);
173         return DHCP_OPT_FAILED;
174     }
175     iface.ifr_name[IFNAMSIZ - 1] = 0;
176 
177     /* inet addr */
178     if (ioctl(fd, SIOCGIFADDR, &iface) < 0) {
179         DHCP_LOGE("GetLocalIp() %{public}s failed, SIOCGIFADDR err:%{public}d!", strInf.c_str(), errno);
180         close(fd);
181         return DHCP_OPT_FAILED;
182     }
183     struct sockaddr_in *pSockIn = (struct sockaddr_in *)&iface.ifr_addr;
184     char bufIp4[INET_ADDRSTRLEN] = {0};
185     if (inet_ntop(AF_INET, &(pSockIn->sin_addr), bufIp4, INET_ADDRSTRLEN) != nullptr) {
186         strIp = bufIp4;
187     }
188 
189     /* netmask addr */
190     if (ioctl(fd, SIOCGIFNETMASK, &iface) < 0) {
191         DHCP_LOGE("GetLocalIp() %{public}s failed, SIOCGIFNETMASK err:%{public}d!", strInf.c_str(), errno);
192         close(fd);
193         return DHCP_OPT_FAILED;
194     }
195     pSockIn = (struct sockaddr_in *)&iface.ifr_addr;
196     char bufMask[INET_ADDRSTRLEN] = {0};
197     if (inet_ntop(AF_INET, &(pSockIn->sin_addr), bufMask, INET_ADDRSTRLEN) != nullptr) {
198         strMask = bufMask;
199     }
200 
201     close(fd);
202     return DHCP_OPT_SUCCESS;
203 }
204 
GetLocalMac(const std::string ethInf,std::string & ethMac)205 int DhcpFunction::GetLocalMac(const std::string ethInf, std::string& ethMac)
206 {
207     struct ifreq ifr;
208     int sd = 0;
209 
210     bzero(&ifr, sizeof(struct ifreq));
211     if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
212         DHCP_LOGE("GetLocalMac socket ethInf:%{public}s,error:%{public}d!", ethInf.c_str(), errno);
213         return -1;
214     }
215 
216     if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ethInf.c_str(), IFNAMSIZ - 1) != EOK) {
217         close(sd);
218         return -1;
219     }
220 
221     if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) {
222         DHCP_LOGE("GetLocalMac ioctl ethInf:%{public}s,error:%{public}d!", ethInf.c_str(), errno);
223         close(sd);
224         return -1;
225     }
226 
227     char mac[ETH_MAC_ADDR_LEN * ETH_MAC_ADDR_CHAR_NUM] = { 0 };
228     int nRes = snprintf_s(mac,
229         ETH_MAC_ADDR_LEN * ETH_MAC_ADDR_CHAR_NUM,
230         ETH_MAC_ADDR_LEN * ETH_MAC_ADDR_CHAR_NUM - 1,
231         "%02x:%02x:%02x:%02x:%02x:%02x",
232         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_0],
233         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_1],
234         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_2],
235         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_3],
236         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_4],
237         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_5]);
238     if (nRes < 0) {
239         DHCP_LOGE("GetLocalMac snprintf_s ethInf:%{public}s,error:%{public}d!", ethInf.c_str(), errno);
240         close(sd);
241         return -1;
242     }
243     ethMac = mac;
244     close(sd);
245     return 0;
246 }
247 
CheckRangeNetwork(const std::string strInf,const std::string strBegin,const std::string strEnd)248 int DhcpFunction::CheckRangeNetwork(const std::string strInf, const std::string strBegin, const std::string strEnd)
249 {
250     if (strInf.empty() || strBegin.empty() || strEnd.empty()) {
251         DHCP_LOGE("CheckRangeNetwork param error, strInf or strBegin or strEnd is empty!");
252         return DHCP_OPT_ERROR;
253     }
254 
255     std::string strIp, strMask;
256     if (GetLocalIp(strInf, strIp, strMask) != DHCP_OPT_SUCCESS) {
257         DHCP_LOGE("CheckRangeNetwork get %{public}s local ip failed", strInf.c_str());
258         return DHCP_OPT_FAILED;
259     }
260 
261     uint32_t uIp, uMask, uBegin, uEnd;
262     if (!Ip4StrConToInt(strIp, uIp, false) || !Ip4StrConToInt(strMask, uMask, false) ||
263         !Ip4StrConToInt(strBegin, uBegin, false) || !Ip4StrConToInt(strEnd, uEnd, false)) {
264         DHCP_LOGE("CheckRangeNetwork %{public}s Ip4StrConToInt failed", strInf.c_str());
265         return DHCP_OPT_FAILED;
266     }
267 
268     if (!CheckSameNetwork(uIp, uBegin, uMask)) {
269         DHCP_LOGE("Check %{public}s %{private}s %{public}s failed", strInf.c_str(), strIp.c_str(), strBegin.c_str());
270         return DHCP_OPT_FAILED;
271     }
272     if (!CheckSameNetwork(uIp, uEnd, uMask)) {
273         DHCP_LOGE("Check end %{public}s %{private}s %{public}s failed", strInf.c_str(), strIp.c_str(), strEnd.c_str());
274         return DHCP_OPT_FAILED;
275     }
276     return DHCP_OPT_SUCCESS;
277 }
278 
CheckSameNetwork(const uint32_t srcIp,const uint32_t dstIp,const uint32_t maskIp)279 bool DhcpFunction::CheckSameNetwork(const uint32_t srcIp, const uint32_t dstIp, const uint32_t maskIp)
280 {
281     uint32_t srcNet = srcIp & maskIp;
282     uint32_t dstNet = dstIp & maskIp;
283     return (srcNet == dstNet);
284 }
285 
IsExistFile(const std::string & filename)286 bool DhcpFunction::IsExistFile(const std::string& filename)
287 {
288     FILE *file = fopen(filename.c_str(), "r");
289     if (file) {
290         (void)fclose(file);
291         return true;
292     } else {
293         DHCP_LOGE("IsExistFile %{public}s failed, err:%{public}d", filename.c_str(), errno);
294         return false;
295     }
296 }
297 
CreateFile(const std::string & filename,const std::string & filedata)298 bool DhcpFunction::CreateFile(const std::string& filename, const std::string& filedata)
299 {
300     if (!IsValidPath(filename)) {
301         DHCP_LOGE("invalid path:%{public}s", filename.c_str());
302         return false;
303     }
304 
305     FILE *file = fopen(filename.c_str(), "w");
306     if (!file) {
307         DHCP_LOGE("CreateFile %{public}s failed, err:%{public}d", filename.c_str(), errno);
308         return false;
309     }
310     if (fputs(filedata.c_str(), file) == EOF) {
311         DHCP_LOGE("Write to file %{public}s failed, err:%{public}d", filename.c_str(), errno);
312         (void)fclose(file);
313         return false;
314     }
315     (void)fflush(file);
316     (void)fsync(fileno(file));
317     (void)fclose(file);
318     return true;
319 }
320 
RemoveFile(const std::string & filename)321 bool DhcpFunction::RemoveFile(const std::string& filename)
322 {
323     if (std::remove(filename.c_str()) != 0) {
324         DHCP_LOGE("RemoveFile filename:%{public}s failed!", filename.c_str());
325         return false;
326     }
327     DHCP_LOGI("RemoveFile filename:%{public}s success.", filename.c_str());
328     return true;
329 }
330 
FormatString(struct DhcpPacketResult & result)331 int DhcpFunction::FormatString(struct DhcpPacketResult &result)
332 {
333     if (strncmp(result.strYiaddr, "*", 1) == 0) {
334         if (memset_s(result.strYiaddr, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
335             return -1;
336         }
337     }
338     if (strncmp(result.strOptServerId, "*", 1) == 0) {
339         if (memset_s(result.strOptServerId, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
340             return -1;
341         }
342     }
343     if (strncmp(result.strOptSubnet, "*", 1) == 0) {
344         if (memset_s(result.strOptSubnet, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
345             return -1;
346         }
347     }
348     if (strncmp(result.strOptDns1, "*", 1) == 0) {
349         if (memset_s(result.strOptDns1, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
350             return -1;
351         }
352     }
353     if (strncmp(result.strOptDns2, "*", 1) == 0) {
354         if (memset_s(result.strOptDns2, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
355             return -1;
356         }
357     }
358     if (strncmp(result.strOptRouter1, "*", 1) == 0) {
359         if (memset_s(result.strOptRouter1, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
360             return -1;
361         }
362     }
363     if (strncmp(result.strOptRouter2, "*", 1) == 0) {
364         if (memset_s(result.strOptRouter2, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
365             return -1;
366         }
367     }
368     if (strncmp(result.strOptVendor, "*", 1) == 0) {
369         if (memset_s(result.strOptVendor, DHCP_FILE_MAX_BYTES, 0, DHCP_FILE_MAX_BYTES) != EOK) {
370             return -1;
371         }
372     }
373     return 0;
374 }
375 
376 
377 #ifdef OHOS_ARCH_LITE
GetDhcpPacketResult(const std::string & filename,struct DhcpPacketResult & result)378 int DhcpFunction::GetDhcpPacketResult(const std::string& filename, struct DhcpPacketResult &result)
379 {
380     char *realPaths = realpath(filename.c_str(), nullptr);
381     if (realPaths == nullptr) {
382         DHCP_LOGE("realpath failed error");
383         return DHCP_OPT_FAILED;
384     }
385     FILE *pFile = fopen(realPaths, "r");
386     if (pFile == nullptr) {
387         DHCP_LOGE("GetDhcpPacketResult() fopen %{public}s fail, err:%{public}s!", filename.c_str(), strerror(errno));
388         free(realPaths);
389         return DHCP_OPT_FAILED;
390     }
391 
392     char strIpFlag[DHCP_NUM_EIGHT];
393     if (memset_s(strIpFlag, sizeof(strIpFlag), 0, sizeof(strIpFlag)) != EOK) {
394         (void)fclose(pFile);
395         free(realPaths);
396         return DHCP_OPT_FAILED;
397     }
398     /* Format: IpFlag AddTime cliIp servIp subnet dns1 dns2 router1 router2 vendor lease */
399     int nRes = fscanf_s(pFile, "%s %u %s %s %s %s %s %s %s %s %u\n", strIpFlag, DHCP_NUM_EIGHT, &result.uAddTime,
400         result.strYiaddr, INET_ADDRSTRLEN, result.strOptServerId, INET_ADDRSTRLEN, result.strOptSubnet, INET_ADDRSTRLEN,
401         result.strOptDns1, INET_ADDRSTRLEN, result.strOptDns2, INET_ADDRSTRLEN, result.strOptRouter1, INET_ADDRSTRLEN,
402         result.strOptRouter2, INET_ADDRSTRLEN, result.strOptVendor, DHCP_FILE_MAX_BYTES, &result.uOptLeasetime);
403     if (nRes == EOF) {
404         DHCP_LOGE("GetDhcpPacketResult() fscanf %{public}s err:%{public}s!", realPaths, strerror(errno));
405         (void)fclose(pFile);
406         free(realPaths);
407         return DHCP_OPT_FAILED;
408     } else if (nRes == 0) {
409         DHCP_LOGW("GetDhcpPacketResult() fscanf file:%{public}s nRes:0 nullptr!", realPaths);
410         (void)fclose(pFile);
411         free(realPaths);
412         return DHCP_OPT_NULL;
413     } else if (nRes != EVENT_DATA_NUM) {
414         DHCP_LOGE("GetDhcpPacketResult() fscanf file:%{public}s nRes:%{public}d ERROR!", realPaths, nRes);
415         (void)fclose(pFile);
416         free(realPaths);
417         return DHCP_OPT_FAILED;
418     }
419 
420     if (fclose(pFile) != 0) {
421         DHCP_LOGE("GetDhcpPacketResult() fclose file:%{public}s failed!", realPaths);
422         free(realPaths);
423         return DHCP_OPT_FAILED;
424     }
425 
426     /* Format dhcp packet result */
427     if (FormatString(result) != 0) {
428         DHCP_LOGE("GetDhcpPacketResult() file:%{public}s failed, FormatString result error!", realPaths);
429         free(realPaths);
430         return DHCP_OPT_FAILED;
431     }
432     free(realPaths);
433     return DHCP_OPT_SUCCESS;
434 }
435 #endif
436 
CreateDirs(const std::string dirs,int mode)437 int DhcpFunction::CreateDirs(const std::string dirs, int mode)
438 {
439     if (dirs.empty() || (dirs.size() >= DIR_MAX_LEN)) {
440         DHCP_LOGE("CreateDirs() dirs:%{public}s error!", dirs.c_str());
441         return DHCP_OPT_FAILED;
442     }
443 
444     int nSrcLen = (int)dirs.size();
445     char strDir[DIR_MAX_LEN] = {0};
446     if (strncpy_s(strDir, sizeof(strDir), dirs.c_str(), dirs.size()) != EOK) {
447         DHCP_LOGE("CreateDirs() strncpy_s dirs:%{public}s failed!", dirs.c_str());
448         return DHCP_OPT_FAILED;
449     }
450     if (strDir[nSrcLen - 1] != '/') {
451         if (nSrcLen == (DIR_MAX_LEN - 1)) {
452             DHCP_LOGE("CreateDirs() dirs:%{public}s len:%{public}d error!", dirs.c_str(), nSrcLen);
453             return DHCP_OPT_FAILED;
454         }
455         if (strcat_s(strDir, sizeof(strDir), "/") != EOK) {
456             DHCP_LOGE("CreateDirs() strcat_s strDir:%{public}s failed!", strDir);
457             return DHCP_OPT_FAILED;
458         }
459         nSrcLen++;
460     }
461 
462     int i = (strDir[0] == '/') ? 1 : 0;
463     for (; i <= nSrcLen - 1; i++) {
464         if (strDir[i] == '/') {
465             strDir[i] = 0;
466             if ((access(strDir, F_OK) != 0) && (mkdir(strDir, mode) != 0)) {
467                 DHCP_LOGE("CreateDirs() mkdir %{public}s %{public}.4o %{public}d!", strDir, mode, errno);
468                 return DHCP_OPT_FAILED;
469             }
470             strDir[i] = '/';
471         }
472     }
473     DHCP_LOGI("CreateDirs() %{public}s %{public}.4o success.", dirs.c_str(), mode);
474     return DHCP_OPT_SUCCESS;
475 }
476 }  // namespace DHCP
477 }  // namespace OHOS