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