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