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