• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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