1 /*
2 * Copyright (c) 2024 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 "bitmap_manager.h"
17
18 #include <arpa/inet.h>
19 #include <cstdio>
20 #include <netdb.h>
21 #include <securec.h>
22 #include <string>
23 #include <sys/socket.h>
24 #include <vector>
25
26 #include "netmanager_base_common_utils.h"
27 #include "netnative_log_wrapper.h"
28 #include "netsys_net_dns_result_data.h"
29
30 using namespace OHOS::NetsysNative;
31
32 namespace OHOS {
33 namespace NetManagerStandard {
34 const uint32_t BITMAP_BIT_COUNT = (BITMAP_LEN * sizeof(uint32_t) * BIT_PER_BYTE);
35
Bitmap()36 Bitmap::Bitmap()
37 {
38 Clear();
39 }
40
Bitmap(uint32_t n)41 Bitmap::Bitmap(uint32_t n)
42 {
43 Clear();
44 Set(n);
45 }
46
Bitmap(const Bitmap & other)47 Bitmap::Bitmap(const Bitmap &other)
48 {
49 memcpy_s(bitmap_, sizeof(bitmap_), other.bitmap_, sizeof(bitmap_));
50 }
51
Clear()52 void Bitmap::Clear()
53 {
54 memset_s(bitmap_, sizeof(bitmap_), 0, sizeof(bitmap_));
55 }
56
57 const int BIT_OFFSET = 5; // n/32
58 const int BIT_REMAINDER = 0x1f; // n%32
Set(uint32_t n)59 void Bitmap::Set(uint32_t n)
60 {
61 if (n < BITMAP_BIT_COUNT) {
62 int32_t i = n >> BIT_OFFSET;
63 int32_t j = n & BIT_REMAINDER;
64 bitmap_[i] |= 1 << j;
65 }
66 }
67
SpecialHash() const68 uint64_t Bitmap::SpecialHash() const
69 {
70 uint64_t h = 0;
71 for (int32_t i = 0; i < BITMAP_LEN; i++) {
72 if (bitmap_[i]) {
73 h = GetHash(bitmap_[i]);
74 h = h << i;
75 return h;
76 }
77 }
78 return h;
79 }
80
And(const Bitmap & other)81 void Bitmap::And(const Bitmap &other)
82 {
83 for (int32_t i = 0; i < BITMAP_LEN; i++) {
84 bitmap_[i] &= other.bitmap_[i];
85 }
86 }
87
Or(const Bitmap & other)88 void Bitmap::Or(const Bitmap &other)
89 {
90 for (int32_t i = 0; i < BITMAP_LEN; i++) {
91 bitmap_[i] |= other.bitmap_[i];
92 }
93 }
94
operator ==(const Bitmap & other) const95 bool Bitmap::operator == (const Bitmap &other) const
96 {
97 return (memcmp(bitmap_, other.bitmap_, sizeof(bitmap_)) == 0);
98 }
99
operator =(const Bitmap & other)100 Bitmap &Bitmap::operator = (const Bitmap &other)
101 {
102 memcpy_s(bitmap_, sizeof(bitmap_), other.bitmap_, sizeof(bitmap_));
103 return *this;
104 }
105
106 // Thomas Wang's 32 bit Mix Function
GetHash(uint32_t key) const107 uint32_t Bitmap::GetHash(uint32_t key) const
108 {
109 const int THOMAS_INDEX_0 = 15;
110 const int THOMAS_INDEX_1 = 10;
111 const int THOMAS_INDEX_2 = 3;
112 const int THOMAS_INDEX_3 = 6;
113 const int THOMAS_INDEX_4 = 11;
114 const int THOMAS_INDEX_5 = 16;
115 key += ~(key << THOMAS_INDEX_0);
116 key ^= (key >> THOMAS_INDEX_1);
117 key += (key << THOMAS_INDEX_2);
118 key ^= (key >> THOMAS_INDEX_3);
119 key += ~(key << THOMAS_INDEX_4);
120 key ^= (key >> THOMAS_INDEX_5);
121 return key;
122 }
123
Get()124 uint32_t *Bitmap::Get()
125 {
126 return bitmap_;
127 }
128
Hltons(int32_t n)129 uint16_t BitmapManager::Hltons(int32_t n)
130 {
131 return htons((uint16_t)(n & 0x0000ffff));
132 }
133
Nstohl(uint16_t n)134 uint16_t BitmapManager::Nstohl(uint16_t n)
135 {
136 uint16_t m = 0;
137 return m | ntohs(n);
138 }
139
BuildBitmapMap(const std::vector<sptr<NetFirewallIpRule>> & ruleList)140 int32_t BitmapManager::BuildBitmapMap(const std::vector<sptr<NetFirewallIpRule>> &ruleList)
141 {
142 Clear();
143 int32_t ret = BuildMarkBitmap(ruleList);
144 if (ret != NETFIREWALL_SUCCESS) {
145 return ret;
146 }
147
148 Bitmap bitmap;
149 srcIp4Map_.OrInsert(OTHER_IP4_KEY, IPV4_MAX_PREFIXLEN, bitmap);
150 dstIp4Map_.OrInsert(OTHER_IP4_KEY, IPV4_MAX_PREFIXLEN, bitmap);
151 in6_addr otherIp6Key;
152 memset_s(&otherIp6Key, sizeof(in6_addr), 0xff, sizeof(in6_addr));
153 srcIp6Map_.OrInsert(otherIp6Key, IPV6_MAX_PREFIXLEN, bitmap);
154 dstIp6Map_.OrInsert(otherIp6Key, IPV6_MAX_PREFIXLEN, bitmap);
155 srcPortMap_.OrInsert(OTHER_PORT_KEY, Bitmap());
156 dstPortMap_.OrInsert(OTHER_PORT_KEY, Bitmap());
157 protoMap_.OrInsert(OTHER_PROTO_KEY, Bitmap());
158 appUidMap_.OrInsert(OTHER_APPUID_KEY, Bitmap());
159 uidMap_.OrInsert(OTHER_UID_KEY, Bitmap());
160
161 BuildNoMarkBitmap(ruleList);
162 return NETFIREWALL_SUCCESS;
163 }
164
Clear()165 void BitmapManager::Clear()
166 {
167 srcIp4Map_.Clear();
168 srcIp6Map_.Clear();
169 dstIp4Map_.Clear();
170 dstIp6Map_.Clear();
171 srcPortMap_.Clear();
172 dstPortMap_.Clear();
173 protoMap_.Clear();
174 appUidMap_.Clear();
175 uidMap_.Clear();
176 actionMap_.Clear();
177 }
178
InsertIp4SegBitmap(const NetFirewallIpParam & item,Bitmap & bitmap,Ip4RuleMap * ip4Map)179 int32_t BitmapManager::InsertIp4SegBitmap(const NetFirewallIpParam &item, Bitmap &bitmap, Ip4RuleMap *ip4Map)
180 {
181 if (ip4Map == nullptr) {
182 return NETFIREWALL_ERR;
183 }
184 if (item.type == SINGLE_IP) {
185 uint32_t ipInt = item.ipv4.startIp.s_addr;
186 ip4Map->OrInsert(ipInt, static_cast<uint32_t>(item.mask), bitmap);
187 NETNATIVE_LOG_D("InsertIpBitmap ipp[%{public}u] ipn[%{public}s] mask[%{public}u]", ipInt,
188 item.GetStartIp().c_str(), item.mask);
189 } else if (item.type == MULTIPLE_IP) {
190 std::vector<Ip4Data> ips;
191 int32_t ret = IpParamParser::GetIp4AndMask(item.ipv4.startIp, item.ipv4.endIp, ips);
192 if (ret != NETFIREWALL_SUCCESS) {
193 return ret;
194 }
195 for (auto &ipData : ips) {
196 ip4Map->OrInsert(htonl(ipData.data), ipData.mask, bitmap);
197 NETNATIVE_LOG_D("InsertIpBitmap ip[%{public}u], mask[%{public}u]", htonl(ipData.data), ipData.mask);
198 }
199 }
200 return NETFIREWALL_SUCCESS;
201 }
202
203
InsertIp6SegBitmap(const NetFirewallIpParam & item,Bitmap & bitmap,Ip6RuleMap * ip6Map)204 int32_t BitmapManager::InsertIp6SegBitmap(const NetFirewallIpParam &item, Bitmap &bitmap, Ip6RuleMap *ip6Map)
205 {
206 if (ip6Map == nullptr) {
207 return NETFIREWALL_ERR;
208 }
209 if (item.type == SINGLE_IP) {
210 ip6Map->OrInsert(item.ipv6.startIp, static_cast<uint32_t>(item.mask), bitmap);
211 std::string addrStr = IpParamParser::Addr6ToStr(item.ipv6.startIp);
212 NETNATIVE_LOG_D("InsertIp6SegBitmap ip[%{public}s], mask[%{public}u]",
213 CommonUtils::ToAnonymousIp(addrStr).c_str(), item.mask);
214 } else if (item.type == MULTIPLE_IP) {
215 std::vector<Ip6Data> ips;
216 int32_t ret = IpParamParser::GetIp6AndMask(item.ipv6.startIp, item.ipv6.endIp, ips);
217 if (ret != NETFIREWALL_SUCCESS) {
218 NETNATIVE_LOGW("InsertIp6SegBitmap GetIp6AndMask fail ret=%{public}d", ret);
219 return ret;
220 }
221 for (auto &ipData : ips) {
222 ip6Map->OrInsert(ipData.data, ipData.prefixlen, bitmap);
223 }
224 }
225 return NETFIREWALL_SUCCESS;
226 }
227
InsertIpBitmap(const std::vector<NetFirewallIpParam> & ipInfo,bool isSrc,Bitmap & bitmap)228 int32_t BitmapManager::InsertIpBitmap(const std::vector<NetFirewallIpParam> &ipInfo, bool isSrc, Bitmap &bitmap)
229 {
230 for (const NetFirewallIpParam &item : ipInfo) {
231 Ip4RuleMap *ip4Map = nullptr;
232 Ip6RuleMap *ip6Map = nullptr;
233 if (isSrc) {
234 if (item.family == FAMILY_IPV4) {
235 ip4Map = &srcIp4Map_;
236 } else if (item.family == FAMILY_IPV6) {
237 ip6Map = &srcIp6Map_;
238 }
239 } else {
240 if (item.family == FAMILY_IPV4) {
241 ip4Map = &dstIp4Map_;
242 } else if (item.family == FAMILY_IPV6) {
243 ip6Map = &dstIp6Map_;
244 }
245 }
246
247 int32_t ret = NETFIREWALL_SUCCESS;
248 if (item.family == FAMILY_IPV4) {
249 int32_t ret = InsertIp4SegBitmap(item, bitmap, ip4Map);
250 if (ret != NETFIREWALL_SUCCESS) {
251 return ret;
252 }
253 } else {
254 ret = InsertIp6SegBitmap(item, bitmap, ip6Map);
255 if (ret != NETFIREWALL_SUCCESS) {
256 return ret;
257 }
258 }
259 }
260 return NETFIREWALL_SUCCESS;
261 }
262
OrInsertPortBitmap(SegmentBitmapMap & portSegMap,BpfUnorderedMap<PortKey> & portMap)263 void BitmapManager::OrInsertPortBitmap(SegmentBitmapMap &portSegMap, BpfUnorderedMap<PortKey> &portMap)
264 {
265 auto &segMap = portSegMap.GetMap();
266 for (auto &item : segMap) {
267 uint32_t start = item.start;
268 while (start <= item.end) {
269 if (start == 0) {
270 continue;
271 }
272 PortKey key = (PortKey)Hltons(start);
273 portMap.OrInsert(key, item.bitmap);
274 start++;
275 }
276 }
277 }
278
AddPortBitmap(const std::vector<NetFirewallPortParam> & port,Bitmap & bitmap,SegmentBitmapMap & portMap)279 void BitmapManager::AddPortBitmap(const std::vector<NetFirewallPortParam> &port, Bitmap &bitmap,
280 SegmentBitmapMap &portMap)
281 {
282 for (const NetFirewallPortParam &item : port) {
283 uint16_t startPort = item.startPort;
284 if (startPort == 0) {
285 continue;
286 }
287 if (item.startPort <= item.endPort) {
288 portMap.AddMap(item.startPort, item.endPort, bitmap);
289 }
290 }
291 }
292
BuildMarkBitmap(const std::vector<sptr<NetFirewallIpRule>> & ruleList)293 int32_t BitmapManager::BuildMarkBitmap(const std::vector<sptr<NetFirewallIpRule>> &ruleList)
294 {
295 SegmentBitmapMap srcPortMap;
296 SegmentBitmapMap dstPortMap;
297 uint32_t index = 0;
298 int32_t ret;
299 for (const auto &rule : ruleList) {
300 Bitmap bitmap(index);
301 ret = InsertIpBitmap(rule->remoteIps, true, bitmap);
302 if (ret) {
303 NETNATIVE_LOGW("BuildMarkBitmap InsertIpBitmap remoteIps fail ret=%{public}d", ret);
304 return NETFIREWALL_ERR;
305 }
306 ret = InsertIpBitmap(rule->localIps, false, bitmap);
307 if (ret) {
308 NETNATIVE_LOGW("BuildMarkBitmap InsertIpBitmap localIps fail ret=%{public}d", ret);
309 return NETFIREWALL_ERR;
310 }
311 if (!IsNotNeedPort(rule->protocol)) {
312 AddPortBitmap(rule->remotePorts, bitmap, srcPortMap);
313 AddPortBitmap(rule->localPorts, bitmap, dstPortMap);
314 }
315
316 if (rule->protocol != (NetworkProtocol)0) {
317 ProtoKey proto = (ProtoKey)rule->protocol;
318 protoMap_.OrInsert(proto, bitmap);
319 }
320
321 if (rule->appUid > 0) {
322 appUidMap_.OrInsert((AppUidKey)rule->appUid, bitmap);
323 }
324
325 if (rule->userId > 0) {
326 uidMap_.OrInsert((UidKey)rule->userId, bitmap);
327 }
328
329 if (rule->ruleAction != FirewallRuleAction::RULE_ALLOW) {
330 action_key Key = 1;
331 actionMap_.OrInsert(Key, bitmap);
332 }
333 index++;
334 }
335
336 OrInsertPortBitmap(srcPortMap, srcPortMap_);
337 OrInsertPortBitmap(dstPortMap, dstPortMap_);
338 return NETFIREWALL_SUCCESS;
339 }
340
BuildNoMarkBitmap(const std::vector<sptr<NetFirewallIpRule>> & ruleList)341 void BitmapManager::BuildNoMarkBitmap(const std::vector<sptr<NetFirewallIpRule>> &ruleList)
342 {
343 uint32_t index = 0;
344 for (const auto &rule : ruleList) {
345 Bitmap bitmap(index);
346 if (rule->remoteIps.empty()) {
347 srcIp4Map_.OrForEach(bitmap);
348 srcIp6Map_.OrForEach(bitmap);
349 }
350 if (rule->localIps.empty()) {
351 dstIp4Map_.OrForEach(bitmap);
352 dstIp6Map_.OrForEach(bitmap);
353 }
354 if (rule->remotePorts.empty() || IsNotNeedPort(rule->protocol)) {
355 srcPortMap_.OrForEach(bitmap);
356 }
357 if (rule->localPorts.empty() || IsNotNeedPort(rule->protocol)) {
358 dstPortMap_.OrForEach(bitmap);
359 }
360 if (rule->protocol == (NetworkProtocol)0) {
361 protoMap_.OrForEach(bitmap);
362 }
363 if (rule->appUid < 1) {
364 appUidMap_.OrForEach(bitmap);
365 }
366 if (rule->userId < 1) {
367 uidMap_.OrForEach(bitmap);
368 }
369 index++;
370 }
371 }
372
IsNotNeedPort(NetworkProtocol protocol)373 bool BitmapManager::IsNotNeedPort(NetworkProtocol protocol)
374 {
375 if (protocol == NetworkProtocol::ICMPV6 || protocol == NetworkProtocol::ICMP) {
376 return true;
377 }
378 return false;
379 }
380
GetIpUint32(const std::string & address,uint32_t & ipInt)381 int32_t IpParamParser::GetIpUint32(const std::string &address, uint32_t &ipInt)
382 {
383 in_addr out = { 0 };
384 memset_s(&out, sizeof(out), 0, sizeof(out));
385 if (inet_pton(AF_INET, address.c_str(), &out) != 1) {
386 return NETFIREWALL_IP_STR_ERR;
387 }
388
389 ipInt = out.s_addr;
390 return NETFIREWALL_SUCCESS;
391 }
392
AddIp(uint32_t ip,uint32_t mask,std::vector<Ip4Data> & ip4Vec)393 void IpParamParser::AddIp(uint32_t ip, uint32_t mask, std::vector<Ip4Data> &ip4Vec)
394 {
395 Ip4Data info;
396 info.data = ip;
397 info.mask = mask;
398 ip4Vec.emplace_back(info);
399 }
400
Ip4ToStr(uint32_t ip)401 std::string IpParamParser::Ip4ToStr(uint32_t ip)
402 {
403 char str[INET_ADDRSTRLEN] = {0};
404 in_addr ipv4;
405 memset_s(&ipv4, sizeof(ipv4), 0, sizeof(ipv4));
406 ipv4.s_addr = ntohl(ip);
407
408 if (inet_ntop(AF_INET, &ipv4, str, INET_ADDRSTRLEN) == NULL) {
409 return "error ip";
410 }
411 return std::string(str);
412 }
413
GetMask(uint32_t startIp,uint32_t endIp)414 int32_t IpParamParser::GetMask(uint32_t startIp, uint32_t endIp)
415 {
416 int32_t i = static_cast<int32_t>(IPV4_BIT_COUNT - 1);
417 for (; i >= 0; --i) {
418 if (((startIp >> i) & VALUE_ONE) != ((endIp >> i) & VALUE_ONE)) {
419 return IPV4_BIT_COUNT - i - 1;
420 }
421 }
422 return IPV4_BIT_COUNT;
423 }
424
Rfind(uint32_t ip,uint32_t start,uint32_t end,uint32_t value)425 int32_t IpParamParser::Rfind(uint32_t ip, uint32_t start, uint32_t end, uint32_t value)
426 {
427 if (start > end) {
428 return IPV4_BIT_COUNT;
429 }
430 int32_t startIndex = IPV4_BIT_COUNT - end - 1;
431 int32_t endIndex = IPV4_BIT_COUNT - start - 1;
432 for (int32_t i = startIndex; i <= endIndex; ++i) {
433 if (((ip >> i) & VALUE_ONE) == value) {
434 return IPV4_BIT_COUNT - i - 1;
435 }
436 }
437 return IPV4_BIT_COUNT;
438 }
439
Find(uint32_t ip,uint32_t start,uint32_t value)440 int32_t IpParamParser::Find(uint32_t ip, uint32_t start, uint32_t value)
441 {
442 if (start >= IPV4_BIT_COUNT) {
443 return IPV4_BIT_COUNT;
444 }
445 int32_t i = IPV4_BIT_COUNT - start - 1;
446 for (; i >= 0; --i) {
447 if (((ip >> i) & VALUE_ONE) == value) {
448 return IPV4_BIT_COUNT - i - 1;
449 }
450 }
451 return IPV4_BIT_COUNT;
452 }
453
ChangeStart(uint32_t mask,uint32_t & ip)454 void IpParamParser::ChangeStart(uint32_t mask, uint32_t &ip)
455 {
456 bool needSetZero = true;
457 if (mask > IPV4_MAX_PREFIXLEN) {
458 return;
459 } else if (mask == IPV4_MAX_PREFIXLEN) {
460 needSetZero = false;
461 }
462 for (int32_t i = 0; i <= (IPV4_BIT_COUNT - 1); ++i) {
463 uint32_t byte = (1 << i);
464 if (needSetZero && (i <= (IPV4_BIT_COUNT - static_cast<int32_t>(mask) - 1))) {
465 ip &= (~byte);
466 continue;
467 }
468 if (ip & byte) {
469 ip &= (~byte);
470 continue;
471 }
472 ip |= byte;
473 return;
474 }
475 }
476
GetIp4AndMask(const in_addr & startAddr,const in_addr & endAddr,std::vector<Ip4Data> & list)477 int32_t IpParamParser::GetIp4AndMask(const in_addr &startAddr, const in_addr &endAddr, std::vector<Ip4Data> &list)
478 {
479 uint32_t startIpInt = ntohl(startAddr.s_addr);
480 uint32_t endIpInt = ntohl(endAddr.s_addr);
481 if (startIpInt > endIpInt) {
482 return NETFIREWALL_ERR;
483 } else if (startIpInt == endIpInt) {
484 AddIp(startIpInt, IPV4_MAX_PREFIXLEN, list);
485 return NETFIREWALL_SUCCESS;
486 }
487 uint32_t mask = GetMask(startIpInt, endIpInt);
488 uint32_t tmpStart = startIpInt;
489 uint32_t off = Rfind(tmpStart, mask, IPV4_BIT_COUNT - 1, 1);
490 if (off != IPV4_BIT_COUNT) {
491 AddIp(tmpStart, off + 1, list);
492 ChangeStart(off + 1, tmpStart);
493 off = Rfind(startIpInt, mask, off, 0);
494 while (off != IPV4_BIT_COUNT && off != mask) {
495 AddIp(tmpStart, off + 1, list);
496 ChangeStart(off + 1, tmpStart);
497 off = Rfind(startIpInt, mask, off - 1, 0);
498 }
499 } else if (Rfind(endIpInt, mask, IPV4_BIT_COUNT - 1, 0) == IPV4_BIT_COUNT) {
500 AddIp(startIpInt, mask, list);
501 return true;
502 }
503 off = Find(endIpInt, mask, 1);
504 if (off == IPV4_BIT_COUNT) {
505 return NETFIREWALL_ERR;
506 }
507 off = Find(endIpInt, off + 1, 1);
508 while (off != IPV4_BIT_COUNT) {
509 AddIp(tmpStart, off + 1, list);
510 ChangeStart(off + 1, tmpStart);
511 off = Find(endIpInt, off + 1, 1);
512 }
513 if (tmpStart == endIpInt) {
514 AddIp(tmpStart, IPV4_BIT_COUNT, list);
515 }
516 return NETFIREWALL_SUCCESS;
517 }
518
GetInAddr6(const std::string & ipStr,in6_addr & addr)519 int32_t IpParamParser::GetInAddr6(const std::string &ipStr, in6_addr &addr)
520 {
521 int32_t ret = inet_pton(AF_INET6, ipStr.c_str(), &addr);
522 if (ret <= 0) {
523 return NETFIREWALL_IP_STR_ERR;
524 }
525 return NETFIREWALL_SUCCESS;
526 }
527
Addr6ToStr(const in6_addr & v6Addr)528 std::string IpParamParser::Addr6ToStr(const in6_addr &v6Addr)
529 {
530 char buf[INET6_ADDRSTRLEN] = { 0 };
531 if (inet_ntop(AF_INET6, &v6Addr, buf, INET6_ADDRSTRLEN) == NULL) {
532 return "error in6_addr";
533 }
534 return std::string(buf);
535 }
536
GetIp6Prefixlen(const in6_addr & start,const in6_addr & end)537 uint32_t IpParamParser::GetIp6Prefixlen(const in6_addr &start, const in6_addr &end)
538 {
539 uint32_t prefixlen = IPV6_MAX_PREFIXLEN;
540 for (size_t i = 0; i < IPV6_BIT_COUNT; i++) {
541 if (start.s6_addr[i] == end.s6_addr[i]) {
542 continue;
543 }
544 for (int32_t j = static_cast<int32_t>(BIT_PER_BYTE - 1); j >= 0; --j) {
545 uint8_t byte = (1 << j);
546 if ((start.s6_addr[i] & byte) == (end.s6_addr[i] & byte)) {
547 continue;
548 } else {
549 prefixlen = i * BIT_PER_BYTE + BIT_PER_BYTE - j - 1;
550 return prefixlen;
551 }
552 }
553 }
554 return prefixlen;
555 }
556
RfindIp6(const in6_addr & addr,uint32_t startBit,uint32_t endBit,uint8_t value)557 int32_t IpParamParser::RfindIp6(const in6_addr &addr, uint32_t startBit, uint32_t endBit, uint8_t value)
558 {
559 if (startBit > endBit) {
560 return IPV6_BIT_COUNT;
561 }
562 int32_t startBits = static_cast<int32_t>(startBit % BIT_PER_BYTE);
563 int32_t startBytes = static_cast<int32_t>(startBit / BIT_PER_BYTE);
564 int32_t endBits = static_cast<int32_t>(endBit % BIT_PER_BYTE);
565 int32_t endBytes = static_cast<int32_t>(endBit / BIT_PER_BYTE);
566 for (int32_t i = endBytes; i >= startBytes; --i) {
567 int32_t j = (i == endBytes) ? (BIT_PER_BYTE - endBits - 1) : 0;
568 int32_t k = (i == startBytes) ? (BIT_PER_BYTE - startBits - 1) : (BIT_PER_BYTE - 1);
569 for (; j <= k; ++j) {
570 uint8_t byte = (1 << j);
571 uint8_t tmp = (addr.s6_addr[i] & byte) >> j;
572 if (tmp == value) {
573 return i * BIT_PER_BYTE + BIT_PER_BYTE - j - 1;
574 }
575 }
576 }
577 return IPV6_BIT_COUNT;
578 }
579
FindIp6(const in6_addr & addr,uint32_t startBit,uint8_t value)580 int32_t IpParamParser::FindIp6(const in6_addr &addr, uint32_t startBit, uint8_t value)
581 {
582 if (startBit >= IPV6_BIT_COUNT) {
583 return IPV6_BIT_COUNT;
584 }
585 int32_t startBits = static_cast<int32_t>(startBit % BIT_PER_BYTE);
586 int32_t startBytes = static_cast<int32_t>(startBit / BIT_PER_BYTE);
587 for (int32_t i = static_cast<int32_t>(startBytes); i < IPV6_BYTE_COUNT; ++i) {
588 int32_t j = (i == startBytes) ? (BIT_PER_BYTE - startBits - 1) : (BIT_PER_BYTE - 1);
589 for (; j >= 0; --j) {
590 uint8_t tmp = ((addr.s6_addr[i] >> j) & VALUE_ONE);
591 if (tmp == value) {
592 return i * BIT_PER_BYTE + BIT_PER_BYTE - j - 1;
593 }
594 }
595 }
596 return IPV6_BIT_COUNT;
597 }
598
AddIp6(const in6_addr & addr,uint32_t prefixlen,std::vector<Ip6Data> & list)599 void IpParamParser::AddIp6(const in6_addr &addr, uint32_t prefixlen, std::vector<Ip6Data> &list)
600 {
601 Ip6Data info;
602 info.prefixlen = prefixlen;
603 info.data = addr;
604 list.emplace_back(info);
605
606 std::string startIpStr = IpParamParser::Addr6ToStr(info.data);
607 NETNATIVE_LOG_D("AddIp6 ip[%{public}s], mask[%{public}u]",
608 CommonUtils::ToAnonymousIp(startIpStr).c_str(), info.prefixlen);
609 }
610
ChangeIp6Start(uint32_t startBit,in6_addr & addr)611 void IpParamParser::ChangeIp6Start(uint32_t startBit, in6_addr &addr)
612 {
613 uint32_t bits = startBit % BIT_PER_BYTE;
614 uint32_t bytes = startBit / BIT_PER_BYTE;
615 if (bytes < IPV6_BYTE_COUNT - 1) {
616 memset_s(addr.s6_addr + bytes + 1, IPV6_BYTE_COUNT - bytes - 1, 0, IPV6_BYTE_COUNT - bytes - 1);
617 }
618
619 bool needSetZero = true;
620 if (bytes >= IPV6_BYTE_COUNT) {
621 bytes = IPV6_BYTE_COUNT - 1;
622 bits = BIT_PER_BYTE - 1;
623 needSetZero = false;
624 }
625
626 int32_t off = BIT_PER_BYTE - bits - 1;
627 for (int32_t i = bytes; i >= 0; --i) {
628 for (int32_t j = 0; j < static_cast<int32_t>(BIT_PER_BYTE); ++j) {
629 uint8_t byte = (1 << j);
630 if (needSetZero && (i == static_cast<int32_t>(bytes) && j <= off)) {
631 addr.s6_addr[i] &= (~byte);
632 continue;
633 }
634 if (addr.s6_addr[i] & byte) {
635 addr.s6_addr[i] &= (~byte);
636 continue;
637 } else {
638 addr.s6_addr[i] |= byte;
639 return;
640 }
641 }
642 }
643 }
644
GetIp6AndMask(const in6_addr & addr6Start,const in6_addr & addr6End,std::vector<Ip6Data> & list)645 int32_t IpParamParser::GetIp6AndMask(const in6_addr &addr6Start, const in6_addr &addr6End, std::vector<Ip6Data> &list)
646 {
647 int32_t ret = memcmp(&addr6Start, &addr6End, sizeof(addr6Start));
648 if (ret > 0) {
649 NETNATIVE_LOGW("GetIp6AndMask fail ret=%{public}d", ret);
650 return NETFIREWALL_ERR;
651 } else if (ret == 0) {
652 AddIp6(addr6Start, IPV6_MAX_PREFIXLEN, list);
653 return NETFIREWALL_SUCCESS;
654 }
655 uint32_t prefixlen = GetIp6Prefixlen(addr6Start, addr6End);
656 in6_addr tmpAddr;
657 memcpy_s(&tmpAddr, sizeof(tmpAddr), &addr6Start, sizeof(addr6Start));
658 uint32_t off = RfindIp6(addr6Start, prefixlen, IPV6_BIT_COUNT - 1, 1);
659 if (off != IPV6_BIT_COUNT) {
660 AddIp6(tmpAddr, off + 1, list);
661 ChangeIp6Start(off + 1, tmpAddr);
662 off = RfindIp6(addr6Start, prefixlen, off, 0);
663 while (off != IPV6_BIT_COUNT && off != prefixlen) {
664 AddIp6(tmpAddr, off + 1, list);
665 ChangeIp6Start(off + 1, tmpAddr);
666 off = RfindIp6(addr6Start, prefixlen, off - 1, 0);
667 }
668 } else if (off == IPV6_BIT_COUNT) {
669 if (RfindIp6(addr6End, prefixlen, IPV6_BIT_COUNT - 1, 0) == IPV6_BIT_COUNT) {
670 AddIp6(addr6Start, prefixlen, list);
671 return NETFIREWALL_SUCCESS;
672 }
673 }
674 off = FindIp6(addr6End, prefixlen, 1);
675 if (off == IPV6_BIT_COUNT) {
676 NETNATIVE_LOGW("GetIp6AndMask off equal 128");
677 return NETFIREWALL_ERR;
678 }
679 off = FindIp6(addr6End, off + 1, 1);
680 while (off != IPV6_BIT_COUNT) {
681 AddIp6(tmpAddr, off + 1, list);
682 ChangeIp6Start(off + 1, tmpAddr);
683 off = FindIp6(addr6End, off + 1, 1);
684 }
685 ret = memcmp(&tmpAddr, &addr6End, sizeof(addr6Start));
686 if (ret == 0) {
687 AddIp6(tmpAddr, IPV6_MAX_PREFIXLEN, list);
688 }
689 return NETFIREWALL_SUCCESS;
690 }
691 } // namespace NetManagerStandard
692 } // namespace OHOS