• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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