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