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
29namespace OHOS {
30namespace DHCP {
31DEFINE_DHCPLOG_DHCP_LABEL("DhcpFunction");
32
33const int MAX_RETEY_WAIT_COUNT = 60;
34const int WAIT_SLEEP_50MS = 50;
35
36bool 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
64std::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
85bool 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
114std::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
137bool 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
176int 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
228int 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
271int 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
302bool 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
309bool 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
323bool 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
333bool 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
343bool 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
374bool 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
405bool 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
439int 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
485int 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
532int 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
577pid_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
608int 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
640int 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
680bool 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
708int 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