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