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