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