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 
29 namespace OHOS {
30 namespace DHCP {
31 DEFINE_DHCPLOG_DHCP_LABEL("DhcpFunction");
32 
33 const int MAX_RETEY_WAIT_COUNT = 60;
34 const int WAIT_SLEEP_50MS = 50;
35 
Ip4StrConToInt(const std::string & strIp,uint32_t & uIp,bool bHost)36 bool DhcpFunction::Ip4StrConToInt(const std::string& strIp, uint32_t& uIp, bool bHost)
37 {
38     if (strIp.empty()) {
39         DHCP_LOGE("Ip4StrConToInt error, strIp is empty()!");
40         return false;
41     }
42 
43     struct in_addr addr4;
44     int nRet = inet_pton(AF_INET, strIp.c_str(), &addr4);
45     if (nRet != 1) {
46         DHCP_LOGE("Ip4StrConToInt strIp:%{private}s failed, nRet:%{public}d!", strIp.c_str(), nRet);
47         if (nRet == 0) {
48             DHCP_LOGE("Ip4StrConToInt strIp:%{private}s not in presentation format!", strIp.c_str());
49         } else {
50             DHCP_LOGE("Ip4StrConToInt strIp:%{private}s inet_pton not contain a valid address!", strIp.c_str());
51         }
52         return false;
53     }
54 
55     if (bHost) {
56         uIp = ntohl(addr4.s_addr);
57     } else {
58         uIp = addr4.s_addr;
59     }
60 
61     return true;
62 }
63 
Ip4IntConvertToStr(uint32_t uIp,bool bHost)64 std::string DhcpFunction::Ip4IntConvertToStr(uint32_t uIp, bool bHost)
65 {
66     char bufIp4[INET_ADDRSTRLEN] = {0};
67     struct in_addr addr4;
68     if (bHost) {
69         addr4.s_addr = htonl(uIp);
70     } else {
71         addr4.s_addr = uIp;
72     }
73 
74     std::string strIp = "";
75     if (inet_ntop(AF_INET, &addr4, bufIp4, INET_ADDRSTRLEN) == nullptr) {
76         DHCP_LOGE("Ip4IntConvertToStr uIp:%{private}u failed, inet_ntop nullptr!", uIp);
77     } else {
78         strIp = bufIp4;
79         DHCP_LOGI("Ip4IntConvertToStr uIp:%{private}u -> strIp:%{private}s.", uIp, strIp.c_str());
80     }
81 
82     return strIp;
83 }
84 
Ip6StrConToChar(const std::string & strIp,uint8_t chIp[],size_t uSize)85 bool DhcpFunction::Ip6StrConToChar(const std::string& strIp, uint8_t chIp[], size_t uSize)
86 {
87     if (strIp.empty()) {
88         DHCP_LOGE("Ip6StrConToChar param error, strIp is empty()!");
89         return false;
90     }
91 
92     struct in6_addr addr6;
93     if (memset_s(&addr6, sizeof(addr6), 0, sizeof(addr6)) != EOK) {
94         return false;
95     }
96     int nRet = inet_pton(AF_INET6, strIp.c_str(), &addr6);
97     if (nRet != 1) {
98         DHCP_LOGE("Ip6StrConToChar inet_pton strIp:%{private}s failed, nRet:%{public}d!", strIp.c_str(), nRet);
99         if (nRet == 0) {
100             DHCP_LOGE("Ip6StrConToChar strIp:%{private}s not in presentation format!", strIp.c_str());
101         } else {
102             DHCP_LOGE("Ip6StrConToChar strIp:%{private}s inet_pton not contain a valid address!", strIp.c_str());
103         }
104         return false;
105     }
106 
107     for (size_t i = 0; i < uSize; i++) {
108         chIp[i] = addr6.s6_addr[i];
109     }
110 
111     return true;
112 }
113 
Ip6CharConToStr(uint8_t chIp[],int size)114 std::string DhcpFunction::Ip6CharConToStr(uint8_t chIp[], int size)
115 {
116     if (size <= 0) {
117         DHCP_LOGE("Ip6CharConToStr param error, size:%{public}d!", size);
118         return "";
119     }
120 
121     std::string strIp = "";
122     char bufIp6[INET6_ADDRSTRLEN] = {0};
123     struct in6_addr addr6;
124     if (memcpy_s(addr6.s6_addr, sizeof(addr6.s6_addr), &chIp, size) != EOK) {
125         return "";
126     }
127     if (inet_ntop(AF_INET6, &addr6, bufIp6, INET6_ADDRSTRLEN) == nullptr) {
128         DHCP_LOGE("Ip6CharConToStr chIp failed, inet_ntop nullptr!");
129     } else {
130         strIp = bufIp6;
131         DHCP_LOGI("Ip6CharConToStr chIp -> strIp:%{private}s.", strIp.c_str());
132     }
133 
134     return strIp;
135 }
136 
CheckIpStr(const std::string & strIp)137 bool DhcpFunction::CheckIpStr(const std::string& strIp)
138 {
139     if (strIp.empty()) {
140         DHCP_LOGE("CheckIpStr param error, strIp is empty()!");
141         return false;
142     }
143 
144     bool bIp4 = false;
145     bool bIp6 = false;
146     std::string::size_type idx = strIp.find(IP4_SEPARATOR);
147     if (idx != std::string::npos) {
148         bIp4 = true;
149     }
150     idx = strIp.find(IP6_SEPARATOR);
151     if (idx != std::string::npos) {
152         bIp6 = true;
153     }
154     if ((!bIp4 && !bIp6) || (bIp4 && bIp6)) {
155         DHCP_LOGE("CheckIpStr strIp:%{private}s error, bIp4:%{public}d,bIp6:%{public}d!", strIp.c_str(), bIp4, bIp6);
156         return false;
157     }
158 
159     if (bIp4) {
160         uint32_t uIp = 0;
161         if (!Ip4StrConToInt(strIp, uIp)) {
162             DHCP_LOGE("CheckIpStr Ip4StrConToInt failed, strIp:%{private}s.", strIp.c_str());
163             return false;
164         }
165     } else {
166         uint8_t	addr6[sizeof(struct in6_addr)] = {0};
167         if (!Ip6StrConToChar(strIp, addr6, sizeof(struct in6_addr))) {
168             DHCP_LOGE("CheckIpStr Ip6StrConToChar failed, strIp:%{private}s.", strIp.c_str());
169             return false;
170         }
171     }
172 
173     return true;
174 }
175 
GetLocalIp(const std::string strInf,std::string & strIp,std::string & strMask)176 int DhcpFunction::GetLocalIp(const std::string strInf, std::string& strIp, std::string& strMask)
177 {
178     if (strInf.empty()) {
179         DHCP_LOGE("GetLocalIp param error, strInf is empty!");
180         return DHCP_OPT_ERROR;
181     }
182 
183     int fd;
184     if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
185         DHCP_LOGE("GetLocalIp strInf:%{public}s failed, socket err:%{public}d!", strInf.c_str(), errno);
186         return DHCP_OPT_FAILED;
187     }
188 
189     struct ifreq iface;
190     if (memset_s(&iface, sizeof(iface), 0, sizeof(iface)) != EOK) {
191         close(fd);
192         return DHCP_OPT_FAILED;
193     }
194     if (strncpy_s(iface.ifr_name, IFNAMSIZ, strInf.c_str(), IFNAMSIZ - 1) != EOK) {
195         close(fd);
196         return DHCP_OPT_FAILED;
197     }
198     iface.ifr_name[IFNAMSIZ - 1] = 0;
199 
200     /* inet addr */
201     if (ioctl(fd, SIOCGIFADDR, &iface) < 0) {
202         DHCP_LOGE("GetLocalIp() %{public}s failed, SIOCGIFADDR err:%{public}d!", strInf.c_str(), errno);
203         close(fd);
204         return DHCP_OPT_FAILED;
205     }
206     struct sockaddr_in *pSockIn = (struct sockaddr_in *)&iface.ifr_addr;
207     char bufIp4[INET_ADDRSTRLEN] = {0};
208     if (inet_ntop(AF_INET, &(pSockIn->sin_addr), bufIp4, INET_ADDRSTRLEN) != nullptr) {
209         strIp = bufIp4;
210     }
211 
212     /* netmask addr */
213     if (ioctl(fd, SIOCGIFNETMASK, &iface) < 0) {
214         DHCP_LOGE("GetLocalIp() %{public}s failed, SIOCGIFNETMASK err:%{public}d!", strInf.c_str(), errno);
215         close(fd);
216         return DHCP_OPT_FAILED;
217     }
218     pSockIn = (struct sockaddr_in *)&iface.ifr_addr;
219     char bufMask[INET_ADDRSTRLEN] = {0};
220     if (inet_ntop(AF_INET, &(pSockIn->sin_addr), bufMask, INET_ADDRSTRLEN) != nullptr) {
221         strMask = bufMask;
222     }
223 
224     close(fd);
225     return DHCP_OPT_SUCCESS;
226 }
227 
GetLocalMac(const std::string ethInf,std::string & ethMac)228 int DhcpFunction::GetLocalMac(const std::string ethInf, std::string& ethMac)
229 {
230     struct ifreq ifr;
231     int sd = 0;
232 
233     bzero(&ifr, sizeof(struct ifreq));
234     if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
235         DHCP_LOGE("GetLocalMac socket ethInf:%{public}s,error:%{public}d!", ethInf.c_str(), errno);
236         return -1;
237     }
238 
239     if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ethInf.c_str(), IFNAMSIZ - 1) != EOK) {
240         close(sd);
241         return -1;
242     }
243 
244     if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) {
245         DHCP_LOGE("GetLocalMac ioctl ethInf:%{public}s,error:%{public}d!", ethInf.c_str(), errno);
246         close(sd);
247         return -1;
248     }
249 
250     char mac[ETH_MAC_ADDR_LEN * ETH_MAC_ADDR_CHAR_NUM] = { 0 };
251     int nRes = snprintf_s(mac,
252         ETH_MAC_ADDR_LEN * ETH_MAC_ADDR_CHAR_NUM,
253         ETH_MAC_ADDR_LEN * ETH_MAC_ADDR_CHAR_NUM - 1,
254         "%02x:%02x:%02x:%02x:%02x:%02x",
255         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_0],
256         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_1],
257         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_2],
258         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_3],
259         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_4],
260         (unsigned char)ifr.ifr_hwaddr.sa_data[ETH_MAC_ADDR_INDEX_5]);
261     if (nRes < 0) {
262         DHCP_LOGE("GetLocalMac snprintf_s ethInf:%{public}s,error:%{public}d!", ethInf.c_str(), errno);
263         close(sd);
264         return -1;
265     }
266     ethMac = mac;
267     close(sd);
268     return 0;
269 }
270 
CheckRangeNetwork(const std::string strInf,const std::string strBegin,const std::string strEnd)271 int DhcpFunction::CheckRangeNetwork(const std::string strInf, const std::string strBegin, const std::string strEnd)
272 {
273     if (strInf.empty() || strBegin.empty() || strEnd.empty()) {
274         DHCP_LOGE("CheckRangeNetwork param error, strInf or strBegin or strEnd is empty!");
275         return DHCP_OPT_ERROR;
276     }
277 
278     std::string strIp, strMask;
279     if (GetLocalIp(strInf, strIp, strMask) != DHCP_OPT_SUCCESS) {
280         DHCP_LOGE("CheckRangeNetwork get %{public}s local ip failed", strInf.c_str());
281         return DHCP_OPT_FAILED;
282     }
283 
284     uint32_t uIp, uMask, uBegin, uEnd;
285     if (!Ip4StrConToInt(strIp, uIp, false) || !Ip4StrConToInt(strMask, uMask, false) ||
286         !Ip4StrConToInt(strBegin, uBegin, false) || !Ip4StrConToInt(strEnd, uEnd, false)) {
287         DHCP_LOGE("CheckRangeNetwork %{public}s Ip4StrConToInt failed", strInf.c_str());
288         return DHCP_OPT_FAILED;
289     }
290 
291     if (!CheckSameNetwork(uIp, uBegin, uMask)) {
292         DHCP_LOGE("Check %{public}s %{private}s %{public}s failed", strInf.c_str(), strIp.c_str(), strBegin.c_str());
293         return DHCP_OPT_FAILED;
294     }
295     if (!CheckSameNetwork(uIp, uEnd, uMask)) {
296         DHCP_LOGE("Check end %{public}s %{private}s %{public}s failed", strInf.c_str(), strIp.c_str(), strEnd.c_str());
297         return DHCP_OPT_FAILED;
298     }
299     return DHCP_OPT_SUCCESS;
300 }
301 
CheckSameNetwork(const uint32_t srcIp,const uint32_t dstIp,const uint32_t maskIp)302 bool DhcpFunction::CheckSameNetwork(const uint32_t srcIp, const uint32_t dstIp, const uint32_t maskIp)
303 {
304     uint32_t srcNet = srcIp & maskIp;
305     uint32_t dstNet = dstIp & maskIp;
306     return (srcNet == dstNet);
307 }
308 
IsExistFile(const std::string & filename)309 bool DhcpFunction::IsExistFile(const std::string& filename)
310 {
311     bool bExist = false;
312     std::fstream ioFile;
313     ioFile.open(filename.c_str(), std::ios::in);
314     if (ioFile) {
315         bExist = true;
316     }
317     DHCP_LOGE("IsExistFile %{public}s failed, err:%{public}d", filename.c_str(), errno);
318     ioFile.close();
319 
320     return bExist;
321 }
322 
CreateFile(const std::string & filename,const std::string & filedata)323 bool DhcpFunction::CreateFile(const std::string& filename, const std::string& filedata)
324 {
325     std::ofstream outFile;
326     outFile.open(filename.c_str());
327     outFile.flush();
328     outFile << filedata << std::endl;
329     outFile.close();
330     return true;
331 }
332 
RemoveFile(const std::string & filename)333 bool DhcpFunction::RemoveFile(const std::string& filename)
334 {
335     if (std::remove(filename.c_str()) != 0) {
336         DHCP_LOGE("RemoveFile filename:%{public}s failed!", filename.c_str());
337         return false;
338     }
339     DHCP_LOGI("RemoveFile filename:%{public}s success.", filename.c_str());
340     return true;
341 }
342 
AddFileLineData(const std::string & filename,const std::string & prevdata,const std::string & linedata)343 bool DhcpFunction::AddFileLineData(const std::string& filename, const std::string& prevdata, const std::string& linedata)
344 {
345     bool bAdd = false;
346     std::ifstream inFile;
347     inFile.open(filename.c_str());
348     std::string strFileData = "";
349     std::string strTemp = "";
350     char tmpLineData[1024] = {0};
351     while (inFile.getline(tmpLineData, sizeof(tmpLineData))) {
352         strTemp = tmpLineData;
353         strFileData += strTemp;
354         strFileData += "\n";
355         if (strTemp == prevdata) {
356             strFileData += linedata;
357             bAdd = true;
358         }
359     }
360     inFile.close();
361 
362     if (bAdd) {
363         std::ofstream outFile;
364         outFile.open(filename.c_str());
365         outFile.flush();
366         DHCP_LOGI("AddFileLineData Reflush filename:%{public}s, strFileData:%{public}s.",
367             filename.c_str(), strFileData.c_str());
368         outFile << strFileData;
369         outFile.close();
370     }
371     return true;
372 }
373 
DelFileLineData(const std::string & filename,const std::string & linedata)374 bool DhcpFunction::DelFileLineData(const std::string& filename, const std::string& linedata)
375 {
376     bool bDel = false;
377     std::ifstream inFile;
378     inFile.open(filename.c_str());
379     std::string strFileData = "";
380     std::string strTemp = "";
381     char tmpLineData[1024] = {0};
382     while (inFile.getline(tmpLineData, sizeof(tmpLineData))) {
383         strTemp = tmpLineData;
384         if (strTemp != linedata) {
385             strFileData += strTemp;
386             strFileData += "\n";
387         } else {
388             bDel = true;
389         }
390     }
391     inFile.close();
392 
393     if (bDel) {
394         std::ofstream outFile;
395         outFile.open(filename.c_str());
396         outFile.flush();
397         DHCP_LOGI("DelFileLineData Reflush filename:%{public}s, strFileData:%{public}s.",
398             filename.c_str(), strFileData.c_str());
399         outFile << strFileData;
400         outFile.close();
401     }
402     return true;
403 }
404 
ModifyFileLineData(const std::string & filename,const std::string & srcdata,const std::string & dstdata)405 bool DhcpFunction::ModifyFileLineData(const std::string& filename, const std::string& srcdata,
406     const std::string& dstdata)
407 {
408     bool bModify = false;
409     std::ifstream inFile;
410     inFile.open(filename.c_str());
411     std::string strFileData = "";
412     std::string strTemp = "";
413     char tmpLineData[1024] = {0};
414     while (inFile.getline(tmpLineData, sizeof(tmpLineData))) {
415         strTemp = tmpLineData;
416         if (strTemp != srcdata) {
417             strFileData += strTemp;
418             strFileData += "\n";
419         } else {
420             strFileData += dstdata;
421             strFileData += "\n";
422             bModify = true;
423         }
424     }
425     inFile.close();
426 
427     if (bModify) {
428         std::ofstream outFile;
429         outFile.open(filename.c_str());
430         outFile.flush();
431         DHCP_LOGI("ModifyFileLineData Reflush filename:%{public}s, strFileData:%{public}s.",
432             filename.c_str(), strFileData.c_str());
433         outFile << strFileData;
434         outFile.close();
435     }
436     return true;
437 }
438 
FormatString(struct DhcpPacketResult & result)439 int DhcpFunction::FormatString(struct DhcpPacketResult &result)
440 {
441     if (strncmp(result.strYiaddr, "*", 1) == 0) {
442         if (memset_s(result.strYiaddr, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
443             return -1;
444         }
445     }
446     if (strncmp(result.strOptServerId, "*", 1) == 0) {
447         if (memset_s(result.strOptServerId, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
448             return -1;
449         }
450     }
451     if (strncmp(result.strOptSubnet, "*", 1) == 0) {
452         if (memset_s(result.strOptSubnet, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
453             return -1;
454         }
455     }
456     if (strncmp(result.strOptDns1, "*", 1) == 0) {
457         if (memset_s(result.strOptDns1, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
458             return -1;
459         }
460     }
461     if (strncmp(result.strOptDns2, "*", 1) == 0) {
462         if (memset_s(result.strOptDns2, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
463             return -1;
464         }
465     }
466     if (strncmp(result.strOptRouter1, "*", 1) == 0) {
467         if (memset_s(result.strOptRouter1, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
468             return -1;
469         }
470     }
471     if (strncmp(result.strOptRouter2, "*", 1) == 0) {
472         if (memset_s(result.strOptRouter2, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN) != EOK) {
473             return -1;
474         }
475     }
476     if (strncmp(result.strOptVendor, "*", 1) == 0) {
477         if (memset_s(result.strOptVendor, DHCP_FILE_MAX_BYTES, 0, DHCP_FILE_MAX_BYTES) != EOK) {
478             return -1;
479         }
480     }
481     return 0;
482 }
483 
484 #ifdef OHOS_ARCH_LITE
GetDhcpPacketResult(const std::string & filename,struct DhcpPacketResult & result)485 int DhcpFunction::GetDhcpPacketResult(const std::string& filename, struct DhcpPacketResult &result)
486 {
487     FILE *pFile = fopen(filename.c_str(), "r");
488     if (pFile == nullptr) {
489         DHCP_LOGE("GetDhcpPacketResult() fopen %{public}s fail, err:%{public}s!", filename.c_str(), strerror(errno));
490         return DHCP_OPT_FAILED;
491     }
492 
493     char strIpFlag[DHCP_NUM_EIGHT];
494     if (memset_s(strIpFlag, sizeof(strIpFlag), 0, sizeof(strIpFlag)) != EOK) {
495         fclose(pFile);
496         return DHCP_OPT_FAILED;
497     }
498     /* Format: IpFlag AddTime cliIp servIp subnet dns1 dns2 router1 router2 vendor lease */
499     int nRes = fscanf_s(pFile, "%s %u %s %s %s %s %s %s %s %s %u\n", strIpFlag, DHCP_NUM_EIGHT, &result.uAddTime,
500         result.strYiaddr, INET_ADDRSTRLEN, result.strOptServerId, INET_ADDRSTRLEN, result.strOptSubnet, INET_ADDRSTRLEN,
501         result.strOptDns1, INET_ADDRSTRLEN, result.strOptDns2, INET_ADDRSTRLEN, result.strOptRouter1, INET_ADDRSTRLEN,
502         result.strOptRouter2, INET_ADDRSTRLEN, result.strOptVendor, DHCP_FILE_MAX_BYTES, &result.uOptLeasetime);
503     if (nRes == EOF) {
504         DHCP_LOGE("GetDhcpPacketResult() fscanf %{public}s err:%{public}s!", filename.c_str(), strerror(errno));
505         fclose(pFile);
506         return DHCP_OPT_FAILED;
507     } else if (nRes == 0) {
508         DHCP_LOGW("GetDhcpPacketResult() fscanf file:%{public}s nRes:0 nullptr!", filename.c_str());
509         fclose(pFile);
510         return DHCP_OPT_NULL;
511     } else if (nRes != EVENT_DATA_NUM) {
512         DHCP_LOGE("GetDhcpPacketResult() fscanf file:%{public}s nRes:%{public}d ERROR!", filename.c_str(), nRes);
513         fclose(pFile);
514         return DHCP_OPT_FAILED;
515     }
516 
517     if (fclose(pFile) != 0) {
518         DHCP_LOGE("GetDhcpPacketResult() fclose file:%{public}s failed!", filename.c_str());
519         return DHCP_OPT_FAILED;
520     }
521 
522     /* Format dhcp packet result */
523     if (FormatString(result) != 0) {
524         DHCP_LOGE("GetDhcpPacketResult() file:%{public}s failed, FormatString result error!", filename.c_str());
525         return DHCP_OPT_FAILED;
526     }
527 
528     return DHCP_OPT_SUCCESS;
529 }
530 #endif
531 
InitPidfile(const std::string & piddir,const std::string & pidfile)532 int DhcpFunction::InitPidfile(const std::string& piddir, const std::string& pidfile)
533 {
534     if (piddir.empty() || pidfile.empty()) {
535         DHCP_LOGE("InitPidfile() failed, piddir or pidfile is empty!");
536         return DHCP_OPT_FAILED;
537     }
538     DHCP_LOGI("InitPidfile() piddir:%{public}s, pidfile:%{public}s.", piddir.c_str(), pidfile.c_str());
539     unlink(pidfile.c_str());
540 
541     int fd;
542     if ((fd = open(pidfile.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
543         DHCP_LOGE("InitPidfile() failed, open pidfile:%{public}s err:%{public}d!", pidfile.c_str(), errno);
544         return DHCP_OPT_FAILED;
545     }
546 
547     char buf[PID_MAX_LEN] = {0};
548     if (snprintf_s(buf, PID_MAX_LEN, PID_MAX_LEN - 1, "%d", getpid()) < 0) {
549         DHCP_LOGE("InitPidfile() %{public}s failed, snprintf_s error:%{public}d!", pidfile.c_str(), errno);
550         close(fd);
551         return DHCP_OPT_FAILED;
552     }
553     ssize_t bytes;
554     if ((bytes = write(fd, buf, strlen(buf))) <= 0) {
555         DHCP_LOGE("InitPidfile() failed, write pidfile:%{public}s error:%{public}d, bytes:%{public}zd!",
556             pidfile.c_str(), errno, bytes);
557         close(fd);
558         return DHCP_OPT_FAILED;
559     }
560     DHCP_LOGI("InitPidfile() pid:%{public}s write %{public}s, bytes:%{public}zd!", buf, pidfile.c_str(), bytes);
561     close(fd);
562 
563     if (chdir(piddir.c_str()) != 0) {
564         DHCP_LOGE("InitPidfile() failed, chdir piddir:%{public}s err:%{public}d!", piddir.c_str(), errno);
565         return DHCP_OPT_FAILED;
566     }
567 
568     /* Set default permissions for the specified client process id files and directories. */
569     umask(DEFAULT_UMASK);
570 
571     /* Change attribs to the specified client process id files: 644 (user=rw, group=r, other=r). */
572     chmod(pidfile.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
573 
574     return DHCP_OPT_SUCCESS;
575 }
576 
GetPID(const std::string & pidfile)577 pid_t DhcpFunction::GetPID(const std::string& pidfile)
578 {
579     /* Check pidfile is or not exists. */
580     struct stat sb;
581     if (stat(pidfile.c_str(), &sb) != 0) {
582         DHCP_LOGW("GetPID() pidfile:%{public}s stat:%{public}d!", pidfile.c_str(), errno);
583         return -1;
584     }
585     DHCP_LOGI("GetPID() pidfile:%{public}s stat st_size:%{public}d.", pidfile.c_str(), (int)sb.st_size);
586 
587     int fd;
588     if ((fd = open(pidfile.c_str(), O_RDONLY)) < 0) {
589         DHCP_LOGE("GetPID() failed, open pidfile:%{public}s error!", pidfile.c_str());
590         return -1;
591     }
592 
593     lseek(fd, 0, SEEK_SET);
594 
595     char buf[PID_MAX_LEN] = {0};
596     ssize_t bytes;
597     if ((bytes = read(fd, buf, sb.st_size)) < 0) {
598         DHCP_LOGE("GetPID() failed, read pidfile:%{public}s error, bytes:%{public}zd!", pidfile.c_str(), bytes);
599         close(fd);
600         return -1;
601     }
602     DHCP_LOGI("GetPID() read pidfile:%{public}s, buf:%{public}s, bytes:%{public}zd.", pidfile.c_str(), buf, bytes);
603     close(fd);
604 
605     return atoi(buf);
606 }
607 
CheckProRunning(const pid_t proPid,const std::string & proName)608 int DhcpFunction::CheckProRunning(const pid_t proPid, const std::string& proName)
609 {
610     if ((proPid == 0) || proName.empty()) {
611         DHCP_LOGE("CheckProRunning %{public}s param error!", proName.c_str());
612         return -1;
613     }
614     char buf[DIR_MAX_LEN] = {0};
615     if (snprintf_s(buf, DIR_MAX_LEN, DIR_MAX_LEN - 1, "/proc/%ld", (long int)proPid) < 0) {
616         DHCP_LOGE("CheckProRunning %{public}s failed, snprintf_s errno:%{public}d!", proName.c_str(), errno);
617         return -1;
618     }
619     if (access(buf, F_OK) != 0) {
620         DHCP_LOGI("CheckProRunning %{public}s is not exist, %{public}s no running", buf, proName.c_str());
621         return 0;
622     }
623     if (strcat_s(buf, sizeof(buf), "/exe") != EOK) {
624         DHCP_LOGE("CheckProRunning %{public}s failed, strcat_s errno:%{public}d!", proName.c_str(), errno);
625         return -1;
626     }
627     char proBuf[DIR_MAX_LEN] = {0};
628     if (readlink(buf, proBuf, sizeof(proBuf)) < 0) {
629         DHCP_LOGE("CheckProRunning %{public}s failed, readlink errno:%{public}d!", proName.c_str(), errno);
630         return -1;
631     }
632     if (strstr(proBuf, proName.c_str()) == nullptr) {
633         DHCP_LOGI("CheckProRunning %{public}s exe -> %{public}s, %{public}s no running", buf, proBuf, proName.c_str());
634         return 0;
635     }
636     DHCP_LOGI("CheckProRunning %{public}s exe -> %{public}s, %{public}s is running", buf, proBuf, proName.c_str());
637     return 1;
638 }
639 
CreateDirs(const std::string dirs,int mode)640 int DhcpFunction::CreateDirs(const std::string dirs, int mode)
641 {
642     if (dirs.empty() || (dirs.size() >= DIR_MAX_LEN)) {
643         DHCP_LOGE("CreateDirs() dirs:%{public}s error!", dirs.c_str());
644         return DHCP_OPT_FAILED;
645     }
646 
647     int nSrcLen = (int)dirs.size();
648     char strDir[DIR_MAX_LEN] = {0};
649     if (strncpy_s(strDir, sizeof(strDir), dirs.c_str(), dirs.size()) != EOK) {
650         DHCP_LOGE("CreateDirs() strncpy_s dirs:%{public}s failed!", dirs.c_str());
651         return DHCP_OPT_FAILED;
652     }
653     if (strDir[nSrcLen - 1] != '/') {
654         if (nSrcLen == (DIR_MAX_LEN - 1)) {
655             DHCP_LOGE("CreateDirs() dirs:%{public}s len:%{public}d error!", dirs.c_str(), nSrcLen);
656             return DHCP_OPT_FAILED;
657         }
658         if (strcat_s(strDir, sizeof(strDir), "/") != EOK) {
659             DHCP_LOGE("CreateDirs() strcat_s strDir:%{public}s failed!", strDir);
660             return DHCP_OPT_FAILED;
661         }
662         nSrcLen++;
663     }
664 
665     int i = (strDir[0] == '/') ? 1 : 0;
666     for (; i <= nSrcLen - 1; i++) {
667         if (strDir[i] == '/') {
668             strDir[i] = 0;
669             if ((access(strDir, F_OK) != 0) && (mkdir(strDir, mode) != 0)) {
670                 DHCP_LOGE("CreateDirs() mkdir %{public}s %{public}.4o %{public}d!", strDir, mode, errno);
671                 return DHCP_OPT_FAILED;
672             }
673             strDir[i] = '/';
674         }
675     }
676     DHCP_LOGI("CreateDirs() %{public}s %{public}.4o success.", dirs.c_str(), mode);
677     return DHCP_OPT_SUCCESS;
678 }
679 
SplitString(const std::string src,const std::string delim,const int count,std::vector<std::string> & splits)680 bool DhcpFunction::SplitString(
681     const std::string src, const std::string delim, const int count, std::vector<std::string> &splits)
682 {
683     if (src.empty() || delim.empty()) {
684         DHCP_LOGE("SplitString() error, src or delim is empty!");
685         return false;
686     }
687 
688     splits.clear();
689 
690     std::string strData(src);
691     int nDelim = 0;
692     char *pSave = nullptr;
693     char *pTok = strtok_r(const_cast<char *>(strData.c_str()), delim.c_str(), &pSave);
694     while (pTok != nullptr) {
695         splits.push_back(std::string(pTok));
696         nDelim++;
697         pTok = strtok_r(nullptr, delim.c_str(), &pSave);
698     }
699     if (nDelim != count) {
700         DHCP_LOGE("SplitString() %{private}s failed, nDelim:%{public}d,count:%{public}d!", src.c_str(), nDelim, count);
701         return false;
702     }
703     DHCP_LOGI("SplitString() %{private}s success, delim:%{public}s, count:%{public}d, splits.size():%{public}d.",
704         src.c_str(), delim.c_str(), count, (int)splits.size());
705     return true;
706 }
707 
WaitProcessExit(const pid_t & serverPid)708 int DhcpFunction::WaitProcessExit(const pid_t& serverPid)
709 {
710     int retryCount = 0;
711     while (retryCount < MAX_RETEY_WAIT_COUNT) {
712         pid_t ret = waitpid(serverPid, nullptr, WNOHANG);
713         if (ret == -1) {
714             DHCP_LOGE("WaitProcessExit() waitpid [%{public}d] failed, errno:%{public}d!", serverPid, errno);
715             return -1;
716         } else if (ret == 0) {
717             retryCount++;
718             usleep(WAIT_SLEEP_50MS);
719         }
720         return 0;
721     }
722     DHCP_LOGE("WaitProcessExit() timeout waitpid [%{public}d] failed!", serverPid);
723     return -1;
724 }
725 }  // namespace DHCP
726 }  // namespace OHOS