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 "ipv6_address.h"
16 #include <climits>
17 #include "securec.h"
18 #include "wifi_log.h"
19 #include "wifi_common_util.h"
20
21 #undef LOG_TAG
22 #define LOG_TAG "OHWIFI_UTIL_Ipv6Address"
23
24 namespace OHOS {
25 namespace Wifi {
26 constexpr int MAX_IPV6_PREFIX_LENGTH = 128;
27 constexpr int MAX_BIN = 2;
28 constexpr int BIN_TO_HEX = 4;
29 constexpr int IPV6_INTERVAL = 5;
30 constexpr int HALF_IN6ADDR = 8;
31 constexpr int MAX_DEC = 10;
32 constexpr int MAX_HEX = 16;
33 constexpr int BUFFER_SIZE = 32;
34 constexpr int HALF_PREFIX_LENGTH = 64;
35 constexpr int MASK_FILTER = 0x7;
36 const char* const DEFAULT_IPV6_ANY_INIT_ADDR = "::";
37 const Ipv6Address Ipv6Address::INVALID_INET6_ADDRESS(std::string("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
38 MAX_IPV6_PREFIX_LENGTH);
39
IsValidIPv6(const std::string & ipv6)40 bool Ipv6Address::IsValidIPv6(const std::string &ipv6)
41 {
42 struct in6_addr ipv6Addr = IN6ADDR_ANY_INIT;
43 if (inet_pton(AF_INET6, ipv6.c_str(), &ipv6Addr) != 1 ||
44 ipv6 == INVALID_INET6_ADDRESS.GetAddressWithString()) {
45 return false;
46 } else {
47 return true;
48 }
49 }
50
IsAddrLocallink(const struct in6_addr & ip6Addr)51 bool Ipv6Address::IsAddrLocallink(const struct in6_addr &ip6Addr)
52 {
53 return IN6_IS_ADDR_LINKLOCAL(&ip6Addr);
54 }
55
Create(std::string ipv6)56 Ipv6Address Ipv6Address::Create(std::string ipv6)
57 {
58 std::transform(ipv6.begin(), ipv6.end(), ipv6.begin(), ::tolower);
59 std::size_t index = ipv6.find("/");
60 std::string ip;
61 size_t prefixLength = 0;
62
63 if (index == std::string::npos) {
64 ip = ipv6;
65 prefixLength = MAX_IPV6_PREFIX_LENGTH;
66 } else {
67 ip = std::string(ipv6.begin(), ipv6.begin() + index);
68 std::string ipv6Tmp = ipv6.substr(index + 1);
69 prefixLength = CheckDataToUint(ipv6Tmp);
70 }
71
72 if (!IsValidIPv6(ip)) {
73 return INVALID_INET6_ADDRESS;
74 }
75 return {ip, prefixLength};
76 }
77
Create(const std::string & ipv6Prefix,MacAddress & mac,const size_t prefixLength)78 Ipv6Address Ipv6Address::Create(const std::string &ipv6Prefix, MacAddress &mac, const size_t prefixLength)
79 {
80 if (prefixLength > HALF_PREFIX_LENGTH || !IsValidIPv6(ipv6Prefix)) {
81 return INVALID_INET6_ADDRESS;
82 }
83 std::string eui64Addr = std::string("::") + MacToEui64addr(mac);
84 struct in6_addr eui64 = IN6ADDR_ANY_INIT;
85 inet_pton(AF_INET6, eui64Addr.c_str(), &eui64);
86 struct in6_addr ipv6Buf = IN6ADDR_ANY_INIT;
87 inet_pton(AF_INET6, ipv6Prefix.c_str(), &ipv6Buf);
88
89 struct in6_addr ipv6 = GetIpv6Prefix(ipv6Buf, prefixLength);
90 for (int n = HALF_IN6ADDR; n < MAX_IPV6_PREFIX_LENGTH / CHAR_BIT; ++n) {
91 ipv6.s6_addr[n] = eui64.s6_addr[n];
92 }
93 char ip[INET6_ADDRSTRLEN] = {0};
94 inet_ntop(AF_INET6, &ipv6, ip, INET6_ADDRSTRLEN);
95 return Ipv6Address(ip, prefixLength);
96 }
97
Create(const std::string & ipv6Prefix,const size_t prefixLength,unsigned int rndSeed)98 Ipv6Address Ipv6Address::Create(const std::string &ipv6Prefix, const size_t prefixLength, unsigned int rndSeed)
99 {
100 if (prefixLength > MAX_IPV6_PREFIX_LENGTH || !IsValidIPv6(ipv6Prefix)) {
101 return INVALID_INET6_ADDRESS;
102 }
103 LOGD("Create use rand seed, %{public}u", rndSeed);
104 std::string rndAddr = GetRandomAddr(ipv6Prefix, prefixLength);
105 return Ipv6Address(rndAddr, prefixLength);
106 }
107
Create(const struct in6_addr & i6Addr,const size_t prefixLength)108 Ipv6Address Ipv6Address::Create(const struct in6_addr &i6Addr, const size_t prefixLength)
109 {
110 if (prefixLength > MAX_IPV6_PREFIX_LENGTH) {
111 return INVALID_INET6_ADDRESS;
112 }
113 char ipv6Buf[INET6_ADDRSTRLEN] = {0};
114 if (inet_ntop(AF_INET6, &i6Addr, ipv6Buf, INET6_ADDRSTRLEN) == nullptr) {
115 return INVALID_INET6_ADDRESS;
116 }
117 return Ipv6Address(ipv6Buf, prefixLength);
118 }
119
Create(std::string ipv6,const size_t prefixLength)120 Ipv6Address Ipv6Address::Create(std::string ipv6, const size_t prefixLength)
121 {
122 if ((prefixLength > MAX_IPV6_PREFIX_LENGTH) || (!IsValidIPv6(ipv6))) {
123 return INVALID_INET6_ADDRESS;
124 }
125 std::transform(ipv6.begin(), ipv6.end(), ipv6.begin(), ::tolower);
126 return Ipv6Address(ipv6, prefixLength);
127 }
128
Create(std::string ipv6,const std::string & mask)129 Ipv6Address Ipv6Address::Create(std::string ipv6, const std::string &mask)
130 {
131 if (!IsValidIPv6(ipv6)) {
132 return INVALID_INET6_ADDRESS;
133 }
134 std::transform(ipv6.begin(), ipv6.end(), ipv6.begin(), ::tolower);
135 std::string copyMask = mask;
136 unsigned int i = 0;
137 while (i < copyMask.size()) {
138 if (copyMask.at(i) == ':') {
139 copyMask.erase(i, 1);
140 } else {
141 ++i;
142 }
143 }
144
145 std::string maskBin;
146 std::string binBuffer;
147 for (unsigned int n = 0; n < copyMask.size(); ++n) {
148 binBuffer = copyMask.substr(n, 1);
149 maskBin += HexToBin(binBuffer);
150 }
151
152 size_t count = 0;
153 for (unsigned int n = 0; n < maskBin.size(); ++n) {
154 if (maskBin.at(n) == '1') {
155 ++count;
156 }
157 }
158 return Ipv6Address(ipv6, count);
159 }
160
Ipv6Address(const std::string & ipv6,const size_t prefixLength)161 Ipv6Address::Ipv6Address(const std::string &ipv6, const size_t prefixLength)
162 : BaseAddress(ipv6, prefixLength, FamilyType::FAMILY_INET6)
163 {}
164
IsValid() const165 bool Ipv6Address::IsValid() const
166 {
167 return IsValidIPv6(GetAddressWithString());
168 }
169
GetIn6Addr() const170 struct in6_addr Ipv6Address::GetIn6Addr() const
171 {
172 struct in6_addr ipv6Addr = IN6ADDR_ANY_INIT;
173 inet_pton(AF_INET6, GetAddressWithString().c_str(), &ipv6Addr);
174 return ipv6Addr;
175 }
176
GetPrefix() const177 std::string Ipv6Address::GetPrefix() const
178 {
179 struct in6_addr ipv6Prefix = IN6ADDR_ANY_INIT;
180 struct in6_addr ipv6AddrBuf = GetIn6Addr();
181 ipv6Prefix = GetIpv6Prefix(ipv6AddrBuf, GetAddressPrefixLength());
182 char ipv6PrefixBuf[INET6_ADDRSTRLEN] = {0};
183 inet_ntop(AF_INET6, &ipv6Prefix, ipv6PrefixBuf, INET6_ADDRSTRLEN);
184 std::string prefixStr = ipv6PrefixBuf;
185 return prefixStr;
186 }
187
GetPrefixByAddr(const std::string & ipv6Addr,unsigned int prefixLen)188 std::string Ipv6Address::GetPrefixByAddr(const std::string &ipv6Addr, unsigned int prefixLen)
189 {
190 if (prefixLen >= MAX_IPV6_PREFIX_LENGTH) {
191 return ipv6Addr;
192 }
193
194 in6_addr ipv6AddrBuf = IN6ADDR_ANY_INIT;
195 inet_pton(AF_INET6, ipv6Addr.c_str(), &ipv6AddrBuf);
196
197 char buf[INET6_ADDRSTRLEN] = {0};
198 if (inet_ntop(AF_INET6, &ipv6AddrBuf, buf, INET6_ADDRSTRLEN) == nullptr) {
199 return ipv6Addr;
200 }
201
202 in6_addr ipv6Prefix = IN6ADDR_ANY_INIT;
203 uint32_t byteIndex = prefixLen / CHAR_BIT;
204 if (memset_s(ipv6Prefix.s6_addr, sizeof(ipv6Prefix.s6_addr), 0, sizeof(ipv6Prefix.s6_addr)) != EOK ||
205 memcpy_s(ipv6Prefix.s6_addr, sizeof(ipv6Prefix.s6_addr), &ipv6AddrBuf, byteIndex) != EOK) {
206 return DEFAULT_IPV6_ANY_INIT_ADDR;
207 }
208 uint32_t bitOffset = prefixLen & MASK_FILTER;
209 if ((bitOffset != 0) && (byteIndex < INET_ADDRSTRLEN)) {
210 ipv6Prefix.s6_addr[byteIndex] = ipv6AddrBuf.s6_addr[byteIndex] & (0xff00 >> bitOffset);
211 }
212 char ipv6PrefixBuf[INET6_ADDRSTRLEN] = {0};
213 inet_ntop(AF_INET6, &ipv6Prefix, ipv6PrefixBuf, INET6_ADDRSTRLEN);
214 return ipv6PrefixBuf;
215 }
216
GetIpv6Prefix(struct in6_addr & ip6Addr,size_t prefixLength)217 struct in6_addr Ipv6Address::GetIpv6Prefix(struct in6_addr &ip6Addr, size_t prefixLength)
218 {
219 struct in6_addr addr = IN6ADDR_ANY_INIT;
220 if (prefixLength > MAX_IPV6_PREFIX_LENGTH) {
221 return addr;
222 }
223 char buf[INET6_ADDRSTRLEN] = {0};
224 if (inet_ntop(AF_INET6, &ip6Addr, buf, INET6_ADDRSTRLEN) == nullptr) {
225 return addr;
226 }
227
228 unsigned int o = prefixLength / CHAR_BIT;
229 unsigned int b = prefixLength & 0x7;
230 if (memset_s(addr.s6_addr, sizeof(addr.s6_addr), 0, sizeof(addr.s6_addr)) != EOK ||
231 memcpy_s(addr.s6_addr, sizeof(addr.s6_addr), &ip6Addr, o) != EOK) {
232 return IN6ADDR_ANY_INIT;
233 }
234 if ((b != 0) && (o < INET_ADDRSTRLEN)) {
235 addr.s6_addr[o] = ip6Addr.s6_addr[o] & (0xff00 >> b);
236 }
237 return addr;
238 }
239
GetIpv6Mask(size_t prefixLength)240 struct in6_addr Ipv6Address::GetIpv6Mask(size_t prefixLength)
241 {
242 struct in6_addr addr = IN6ADDR_ANY_INIT;
243 if (prefixLength > MAX_IPV6_PREFIX_LENGTH) {
244 return addr;
245 } else if (prefixLength == MAX_IPV6_PREFIX_LENGTH) {
246 for (unsigned int count = 0; count < prefixLength / CHAR_BIT; ++count) {
247 addr.s6_addr[count] = UCHAR_MAX;
248 }
249 return addr;
250 }
251
252 unsigned int count = 0;
253 for (; count < prefixLength / CHAR_BIT; ++count) {
254 addr.s6_addr[count] = UCHAR_MAX;
255 }
256 addr.s6_addr[count] = 0;
257 for (unsigned int n = CHAR_BIT - prefixLength % CHAR_BIT; n < CHAR_BIT; ++n) {
258 addr.s6_addr[count] |= (0x01 << n);
259 }
260 ++count;
261 for (; count < MAX_IPV6_PREFIX_LENGTH / CHAR_BIT; ++count) {
262 addr.s6_addr[count] = 0;
263 }
264 return addr;
265 }
266
GetRandomAddr(const std::string & ipv6Prefix,int prefixLength)267 std::string Ipv6Address::GetRandomAddr(const std::string &ipv6Prefix, int prefixLength)
268 {
269 int rndLength = MAX_IPV6_PREFIX_LENGTH - prefixLength;
270 std::random_device rd;
271 std::string resBin;
272 int rndnum = 0;
273 for (int n = 0; n < rndLength; ++n) {
274 rndnum = std::abs(static_cast<int>(rd()));
275 switch (rndnum % MAX_BIN) {
276 case 0:
277 resBin += "0";
278 break;
279 default:
280 resBin += "1";
281 break;
282 }
283 }
284 for (int n = rndLength; n < MAX_IPV6_PREFIX_LENGTH; ++n) {
285 resBin += "0";
286 }
287 std::reverse(resBin.begin(), resBin.end());
288
289 std::string resHex;
290 std::string bin2HexBuf;
291 for (unsigned int n = 0; n < resBin.size(); n += BIN_TO_HEX) {
292 bin2HexBuf = resBin.substr(n, BIN_TO_HEX);
293 resHex += BinToHex(bin2HexBuf);
294 }
295 for (unsigned int n = BIN_TO_HEX; n < resHex.size(); n += IPV6_INTERVAL) {
296 resHex.insert(n, ":");
297 }
298
299 struct in6_addr rndAddr = IN6ADDR_ANY_INIT;
300 inet_pton(AF_INET6, resHex.c_str(), &rndAddr);
301 struct in6_addr ipv6Addr = IN6ADDR_ANY_INIT;
302 inet_pton(AF_INET6, ipv6Prefix.c_str(), &ipv6Addr);
303 if (prefixLength < 0 || (prefixLength / CHAR_BIT) >= sizeof(rndAddr.s6_addr)) {
304 LOGE("Get random address error: prefix");
305 return "";
306 }
307 ipv6Addr.s6_addr[prefixLength / CHAR_BIT] |= rndAddr.s6_addr[prefixLength / CHAR_BIT];
308 for (int n = prefixLength / CHAR_BIT + 1; n < MAX_IPV6_PREFIX_LENGTH / CHAR_BIT; ++n) {
309 ipv6Addr.s6_addr[n] = rndAddr.s6_addr[n];
310 }
311 char ipv6Buf[INET6_ADDRSTRLEN] = {0};
312 inet_ntop(AF_INET6, &ipv6Addr, ipv6Buf, INET6_ADDRSTRLEN);
313 std::string res = ipv6Buf;
314 return res;
315 }
316
GetNetwork() const317 std::string Ipv6Address::GetNetwork() const
318 {
319 std::string ret = GetPrefix();
320 ret += "/";
321 ret += std::to_string(GetAddressPrefixLength());
322 return ret;
323 }
324
BinToHex(const std::string & strBin)325 std::string Ipv6Address::BinToHex(const std::string &strBin)
326 {
327 int addrDec = CheckDataLegalBin(strBin);
328 std::string addrHex;
329 char buf[2] = {0};
330 if (addrDec % MAX_HEX < MAX_DEC) {
331 buf[0] = addrDec % MAX_HEX + '0';
332 buf[1] = '\0';
333 } else {
334 buf[0] = addrDec % MAX_HEX - MAX_DEC + 'a';
335 buf[1] = '\0';
336 }
337 addrHex = buf;
338 return addrHex;
339 }
340
HexToBin(const std::string & strHex)341 std::string Ipv6Address::HexToBin(const std::string &strHex)
342 {
343 int addrDec = CheckDataLegalHex(strHex);
344 std::string addrBin;
345 for (int n = addrDec; n; n = n / MAX_BIN) {
346 addrBin += ((n % MAX_BIN) ? "1" : "0");
347 }
348 std::reverse(addrBin.begin(), addrBin.end());
349 return addrBin;
350 }
351
MacToEui64addr(MacAddress & mac)352 std::string Ipv6Address::MacToEui64addr(MacAddress &mac)
353 {
354 struct sockaddr macSockaddr = mac.GetMacAddressWifiSockaddr();
355
356 unsigned char eui64Sa[HALF_IN6ADDR] = {0};
357 char eui64Addr[BUFFER_SIZE] = {0};
358
359 eui64Sa[0] = macSockaddr.sa_data[0] | ((macSockaddr.sa_data[0] & 0x2) ^ 0x2);
360 eui64Sa[1] = macSockaddr.sa_data[1];
361 eui64Sa[TWO] = macSockaddr.sa_data[TWO];
362 eui64Sa[THREE] = 0xFF;
363 eui64Sa[FOUR] = 0xFE;
364 eui64Sa[FIVE] = macSockaddr.sa_data[THREE];
365 eui64Sa[SIX] = macSockaddr.sa_data[FOUR];
366 eui64Sa[SEVEN] = macSockaddr.sa_data[FIVE];
367
368 if (snprintf_s(eui64Addr,
369 sizeof(eui64Addr),
370 sizeof(eui64Addr) - 1,
371 "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
372 eui64Sa[0],
373 eui64Sa[1],
374 eui64Sa[TWO],
375 eui64Sa[THREE],
376 eui64Sa[FOUR],
377 eui64Sa[FIVE],
378 eui64Sa[SIX],
379 eui64Sa[SEVEN]) < 0) {
380 return std::string("");
381 }
382 return std::string(eui64Addr);
383 }
384 } // namespace WiFi
385 } // namespace OHOS
386