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