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