/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <arpa/inet.h> #include <cstdio> #include <libbpf.h> #include <linux/bpf.h> #include <net/if.h> #include <netinet/in.h> #include <securec.h> #include <sys/epoll.h> #include <sys/socket.h> #include <vector> #include <ctime> #include "bpf_loader.h" #include "bpf_netfirewall.h" #include "netnative_log_wrapper.h" #include "iservice_registry.h" #include "bpf_ring_buffer.h" #include "ffrt_inner.h" using namespace std; using namespace OHOS; using namespace OHOS::NetsysNative; namespace OHOS { namespace NetManagerStandard { std::shared_ptr<NetsysBpfNetFirewall> NetsysBpfNetFirewall::instance_ = nullptr; bool NetsysBpfNetFirewall::keepListen_ = false; bool NetsysBpfNetFirewall::keepGc_ = false; bool NetsysBpfNetFirewall::isBpfLoaded_ = false; std::unique_ptr<BpfMapper<CtKey, CtVaule>> NetsysBpfNetFirewall::ctRdMap_ = nullptr; std::unique_ptr<BpfMapper<CtKey, CtVaule>> NetsysBpfNetFirewall::ctWrMap_ = nullptr; NetsysBpfNetFirewall::NetsysBpfNetFirewall() { NETNATIVE_LOG_D("NetsysBpfNetFirewall construct"); isBpfLoaded_ = false; } std::shared_ptr<NetsysBpfNetFirewall> NetsysBpfNetFirewall::GetInstance() { static std::mutex instanceMutex; std::lock_guard<std::mutex> guard(instanceMutex); if (instance_ == nullptr) { instance_.reset(new NetsysBpfNetFirewall()); return instance_; } return instance_; } void NetsysBpfNetFirewall::ConntrackGcTask() { NETNATIVE_LOG_D("ConntrackGcTask: running"); std::vector<CtKey> keys = ctRdMap_->GetAllKeys(); if (keys.empty()) { NETNATIVE_LOG_D("GcConntrackCb: key is empty"); return; } timespec now = { 0 }; // bpf_ktime_get_ns: CLOCK_MONOTONIC if (!clock_gettime(CLOCK_MONOTONIC, &now)) { return; } for (const CtKey &k : keys) { CtVaule v = {}; if (ctRdMap_->Read(k, v) < 0) { NETNATIVE_LOGE("GcConntrackCb: read failed"); continue; } if (v.lifetime < now.tv_sec) { if (ctWrMap_->Delete(k) != 0) { NETNATIVE_LOGE("GcConntrackCb: delete failed"); continue; } } } } void NetsysBpfNetFirewall::RingBufferListenThread(void) { if (keepListen_) { NETNATIVE_LOG_D("under listening"); return; } int mapFd = NetsysBpfRingBuffer::GetRingbufFd(MAP_PATH(EVENT_MAP), 0); if (mapFd < 0) { NETNATIVE_LOGE("failed to get ring buffer fd: errno=%{public}d", errno); return; } ring_buffer *rb = ring_buffer__new(mapFd, NetsysBpfNetFirewall::HandleEvent, NULL, NULL); if (!rb) { NETNATIVE_LOGE("failed to create ring buffer: errno=%{public}d", errno); return; } keepListen_ = true; while (keepListen_) { if (ffrt::this_task::get_id() != 0) { ffrt::sync_io(mapFd); } int err = ring_buffer__poll(rb, RING_BUFFER_POLL_TIME_OUT_MS); if (err < 0) { NETNATIVE_LOGE("Error polling ring buffer: errno=%{public}d", errno); keepListen_ = false; break; } } NETNATIVE_LOGE("Could not get bpf event ring buffer map"); ring_buffer__free(rb); } int32_t NetsysBpfNetFirewall::StartListener() { if (!isBpfLoaded_) { NETNATIVE_LOG_D("bfp is not loaded"); return -1; } ctRdMap_ = std::make_unique<BpfMapper<CtKey, CtVaule>>(MAP_PATH(CT_MAP), BPF_F_RDONLY); ctWrMap_ = std::make_unique<BpfMapper<CtKey, CtVaule>>(MAP_PATH(CT_MAP), BPF_F_WRONLY); ffrt::submit(RingBufferListenThread, {}, {}, ffrt::task_attr().name("RingBufferListen")); ffrt::submit(StartConntrackGcThread, { &ctRdMap_ }, { &ctWrMap_ }); return 0; } int32_t NetsysBpfNetFirewall::StopListener() { keepListen_ = false; StopConntrackGc(); return 0; } void NetsysBpfNetFirewall::StartConntrackGcThread(void) { if (keepGc_) { NETNATIVE_LOG_D("under keepGc"); return; } if (!ctRdMap_->IsValid()) { NETNATIVE_LOGE("GcConntrackCb: ctRdMap is invalid"); return; } if (!ctWrMap_->IsValid()) { NETNATIVE_LOGE("GcConntrackCb: ctWrMap is invalid"); return; } keepGc_ = true; int rdMapFd = NetsysBpfRingBuffer::GetRingbufFd(MAP_PATH(CT_MAP), BPF_F_RDONLY); int wrMapFd = NetsysBpfRingBuffer::GetRingbufFd(MAP_PATH(CT_MAP), BPF_F_WRONLY); if (rdMapFd < 0 || wrMapFd < 0) { NETNATIVE_LOGE("failed to get rdMapFd or wrMapFd: errno=%{public}d", errno); return; } while (keepGc_) { ffrt::this_task::sleep_for(std::chrono::milliseconds(CONNTRACK_GC_INTTERVAL_MS)); if (ffrt::this_task::get_id() != 0) { ffrt::sync_io(rdMapFd); ffrt::sync_io(wrMapFd); } ConntrackGcTask(); } } void NetsysBpfNetFirewall::StopConntrackGc() { keepGc_ = false; } void NetsysBpfNetFirewall::SetBpfLoaded(bool load) { isBpfLoaded_ = load; } void NetsysBpfNetFirewall::ClearBpfFirewallRules(NetFirewallRuleDirection direction) { NETNATIVE_LOG_D("ClearBpfFirewallRules: direction=%{public}d", direction); Ipv4LpmKey ip4Key = {}; Ipv6LpmKey ip6Key = {}; PortKey portKey = 0; ProtoKey protoKey = 0; AppUidKey appIdKey = 0; UidKey uidKey = 0; ActionKey actKey = 1; ActionValue actVal; RuleCode ruleCode; CtKey ctKey; CtVaule ctVal; bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); ClearBpfMap(GET_MAP_PATH(ingress, saddr), ip4Key, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, saddr6), ip6Key, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, daddr), ip4Key, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, daddr6), ip6Key, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, sport), portKey, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, dport), portKey, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, proto), protoKey, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, appuid), appIdKey, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, uid), uidKey, ruleCode); ClearBpfMap(GET_MAP_PATH(ingress, action), actKey, actVal); ClearBpfMap(MAP_PATH(CT_MAP), ctKey, ctVal); } int32_t NetsysBpfNetFirewall::ClearFirewallRules() { firewallIpRules_.clear(); ClearBpfFirewallRules(NetFirewallRuleDirection::RULE_IN); ClearBpfFirewallRules(NetFirewallRuleDirection::RULE_OUT); return NETFIREWALL_SUCCESS; } int32_t NetsysBpfNetFirewall::SetBpfFirewallRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList, NetFirewallRuleDirection direction) { BitmapManager manager; int32_t ret = manager.BuildBitmapMap(ruleList); if (ret) { NETNATIVE_LOGE("SetBpfFirewallRules: BuildBitmapMap failed: %{public}d", ret); return ret; } ClearBpfFirewallRules(direction); WriteSrcIpv4BpfMap(manager, direction); WriteSrcIpv6BpfMap(manager, direction); WriteDstIpv4BpfMap(manager, direction); WriteDstIpv6BpfMap(manager, direction); WriteSrcPortBpfMap(manager, direction); WriteDstPortBpfMap(manager, direction); WriteProtoBpfMap(manager, direction); WriteAppUidBpfMap(manager, direction); WriteUidBpfMap(manager, direction); WriteActionBpfMap(manager, direction); return NETFIREWALL_SUCCESS; } int32_t NetsysBpfNetFirewall::SetFirewallRules(const std::vector<sptr<NetFirewallBaseRule>> &ruleList, bool isFinish) { NETNATIVE_LOGI("SetFirewallRules: size=%{public}zu isFinish=%{public}" PRId32, ruleList.size(), isFinish); if (!isBpfLoaded_) { NETNATIVE_LOGE("SetFirewallRules: bpf not loaded"); return NETFIREWALL_ERR; } if (ruleList.empty()) { NETNATIVE_LOGE("SetFirewallRules: rules is empty"); return NETFIREWALL_ERR; } for (const auto &rule : ruleList) { firewallIpRules_.emplace_back(firewall_rule_cast<NetFirewallIpRule>(rule)); } int32_t ret = NETFIREWALL_SUCCESS; if (isFinish) { ret = SetFirewallIpRules(firewallIpRules_); firewallIpRules_.clear(); } return ret; } int32_t NetsysBpfNetFirewall::SetFirewallIpRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList) { std::vector<sptr<NetFirewallIpRule>> inRules; std::vector<sptr<NetFirewallIpRule>> outRules; for (const auto &rule : ruleList) { if (rule->ruleDirection == NetFirewallRuleDirection::RULE_IN) { if (rule->protocol == NetworkProtocol::ICMP || rule->protocol == NetworkProtocol::ICMPV6) { outRules.emplace_back(rule); } else { inRules.emplace_back(rule); } } if (rule->ruleDirection == NetFirewallRuleDirection::RULE_OUT) { outRules.emplace_back(rule); } } int32_t ret = NETFIREWALL_SUCCESS; if (!inRules.empty()) { ret = SetBpfFirewallRules(inRules, NetFirewallRuleDirection::RULE_IN); } if (!outRules.empty()) { ret += SetBpfFirewallRules(outRules, NetFirewallRuleDirection::RULE_OUT); } return ret; } int32_t NetsysBpfNetFirewall::SetFirewallDefaultAction(FirewallRuleAction inDefault, FirewallRuleAction outDefault) { if (!isBpfLoaded_) { NETNATIVE_LOGE("SetFirewallDefaultAction: bpf not loaded"); return NETFIREWALL_ERR; } DefaultActionKey key = DEFAULT_ACT_IN_KEY; enum sk_action val = (inDefault == FirewallRuleAction::RULE_ALLOW) ? SK_PASS : SK_DROP; WriteBpfMap(MAP_PATH(DEFAULT_ACTION_MAP), key, val); key = DEFAULT_ACT_OUT_KEY; val = (outDefault == FirewallRuleAction::RULE_ALLOW) ? SK_PASS : SK_DROP; WriteBpfMap(MAP_PATH(DEFAULT_ACTION_MAP), key, val); return NETFIREWALL_SUCCESS; } int32_t NetsysBpfNetFirewall::SetFirewallCurrentUserId(int32_t userId) { if (!isBpfLoaded_) { NETNATIVE_LOGE("SetFirewallCurrentUserId: bpf not loaded"); return NETFIREWALL_ERR; } CurrentUserIdKey key = CURRENT_USER_ID_KEY; UidKey val = (UidKey)userId; WriteBpfMap(MAP_PATH(CURRENT_UID_MAP), key, val); return NETFIREWALL_SUCCESS; } void NetsysBpfNetFirewall::WriteSrcIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { std::vector<Ip4RuleBitmap> &srcIp4Map = manager.GetSrcIp4Map(); if (srcIp4Map.empty()) { NETNATIVE_LOGE("WriteSrcIpv4BpfMap: srcIp4Map is empty"); return; } bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &node : srcIp4Map) { Bitmap val = node.bitmap; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); Ipv4LpmKey key = { 0 }; key.prefixlen = node.mask; key.data = static_cast<Ip4Key>(node.data); WriteBpfMap(GET_MAP_PATH(ingress, saddr), key, rule); } } void NetsysBpfNetFirewall::WriteSrcIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { std::vector<Ip6RuleBitmap> &srcIp6Map = manager.GetSrcIp6Map(); if (srcIp6Map.empty()) { NETNATIVE_LOGE("WriteSrcIpv6BpfMap: srcIp6Map is empty"); return; } bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &node : srcIp6Map) { Bitmap val = node.bitmap; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); Ipv6LpmKey key = { 0 }; key.prefixlen = node.prefixlen; key.data = static_cast<Ip6Key>(node.data); WriteBpfMap(GET_MAP_PATH(ingress, saddr6), key, rule); } } void NetsysBpfNetFirewall::WriteDstIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { std::vector<Ip4RuleBitmap> &dstIp4Map = manager.GetDstIp4Map(); if (dstIp4Map.empty()) { NETNATIVE_LOGE("WriteDstIp4BpfMap: dstIp4Map is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &node : dstIp4Map) { Bitmap val = node.bitmap; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); Ipv4LpmKey key = { 0 }; key.prefixlen = node.mask; key.data = static_cast<Ip4Key>(node.data); WriteBpfMap(GET_MAP_PATH(ingress, daddr), key, rule); } } } void NetsysBpfNetFirewall::WriteDstIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { std::vector<Ip6RuleBitmap> &dstIp6Map = manager.GetDstIp6Map(); if (dstIp6Map.empty()) { NETNATIVE_LOGE("WriteDstIp6BpfMap: dstIp6Map is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &node : dstIp6Map) { Bitmap val = node.bitmap; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); Ipv6LpmKey key = { 0 }; key.prefixlen = node.prefixlen; key.data = static_cast<Ip6Key>(node.data); WriteBpfMap(GET_MAP_PATH(ingress, daddr6), key, rule); } } } void NetsysBpfNetFirewall::WriteSrcPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { BpfPortMap &srcPortMap = manager.GetSrcPortMap(); if (srcPortMap.Empty()) { NETNATIVE_LOGE("WriteSrcPortBpfMap: srcPortMap is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &pair : srcPortMap.Get()) { PortKey key = pair.first; Bitmap val = pair.second; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); NETNATIVE_LOG_D("sport_map=%{public}d", key); WriteBpfMap(GET_MAP_PATH(ingress, sport), key, rule); } } } void NetsysBpfNetFirewall::WriteDstPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { BpfPortMap &dstPortMap = manager.GetDstPortMap(); if (dstPortMap.Empty()) { NETNATIVE_LOGE("WriteDstPortBpfMap: dstPortMap is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &pair : dstPortMap.Get()) { PortKey key = pair.first; Bitmap val = pair.second; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); NETNATIVE_LOG_D("dport_map=%{public}d", key); WriteBpfMap(GET_MAP_PATH(ingress, dport), key, rule); } } } void NetsysBpfNetFirewall::WriteProtoBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { BpfProtoMap &protoMap = manager.GetProtoMap(); if (protoMap.Empty()) { NETNATIVE_LOGE("WriteProtoBpfMap: protoMap is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &pair : protoMap.Get()) { ProtoKey key = pair.first; Bitmap val = pair.second; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); NETNATIVE_LOG_D("proto_map=%{public}d", key); WriteBpfMap(GET_MAP_PATH(ingress, proto), key, rule); } } } void NetsysBpfNetFirewall::WriteAppUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { BpfAppUidMap &appIdMap = manager.GetAppIdMap(); if (appIdMap.Empty()) { NETNATIVE_LOGE("WriteAppUidBpfMap: appIdMap is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &pair : appIdMap.Get()) { AppUidKey key = pair.first; Bitmap val = pair.second; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); NETNATIVE_LOG_D("appuid_map=%{public}d", key); WriteBpfMap(GET_MAP_PATH(ingress, appuid), key, rule); } } } void NetsysBpfNetFirewall::WriteUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { BpfUidMap &uidMap = manager.GetUidMap(); if (uidMap.Empty()) { NETNATIVE_LOGE("WriteUidBpfMap: uidMap is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &pair : uidMap.Get()) { UidKey key = pair.first; Bitmap val = pair.second; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); NETNATIVE_LOG_D("uidMap=%{public}d", key); WriteBpfMap(GET_MAP_PATH(ingress, uid), key, rule); } } } void NetsysBpfNetFirewall::WriteActionBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction) { BpfActionMap &actionMap = manager.GetActionMap(); if (actionMap.Empty()) { NETNATIVE_LOGE("WriteActionBpfMap: actionMap is empty"); } else { bool ingress = (direction == NetFirewallRuleDirection::RULE_IN); for (const auto &pair : actionMap.Get()) { ActionKey key = pair.first; Bitmap val = pair.second; RuleCode rule; memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode)); NETNATIVE_LOG_D("action_map=%{public}d", val.Get()[0]); WriteBpfMap(GET_MAP_PATH(ingress, action), key, rule); } } } int32_t NetsysBpfNetFirewall::RegisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback) { if (!callback) { return -1; } callbacks_.emplace_back(callback); return 0; } int32_t NetsysBpfNetFirewall::UnregisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback) { if (!callback) { return -1; } for (auto it = callbacks_.begin(); it != callbacks_.end(); ++it) { if (*it == callback) { callbacks_.erase(it); return 0; } } return -1; } bool NetsysBpfNetFirewall::ShouldSkipNotify(sptr<InterceptRecord> record) { if (!record) { return true; } if (oldRecord_ != nullptr && (record->time - oldRecord_->time) < INTERCEPT_BUFF_INTERVAL_SEC) { if (record->localIp == oldRecord_->localIp && record->remoteIp == oldRecord_->remoteIp && record->localPort == oldRecord_->localPort && record->remotePort == oldRecord_->remotePort && record->protocol == oldRecord_->protocol && record->appUid == oldRecord_->appUid) { return true; } } oldRecord_ = record; return false; } void NetsysBpfNetFirewall::NotifyInterceptEvent(InterceptEvent *info) { if (!info) { return; } sptr<InterceptRecord> record = new (std::nothrow) InterceptRecord(); record->time = (int32_t)time(NULL); record->localPort = BitmapManager::Nstohl(info->sport); record->remotePort = BitmapManager::Nstohl(info->dport); record->protocol = static_cast<uint16_t>(info->protocol); record->appUid = (int32_t)info->appuid; std::string srcIp; std::string dstIp; if (info->family == AF_INET) { char ip4[INET_ADDRSTRLEN] = {}; inet_ntop(AF_INET, &(info->ipv4.saddr), ip4, INET_ADDRSTRLEN); srcIp = ip4; memset_s(ip4, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(info->ipv4.daddr), ip4, INET_ADDRSTRLEN); dstIp = ip4; } else { char ip6[INET6_ADDRSTRLEN] = {}; inet_ntop(AF_INET6, &(info->ipv6.saddr), ip6, INET6_ADDRSTRLEN); srcIp = ip6; memset_s(ip6, INET6_ADDRSTRLEN, 0, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &(info->ipv6.daddr), ip6, INET6_ADDRSTRLEN); dstIp = ip6; } if (info->dir == INGRESS) { record->localIp = srcIp; record->remoteIp = dstIp; } else { record->localIp = dstIp; record->remoteIp = srcIp; } if (ShouldSkipNotify(record)) { return; } for (auto callback : callbacks_) { callback->OnIntercept(record); } } void NetsysBpfNetFirewall::HandleTupleEvent(TupleEvent *ev) { NETNATIVE_LOG_D( "%{public}s tuple: sport=%{public}u dport=%{public}u protocol=%{public}u appuid=%{public}u uid=%{public}u", (ev->dir == INGRESS) ? "> ingress" : "< egress", ntohs(ev->sport), ntohs(ev->dport), ev->protocol, ev->appuid, ev->uid); if (ev->family == AF_INET) { in_addr in; in.s_addr = ev->ipv4.saddr; NETNATIVE_LOG_D("\tsaddr=%{public}s", inet_ntoa(in)); in.s_addr = ev->ipv4.daddr; NETNATIVE_LOG_D("\tdaddr=%{public}s", inet_ntoa(in)); } else { char buf[INET6_ADDRSTRLEN] = {}; inet_ntop(AF_INET6, &(ev->ipv6.saddr), buf, INET6_ADDRSTRLEN); NETNATIVE_LOG_D("\tsaddr6=%{public}s", buf); memset_s(buf, INET6_ADDRSTRLEN, 0, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &(ev->ipv6.daddr), buf, INET6_ADDRSTRLEN); NETNATIVE_LOG_D("\tdaddr6=%{public}s", buf); } NETNATIVE_LOG_D("\trstpacket=%{public}u", ev->rst); } void NetsysBpfNetFirewall::HandleInterceptEvent(InterceptEvent *ev) { GetInstance()->NotifyInterceptEvent(ev); NETNATIVE_LOGI("%{public}s intercept: sport=%{public}u dport=%{public}u protocol=%{public}u appuid=%{public}u", (ev->dir == INGRESS) ? "ingress" : "egress", ntohs(ev->sport), ntohs(ev->dport), ev->protocol, ev->appuid); if (ev->family == AF_INET) { in_addr in; in.s_addr = ev->ipv4.saddr; NETNATIVE_LOGI("\tsaddr=%{public}s", inet_ntoa(in)); in.s_addr = ev->ipv4.daddr; NETNATIVE_LOGI("\tdaddr=%{public}s", inet_ntoa(in)); } else { char buf[INET6_ADDRSTRLEN] = {}; inet_ntop(AF_INET6, &(ev->ipv6.saddr), buf, INET6_ADDRSTRLEN); NETNATIVE_LOGI("\tsaddr6=%{public}s", buf); memset_s(buf, INET6_ADDRSTRLEN, 0, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &(ev->ipv6.daddr), buf, INET6_ADDRSTRLEN); NETNATIVE_LOGI("\tdaddr6=%{public}s", buf); } } void NetsysBpfNetFirewall::HandleDebugEvent(DebugEvent *ev) { const char *direction = ev->dir == INGRESS ? ">" : "<"; switch (ev->type) { case DBG_LOOKUP_FAIL: NETNATIVE_LOG_D("bpf map lookup: fail"); break; case DBG_MATCH_SADDR: { in_addr in; in.s_addr = ev->arg1; NETNATIVE_LOG_D("%{public}s saddr: %{public}s bitmap: %{public}x", direction, inet_ntoa(in), ev->arg2); break; } case DBG_MATCH_DADDR: { in_addr in; in.s_addr = ev->arg1; NETNATIVE_LOG_D("%{public}s daddr: %{public}s bitmap: %{public}x", direction, inet_ntoa(in), ev->arg2); break; } case DBG_MATCH_SPORT: NETNATIVE_LOG_D("%{public}s sport: %{public}u bitmap: %{public}x", direction, ntohs(ev->arg1), ev->arg2); break; case DBG_MATCH_DPORT: NETNATIVE_LOG_D("%{public}s dport: %{public}u bitmap: %{public}x", direction, ntohs(ev->arg1), ev->arg2); break; case DBG_MATCH_PROTO: NETNATIVE_LOG_D("%{public}s protocol: %{public}u bitmap: %{public}x", direction, ev->arg1, ev->arg2); break; case DBG_MATCH_APPUID: NETNATIVE_LOG_D("%{public}s appuid: %{public}u bitmap: %{public}x", direction, ev->arg1, ev->arg2); break; case DBG_MATCH_UID: NETNATIVE_LOG_D("%{public}s uid: %{public}u bitmap: %{public}x", direction, ev->arg1, ev->arg2); break; case DBG_ACTION_KEY: NETNATIVE_LOG_D("%{public}s actionkey: %{public}x", direction, ev->arg1); break; case DBG_MATCH_ACTION: NETNATIVE_LOG_D("%{public}s action: %{public}s", direction, (ev->arg1 == SK_PASS ? "PASS" : "DROP")); break; case DBG_CT_LOOKUP: NETNATIVE_LOG_D("%{public}s ct lookup status: %{public}u", direction, ev->arg1); break; default: break; } } int NetsysBpfNetFirewall::HandleEvent(void *ctx, void *data, size_t len) { if (data && len > 0) { Event *ev = (Event *)data; switch (ev->type) { case EVENT_DEBUG: { HandleDebugEvent(&(ev->debug)); break; } case EVENT_INTERCEPT: { HandleInterceptEvent(&(ev->intercept)); break; } case EVENT_TUPLE_DEBUG: { HandleTupleEvent(&(ev->tuple)); break; } default: break; } } return 0; } void OnDemandLoadManagerCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject) { NETNATIVE_LOG_D("OnLoadSystemAbilitySuccess systemAbilityId: [%{public}d]", systemAbilityId); } void OnDemandLoadManagerCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId) { NETNATIVE_LOG_D("OnLoadSystemAbilityFail: [%{public}d]", systemAbilityId); } int32_t NetsysBpfNetFirewall::LoadSystemAbility(int32_t systemAbilityId) { NETNATIVE_LOG_D("LoadSystemAbility: [%{public}d]", systemAbilityId); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (saManager == nullptr) { NETNATIVE_LOGE("GetCmProxy registry is null"); return -1; } auto object = saManager->CheckSystemAbility(systemAbilityId); if (object != nullptr) { return 0; } sptr<OnDemandLoadManagerCallback> loadCallBack = new (std::nothrow) OnDemandLoadManagerCallback(); if (loadCallBack == nullptr) { NETNATIVE_LOGE("new OnDemandLoadCertManagerCallback failed"); return -1; } int32_t ret = saManager->LoadSystemAbility(systemAbilityId, loadCallBack); if (ret != ERR_OK) { NETNATIVE_LOGE("systemAbilityId:%d load failed,result code:%d", systemAbilityId, ret); return -1; } return 0; } } // namespace NetManagerStandard } // namespace OHOS