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