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