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