1b1b8bc3fSopenharmony_ci/*
2b1b8bc3fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3b1b8bc3fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1b8bc3fSopenharmony_ci * you may not use this file except in compliance with the License.
5b1b8bc3fSopenharmony_ci * You may obtain a copy of the License at
6b1b8bc3fSopenharmony_ci *
7b1b8bc3fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1b8bc3fSopenharmony_ci *
9b1b8bc3fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1b8bc3fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1b8bc3fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1b8bc3fSopenharmony_ci * See the License for the specific language governing permissions and
13b1b8bc3fSopenharmony_ci * limitations under the License.
14b1b8bc3fSopenharmony_ci */
15b1b8bc3fSopenharmony_ci
16b1b8bc3fSopenharmony_ci#include <arpa/inet.h>
17b1b8bc3fSopenharmony_ci#include <cstdio>
18b1b8bc3fSopenharmony_ci#include <libbpf.h>
19b1b8bc3fSopenharmony_ci#include <linux/bpf.h>
20b1b8bc3fSopenharmony_ci#include <net/if.h>
21b1b8bc3fSopenharmony_ci#include <netinet/in.h>
22b1b8bc3fSopenharmony_ci#include <securec.h>
23b1b8bc3fSopenharmony_ci#include <sys/epoll.h>
24b1b8bc3fSopenharmony_ci#include <sys/socket.h>
25b1b8bc3fSopenharmony_ci#include <vector>
26b1b8bc3fSopenharmony_ci#include <ctime>
27b1b8bc3fSopenharmony_ci
28b1b8bc3fSopenharmony_ci#include "bpf_loader.h"
29b1b8bc3fSopenharmony_ci#include "bpf_netfirewall.h"
30b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h"
31b1b8bc3fSopenharmony_ci#include "iservice_registry.h"
32b1b8bc3fSopenharmony_ci#include "bpf_ring_buffer.h"
33b1b8bc3fSopenharmony_ci#include "ffrt_inner.h"
34b1b8bc3fSopenharmony_ci
35b1b8bc3fSopenharmony_ciusing namespace std;
36b1b8bc3fSopenharmony_ciusing namespace OHOS;
37b1b8bc3fSopenharmony_ciusing namespace OHOS::NetsysNative;
38b1b8bc3fSopenharmony_ci
39b1b8bc3fSopenharmony_cinamespace OHOS {
40b1b8bc3fSopenharmony_cinamespace NetManagerStandard {
41b1b8bc3fSopenharmony_cistd::shared_ptr<NetsysBpfNetFirewall> NetsysBpfNetFirewall::instance_ = nullptr;
42b1b8bc3fSopenharmony_cibool NetsysBpfNetFirewall::keepListen_ = false;
43b1b8bc3fSopenharmony_cibool NetsysBpfNetFirewall::keepGc_ = false;
44b1b8bc3fSopenharmony_cibool NetsysBpfNetFirewall::isBpfLoaded_ = false;
45b1b8bc3fSopenharmony_cistd::unique_ptr<BpfMapper<CtKey, CtVaule>> NetsysBpfNetFirewall::ctRdMap_ = nullptr;
46b1b8bc3fSopenharmony_cistd::unique_ptr<BpfMapper<CtKey, CtVaule>> NetsysBpfNetFirewall::ctWrMap_ = nullptr;
47b1b8bc3fSopenharmony_ci
48b1b8bc3fSopenharmony_ciNetsysBpfNetFirewall::NetsysBpfNetFirewall()
49b1b8bc3fSopenharmony_ci{
50b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("NetsysBpfNetFirewall construct");
51b1b8bc3fSopenharmony_ci    isBpfLoaded_ = false;
52b1b8bc3fSopenharmony_ci}
53b1b8bc3fSopenharmony_ci
54b1b8bc3fSopenharmony_cistd::shared_ptr<NetsysBpfNetFirewall> NetsysBpfNetFirewall::GetInstance()
55b1b8bc3fSopenharmony_ci{
56b1b8bc3fSopenharmony_ci    static std::mutex instanceMutex;
57b1b8bc3fSopenharmony_ci    std::lock_guard<std::mutex> guard(instanceMutex);
58b1b8bc3fSopenharmony_ci    if (instance_ == nullptr) {
59b1b8bc3fSopenharmony_ci        instance_.reset(new NetsysBpfNetFirewall());
60b1b8bc3fSopenharmony_ci        return instance_;
61b1b8bc3fSopenharmony_ci    }
62b1b8bc3fSopenharmony_ci    return instance_;
63b1b8bc3fSopenharmony_ci}
64b1b8bc3fSopenharmony_ci
65b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::ConntrackGcTask()
66b1b8bc3fSopenharmony_ci{
67b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("ConntrackGcTask: running");
68b1b8bc3fSopenharmony_ci    std::vector<CtKey> keys = ctRdMap_->GetAllKeys();
69b1b8bc3fSopenharmony_ci    if (keys.empty()) {
70b1b8bc3fSopenharmony_ci        NETNATIVE_LOG_D("GcConntrackCb: key is empty");
71b1b8bc3fSopenharmony_ci        return;
72b1b8bc3fSopenharmony_ci    }
73b1b8bc3fSopenharmony_ci
74b1b8bc3fSopenharmony_ci    timespec now = { 0 };
75b1b8bc3fSopenharmony_ci    // bpf_ktime_get_ns: CLOCK_MONOTONIC
76b1b8bc3fSopenharmony_ci    if (!clock_gettime(CLOCK_MONOTONIC, &now)) {
77b1b8bc3fSopenharmony_ci        return;
78b1b8bc3fSopenharmony_ci    }
79b1b8bc3fSopenharmony_ci    for (const CtKey &k : keys) {
80b1b8bc3fSopenharmony_ci        CtVaule v = {};
81b1b8bc3fSopenharmony_ci        if (ctRdMap_->Read(k, v) < 0) {
82b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("GcConntrackCb: read failed");
83b1b8bc3fSopenharmony_ci            continue;
84b1b8bc3fSopenharmony_ci        }
85b1b8bc3fSopenharmony_ci
86b1b8bc3fSopenharmony_ci        if (v.lifetime < now.tv_sec) {
87b1b8bc3fSopenharmony_ci            if (ctWrMap_->Delete(k) != 0) {
88b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("GcConntrackCb: delete failed");
89b1b8bc3fSopenharmony_ci                continue;
90b1b8bc3fSopenharmony_ci            }
91b1b8bc3fSopenharmony_ci        }
92b1b8bc3fSopenharmony_ci    }
93b1b8bc3fSopenharmony_ci}
94b1b8bc3fSopenharmony_ci
95b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::RingBufferListenThread(void)
96b1b8bc3fSopenharmony_ci{
97b1b8bc3fSopenharmony_ci    if (keepListen_) {
98b1b8bc3fSopenharmony_ci        NETNATIVE_LOG_D("under listening");
99b1b8bc3fSopenharmony_ci        return;
100b1b8bc3fSopenharmony_ci    }
101b1b8bc3fSopenharmony_ci
102b1b8bc3fSopenharmony_ci    int mapFd = NetsysBpfRingBuffer::GetRingbufFd(MAP_PATH(EVENT_MAP), 0);
103b1b8bc3fSopenharmony_ci    if (mapFd < 0) {
104b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("failed to get ring buffer fd: errno=%{public}d", errno);
105b1b8bc3fSopenharmony_ci        return;
106b1b8bc3fSopenharmony_ci    }
107b1b8bc3fSopenharmony_ci    ring_buffer *rb = ring_buffer__new(mapFd, NetsysBpfNetFirewall::HandleEvent, NULL, NULL);
108b1b8bc3fSopenharmony_ci    if (!rb) {
109b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("failed to create ring buffer: errno=%{public}d", errno);
110b1b8bc3fSopenharmony_ci        return;
111b1b8bc3fSopenharmony_ci    }
112b1b8bc3fSopenharmony_ci
113b1b8bc3fSopenharmony_ci    keepListen_ = true;
114b1b8bc3fSopenharmony_ci    while (keepListen_) {
115b1b8bc3fSopenharmony_ci        if (ffrt::this_task::get_id() != 0) {
116b1b8bc3fSopenharmony_ci            ffrt::sync_io(mapFd);
117b1b8bc3fSopenharmony_ci        }
118b1b8bc3fSopenharmony_ci        int err = ring_buffer__poll(rb, RING_BUFFER_POLL_TIME_OUT_MS);
119b1b8bc3fSopenharmony_ci        if (err < 0) {
120b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("Error polling ring buffer: errno=%{public}d", errno);
121b1b8bc3fSopenharmony_ci            keepListen_ = false;
122b1b8bc3fSopenharmony_ci            break;
123b1b8bc3fSopenharmony_ci        }
124b1b8bc3fSopenharmony_ci    }
125b1b8bc3fSopenharmony_ci
126b1b8bc3fSopenharmony_ci    NETNATIVE_LOGE("Could not get bpf event ring buffer map");
127b1b8bc3fSopenharmony_ci    ring_buffer__free(rb);
128b1b8bc3fSopenharmony_ci}
129b1b8bc3fSopenharmony_ci
130b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::StartListener()
131b1b8bc3fSopenharmony_ci{
132b1b8bc3fSopenharmony_ci    if (!isBpfLoaded_) {
133b1b8bc3fSopenharmony_ci        NETNATIVE_LOG_D("bfp is not loaded");
134b1b8bc3fSopenharmony_ci        return -1;
135b1b8bc3fSopenharmony_ci    }
136b1b8bc3fSopenharmony_ci    ctRdMap_ = std::make_unique<BpfMapper<CtKey, CtVaule>>(MAP_PATH(CT_MAP), BPF_F_RDONLY);
137b1b8bc3fSopenharmony_ci    ctWrMap_ = std::make_unique<BpfMapper<CtKey, CtVaule>>(MAP_PATH(CT_MAP), BPF_F_WRONLY);
138b1b8bc3fSopenharmony_ci
139b1b8bc3fSopenharmony_ci    ffrt::submit(RingBufferListenThread, {}, {}, ffrt::task_attr().name("RingBufferListen"));
140b1b8bc3fSopenharmony_ci    ffrt::submit(StartConntrackGcThread, { &ctRdMap_ }, { &ctWrMap_ });
141b1b8bc3fSopenharmony_ci    return 0;
142b1b8bc3fSopenharmony_ci}
143b1b8bc3fSopenharmony_ci
144b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::StopListener()
145b1b8bc3fSopenharmony_ci{
146b1b8bc3fSopenharmony_ci    keepListen_ = false;
147b1b8bc3fSopenharmony_ci    StopConntrackGc();
148b1b8bc3fSopenharmony_ci    return 0;
149b1b8bc3fSopenharmony_ci}
150b1b8bc3fSopenharmony_ci
151b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::StartConntrackGcThread(void)
152b1b8bc3fSopenharmony_ci{
153b1b8bc3fSopenharmony_ci    if (keepGc_) {
154b1b8bc3fSopenharmony_ci        NETNATIVE_LOG_D("under keepGc");
155b1b8bc3fSopenharmony_ci        return;
156b1b8bc3fSopenharmony_ci    }
157b1b8bc3fSopenharmony_ci    if (!ctRdMap_->IsValid()) {
158b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("GcConntrackCb: ctRdMap is invalid");
159b1b8bc3fSopenharmony_ci        return;
160b1b8bc3fSopenharmony_ci    }
161b1b8bc3fSopenharmony_ci
162b1b8bc3fSopenharmony_ci    if (!ctWrMap_->IsValid()) {
163b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("GcConntrackCb: ctWrMap is invalid");
164b1b8bc3fSopenharmony_ci        return;
165b1b8bc3fSopenharmony_ci    }
166b1b8bc3fSopenharmony_ci
167b1b8bc3fSopenharmony_ci    keepGc_ = true;
168b1b8bc3fSopenharmony_ci
169b1b8bc3fSopenharmony_ci    int rdMapFd = NetsysBpfRingBuffer::GetRingbufFd(MAP_PATH(CT_MAP), BPF_F_RDONLY);
170b1b8bc3fSopenharmony_ci    int wrMapFd = NetsysBpfRingBuffer::GetRingbufFd(MAP_PATH(CT_MAP), BPF_F_WRONLY);
171b1b8bc3fSopenharmony_ci    if (rdMapFd < 0 || wrMapFd < 0) {
172b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("failed to get rdMapFd or wrMapFd: errno=%{public}d", errno);
173b1b8bc3fSopenharmony_ci        return;
174b1b8bc3fSopenharmony_ci    }
175b1b8bc3fSopenharmony_ci
176b1b8bc3fSopenharmony_ci    while (keepGc_) {
177b1b8bc3fSopenharmony_ci        ffrt::this_task::sleep_for(std::chrono::milliseconds(CONNTRACK_GC_INTTERVAL_MS));
178b1b8bc3fSopenharmony_ci        if (ffrt::this_task::get_id() != 0) {
179b1b8bc3fSopenharmony_ci            ffrt::sync_io(rdMapFd);
180b1b8bc3fSopenharmony_ci            ffrt::sync_io(wrMapFd);
181b1b8bc3fSopenharmony_ci        }
182b1b8bc3fSopenharmony_ci        ConntrackGcTask();
183b1b8bc3fSopenharmony_ci    }
184b1b8bc3fSopenharmony_ci}
185b1b8bc3fSopenharmony_ci
186b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::StopConntrackGc()
187b1b8bc3fSopenharmony_ci{
188b1b8bc3fSopenharmony_ci    keepGc_ = false;
189b1b8bc3fSopenharmony_ci}
190b1b8bc3fSopenharmony_ci
191b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::SetBpfLoaded(bool load)
192b1b8bc3fSopenharmony_ci{
193b1b8bc3fSopenharmony_ci    isBpfLoaded_ = load;
194b1b8bc3fSopenharmony_ci}
195b1b8bc3fSopenharmony_ci
196b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::ClearBpfFirewallRules(NetFirewallRuleDirection direction)
197b1b8bc3fSopenharmony_ci{
198b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("ClearBpfFirewallRules: direction=%{public}d", direction);
199b1b8bc3fSopenharmony_ci    Ipv4LpmKey ip4Key = {};
200b1b8bc3fSopenharmony_ci    Ipv6LpmKey ip6Key = {};
201b1b8bc3fSopenharmony_ci    PortKey portKey = 0;
202b1b8bc3fSopenharmony_ci    ProtoKey protoKey = 0;
203b1b8bc3fSopenharmony_ci    AppUidKey appIdKey = 0;
204b1b8bc3fSopenharmony_ci    UidKey uidKey = 0;
205b1b8bc3fSopenharmony_ci    ActionKey actKey = 1;
206b1b8bc3fSopenharmony_ci    ActionValue actVal;
207b1b8bc3fSopenharmony_ci    RuleCode ruleCode;
208b1b8bc3fSopenharmony_ci    CtKey ctKey;
209b1b8bc3fSopenharmony_ci    CtVaule ctVal;
210b1b8bc3fSopenharmony_ci
211b1b8bc3fSopenharmony_ci    bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
212b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, saddr), ip4Key, ruleCode);
213b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, saddr6), ip6Key, ruleCode);
214b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, daddr), ip4Key, ruleCode);
215b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, daddr6), ip6Key, ruleCode);
216b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, sport), portKey, ruleCode);
217b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, dport), portKey, ruleCode);
218b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, proto), protoKey, ruleCode);
219b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, appuid), appIdKey, ruleCode);
220b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, uid), uidKey, ruleCode);
221b1b8bc3fSopenharmony_ci    ClearBpfMap(GET_MAP_PATH(ingress, action), actKey, actVal);
222b1b8bc3fSopenharmony_ci    ClearBpfMap(MAP_PATH(CT_MAP), ctKey, ctVal);
223b1b8bc3fSopenharmony_ci}
224b1b8bc3fSopenharmony_ci
225b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::ClearFirewallRules()
226b1b8bc3fSopenharmony_ci{
227b1b8bc3fSopenharmony_ci    firewallIpRules_.clear();
228b1b8bc3fSopenharmony_ci    ClearBpfFirewallRules(NetFirewallRuleDirection::RULE_IN);
229b1b8bc3fSopenharmony_ci    ClearBpfFirewallRules(NetFirewallRuleDirection::RULE_OUT);
230b1b8bc3fSopenharmony_ci    return NETFIREWALL_SUCCESS;
231b1b8bc3fSopenharmony_ci}
232b1b8bc3fSopenharmony_ci
233b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::SetBpfFirewallRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList,
234b1b8bc3fSopenharmony_ci    NetFirewallRuleDirection direction)
235b1b8bc3fSopenharmony_ci{
236b1b8bc3fSopenharmony_ci    BitmapManager manager;
237b1b8bc3fSopenharmony_ci    int32_t ret = manager.BuildBitmapMap(ruleList);
238b1b8bc3fSopenharmony_ci    if (ret) {
239b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("SetBpfFirewallRules: BuildBitmapMap failed: %{public}d", ret);
240b1b8bc3fSopenharmony_ci        return ret;
241b1b8bc3fSopenharmony_ci    }
242b1b8bc3fSopenharmony_ci
243b1b8bc3fSopenharmony_ci    ClearBpfFirewallRules(direction);
244b1b8bc3fSopenharmony_ci    WriteSrcIpv4BpfMap(manager, direction);
245b1b8bc3fSopenharmony_ci    WriteSrcIpv6BpfMap(manager, direction);
246b1b8bc3fSopenharmony_ci    WriteDstIpv4BpfMap(manager, direction);
247b1b8bc3fSopenharmony_ci    WriteDstIpv6BpfMap(manager, direction);
248b1b8bc3fSopenharmony_ci    WriteSrcPortBpfMap(manager, direction);
249b1b8bc3fSopenharmony_ci    WriteDstPortBpfMap(manager, direction);
250b1b8bc3fSopenharmony_ci    WriteProtoBpfMap(manager, direction);
251b1b8bc3fSopenharmony_ci    WriteAppUidBpfMap(manager, direction);
252b1b8bc3fSopenharmony_ci    WriteUidBpfMap(manager, direction);
253b1b8bc3fSopenharmony_ci    WriteActionBpfMap(manager, direction);
254b1b8bc3fSopenharmony_ci    return NETFIREWALL_SUCCESS;
255b1b8bc3fSopenharmony_ci}
256b1b8bc3fSopenharmony_ci
257b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::SetFirewallRules(const std::vector<sptr<NetFirewallBaseRule>> &ruleList, bool isFinish)
258b1b8bc3fSopenharmony_ci{
259b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("SetFirewallRules: size=%{public}zu isFinish=%{public}" PRId32, ruleList.size(), isFinish);
260b1b8bc3fSopenharmony_ci    if (!isBpfLoaded_) {
261b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("SetFirewallRules: bpf not loaded");
262b1b8bc3fSopenharmony_ci        return NETFIREWALL_ERR;
263b1b8bc3fSopenharmony_ci    }
264b1b8bc3fSopenharmony_ci    if (ruleList.empty()) {
265b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("SetFirewallRules: rules is empty");
266b1b8bc3fSopenharmony_ci        return NETFIREWALL_ERR;
267b1b8bc3fSopenharmony_ci    }
268b1b8bc3fSopenharmony_ci    for (const auto &rule : ruleList) {
269b1b8bc3fSopenharmony_ci        firewallIpRules_.emplace_back(firewall_rule_cast<NetFirewallIpRule>(rule));
270b1b8bc3fSopenharmony_ci    }
271b1b8bc3fSopenharmony_ci    int32_t ret = NETFIREWALL_SUCCESS;
272b1b8bc3fSopenharmony_ci    if (isFinish) {
273b1b8bc3fSopenharmony_ci        ret = SetFirewallIpRules(firewallIpRules_);
274b1b8bc3fSopenharmony_ci        firewallIpRules_.clear();
275b1b8bc3fSopenharmony_ci    }
276b1b8bc3fSopenharmony_ci    return ret;
277b1b8bc3fSopenharmony_ci}
278b1b8bc3fSopenharmony_ci
279b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::SetFirewallIpRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList)
280b1b8bc3fSopenharmony_ci{
281b1b8bc3fSopenharmony_ci    std::vector<sptr<NetFirewallIpRule>> inRules;
282b1b8bc3fSopenharmony_ci    std::vector<sptr<NetFirewallIpRule>> outRules;
283b1b8bc3fSopenharmony_ci
284b1b8bc3fSopenharmony_ci    for (const auto &rule : ruleList) {
285b1b8bc3fSopenharmony_ci        if (rule->ruleDirection == NetFirewallRuleDirection::RULE_IN) {
286b1b8bc3fSopenharmony_ci            if (rule->protocol == NetworkProtocol::ICMP || rule->protocol == NetworkProtocol::ICMPV6) {
287b1b8bc3fSopenharmony_ci                outRules.emplace_back(rule);
288b1b8bc3fSopenharmony_ci            } else {
289b1b8bc3fSopenharmony_ci                inRules.emplace_back(rule);
290b1b8bc3fSopenharmony_ci            }
291b1b8bc3fSopenharmony_ci        }
292b1b8bc3fSopenharmony_ci        if (rule->ruleDirection == NetFirewallRuleDirection::RULE_OUT) {
293b1b8bc3fSopenharmony_ci            outRules.emplace_back(rule);
294b1b8bc3fSopenharmony_ci        }
295b1b8bc3fSopenharmony_ci    }
296b1b8bc3fSopenharmony_ci
297b1b8bc3fSopenharmony_ci    int32_t ret = NETFIREWALL_SUCCESS;
298b1b8bc3fSopenharmony_ci    if (!inRules.empty()) {
299b1b8bc3fSopenharmony_ci        ret = SetBpfFirewallRules(inRules, NetFirewallRuleDirection::RULE_IN);
300b1b8bc3fSopenharmony_ci    }
301b1b8bc3fSopenharmony_ci    if (!outRules.empty()) {
302b1b8bc3fSopenharmony_ci        ret += SetBpfFirewallRules(outRules, NetFirewallRuleDirection::RULE_OUT);
303b1b8bc3fSopenharmony_ci    }
304b1b8bc3fSopenharmony_ci    return ret;
305b1b8bc3fSopenharmony_ci}
306b1b8bc3fSopenharmony_ci
307b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::SetFirewallDefaultAction(FirewallRuleAction inDefault, FirewallRuleAction outDefault)
308b1b8bc3fSopenharmony_ci{
309b1b8bc3fSopenharmony_ci    if (!isBpfLoaded_) {
310b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("SetFirewallDefaultAction: bpf not loaded");
311b1b8bc3fSopenharmony_ci        return NETFIREWALL_ERR;
312b1b8bc3fSopenharmony_ci    }
313b1b8bc3fSopenharmony_ci    DefaultActionKey key = DEFAULT_ACT_IN_KEY;
314b1b8bc3fSopenharmony_ci    enum sk_action val = (inDefault == FirewallRuleAction::RULE_ALLOW) ? SK_PASS : SK_DROP;
315b1b8bc3fSopenharmony_ci    WriteBpfMap(MAP_PATH(DEFAULT_ACTION_MAP), key, val);
316b1b8bc3fSopenharmony_ci
317b1b8bc3fSopenharmony_ci    key = DEFAULT_ACT_OUT_KEY;
318b1b8bc3fSopenharmony_ci    val = (outDefault == FirewallRuleAction::RULE_ALLOW) ? SK_PASS : SK_DROP;
319b1b8bc3fSopenharmony_ci    WriteBpfMap(MAP_PATH(DEFAULT_ACTION_MAP), key, val);
320b1b8bc3fSopenharmony_ci    CtKey ctKey;
321b1b8bc3fSopenharmony_ci    CtVaule ctVal;
322b1b8bc3fSopenharmony_ci    ClearBpfMap(MAP_PATH(CT_MAP), ctKey, ctVal);
323b1b8bc3fSopenharmony_ci    return NETFIREWALL_SUCCESS;
324b1b8bc3fSopenharmony_ci}
325b1b8bc3fSopenharmony_ci
326b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::SetFirewallCurrentUserId(int32_t userId)
327b1b8bc3fSopenharmony_ci{
328b1b8bc3fSopenharmony_ci    if (!isBpfLoaded_) {
329b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("SetFirewallCurrentUserId: bpf not loaded");
330b1b8bc3fSopenharmony_ci        return NETFIREWALL_ERR;
331b1b8bc3fSopenharmony_ci    }
332b1b8bc3fSopenharmony_ci
333b1b8bc3fSopenharmony_ci    CurrentUserIdKey key = CURRENT_USER_ID_KEY;
334b1b8bc3fSopenharmony_ci    UidKey val = (UidKey)userId;
335b1b8bc3fSopenharmony_ci    WriteBpfMap(MAP_PATH(CURRENT_UID_MAP), key, val);
336b1b8bc3fSopenharmony_ci    return NETFIREWALL_SUCCESS;
337b1b8bc3fSopenharmony_ci}
338b1b8bc3fSopenharmony_ci
339b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteSrcIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
340b1b8bc3fSopenharmony_ci{
341b1b8bc3fSopenharmony_ci    std::vector<Ip4RuleBitmap> &srcIp4Map = manager.GetSrcIp4Map();
342b1b8bc3fSopenharmony_ci    if (srcIp4Map.empty()) {
343b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteSrcIpv4BpfMap: srcIp4Map is empty");
344b1b8bc3fSopenharmony_ci        return;
345b1b8bc3fSopenharmony_ci    }
346b1b8bc3fSopenharmony_ci    bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
347b1b8bc3fSopenharmony_ci    for (const auto &node : srcIp4Map) {
348b1b8bc3fSopenharmony_ci        Bitmap val = node.bitmap;
349b1b8bc3fSopenharmony_ci        RuleCode rule;
350b1b8bc3fSopenharmony_ci        memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
351b1b8bc3fSopenharmony_ci
352b1b8bc3fSopenharmony_ci        Ipv4LpmKey key = { 0 };
353b1b8bc3fSopenharmony_ci        key.prefixlen = node.mask;
354b1b8bc3fSopenharmony_ci        key.data = static_cast<Ip4Key>(node.data);
355b1b8bc3fSopenharmony_ci        WriteBpfMap(GET_MAP_PATH(ingress, saddr), key, rule);
356b1b8bc3fSopenharmony_ci    }
357b1b8bc3fSopenharmony_ci}
358b1b8bc3fSopenharmony_ci
359b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteSrcIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
360b1b8bc3fSopenharmony_ci{
361b1b8bc3fSopenharmony_ci    std::vector<Ip6RuleBitmap> &srcIp6Map = manager.GetSrcIp6Map();
362b1b8bc3fSopenharmony_ci    if (srcIp6Map.empty()) {
363b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteSrcIpv6BpfMap: srcIp6Map is empty");
364b1b8bc3fSopenharmony_ci        return;
365b1b8bc3fSopenharmony_ci    }
366b1b8bc3fSopenharmony_ci    bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
367b1b8bc3fSopenharmony_ci    for (const auto &node : srcIp6Map) {
368b1b8bc3fSopenharmony_ci        Bitmap val = node.bitmap;
369b1b8bc3fSopenharmony_ci        RuleCode rule;
370b1b8bc3fSopenharmony_ci        memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
371b1b8bc3fSopenharmony_ci
372b1b8bc3fSopenharmony_ci        Ipv6LpmKey key = { 0 };
373b1b8bc3fSopenharmony_ci        key.prefixlen = node.prefixlen;
374b1b8bc3fSopenharmony_ci        key.data = static_cast<Ip6Key>(node.data);
375b1b8bc3fSopenharmony_ci        WriteBpfMap(GET_MAP_PATH(ingress, saddr6), key, rule);
376b1b8bc3fSopenharmony_ci    }
377b1b8bc3fSopenharmony_ci}
378b1b8bc3fSopenharmony_ci
379b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteDstIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
380b1b8bc3fSopenharmony_ci{
381b1b8bc3fSopenharmony_ci    std::vector<Ip4RuleBitmap> &dstIp4Map = manager.GetDstIp4Map();
382b1b8bc3fSopenharmony_ci    if (dstIp4Map.empty()) {
383b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteDstIp4BpfMap: dstIp4Map is empty");
384b1b8bc3fSopenharmony_ci    } else {
385b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
386b1b8bc3fSopenharmony_ci        for (const auto &node : dstIp4Map) {
387b1b8bc3fSopenharmony_ci            Bitmap val = node.bitmap;
388b1b8bc3fSopenharmony_ci            RuleCode rule;
389b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
390b1b8bc3fSopenharmony_ci
391b1b8bc3fSopenharmony_ci            Ipv4LpmKey key = { 0 };
392b1b8bc3fSopenharmony_ci            key.prefixlen = node.mask;
393b1b8bc3fSopenharmony_ci            key.data = static_cast<Ip4Key>(node.data);
394b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, daddr), key, rule);
395b1b8bc3fSopenharmony_ci        }
396b1b8bc3fSopenharmony_ci    }
397b1b8bc3fSopenharmony_ci}
398b1b8bc3fSopenharmony_ci
399b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteDstIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
400b1b8bc3fSopenharmony_ci{
401b1b8bc3fSopenharmony_ci    std::vector<Ip6RuleBitmap> &dstIp6Map = manager.GetDstIp6Map();
402b1b8bc3fSopenharmony_ci    if (dstIp6Map.empty()) {
403b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteDstIp6BpfMap: dstIp6Map is empty");
404b1b8bc3fSopenharmony_ci    } else {
405b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
406b1b8bc3fSopenharmony_ci        for (const auto &node : dstIp6Map) {
407b1b8bc3fSopenharmony_ci            Bitmap val = node.bitmap;
408b1b8bc3fSopenharmony_ci            RuleCode rule;
409b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
410b1b8bc3fSopenharmony_ci
411b1b8bc3fSopenharmony_ci            Ipv6LpmKey key = { 0 };
412b1b8bc3fSopenharmony_ci            key.prefixlen = node.prefixlen;
413b1b8bc3fSopenharmony_ci            key.data = static_cast<Ip6Key>(node.data);
414b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, daddr6), key, rule);
415b1b8bc3fSopenharmony_ci        }
416b1b8bc3fSopenharmony_ci    }
417b1b8bc3fSopenharmony_ci}
418b1b8bc3fSopenharmony_ci
419b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteSrcPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
420b1b8bc3fSopenharmony_ci{
421b1b8bc3fSopenharmony_ci    BpfPortMap &srcPortMap = manager.GetSrcPortMap();
422b1b8bc3fSopenharmony_ci    if (srcPortMap.Empty()) {
423b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteSrcPortBpfMap: srcPortMap is empty");
424b1b8bc3fSopenharmony_ci    } else {
425b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
426b1b8bc3fSopenharmony_ci        for (const auto &pair : srcPortMap.Get()) {
427b1b8bc3fSopenharmony_ci            PortKey key = pair.first;
428b1b8bc3fSopenharmony_ci            Bitmap val = pair.second;
429b1b8bc3fSopenharmony_ci            RuleCode rule;
430b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
431b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("sport_map=%{public}u", key);
432b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, sport), key, rule);
433b1b8bc3fSopenharmony_ci        }
434b1b8bc3fSopenharmony_ci    }
435b1b8bc3fSopenharmony_ci}
436b1b8bc3fSopenharmony_ci
437b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteDstPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
438b1b8bc3fSopenharmony_ci{
439b1b8bc3fSopenharmony_ci    BpfPortMap &dstPortMap = manager.GetDstPortMap();
440b1b8bc3fSopenharmony_ci    if (dstPortMap.Empty()) {
441b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteDstPortBpfMap: dstPortMap is empty");
442b1b8bc3fSopenharmony_ci    } else {
443b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
444b1b8bc3fSopenharmony_ci        for (const auto &pair : dstPortMap.Get()) {
445b1b8bc3fSopenharmony_ci            PortKey key = pair.first;
446b1b8bc3fSopenharmony_ci            Bitmap val = pair.second;
447b1b8bc3fSopenharmony_ci            RuleCode rule;
448b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
449b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("dport_map=%{public}u", key);
450b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, dport), key, rule);
451b1b8bc3fSopenharmony_ci        }
452b1b8bc3fSopenharmony_ci    }
453b1b8bc3fSopenharmony_ci}
454b1b8bc3fSopenharmony_ci
455b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteProtoBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
456b1b8bc3fSopenharmony_ci{
457b1b8bc3fSopenharmony_ci    BpfProtoMap &protoMap = manager.GetProtoMap();
458b1b8bc3fSopenharmony_ci    if (protoMap.Empty()) {
459b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteProtoBpfMap: protoMap is empty");
460b1b8bc3fSopenharmony_ci    } else {
461b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
462b1b8bc3fSopenharmony_ci        for (const auto &pair : protoMap.Get()) {
463b1b8bc3fSopenharmony_ci            ProtoKey key = pair.first;
464b1b8bc3fSopenharmony_ci            Bitmap val = pair.second;
465b1b8bc3fSopenharmony_ci            RuleCode rule;
466b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
467b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("proto_map=%{public}u", key);
468b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, proto), key, rule);
469b1b8bc3fSopenharmony_ci        }
470b1b8bc3fSopenharmony_ci    }
471b1b8bc3fSopenharmony_ci}
472b1b8bc3fSopenharmony_ci
473b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteAppUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
474b1b8bc3fSopenharmony_ci{
475b1b8bc3fSopenharmony_ci    BpfAppUidMap &appIdMap = manager.GetAppIdMap();
476b1b8bc3fSopenharmony_ci    if (appIdMap.Empty()) {
477b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteAppUidBpfMap: appIdMap is empty");
478b1b8bc3fSopenharmony_ci    } else {
479b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
480b1b8bc3fSopenharmony_ci        for (const auto &pair : appIdMap.Get()) {
481b1b8bc3fSopenharmony_ci            AppUidKey key = pair.first;
482b1b8bc3fSopenharmony_ci            Bitmap val = pair.second;
483b1b8bc3fSopenharmony_ci            RuleCode rule;
484b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
485b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("appuid_map=%{public}u", key);
486b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, appuid), key, rule);
487b1b8bc3fSopenharmony_ci        }
488b1b8bc3fSopenharmony_ci    }
489b1b8bc3fSopenharmony_ci}
490b1b8bc3fSopenharmony_ci
491b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
492b1b8bc3fSopenharmony_ci{
493b1b8bc3fSopenharmony_ci    BpfUidMap &uidMap = manager.GetUidMap();
494b1b8bc3fSopenharmony_ci    if (uidMap.Empty()) {
495b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteUidBpfMap: uidMap is empty");
496b1b8bc3fSopenharmony_ci    } else {
497b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
498b1b8bc3fSopenharmony_ci        for (const auto &pair : uidMap.Get()) {
499b1b8bc3fSopenharmony_ci            UidKey key = pair.first;
500b1b8bc3fSopenharmony_ci            Bitmap val = pair.second;
501b1b8bc3fSopenharmony_ci            RuleCode rule;
502b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
503b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("uidMap=%{public}u", key);
504b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, uid), key, rule);
505b1b8bc3fSopenharmony_ci        }
506b1b8bc3fSopenharmony_ci    }
507b1b8bc3fSopenharmony_ci}
508b1b8bc3fSopenharmony_ci
509b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::WriteActionBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction)
510b1b8bc3fSopenharmony_ci{
511b1b8bc3fSopenharmony_ci    BpfActionMap &actionMap = manager.GetActionMap();
512b1b8bc3fSopenharmony_ci    if (actionMap.Empty()) {
513b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("WriteActionBpfMap: actionMap is empty");
514b1b8bc3fSopenharmony_ci    } else {
515b1b8bc3fSopenharmony_ci        bool ingress = (direction == NetFirewallRuleDirection::RULE_IN);
516b1b8bc3fSopenharmony_ci        for (const auto &pair : actionMap.Get()) {
517b1b8bc3fSopenharmony_ci            ActionKey key = pair.first;
518b1b8bc3fSopenharmony_ci            Bitmap val = pair.second;
519b1b8bc3fSopenharmony_ci            RuleCode rule;
520b1b8bc3fSopenharmony_ci            memcpy_s(rule.val, sizeof(RuleCode), val.Get(), sizeof(RuleCode));
521b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("action_map=%{public}u", val.Get()[0]);
522b1b8bc3fSopenharmony_ci            WriteBpfMap(GET_MAP_PATH(ingress, action), key, rule);
523b1b8bc3fSopenharmony_ci        }
524b1b8bc3fSopenharmony_ci    }
525b1b8bc3fSopenharmony_ci}
526b1b8bc3fSopenharmony_ci
527b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::RegisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback)
528b1b8bc3fSopenharmony_ci{
529b1b8bc3fSopenharmony_ci    if (!callback) {
530b1b8bc3fSopenharmony_ci        return -1;
531b1b8bc3fSopenharmony_ci    }
532b1b8bc3fSopenharmony_ci
533b1b8bc3fSopenharmony_ci    callbacks_.emplace_back(callback);
534b1b8bc3fSopenharmony_ci
535b1b8bc3fSopenharmony_ci    return 0;
536b1b8bc3fSopenharmony_ci}
537b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::UnregisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback)
538b1b8bc3fSopenharmony_ci{
539b1b8bc3fSopenharmony_ci    if (!callback) {
540b1b8bc3fSopenharmony_ci        return -1;
541b1b8bc3fSopenharmony_ci    }
542b1b8bc3fSopenharmony_ci
543b1b8bc3fSopenharmony_ci    for (auto it = callbacks_.begin(); it != callbacks_.end(); ++it) {
544b1b8bc3fSopenharmony_ci        if (*it == callback) {
545b1b8bc3fSopenharmony_ci            callbacks_.erase(it);
546b1b8bc3fSopenharmony_ci            return 0;
547b1b8bc3fSopenharmony_ci        }
548b1b8bc3fSopenharmony_ci    }
549b1b8bc3fSopenharmony_ci    return -1;
550b1b8bc3fSopenharmony_ci}
551b1b8bc3fSopenharmony_ci
552b1b8bc3fSopenharmony_cibool NetsysBpfNetFirewall::ShouldSkipNotify(sptr<InterceptRecord> record)
553b1b8bc3fSopenharmony_ci{
554b1b8bc3fSopenharmony_ci    if (!record) {
555b1b8bc3fSopenharmony_ci        return true;
556b1b8bc3fSopenharmony_ci    }
557b1b8bc3fSopenharmony_ci    if (oldRecord_ != nullptr && (record->time - oldRecord_->time) < INTERCEPT_BUFF_INTERVAL_SEC) {
558b1b8bc3fSopenharmony_ci        if (record->localIp == oldRecord_->localIp && record->remoteIp == oldRecord_->remoteIp &&
559b1b8bc3fSopenharmony_ci            record->localPort == oldRecord_->localPort && record->remotePort == oldRecord_->remotePort &&
560b1b8bc3fSopenharmony_ci            record->protocol == oldRecord_->protocol && record->appUid == oldRecord_->appUid) {
561b1b8bc3fSopenharmony_ci            return true;
562b1b8bc3fSopenharmony_ci        }
563b1b8bc3fSopenharmony_ci    }
564b1b8bc3fSopenharmony_ci    oldRecord_ = record;
565b1b8bc3fSopenharmony_ci    return false;
566b1b8bc3fSopenharmony_ci}
567b1b8bc3fSopenharmony_ci
568b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::NotifyInterceptEvent(InterceptEvent *info)
569b1b8bc3fSopenharmony_ci{
570b1b8bc3fSopenharmony_ci    if (!info) {
571b1b8bc3fSopenharmony_ci        return;
572b1b8bc3fSopenharmony_ci    }
573b1b8bc3fSopenharmony_ci    sptr<InterceptRecord> record = new (std::nothrow) InterceptRecord();
574b1b8bc3fSopenharmony_ci    record->time = (int32_t)time(NULL);
575b1b8bc3fSopenharmony_ci    record->localPort = BitmapManager::Nstohl(info->sport);
576b1b8bc3fSopenharmony_ci    record->remotePort = BitmapManager::Nstohl(info->dport);
577b1b8bc3fSopenharmony_ci    record->protocol = static_cast<uint16_t>(info->protocol);
578b1b8bc3fSopenharmony_ci    record->appUid = (int32_t)info->appuid;
579b1b8bc3fSopenharmony_ci    std::string srcIp;
580b1b8bc3fSopenharmony_ci    std::string dstIp;
581b1b8bc3fSopenharmony_ci    if (info->family == AF_INET) {
582b1b8bc3fSopenharmony_ci        char ip4[INET_ADDRSTRLEN] = {};
583b1b8bc3fSopenharmony_ci        inet_ntop(AF_INET, &(info->ipv4.saddr), ip4, INET_ADDRSTRLEN);
584b1b8bc3fSopenharmony_ci        srcIp = ip4;
585b1b8bc3fSopenharmony_ci        memset_s(ip4, INET_ADDRSTRLEN, 0, INET_ADDRSTRLEN);
586b1b8bc3fSopenharmony_ci        inet_ntop(AF_INET, &(info->ipv4.daddr), ip4, INET_ADDRSTRLEN);
587b1b8bc3fSopenharmony_ci        dstIp = ip4;
588b1b8bc3fSopenharmony_ci    } else {
589b1b8bc3fSopenharmony_ci        char ip6[INET6_ADDRSTRLEN] = {};
590b1b8bc3fSopenharmony_ci        inet_ntop(AF_INET6, &(info->ipv6.saddr), ip6, INET6_ADDRSTRLEN);
591b1b8bc3fSopenharmony_ci        srcIp = ip6;
592b1b8bc3fSopenharmony_ci        memset_s(ip6, INET6_ADDRSTRLEN, 0, INET6_ADDRSTRLEN);
593b1b8bc3fSopenharmony_ci        inet_ntop(AF_INET6, &(info->ipv6.daddr), ip6, INET6_ADDRSTRLEN);
594b1b8bc3fSopenharmony_ci        dstIp = ip6;
595b1b8bc3fSopenharmony_ci    }
596b1b8bc3fSopenharmony_ci    if (info->dir == INGRESS) {
597b1b8bc3fSopenharmony_ci        record->localIp = srcIp;
598b1b8bc3fSopenharmony_ci        record->remoteIp = dstIp;
599b1b8bc3fSopenharmony_ci    } else {
600b1b8bc3fSopenharmony_ci        record->localIp = dstIp;
601b1b8bc3fSopenharmony_ci        record->remoteIp = srcIp;
602b1b8bc3fSopenharmony_ci    }
603b1b8bc3fSopenharmony_ci    if (ShouldSkipNotify(record)) {
604b1b8bc3fSopenharmony_ci        return;
605b1b8bc3fSopenharmony_ci    }
606b1b8bc3fSopenharmony_ci    for (auto callback : callbacks_) {
607b1b8bc3fSopenharmony_ci        callback->OnIntercept(record);
608b1b8bc3fSopenharmony_ci    }
609b1b8bc3fSopenharmony_ci}
610b1b8bc3fSopenharmony_ci
611b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::HandleTupleEvent(TupleEvent *ev)
612b1b8bc3fSopenharmony_ci{
613b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D(
614b1b8bc3fSopenharmony_ci        "%{public}s tuple: sport=%{public}u dport=%{public}u protocol=%{public}u appuid=%{public}u uid=%{public}u",
615b1b8bc3fSopenharmony_ci        (ev->dir == INGRESS) ? "> ingress" : "< egress", ntohs(ev->sport), ntohs(ev->dport), ev->protocol, ev->appuid,
616b1b8bc3fSopenharmony_ci        ev->uid);
617b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("\trstpacket=%{public}u", ev->rst);
618b1b8bc3fSopenharmony_ci}
619b1b8bc3fSopenharmony_ci
620b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::HandleInterceptEvent(InterceptEvent *ev)
621b1b8bc3fSopenharmony_ci{
622b1b8bc3fSopenharmony_ci    GetInstance()->NotifyInterceptEvent(ev);
623b1b8bc3fSopenharmony_ci
624b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("%{public}s intercept: sport=%{public}u dport=%{public}u protocol=%{public}u appuid=%{public}u",
625b1b8bc3fSopenharmony_ci        (ev->dir == INGRESS) ? "ingress" : "egress", ntohs(ev->sport), ntohs(ev->dport), ev->protocol, ev->appuid);
626b1b8bc3fSopenharmony_ci}
627b1b8bc3fSopenharmony_ci
628b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::HandleDebugEvent(DebugEvent *ev)
629b1b8bc3fSopenharmony_ci{
630b1b8bc3fSopenharmony_ci    const char *direction = ev->dir == INGRESS ? ">" : "<";
631b1b8bc3fSopenharmony_ci    switch (ev->type) {
632b1b8bc3fSopenharmony_ci        case DBG_MATCH_SPORT:
633b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s sport: %{public}u bitmap: %{public}x", direction, ntohs(ev->arg1), ev->arg2);
634b1b8bc3fSopenharmony_ci            break;
635b1b8bc3fSopenharmony_ci        case DBG_MATCH_DPORT:
636b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s dport: %{public}u bitmap: %{public}x", direction, ntohs(ev->arg1), ev->arg2);
637b1b8bc3fSopenharmony_ci            break;
638b1b8bc3fSopenharmony_ci        case DBG_MATCH_PROTO:
639b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s protocol: %{public}u bitmap: %{public}x", direction, ev->arg1, ev->arg2);
640b1b8bc3fSopenharmony_ci            break;
641b1b8bc3fSopenharmony_ci        case DBG_MATCH_APPUID:
642b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s appuid: %{public}u bitmap: %{public}x", direction, ev->arg1, ev->arg2);
643b1b8bc3fSopenharmony_ci            break;
644b1b8bc3fSopenharmony_ci        case DBG_MATCH_UID:
645b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s uid: %{public}u bitmap: %{public}x", direction, ev->arg1, ev->arg2);
646b1b8bc3fSopenharmony_ci            break;
647b1b8bc3fSopenharmony_ci        case DBG_ACTION_KEY:
648b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s actionkey: %{public}x", direction, ev->arg1);
649b1b8bc3fSopenharmony_ci            break;
650b1b8bc3fSopenharmony_ci        case DBG_MATCH_ACTION:
651b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s    action: %{public}s", direction, (ev->arg1 == SK_PASS ? "PASS" : "DROP"));
652b1b8bc3fSopenharmony_ci            break;
653b1b8bc3fSopenharmony_ci        case DBG_CT_LOOKUP:
654b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("%{public}s ct lookup status: %{public}u", direction, ev->arg1);
655b1b8bc3fSopenharmony_ci            break;
656b1b8bc3fSopenharmony_ci        case DBG_MATCH_DOMAIN:
657b1b8bc3fSopenharmony_ci            NETNATIVE_LOG_D("egress match domain, action PASS");
658b1b8bc3fSopenharmony_ci            break;
659b1b8bc3fSopenharmony_ci        default:
660b1b8bc3fSopenharmony_ci            break;
661b1b8bc3fSopenharmony_ci    }
662b1b8bc3fSopenharmony_ci}
663b1b8bc3fSopenharmony_ci
664b1b8bc3fSopenharmony_ciint NetsysBpfNetFirewall::HandleEvent(void *ctx, void *data, size_t len)
665b1b8bc3fSopenharmony_ci{
666b1b8bc3fSopenharmony_ci    if (data && len > 0) {
667b1b8bc3fSopenharmony_ci        Event *ev = (Event *)data;
668b1b8bc3fSopenharmony_ci
669b1b8bc3fSopenharmony_ci        switch (ev->type) {
670b1b8bc3fSopenharmony_ci            case EVENT_DEBUG: {
671b1b8bc3fSopenharmony_ci                HandleDebugEvent(&(ev->debug));
672b1b8bc3fSopenharmony_ci                break;
673b1b8bc3fSopenharmony_ci            }
674b1b8bc3fSopenharmony_ci            case EVENT_INTERCEPT: {
675b1b8bc3fSopenharmony_ci                HandleInterceptEvent(&(ev->intercept));
676b1b8bc3fSopenharmony_ci                break;
677b1b8bc3fSopenharmony_ci            }
678b1b8bc3fSopenharmony_ci            case EVENT_TUPLE_DEBUG: {
679b1b8bc3fSopenharmony_ci                HandleTupleEvent(&(ev->tuple));
680b1b8bc3fSopenharmony_ci                break;
681b1b8bc3fSopenharmony_ci            }
682b1b8bc3fSopenharmony_ci            default:
683b1b8bc3fSopenharmony_ci                break;
684b1b8bc3fSopenharmony_ci        }
685b1b8bc3fSopenharmony_ci    }
686b1b8bc3fSopenharmony_ci    return 0;
687b1b8bc3fSopenharmony_ci}
688b1b8bc3fSopenharmony_ci
689b1b8bc3fSopenharmony_civoid OnDemandLoadManagerCallback::OnLoadSystemAbilitySuccess(int32_t systemAbilityId,
690b1b8bc3fSopenharmony_ci    const sptr<IRemoteObject> &remoteObject)
691b1b8bc3fSopenharmony_ci{
692b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("OnLoadSystemAbilitySuccess systemAbilityId: [%{public}d]", systemAbilityId);
693b1b8bc3fSopenharmony_ci}
694b1b8bc3fSopenharmony_ci
695b1b8bc3fSopenharmony_civoid OnDemandLoadManagerCallback::OnLoadSystemAbilityFail(int32_t systemAbilityId)
696b1b8bc3fSopenharmony_ci{
697b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("OnLoadSystemAbilityFail: [%{public}d]", systemAbilityId);
698b1b8bc3fSopenharmony_ci}
699b1b8bc3fSopenharmony_ci
700b1b8bc3fSopenharmony_ciint32_t NetsysBpfNetFirewall::LoadSystemAbility(int32_t systemAbilityId)
701b1b8bc3fSopenharmony_ci{
702b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("LoadSystemAbility: [%{public}d]", systemAbilityId);
703b1b8bc3fSopenharmony_ci    auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
704b1b8bc3fSopenharmony_ci    if (saManager == nullptr) {
705b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("GetCmProxy registry is null");
706b1b8bc3fSopenharmony_ci        return -1;
707b1b8bc3fSopenharmony_ci    }
708b1b8bc3fSopenharmony_ci
709b1b8bc3fSopenharmony_ci    auto object = saManager->CheckSystemAbility(systemAbilityId);
710b1b8bc3fSopenharmony_ci    if (object != nullptr) {
711b1b8bc3fSopenharmony_ci        return 0;
712b1b8bc3fSopenharmony_ci    }
713b1b8bc3fSopenharmony_ci
714b1b8bc3fSopenharmony_ci    sptr<OnDemandLoadManagerCallback> loadCallBack = new (std::nothrow) OnDemandLoadManagerCallback();
715b1b8bc3fSopenharmony_ci    if (loadCallBack == nullptr) {
716b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("new OnDemandLoadCertManagerCallback failed");
717b1b8bc3fSopenharmony_ci        return -1;
718b1b8bc3fSopenharmony_ci    }
719b1b8bc3fSopenharmony_ci
720b1b8bc3fSopenharmony_ci    int32_t ret = saManager->LoadSystemAbility(systemAbilityId, loadCallBack);
721b1b8bc3fSopenharmony_ci    if (ret != ERR_OK) {
722b1b8bc3fSopenharmony_ci        NETNATIVE_LOGE("systemAbilityId:%d load failed,result code:%d", systemAbilityId, ret);
723b1b8bc3fSopenharmony_ci        return -1;
724b1b8bc3fSopenharmony_ci    }
725b1b8bc3fSopenharmony_ci    return 0;
726b1b8bc3fSopenharmony_ci}
727b1b8bc3fSopenharmony_ci
728b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::AddDomainCache(const NetAddrInfo &addrInfo)
729b1b8bc3fSopenharmony_ci{
730b1b8bc3fSopenharmony_ci    NETNATIVE_LOGI("AddDomainCache");
731b1b8bc3fSopenharmony_ci    domain_value value = 1;
732b1b8bc3fSopenharmony_ci    if (addrInfo.aiFamily == AF_INET) {
733b1b8bc3fSopenharmony_ci        Ipv4LpmKey key = { 0 };
734b1b8bc3fSopenharmony_ci        key.prefixlen = IPV4_MAX_PREFIXLEN;
735b1b8bc3fSopenharmony_ci        key.data = addrInfo.aiAddr.sin.s_addr;
736b1b8bc3fSopenharmony_ci        WriteBpfMap(MAP_PATH(DOMAIN_IPV4_MAP), key, value);
737b1b8bc3fSopenharmony_ci    } else {
738b1b8bc3fSopenharmony_ci        Ipv6LpmKey key = { 0 };
739b1b8bc3fSopenharmony_ci        key.prefixlen = IPV6_MAX_PREFIXLEN;
740b1b8bc3fSopenharmony_ci        key.data = addrInfo.aiAddr.sin6;
741b1b8bc3fSopenharmony_ci        WriteBpfMap(MAP_PATH(DOMAIN_IPV6_MAP), key, value);
742b1b8bc3fSopenharmony_ci    }
743b1b8bc3fSopenharmony_ci}
744b1b8bc3fSopenharmony_ci
745b1b8bc3fSopenharmony_civoid NetsysBpfNetFirewall::ClearDomainCache()
746b1b8bc3fSopenharmony_ci{
747b1b8bc3fSopenharmony_ci    NETNATIVE_LOG_D("ClearDomainCache");
748b1b8bc3fSopenharmony_ci    Ipv4LpmKey ip4Key = {};
749b1b8bc3fSopenharmony_ci    Ipv6LpmKey ip6Key = {};
750b1b8bc3fSopenharmony_ci    domain_value value;
751b1b8bc3fSopenharmony_ci    ClearBpfMap(MAP_PATH(DOMAIN_IPV4_MAP), ip4Key, value);
752b1b8bc3fSopenharmony_ci    ClearBpfMap(MAP_PATH(DOMAIN_IPV6_MAP), ip6Key, value);
753b1b8bc3fSopenharmony_ci}
754b1b8bc3fSopenharmony_ci} // namespace NetManagerStandard
755b1b8bc3fSopenharmony_ci} // namespace OHOS