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