1 /*
2 * Copyright (C) 2021 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 "ip_tools.h"
17 #include "wifi_common_util.h"
18
19 namespace OHOS {
20 namespace Wifi {
ConvertIpv4Address(unsigned int addressIpv4)21 std::string IpTools::ConvertIpv4Address(unsigned int addressIpv4)
22 {
23 std::string address;
24 if (addressIpv4 == 0) {
25 return address;
26 }
27
28 std::ostringstream stream;
29 stream<<((addressIpv4>>BITS_24) & 0xFF)<<"."<<((addressIpv4>>BITS_16) & 0xFF)<<"."
30 <<((addressIpv4>>BITS_8) & 0xFF)<<"."<<(addressIpv4 & 0xFF);
31 address = stream.str();
32
33 return address;
34 }
35
ConvertIpv4Address(const std::string & address)36 unsigned int IpTools::ConvertIpv4Address(const std::string &address)
37 {
38 std::string tmpAddress = address;
39 unsigned int addrInt = 0;
40 unsigned int i = 0;
41 for (i = 0; i < IPV4_DOT_NUM; i++) {
42 std::string::size_type npos = tmpAddress.find(".");
43 if (npos == std::string::npos) {
44 break;
45 }
46 std::string value = tmpAddress.substr(0, npos);
47 unsigned int tmp = CheckDataToUint(value);
48 if ((tmp < MIN_BYTE) || (tmp > MAX_BYTE)) {
49 break;
50 }
51 addrInt += tmp << ((IPV4_DOT_NUM - i) * BIT_NUM_BYTE);
52 tmpAddress = tmpAddress.substr(npos + 1);
53 }
54
55 if (i != IPV4_DOT_NUM) {
56 return 0;
57 }
58 int tmp = CheckDataLegal(tmpAddress);
59 if ((tmp < MIN_BYTE) || (tmp > MAX_BYTE)) {
60 return 0;
61 }
62 addrInt += tmp;
63
64 return addrInt;
65 }
66
ConvertIpv6Address(const std::vector<unsigned char> & addressIpv6)67 std::string IpTools::ConvertIpv6Address(const std::vector<unsigned char> &addressIpv6)
68 {
69 std::string address;
70 if (addressIpv6.size() != IPV6_BYTE_NUM) {
71 return address;
72 }
73
74 std::ostringstream stream;
75 stream << std::hex << std::setw(POS_2) << std::setfill('0') << static_cast<int>(addressIpv6[0]);
76 stream << std::hex << std::setw(POS_2) << std::setfill('0') << static_cast<int>(addressIpv6[1]);
77 for (int i = POS_2; i < IPV6_BYTE_NUM; i += POS_2) {
78 stream << ":";
79 stream << std::hex << std::setw(POS_2) << std::setfill('0') << static_cast<int>(addressIpv6[i]);
80 stream << std::hex << std::setw(POS_2) << std::setfill('0') << static_cast<int>(addressIpv6[i + 1]);
81 }
82 address = stream.str();
83
84 return address;
85 }
86
ConvertIpv6Address(const std::string & address,std::vector<unsigned char> & addressIpv6)87 void IpTools::ConvertIpv6Address(const std::string &address, std::vector<unsigned char> &addressIpv6)
88 {
89 std::string tmpAddress = address;
90 addressIpv6.clear();
91 std::vector<unsigned char> ipv6;
92 int i = 0;
93 for (i = 0; i < IPV6_COLON_NUM; i++) {
94 std::string::size_type npos = tmpAddress.find(":");
95 if (npos == std::string::npos) {
96 break;
97 }
98
99 std::string value = tmpAddress.substr(0, npos);
100 if (value.size() != IPV6_DIGIT_NUM_PER_SEG) {
101 break;
102 }
103 std::string valueFromPos0 = value.substr(POS_0, HEX_BYTE_DIGIT_NUM);
104 std::string valueFromPos2 = value.substr(POS_2, HEX_BYTE_DIGIT_NUM);
105 ipv6.push_back(CheckDataLegalHex(valueFromPos0));
106 ipv6.push_back(CheckDataLegalHex(valueFromPos2));
107 tmpAddress = tmpAddress.substr(npos + 1);
108 }
109
110 if (i != IPV6_COLON_NUM) {
111 return;
112 }
113 if (tmpAddress.size() != IPV6_DIGIT_NUM_PER_SEG) {
114 return;
115 }
116 std::string addressFromPos0 = tmpAddress.substr(POS_0, HEX_BYTE_DIGIT_NUM);
117 std::string addressFromPos2 = tmpAddress.substr(POS_2, HEX_BYTE_DIGIT_NUM);
118 ipv6.push_back(CheckDataLegalHex(addressFromPos0));
119 ipv6.push_back(CheckDataLegalHex(addressFromPos2));
120
121 addressIpv6.assign(ipv6.begin(), ipv6.end());
122 return;
123 }
124
ConvertIpv4Mask(int prefixLength)125 std::string IpTools::ConvertIpv4Mask(int prefixLength)
126 {
127 std::string netMask;
128 if (prefixLength <= MIN_PREFIX_LEN || prefixLength > MAX_PREFIX_LEN) {
129 const int defaultPrefix = 24;
130 prefixLength = defaultPrefix;
131 }
132
133 int mask[IPV4_BYTE_NUM] = {0, 0, 0, 0};
134 int quot = prefixLength / BIT_NUM_PER_BYTE;
135 int remain = prefixLength % BIT_NUM_PER_BYTE;
136 for (int i = 0; i < quot; i++) {
137 mask[i] = MAX_IPV4_MASK_BYTE;
138 }
139 if (quot < IPV4_BYTE_NUM) {
140 mask[quot] = (MAX_BYTE + 1) - (1 << (BIT_NUM_PER_BYTE - remain));
141 }
142 std::ostringstream stream;
143 stream << mask[POS_0] << "." << mask[POS_1] << "." << mask[POS_2] << "." << mask[POS_3];
144 netMask = stream.str();
145
146 return netMask;
147 }
148
ConvertIpv6Mask(int prefixLength)149 std::string IpTools::ConvertIpv6Mask(int prefixLength)
150 {
151 if (prefixLength < MIN_PREFIX_LEN || prefixLength > MAX_IPV6_PREFIX_LEN) {
152 return "";
153 }
154 // 初始化 16 字节的 IPv6 掩码(全 0)
155 uint8_t mask[16];
156 memset_s(mask, sizeof(mask), 0, sizeof(mask));
157
158 // 逐字节设置掩码
159 uint8_t bytesLen = 8;
160 uint8_t ipv6Bytes = 16;
161 for (unsigned int i = 0; i < ipv6Bytes; i++) {
162 if (prefixLength >= bytesLen) {
163 mask[i] = 0xFF; // 当前字节全 1
164 prefixLength -= bytesLen;
165 } else if (prefixLength > 0) {
166 mask[i] = 0xFF << (bytesLen - prefixLength); // 部分 1
167 prefixLength = 0;
168 }
169 // 剩余字节保持 0
170 }
171
172 // 转换为 IPv6 字符串格式(压缩形式,如 "ffff::")
173 char buffer[INET6_ADDRSTRLEN];
174 inet_ntop(AF_INET6, mask, buffer, INET6_ADDRSTRLEN);
175 return std::string(buffer);
176 }
177
GetMaskLength(std::string mask)178 int IpTools::GetMaskLength(std::string mask)
179 {
180 int netMask = 0;
181 const unsigned int constMask = 0x80000000;
182 unsigned int maskTmp = ntohl(static_cast<int>(inet_addr(mask.c_str())));
183 while (maskTmp & constMask) {
184 netMask++;
185 maskTmp = (maskTmp << 1);
186 }
187
188 return netMask;
189 }
190
191 /**
192 * @Description : Obtains the length based on the subnet mask.
193 *
194 * @param mask - The mask.[in]
195 * @return int
196 */
GetIPV6MaskLength(std::string ip)197 int IpTools::GetIPV6MaskLength(std::string ip)
198 {
199 constexpr int32_t LENGTH_8 = 8;
200 constexpr int32_t LENGTH_7 = 7;
201 constexpr int32_t LENGTH_6 = 6;
202 constexpr int32_t LENGTH_5 = 5;
203 constexpr int32_t LENGTH_4 = 4;
204 constexpr int32_t LENGTH_3 = 3;
205 constexpr int32_t LENGTH_2 = 2;
206 constexpr int32_t LENGTH_1 = 1;
207 if (ip.empty()) {
208 return 0;
209 }
210 in6_addr addr{};
211 inet_pton(AF_INET6, ip.c_str(), &addr);
212 int32_t prefixLen = 0;
213 for (int32_t i = 0; i < BITS_16; ++i) {
214 if (addr.s6_addr[i] == 0xFF) {
215 prefixLen += LENGTH_8;
216 } else if (addr.s6_addr[i] == 0xFE) {
217 prefixLen += LENGTH_7;
218 break;
219 } else if (addr.s6_addr[i] == 0xFC) {
220 prefixLen += LENGTH_6;
221 break;
222 } else if (addr.s6_addr[i] == 0xF8) {
223 prefixLen += LENGTH_5;
224 break;
225 } else if (addr.s6_addr[i] == 0xF0) {
226 prefixLen += LENGTH_4;
227 break;
228 } else if (addr.s6_addr[i] == 0xE0) {
229 prefixLen += LENGTH_3;
230 break;
231 } else if (addr.s6_addr[i] == 0xC0) {
232 prefixLen += LENGTH_2;
233 break;
234 } else if (addr.s6_addr[i] == 0x80) {
235 prefixLen += LENGTH_1;
236 break;
237 } else {
238 break;
239 }
240 }
241 return prefixLen;
242 }
243
GetExclusionObjectList(const std::string & exclusionObjectList,std::vector<std::string> & exclusionList)244 void IpTools::GetExclusionObjectList(const std::string &exclusionObjectList, std::vector<std::string> &exclusionList)
245 {
246 std::string tmpExclusionList = exclusionObjectList;
247 std::vector<std::string> list;
248 int listNum = count(tmpExclusionList.begin(), tmpExclusionList.end(), ',');
249 int i = 0;
250 for (i = 0; i < listNum; ++i) {
251 std::string::size_type npos = tmpExclusionList.find(",");
252 if (npos == std::string::npos) {
253 break;
254 }
255
256 std::string exclusionOne = tmpExclusionList.substr(0, npos);
257 /* Do you need to check whether the format of this website is correct? */
258 list.push_back(exclusionOne);
259 tmpExclusionList = tmpExclusionList.substr(npos + 1);
260 }
261 if (i != listNum) {
262 return;
263 }
264 list.push_back(tmpExclusionList);
265 exclusionList.assign(list.begin(), list.end());
266 return;
267 }
268
ConvertIpv6AddressToCompleted(const std::string & address)269 std::string IpTools::ConvertIpv6AddressToCompleted(const std::string &address)
270 {
271 size_t dblColonPos = address.find("::");
272 bool hasDblColon = (dblColonPos != std::string::npos);
273 std::vector<std::string> parts;
274 std::string firstPart = address.substr(0, dblColonPos);
275 std::string secondPart = hasDblColon ? address.substr(dblColonPos + 2) : "";
276
277 std::istringstream firstStream(firstPart);
278 std::string segment;
279 while (getline(firstStream, segment, ':')) {
280 parts.push_back(segment);
281 }
282
283 std::istringstream secondStream(secondPart);
284 std::vector<std::string> secondParts;
285 while (getline(secondStream, segment, ':')) {
286 secondParts.push_back(segment);
287 }
288
289 size_t totalParts = 8;
290 size_t existingParts = parts.size() + secondParts.size();
291 size_t zeroPartsToInsert = totalParts - existingParts;
292 int8_t bitNum = 4;
293 parts.insert(parts.end(), zeroPartsToInsert, "0");
294 parts.insert(parts.end(), secondParts.begin(), secondParts.end());
295 std::ostringstream stream;
296 for (size_t i = 0; i < parts.size(); i++) {
297 if (i != 0) {
298 stream << ":";
299 }
300 std::string seg = parts[i];
301 if (seg.empty()) {
302 seg = "0";
303 }
304 unsigned int num = std::stoul(seg, nullptr, 16);
305 stream << std::setw(bitNum) << std::setfill('0') << std::hex << num;
306 }
307 return stream.str();
308 }
309 } // namespace Wifi
310 } // namespace OHOS