1 /*
2  * Copyright (C) 2024 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 <sys/socket.h>
16 #include <sys/ioctl.h>
17 #include <net/if_arp.h>
18 #include <netinet/in.h>
19 #include <unistd.h>
20 
21 #include "dhcp_common_utils.h"
22 #include <arpa/inet.h>
23 #include <netinet/if_ether.h>
24 #include <regex>
25 #include "securec.h"
26 #include "dhcp_logger.h"
27 
28 namespace OHOS {
29 namespace DHCP {
30 DEFINE_DHCPLOG_DHCP_LABEL("DhcpCommonUtils");
31 
32 constexpr int32_t GATEWAY_MAC_LENTH = 18;
33 constexpr int32_t MAC_INDEX_0 = 0;
34 constexpr int32_t MAC_INDEX_1 = 1;
35 constexpr int32_t MAC_INDEX_2 = 2;
36 constexpr int32_t MAC_INDEX_3 = 3;
37 constexpr int32_t MAC_INDEX_4 = 4;
38 constexpr int32_t MAC_INDEX_5 = 5;
39 constexpr int32_t MAC_LENTH = 6;
40 
Ipv4Anonymize(const std::string str)41 std::string Ipv4Anonymize(const std::string str)
42 {
43     std::string strTemp = str;
44     std::string::size_type begin = strTemp.find_last_of('.');
45     while (begin < strTemp.length()) {
46         if (strTemp[begin] != '.') {
47             strTemp[begin] = '*';
48         }
49         begin++;
50     }
51     return strTemp;
52 }
53 
UintIp4ToStr(uint32_t uIp,bool bHost)54 char *UintIp4ToStr(uint32_t uIp, bool bHost)
55 {
56     char bufIp4[INET_ADDRSTRLEN] = {0};
57     struct in_addr addr4;
58     if (bHost) {
59         addr4.s_addr = htonl(uIp);
60     } else {
61         addr4.s_addr = uIp;
62     }
63     const char *p = inet_ntop(AF_INET, &addr4, bufIp4, INET_ADDRSTRLEN);
64     if (p == nullptr) {
65         DHCP_LOGE("UintIp4ToStr inet_ntop p == nullptr!");
66         return nullptr;
67     }
68     char *strIp = static_cast<char *>(malloc(INET_ADDRSTRLEN));
69     if (strIp == nullptr) {
70         DHCP_LOGE("UintIp4ToStr strIp malloc failed!");
71         return nullptr;
72     }
73     if (strncpy_s(strIp, INET_ADDRSTRLEN, bufIp4, strlen(bufIp4)) != EOK) {
74         DHCP_LOGE("UintIp4ToStr strIp strncpy_s failed!");
75         free(strIp);
76         strIp = nullptr;
77         return nullptr;
78     }
79     return strIp;
80 }
81 
IntIpv4ToAnonymizeStr(uint32_t ip)82 std::string IntIpv4ToAnonymizeStr(uint32_t ip)
83 {
84     std::string strTemp = "";
85     char *pIp = UintIp4ToStr(ip, false);
86     if (pIp != nullptr) {
87         strTemp = Ipv4Anonymize(pIp);
88         free(pIp);
89         pIp = nullptr;
90     }
91     return strTemp;
92 }
93 
MacArray2Str(uint8_t * macArray,int32_t len)94 std::string MacArray2Str(uint8_t *macArray, int32_t len)
95 {
96     if ((macArray == nullptr) || (len != ETH_ALEN)) {
97         DHCP_LOGE("MacArray2Str arg is invalid!");
98         return "";
99     }
100 
101     char gwMacAddr[GATEWAY_MAC_LENTH] = {0};
102     if (sprintf_s(gwMacAddr, sizeof(gwMacAddr), "%02x:%02x:%02x:%02x:%02x:%02x", macArray[MAC_INDEX_0],
103         macArray[MAC_INDEX_1], macArray[MAC_INDEX_2], macArray[MAC_INDEX_3], macArray[MAC_INDEX_4],
104         macArray[MAC_INDEX_5]) < 0) {
105         DHCP_LOGE("MacArray2Str sprintf_s err");
106         return "";
107     }
108     std::string ret = gwMacAddr;
109     return ret;
110 }
111 
CheckDataLegal(std::string & data,int base)112 int CheckDataLegal(std::string &data, int base)
113 {
114     std::regex pattern("\\d+");
115     if (!std::regex_search(data, pattern)) {
116         return 0;
117     }
118     errno = 0;
119     char *endptr = nullptr;
120     long int num = std::strtol(data.c_str(), &endptr, base);
121     if (errno == ERANGE) {
122         DHCP_LOGE("CheckDataLegal errno == ERANGE, data:%{private}s", data.c_str());
123         return 0;
124     }
125     return static_cast<int>(num);
126 }
127 
CheckDataToUint(std::string & data,int base)128 unsigned int CheckDataToUint(std::string &data, int base)
129 {
130     std::regex pattern("\\d+");
131     std::regex patternTmp("-\\d+");
132     if (!std::regex_search(data, pattern) || std::regex_search(data, patternTmp)) {
133         DHCP_LOGE("CheckDataToUint regex unsigned int value fail, data:%{private}s", data.c_str());
134         return 0;
135     }
136     errno = 0;
137     char *endptr = nullptr;
138     unsigned long int num = std::strtoul(data.c_str(), &endptr, base);
139     if (errno == ERANGE) {
140         DHCP_LOGE("CheckDataToUint errno == ERANGE, data:%{private}s", data.c_str());
141         return 0;
142     }
143     return static_cast<unsigned int>(num);
144 }
145 
CheckDataTolonglong(std::string & data,int base)146 long long CheckDataTolonglong(std::string &data, int base)
147 {
148     std::regex pattern("\\d+");
149     if (!std::regex_search(data, pattern)) {
150         return 0;
151     }
152     errno = 0;
153     char *endptr = nullptr;
154     long long int num = std::strtoll(data.c_str(), &endptr, base);
155     if (errno == ERANGE) {
156         DHCP_LOGE("CheckDataTolonglong errno == ERANGE, data:%{private}s", data.c_str());
157         return 0;
158     }
159     return num;
160 }
161 
GetElapsedSecondsSinceBoot()162 int64_t GetElapsedSecondsSinceBoot()
163 {
164     struct timespec times = {0, 0};
165     clock_gettime(CLOCK_BOOTTIME, &times);
166     return static_cast<int64_t>(times.tv_sec);
167 }
168 
Ip4IntConvertToStr(uint32_t uIp,bool bHost)169 std::string Ip4IntConvertToStr(uint32_t uIp, bool bHost)
170 {
171     char bufIp4[INET_ADDRSTRLEN] = {0};
172     struct in_addr addr4;
173     if (bHost) {
174         addr4.s_addr = htonl(uIp);
175     } else {
176         addr4.s_addr = uIp;
177     }
178 
179     std::string strIp = "";
180     if (inet_ntop(AF_INET, &addr4, bufIp4, INET_ADDRSTRLEN) == nullptr) {
181         DHCP_LOGE("Ip4IntConvertToStr uIp:%{private}u failed, inet_ntop nullptr!", uIp);
182     } else {
183         strIp = bufIp4;
184         DHCP_LOGI("Ip4IntConvertToStr uIp:%{private}u -> strIp:%{private}s.", uIp, strIp.c_str());
185     }
186 
187     return strIp;
188 }
189 
GetMacAddr(char * buff,const char * macAddr)190 static int32_t GetMacAddr(char *buff, const char *macAddr)
191 {
192     unsigned int addr[MAC_LENTH] = {0};
193     if (buff == nullptr || macAddr == nullptr) {
194         DHCP_LOGE("buff or macAddr is nullptr");
195         return -1;
196     }
197 
198     if (sscanf_s(macAddr, "%x:%x:%x:%x:%x:%x", &addr[MAC_INDEX_0], &addr[MAC_INDEX_1], &addr[MAC_INDEX_2],
199         &addr[MAC_INDEX_3], &addr[MAC_INDEX_4], &addr[MAC_INDEX_5]) < MAC_LENTH) {
200         DHCP_LOGE("sscanf_s macAddr err");
201         return -1;
202     }
203 
204     for (int32_t i = 0; i < MAC_LENTH; i++) {
205         buff[i] = addr[i];
206     }
207     return 0;
208 }
209 
AddArpEntry(const std::string & iface,const std::string & ipAddr,const std::string & macAddr)210 int32_t AddArpEntry(const std::string& iface, const std::string& ipAddr, const std::string& macAddr)
211 {
212     DHCP_LOGI("AddArpEntry enter");
213     struct arpreq req;
214     struct sockaddr_in *sin = nullptr;
215 
216     if (iface.empty() || ipAddr.empty() || macAddr.empty()) {
217         DHCP_LOGE("AddArpEntry arg is invalid");
218         return -1;
219     }
220 
221     if (memset_s(&req, sizeof(struct arpreq), 0, sizeof(struct arpreq)) != EOK) {
222         DHCP_LOGE("DelStaticArp memset_s err");
223         return -1;
224     }
225     sin = reinterpret_cast<struct sockaddr_in *>(&req.arp_pa);
226     sin->sin_family = AF_INET;
227     sin->sin_addr.s_addr = inet_addr(ipAddr.c_str());
228     if (strncpy_s(req.arp_dev, sizeof(req.arp_dev), iface.c_str(), iface.size()) != EOK) {
229         DHCP_LOGE("strncpy_s req err");
230         return -1;
231     }
232 
233     req.arp_flags = ATF_PERM | ATF_COM;
234     if (GetMacAddr(reinterpret_cast<char *>(req.arp_ha.sa_data), macAddr.c_str()) < 0) {
235         DHCP_LOGE("AddArpEntry GetMacAddr error");
236         return -1;
237     }
238 
239     int32_t sockFd = socket(AF_INET, SOCK_DGRAM, 0);
240     if (sockFd < 0) {
241         DHCP_LOGE("DoArpItem socket creat error");
242         return -1;
243     }
244 
245     int32_t ret = ioctl(sockFd, SIOCSARP, req);
246     if (ret < 0) {
247         DHCP_LOGE("DoArpItem ioctl error");
248     }
249     close(sockFd);
250     return ret;
251 }
252 }
253 }