• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 
16 #include "netmanager_base_common_utils.h"
17 
18 #include <algorithm>
19 #include <arpa/inet.h>
20 #include <cstddef>
21 #include <cstdlib>
22 #include <netinet/in.h>
23 #include <regex>
24 #include <string>
25 #include <sys/socket.h>
26 #include <sys/wait.h>
27 #include <type_traits>
28 #include <unistd.h>
29 #include <vector>
30 
31 #include "net_manager_constants.h"
32 #include "net_mgr_log_wrapper.h"
33 #include "securec.h"
34 
35 namespace OHOS::NetManagerStandard::CommonUtils {
36 constexpr int32_t INET_OPTION_SUC = 1;
37 constexpr int32_t DECIMAL_SYSTEM = 10;
38 constexpr uint32_t CONST_MASK = 0x80000000;
39 constexpr size_t MAX_DISPLAY_NUM = 2;
40 constexpr uint32_t IPV4_DOT_NUM = 3;
41 constexpr int32_t MIN_BYTE = 0;
42 constexpr int32_t MAX_BYTE = 255;
43 constexpr uint32_t BIT_NUM_BYTE = 8;
44 constexpr int32_t BITS_24 = 24;
45 constexpr int32_t BITS_16 = 16;
46 constexpr int32_t BITS_8 = 8;
47 constexpr uint32_t INTERFACE_NAME_MAX_SIZE = 16;
48 constexpr int32_t CHAR_ARRAY_SIZE_MAX = 1024;
49 constexpr int32_t PIPE_FD_NUM = 2;
50 constexpr int32_t PIPE_OUT = 0;
51 constexpr int32_t PIPE_IN = 1;
52 const std::string IPADDR_DELIMITER = ".";
53 constexpr const char *CMD_SEP = " ";
54 const std::regex IP_PATTERN{
55     "((2([0-4]\\d|5[0-5])|1\\d\\d|[1-9]\\d|\\d)\\.){3}(2([0-4]\\d|5[0-5])|1\\d\\d|[1-9]\\d|\\d)"};
56 
57 const std::regex IP_MASK_PATTERN{
58     "((2([0-4]\\d|5[0-5])|1\\d\\d|[1-9]\\d|\\d)\\.){3}(2([0-4]\\d|5[0-5])|1\\d\\d|[1-9]\\d|\\d)/"
59     "(3[0-2]|[1-2]\\d|\\d)"};
60 
61 const std::regex IPV6_PATTERN{"([\\da-fA-F]{0,4}:){2,7}([\\da-fA-F]{0,4})"};
62 
63 const std::regex IPV6_MASK_PATTERN{"([\\da-fA-F]{0,4}:){2,7}([\\da-fA-F]{0,4})/(1[0-2][0-8]|[1-9]\\d|[1-9])"};
64 
65 constexpr int32_t NET_MASK_MAX_LENGTH = 32;
66 constexpr int32_t NET_MASK_GROUP_COUNT = 4;
67 std::mutex g_commonUtilsMutex;
68 std::mutex g_forkExecMutex;
69 
Strip(const std::string & str,char ch)70 std::string Strip(const std::string &str, char ch)
71 {
72     auto size = static_cast<int64_t>(str.size());
73     int64_t i = 0;
74     while (i < size && str[i] == ch) {
75         ++i;
76     }
77     int64_t j = size - 1;
78     while (j > 0 && str[j] == ch) {
79         --j;
80     }
81     if (i >= 0 && i < size && j >= 0 && j < size && j - i + 1 > 0) {
82         return str.substr(i, j - i + 1);
83     }
84     return "";
85 }
86 
ToLower(const std::string & s)87 std::string ToLower(const std::string &s)
88 {
89     std::string res = s;
90     std::transform(res.begin(), res.end(), res.begin(), tolower);
91     return res;
92 }
93 
IsValidIPV4(const std::string & ip)94 bool IsValidIPV4(const std::string &ip)
95 {
96     if (ip.empty()) {
97         return false;
98     }
99     struct in_addr s;
100     return inet_pton(AF_INET, ip.c_str(), reinterpret_cast<void *>(&s)) == INET_OPTION_SUC;
101 }
102 
IsValidIPV6(const std::string & ip)103 bool IsValidIPV6(const std::string &ip)
104 {
105     if (ip.empty()) {
106         return false;
107     }
108     struct in6_addr s;
109     return inet_pton(AF_INET6, ip.c_str(), reinterpret_cast<void *>(&s)) == INET_OPTION_SUC;
110 }
111 
GetAddrFamily(const std::string & ip)112 int8_t GetAddrFamily(const std::string &ip)
113 {
114     if (IsValidIPV4(ip)) {
115         return AF_INET;
116     }
117     if (IsValidIPV6(ip)) {
118         return AF_INET6;
119     }
120     return 0;
121 }
122 
GetMaskLength(const std::string & mask)123 int GetMaskLength(const std::string &mask)
124 {
125     int netMask = 0;
126     unsigned int maskTmp = ntohl(static_cast<int>(inet_addr(mask.c_str())));
127     while (maskTmp & CONST_MASK) {
128         ++netMask;
129         maskTmp = (maskTmp << 1);
130     }
131     return netMask;
132 }
133 
GetMaskByLength(uint32_t length)134 std::string GetMaskByLength(uint32_t length)
135 {
136     const auto mask = length == 0 ? 0 : -1 << (NET_MASK_MAX_LENGTH - length);
137     auto maskGroup = new int[NET_MASK_GROUP_COUNT];
138     for (int i = 0; i < NET_MASK_GROUP_COUNT; i++) {
139         int pos = NET_MASK_GROUP_COUNT - 1 - i;
140         maskGroup[pos] = (static_cast<uint32_t>(mask) >> (i * BIT_NUM_BYTE)) & 0x000000ff;
141     }
142     std::string sMask = "" + std::to_string(maskGroup[0]);
143     for (int i = 1; i < NET_MASK_GROUP_COUNT; i++) {
144         sMask = sMask + "." + std::to_string(maskGroup[i]);
145     }
146     delete[] maskGroup;
147     return sMask;
148 }
149 
ConvertIpv4Address(uint32_t addressIpv4)150 std::string ConvertIpv4Address(uint32_t addressIpv4)
151 {
152     if (addressIpv4 == 0) {
153         return "";
154     }
155 
156     std::ostringstream stream;
157     stream << ((addressIpv4 >> BITS_24) & 0xFF) << IPADDR_DELIMITER << ((addressIpv4 >> BITS_16) & 0xFF)
158            << IPADDR_DELIMITER << ((addressIpv4 >> BITS_8) & 0xFF) << IPADDR_DELIMITER << (addressIpv4 & 0xFF);
159     return stream.str();
160 }
161 
ConvertIpv4Address(const std::string & address)162 uint32_t ConvertIpv4Address(const std::string &address)
163 {
164     std::string tmpAddress = address;
165     uint32_t addrInt = 0;
166     uint32_t i = 0;
167     for (i = 0; i < IPV4_DOT_NUM; i++) {
168         std::string::size_type npos = tmpAddress.find(IPADDR_DELIMITER);
169         if (npos == std::string::npos) {
170             break;
171         }
172         const auto &value = tmpAddress.substr(0, npos);
173         int32_t itmp = std::atoi(value.c_str());
174         if ((itmp < MIN_BYTE) || (itmp > MAX_BYTE)) {
175             break;
176         }
177         uint32_t utmp = static_cast<uint32_t>(itmp);
178         addrInt += utmp << ((IPV4_DOT_NUM - i) * BIT_NUM_BYTE);
179         tmpAddress = tmpAddress.substr(npos + 1);
180     }
181 
182     if (i != IPV4_DOT_NUM) {
183         return 0;
184     }
185     int32_t itmp = std::atoi(tmpAddress.c_str());
186     if ((itmp < MIN_BYTE) || (itmp > MAX_BYTE)) {
187         return 0;
188     }
189     uint32_t utmp = static_cast<uint32_t>(itmp);
190     addrInt += utmp;
191 
192     return addrInt;
193 }
194 
Ipv4PrefixLen(const std::string & ip)195 int32_t Ipv4PrefixLen(const std::string &ip)
196 {
197     constexpr int32_t BIT32 = 32;
198     constexpr int32_t BIT24 = 24;
199     constexpr int32_t BIT16 = 16;
200     constexpr int32_t BIT8 = 8;
201     if (ip.empty()) {
202         return 0;
203     }
204     int32_t ret = 0;
205     uint32_t ipNum = 0;
206     uint8_t c1 = 0;
207     uint8_t c2 = 0;
208     uint8_t c3 = 0;
209     uint8_t c4 = 0;
210     int32_t cnt = 0;
211     ret = sscanf_s(ip.c_str(), "%hhu.%hhu.%hhu.%hhu", &c1, &c2, &c3, &c4);
212     if (ret != sizeof(int32_t)) {
213         return 0;
214     }
215     ipNum = (c1 << static_cast<uint32_t>(BIT24)) | (c2 << static_cast<uint32_t>(BIT16)) |
216             (c3 << static_cast<uint32_t>(BIT8)) | c4;
217     if (ipNum == 0xFFFFFFFF) {
218         return BIT32;
219     }
220     if (ipNum == 0xFFFFFF00) {
221         return BIT24;
222     }
223     if (ipNum == 0xFFFF0000) {
224         return BIT16;
225     }
226     if (ipNum == 0xFF000000) {
227         return BIT8;
228     }
229     for (int32_t i = 0; i < BIT32; i++) {
230         if ((ipNum << i) & 0x80000000) {
231             cnt++;
232         } else {
233             break;
234         }
235     }
236     return cnt;
237 }
238 
ParseInt(const std::string & str,int32_t * value)239 bool ParseInt(const std::string &str, int32_t *value)
240 {
241     char *end;
242     long long v = strtoll(str.c_str(), &end, 10);
243     if (std::string(end) == str || *end != '\0' || v < INT_MIN || v > INT_MAX) {
244         return false;
245     }
246     *value = v;
247     return true;
248 }
249 
ConvertToInt64(const std::string & str)250 int64_t ConvertToInt64(const std::string &str)
251 {
252     return strtoll(str.c_str(), nullptr, DECIMAL_SYSTEM);
253 }
254 
MaskIpv4(std::string & maskedResult)255 std::string MaskIpv4(std::string &maskedResult)
256 {
257     int maxDisplayNum = MAX_DISPLAY_NUM;
258     for (char &i : maskedResult) {
259         if (i == '/') {
260             break;
261         }
262         if (maxDisplayNum > 0) {
263             if (i == '.') {
264                 maxDisplayNum--;
265             }
266         } else {
267             if (i != '.') {
268                 i = '*';
269             }
270         }
271     }
272     return maskedResult;
273 }
274 
MaskIpv6(std::string & maskedResult)275 std::string MaskIpv6(std::string &maskedResult)
276 {
277     size_t colonCount = 0;
278     for (char &i : maskedResult) {
279         if (i == '/') {
280             break;
281         }
282         if (i == ':') {
283             colonCount++;
284         }
285 
286         if (colonCount >= MAX_DISPLAY_NUM) { // An legal ipv6 address has at least 2 ':'.
287             if (i != ':' && i != '/') {
288                 i = '*';
289             }
290         }
291     }
292     return maskedResult;
293 }
294 
ToAnonymousIp(const std::string & input)295 std::string ToAnonymousIp(const std::string &input)
296 {
297     std::lock_guard<std::mutex> lock(g_commonUtilsMutex);
298     std::string maskedResult{input};
299     // Mask ipv4 address.
300     if (std::regex_match(maskedResult, IP_PATTERN) || std::regex_match(maskedResult, IP_MASK_PATTERN)) {
301         return MaskIpv4(maskedResult);
302     }
303     // Mask ipv6 address.
304     if (std::regex_match(maskedResult, IPV6_PATTERN) || std::regex_match(maskedResult, IPV6_MASK_PATTERN)) {
305         return MaskIpv6(maskedResult);
306     }
307     return input;
308 }
309 
StrToInt(const std::string & str)310 int32_t StrToInt(const std::string &str)
311 {
312     return std::strtol(str.c_str(), nullptr, 0);
313 }
314 
StrToUint(const std::string & str)315 uint32_t StrToUint(const std::string &str)
316 {
317     return std::strtoul(str.c_str(), nullptr, 0);
318 }
319 
StrToBool(const std::string & str)320 bool StrToBool(const std::string &str)
321 {
322     return static_cast<bool>(std::strtoul(str.c_str(), nullptr, 0));
323 }
324 
StrToLong(const std::string & str)325 int64_t StrToLong(const std::string &str)
326 {
327     return std::strtol(str.c_str(), nullptr, 0);
328 }
329 
CheckIfaceName(const std::string & name)330 bool CheckIfaceName(const std::string &name)
331 {
332     uint32_t index = 0;
333     if (name.empty()) {
334         return false;
335     }
336     size_t len = name.size();
337     if (len > INTERFACE_NAME_MAX_SIZE) {
338         return false;
339     }
340     while (index < len) {
341         if ((index == 0) && !isalnum(name[index])) {
342             return false;
343         }
344         if (!isalnum(name[index]) && (name[index] != '-') && (name[index] != '_') && (name[index] != '.') &&
345             (name[index] != ':')) {
346             return false;
347         }
348         index++;
349     }
350     return true;
351 }
352 
FormatCmd(const std::vector<std::string> & cmd)353 std::vector<const char *> FormatCmd(const std::vector<std::string> &cmd)
354 {
355     std::vector<const char *> res;
356     res.reserve(cmd.size() + 1);
357 
358     // string is converted to char * and the result is saved in res
359     std::transform(cmd.begin(), cmd.end(), std::back_inserter(res), [](const std::string &str) { return str.c_str(); });
360     res.emplace_back(nullptr);
361     return res;
362 }
363 
ForkExecChildProcess(const int32_t * pipeFd,int32_t count,const std::vector<const char * > & args)364 int32_t ForkExecChildProcess(const int32_t *pipeFd, int32_t count, const std::vector<const char *> &args)
365 {
366     if (count != PIPE_FD_NUM) {
367         NETMGR_LOG_E("fork exec parent process failed");
368         _exit(-1);
369     }
370     if (close(pipeFd[PIPE_OUT]) != 0) {
371         NETMGR_LOG_E("close failed, errorno:%{public}d, errormsg:%{public}s", errno, strerror(errno));
372         _exit(-1);
373     }
374     if (dup2(pipeFd[PIPE_IN], STDOUT_FILENO) == -1) {
375         NETMGR_LOG_E("dup2 failed, errorno:%{public}d, errormsg:%{public}s", errno, strerror(errno));
376         _exit(-1);
377     }
378     if (execv(args[0], const_cast<char *const *>(&args[0])) == -1) {
379         NETMGR_LOG_E("execv command failed, errorno:%{public}d, errormsg:%{public}s", errno, strerror(errno));
380     }
381     _exit(-1);
382 }
383 
ForkExecParentProcess(const int32_t * pipeFd,int32_t count,pid_t childPid,std::string * out)384 int32_t ForkExecParentProcess(const int32_t *pipeFd, int32_t count, pid_t childPid, std::string *out)
385 {
386     if (count != PIPE_FD_NUM) {
387         NETMGR_LOG_E("fork exec parent process failed");
388         return NETMANAGER_ERROR;
389     }
390     if (out != nullptr) {
391         char buf[CHAR_ARRAY_SIZE_MAX] = {0};
392         out->clear();
393         if (close(pipeFd[PIPE_IN]) != 0) {
394             NETMGR_LOG_E("close failed, errorno:%{public}d, errormsg:%{public}s", errno, strerror(errno));
395         }
396         while (read(pipeFd[PIPE_OUT], buf, CHAR_ARRAY_SIZE_MAX - 1) > 0) {
397             out->append(buf);
398         }
399         return NETMANAGER_SUCCESS;
400     }
401     pid_t pidRet = waitpid(childPid, nullptr, 0);
402     if (pidRet != childPid) {
403         NETMGR_LOG_E("waitpid[%{public}d] failed, pidRet:%{public}d", childPid, pidRet);
404         return NETMANAGER_ERROR;
405     }
406     return NETMANAGER_SUCCESS;
407 }
408 
ForkExec(const std::string & command,std::string * out)409 int32_t ForkExec(const std::string &command, std::string *out)
410 {
411     std::unique_lock<std::mutex> lock(g_forkExecMutex);
412     const std::vector<std::string> cmd = Split(command, CMD_SEP);
413     std::vector<const char *> args = FormatCmd(cmd);
414     int32_t pipeFd[PIPE_FD_NUM] = {0};
415     if (pipe(pipeFd) < 0) {
416         NETMGR_LOG_E("creat pipe failed, errorno:%{public}d, errormsg:%{public}s", errno, strerror(errno));
417         return NETMANAGER_ERROR;
418     }
419     pid_t pid = fork();
420     if (pid < 0) {
421         NETMGR_LOG_E("fork failed, errorno:%{public}d, errormsg:%{public}s", errno, strerror(errno));
422         return NETMANAGER_ERROR;
423     }
424     if (pid == 0) {
425         ForkExecChildProcess(pipeFd, PIPE_FD_NUM, args);
426         return NETMANAGER_SUCCESS;
427     } else {
428         return ForkExecParentProcess(pipeFd, PIPE_FD_NUM, pid, out);
429     }
430 }
431 } // namespace OHOS::NetManagerStandard::CommonUtils
432