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 = std::atoi(value.c_str());
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 = std::atoi(tmpAddress.c_str());
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     std::string netMask;
152     if (prefixLength < MIN_PREFIX_LEN || prefixLength > MAX_IPV6_PREFIX_LEN) {
153         return netMask;
154     }
155 
156     std::ostringstream stream;
157     stream << prefixLength;
158     netMask = stream.str();
159 
160     return netMask;
161 }
162 
GetMaskLength(std::string mask)163 int IpTools::GetMaskLength(std::string mask)
164 {
165     int netMask = 0;
166     const unsigned int constMask = 0x80000000;
167     unsigned int maskTmp = ntohl(static_cast<int>(inet_addr(mask.c_str())));
168     while (maskTmp & constMask) {
169         netMask++;
170         maskTmp = (maskTmp << 1);
171     }
172 
173     return netMask;
174 }
175 
176 /**
177     * @Description : Obtains the length based on the subnet mask.
178     *
179     * @param mask - The mask.[in]
180     * @return int
181 */
GetIPV6MaskLength(std::string ip)182 int IpTools::GetIPV6MaskLength(std::string ip)
183 {
184     constexpr int32_t LENGTH_8 = 8;
185     constexpr int32_t LENGTH_7 = 7;
186     constexpr int32_t LENGTH_6 = 6;
187     constexpr int32_t LENGTH_5 = 5;
188     constexpr int32_t LENGTH_4 = 4;
189     constexpr int32_t LENGTH_3 = 3;
190     constexpr int32_t LENGTH_2 = 2;
191     constexpr int32_t LENGTH_1 = 1;
192     if (ip.empty()) {
193         return 0;
194     }
195     in6_addr addr{};
196     inet_pton(AF_INET6, ip.c_str(), &addr);
197     int32_t prefixLen = 0;
198     for (int32_t i = 0; i < BITS_16; ++i) {
199         if (addr.s6_addr[i] == 0xFF) {
200             prefixLen += LENGTH_8;
201         } else if (addr.s6_addr[i] == 0xFE) {
202             prefixLen += LENGTH_7;
203             break;
204         } else if (addr.s6_addr[i] == 0xFC) {
205             prefixLen += LENGTH_6;
206             break;
207         } else if (addr.s6_addr[i] == 0xF8) {
208             prefixLen += LENGTH_5;
209             break;
210         } else if (addr.s6_addr[i] == 0xF0) {
211             prefixLen += LENGTH_4;
212             break;
213         } else if (addr.s6_addr[i] == 0xE0) {
214             prefixLen += LENGTH_3;
215             break;
216         } else if (addr.s6_addr[i] == 0xC0) {
217             prefixLen += LENGTH_2;
218             break;
219         } else if (addr.s6_addr[i] == 0x80) {
220             prefixLen += LENGTH_1;
221             break;
222         } else {
223             break;
224         }
225     }
226     return prefixLen;
227 }
228 
GetExclusionObjectList(const std::string & exclusionObjectList,std::vector<std::string> & exclusionList)229 void IpTools::GetExclusionObjectList(const std::string &exclusionObjectList, std::vector<std::string> &exclusionList)
230 {
231     std::string tmpExclusionList = exclusionObjectList;
232     std::vector<std::string> list;
233     int listNum = count(tmpExclusionList.begin(), tmpExclusionList.end(), ',');
234     int i = 0;
235     for (i = 0; i < listNum; ++i) {
236         std::string::size_type npos = tmpExclusionList.find(",");
237         if (npos == std::string::npos) {
238             break;
239         }
240 
241         std::string exclusionOne = tmpExclusionList.substr(0, npos);
242         /* Do you need to check whether the format of this website is correct? */
243         list.push_back(exclusionOne);
244         tmpExclusionList = tmpExclusionList.substr(npos + 1);
245     }
246     if (i != listNum) {
247         return;
248     }
249     list.push_back(tmpExclusionList);
250     exclusionList.assign(list.begin(), list.end());
251     return;
252 }
253 }  // namespace Wifi
254 }  // namespace OHOS