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#ifndef NETMANAGER_EXT_BPF_NET_FIREWALL_H
17b1b8bc3fSopenharmony_ci#define NETMANAGER_EXT_BPF_NET_FIREWALL_H
18b1b8bc3fSopenharmony_ci
19b1b8bc3fSopenharmony_ci#include <netdb.h>
20b1b8bc3fSopenharmony_ci#include <string>
21b1b8bc3fSopenharmony_ci#include <thread>
22b1b8bc3fSopenharmony_ci#include <unordered_map>
23b1b8bc3fSopenharmony_ci#include <chrono>
24b1b8bc3fSopenharmony_ci#include <functional>
25b1b8bc3fSopenharmony_ci
26b1b8bc3fSopenharmony_ci#include "bitmap_manager.h"
27b1b8bc3fSopenharmony_ci#include "bpf_mapper.h"
28b1b8bc3fSopenharmony_ci#include "i_netfirewall_callback.h"
29b1b8bc3fSopenharmony_ci#include "netfirewall/netfirewall_def.h"
30b1b8bc3fSopenharmony_ci#include "netfirewall_parcel.h"
31b1b8bc3fSopenharmony_ci#include "system_ability.h"
32b1b8bc3fSopenharmony_ci#include "system_ability_load_callback_stub.h"
33b1b8bc3fSopenharmony_ci
34b1b8bc3fSopenharmony_cinamespace OHOS::NetManagerStandard {
35b1b8bc3fSopenharmony_ci// Only used for unittest code currently
36b1b8bc3fSopenharmony_cistatic constexpr const char *FIREWALL_BPF_PATH = "/system/etc/bpf/netsys.o";
37b1b8bc3fSopenharmony_ci
38b1b8bc3fSopenharmony_cistatic constexpr const int CONNTRACK_GC_INTTERVAL_MS = 60000;
39b1b8bc3fSopenharmony_cistatic constexpr const int RING_BUFFER_POLL_TIME_OUT_MS = -1;
40b1b8bc3fSopenharmony_ci
41b1b8bc3fSopenharmony_ci// convert ebpf types from unix style style to CPP's
42b1b8bc3fSopenharmony_ciusing Ip4Key = ip4_key;
43b1b8bc3fSopenharmony_ciusing Ip6Key = ip6_key;
44b1b8bc3fSopenharmony_ciusing Ipv4LpmKey = struct ipv4_lpm_key;
45b1b8bc3fSopenharmony_ciusing Ipv6LpmKey = struct ipv6_lpm_key;
46b1b8bc3fSopenharmony_ciusing PortKey = port_key;
47b1b8bc3fSopenharmony_ciusing ProtoKey = proto_key;
48b1b8bc3fSopenharmony_ciusing AppUidKey = appuid_key;
49b1b8bc3fSopenharmony_ciusing DefaultActionKey = default_action_key;
50b1b8bc3fSopenharmony_ciusing CurrentUserIdKey = current_user_id_key;
51b1b8bc3fSopenharmony_ciusing ActionKey = action_key;
52b1b8bc3fSopenharmony_ciusing ActionValue = action_val;
53b1b8bc3fSopenharmony_ciusing RuleCode = struct bitmap;
54b1b8bc3fSopenharmony_ciusing StreamDir = enum stream_dir;
55b1b8bc3fSopenharmony_ciusing EventType = enum event_type;
56b1b8bc3fSopenharmony_ciusing Event = struct event;
57b1b8bc3fSopenharmony_ciusing InterceptEvent = struct intercept_event;
58b1b8bc3fSopenharmony_ciusing DebugEvent = struct debug_event;
59b1b8bc3fSopenharmony_ciusing TupleEvent = struct match_tuple;
60b1b8bc3fSopenharmony_ciusing DebugType = enum debug_type;
61b1b8bc3fSopenharmony_ci
62b1b8bc3fSopenharmony_ciusing CtKey = struct ct_tuple;
63b1b8bc3fSopenharmony_ciusing CtVaule = struct ct_entry;
64b1b8bc3fSopenharmony_ci
65b1b8bc3fSopenharmony_cistruct NetAddrInfo {
66b1b8bc3fSopenharmony_ci    uint32_t aiFamily;
67b1b8bc3fSopenharmony_ci    union {
68b1b8bc3fSopenharmony_ci        struct in_addr sin;
69b1b8bc3fSopenharmony_ci        struct in6_addr sin6;
70b1b8bc3fSopenharmony_ci    } aiAddr;
71b1b8bc3fSopenharmony_ci};
72b1b8bc3fSopenharmony_ci
73b1b8bc3fSopenharmony_ci/**
74b1b8bc3fSopenharmony_ci * @brief Callback impl for LoadSystemAbility
75b1b8bc3fSopenharmony_ci */
76b1b8bc3fSopenharmony_ciclass OnDemandLoadManagerCallback : public SystemAbilityLoadCallbackStub {
77b1b8bc3fSopenharmony_cipublic:
78b1b8bc3fSopenharmony_ci    /**
79b1b8bc3fSopenharmony_ci     * called when load SA success
80b1b8bc3fSopenharmony_ci     *
81b1b8bc3fSopenharmony_ci     * @param systemAbilityId id of SA which was loaded
82b1b8bc3fSopenharmony_ci     * @param remoteObject poniter of IRemoteObject
83b1b8bc3fSopenharmony_ci     */
84b1b8bc3fSopenharmony_ci    void OnLoadSystemAbilitySuccess(int32_t systemAbilityId, const sptr<IRemoteObject> &remoteObject) override;
85b1b8bc3fSopenharmony_ci
86b1b8bc3fSopenharmony_ci    /**
87b1b8bc3fSopenharmony_ci     * called when load SA fail
88b1b8bc3fSopenharmony_ci     *
89b1b8bc3fSopenharmony_ci     * @param systemAbilityId id of SA which was loaded
90b1b8bc3fSopenharmony_ci     */
91b1b8bc3fSopenharmony_ci    void OnLoadSystemAbilityFail(int32_t systemAbilityId) override;
92b1b8bc3fSopenharmony_ci};
93b1b8bc3fSopenharmony_ci
94b1b8bc3fSopenharmony_ci/**
95b1b8bc3fSopenharmony_ci * Class for setup bpf maps and poll event from bpf ring buffer
96b1b8bc3fSopenharmony_ci */
97b1b8bc3fSopenharmony_ciclass NetsysBpfNetFirewall : public NoCopyable {
98b1b8bc3fSopenharmony_cipublic:
99b1b8bc3fSopenharmony_ci    static std::shared_ptr<NetsysBpfNetFirewall> GetInstance();
100b1b8bc3fSopenharmony_ci
101b1b8bc3fSopenharmony_ci    /**
102b1b8bc3fSopenharmony_ci     * start to listen bpf ring buffer
103b1b8bc3fSopenharmony_ci     *
104b1b8bc3fSopenharmony_ci     * @return 0 if success or -1 if an error occurred
105b1b8bc3fSopenharmony_ci     */
106b1b8bc3fSopenharmony_ci    int32_t StartListener();
107b1b8bc3fSopenharmony_ci
108b1b8bc3fSopenharmony_ci    /* *
109b1b8bc3fSopenharmony_ci     * @brief stop listen bpf ring buffer
110b1b8bc3fSopenharmony_ci     *
111b1b8bc3fSopenharmony_ci     * @return 0 if success or -1 if an error occurred
112b1b8bc3fSopenharmony_ci     */
113b1b8bc3fSopenharmony_ci    int32_t StopListener();
114b1b8bc3fSopenharmony_ci
115b1b8bc3fSopenharmony_ci    /**
116b1b8bc3fSopenharmony_ci     * Set firewall rules to native
117b1b8bc3fSopenharmony_ci     *
118b1b8bc3fSopenharmony_ci     * @param ruleList list of NetFirewallIpRule
119b1b8bc3fSopenharmony_ci     * @param isFinish transmit finish or not
120b1b8bc3fSopenharmony_ci     * @return 0 if success or -1 if an error occurred
121b1b8bc3fSopenharmony_ci     */
122b1b8bc3fSopenharmony_ci    int32_t SetFirewallRules(const std::vector<sptr<NetFirewallBaseRule>> &ruleList, bool isFinish);
123b1b8bc3fSopenharmony_ci
124b1b8bc3fSopenharmony_ci    /**
125b1b8bc3fSopenharmony_ci     * Set firewall default action
126b1b8bc3fSopenharmony_ci     *
127b1b8bc3fSopenharmony_ci     * @param inDefault  Default action of NetFirewallRuleDirection:RULE_IN
128b1b8bc3fSopenharmony_ci     * @param outDefault Default action of NetFirewallRuleDirection:RULE_OUT
129b1b8bc3fSopenharmony_ci     * @return  0 if success or -1 if an error occurred
130b1b8bc3fSopenharmony_ci     */
131b1b8bc3fSopenharmony_ci    int32_t SetFirewallDefaultAction(FirewallRuleAction inDefault, FirewallRuleAction outDefault);
132b1b8bc3fSopenharmony_ci
133b1b8bc3fSopenharmony_ci    /**
134b1b8bc3fSopenharmony_ci     * Set firewall current user id
135b1b8bc3fSopenharmony_ci     *
136b1b8bc3fSopenharmony_ci     * @param userId current user id
137b1b8bc3fSopenharmony_ci     * @return 0 if success or -1 if an error occurred
138b1b8bc3fSopenharmony_ci     */
139b1b8bc3fSopenharmony_ci    int32_t SetFirewallCurrentUserId(int32_t userId);
140b1b8bc3fSopenharmony_ci
141b1b8bc3fSopenharmony_ci    /**
142b1b8bc3fSopenharmony_ci     * Clear all bpf maps
143b1b8bc3fSopenharmony_ci     *
144b1b8bc3fSopenharmony_ci     * @return  0 if success or -1 if an error occurred
145b1b8bc3fSopenharmony_ci     */
146b1b8bc3fSopenharmony_ci    int32_t ClearFirewallRules();
147b1b8bc3fSopenharmony_ci
148b1b8bc3fSopenharmony_ci    /**
149b1b8bc3fSopenharmony_ci     * Register callback for recevie intercept event
150b1b8bc3fSopenharmony_ci     *
151b1b8bc3fSopenharmony_ci     * @param callback implement of INetFirewallCallback
152b1b8bc3fSopenharmony_ci     * @return 0 if success or -1 if an error occurred
153b1b8bc3fSopenharmony_ci     */
154b1b8bc3fSopenharmony_ci    int32_t RegisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback);
155b1b8bc3fSopenharmony_ci
156b1b8bc3fSopenharmony_ci    /**
157b1b8bc3fSopenharmony_ci     * Unregister callback for recevie intercept event
158b1b8bc3fSopenharmony_ci     *
159b1b8bc3fSopenharmony_ci     * @param callback register callback for recevie intercept event
160b1b8bc3fSopenharmony_ci     * @return 0 if success or -1 if an error occurred
161b1b8bc3fSopenharmony_ci     */
162b1b8bc3fSopenharmony_ci    int32_t UnregisterCallback(const sptr<NetsysNative::INetFirewallCallback> &callback);
163b1b8bc3fSopenharmony_ci
164b1b8bc3fSopenharmony_ci    /**
165b1b8bc3fSopenharmony_ci     * Load SA on demand
166b1b8bc3fSopenharmony_ci     *
167b1b8bc3fSopenharmony_ci     * @param systemAbilityId id of SA want to load
168b1b8bc3fSopenharmony_ci     * @return 0 if success or -1 if an error occurred
169b1b8bc3fSopenharmony_ci     */
170b1b8bc3fSopenharmony_ci    int32_t LoadSystemAbility(int32_t systemAbilityId);
171b1b8bc3fSopenharmony_ci
172b1b8bc3fSopenharmony_ci    /**
173b1b8bc3fSopenharmony_ci     * Set bpf prog load state
174b1b8bc3fSopenharmony_ci     *
175b1b8bc3fSopenharmony_ci     * @param load true if load success or false if an error occurred
176b1b8bc3fSopenharmony_ci     */
177b1b8bc3fSopenharmony_ci    void SetBpfLoaded(bool load);
178b1b8bc3fSopenharmony_ci
179b1b8bc3fSopenharmony_ci    /**
180b1b8bc3fSopenharmony_ci     * Get bpf prog load state
181b1b8bc3fSopenharmony_ci     */
182b1b8bc3fSopenharmony_ci    bool IsBpfLoaded()
183b1b8bc3fSopenharmony_ci    {
184b1b8bc3fSopenharmony_ci        return isBpfLoaded_;
185b1b8bc3fSopenharmony_ci    }
186b1b8bc3fSopenharmony_ci
187b1b8bc3fSopenharmony_ci    void AddDomainCache(const NetAddrInfo &addrInfo);
188b1b8bc3fSopenharmony_ci    void ClearDomainCache();
189b1b8bc3fSopenharmony_ci
190b1b8bc3fSopenharmony_ciprivate:
191b1b8bc3fSopenharmony_ci    template <typename Key, typename Value> int ClearBpfMap(const char *path, const Key &key, Value &val)
192b1b8bc3fSopenharmony_ci    {
193b1b8bc3fSopenharmony_ci        (void)key;
194b1b8bc3fSopenharmony_ci        (void)val;
195b1b8bc3fSopenharmony_ci        BpfMapper<Key, Value> rdMap(path, BPF_F_RDONLY);
196b1b8bc3fSopenharmony_ci        if (!rdMap.IsValid()) {
197b1b8bc3fSopenharmony_ci            return -1;
198b1b8bc3fSopenharmony_ci        }
199b1b8bc3fSopenharmony_ci        std::vector<Key> keys = rdMap.GetAllKeys();
200b1b8bc3fSopenharmony_ci        if (keys.empty()) {
201b1b8bc3fSopenharmony_ci            return 0;
202b1b8bc3fSopenharmony_ci        }
203b1b8bc3fSopenharmony_ci        BpfMapper<Key, Value> wrMap(path, BPF_F_WRONLY);
204b1b8bc3fSopenharmony_ci        if (!wrMap.IsValid()) {
205b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("ClearBpfMap: wrMap is invalid");
206b1b8bc3fSopenharmony_ci            return -1;
207b1b8bc3fSopenharmony_ci        }
208b1b8bc3fSopenharmony_ci        if (wrMap.Clear(keys) != 0) {
209b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("ClearBpfMap: clear failed");
210b1b8bc3fSopenharmony_ci            return -1;
211b1b8bc3fSopenharmony_ci        }
212b1b8bc3fSopenharmony_ci
213b1b8bc3fSopenharmony_ci        return 0;
214b1b8bc3fSopenharmony_ci    }
215b1b8bc3fSopenharmony_ci
216b1b8bc3fSopenharmony_ci    template <typename Key, typename Value> int WriteBpfMap(const char *path, const Key &key, Value &val)
217b1b8bc3fSopenharmony_ci    {
218b1b8bc3fSopenharmony_ci        BpfMapper<Key, Value> map(path, BPF_F_WRONLY);
219b1b8bc3fSopenharmony_ci        if (!map.IsValid()) {
220b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("WriteBpfMap: map invalid: %{public}s", path);
221b1b8bc3fSopenharmony_ci            return -1;
222b1b8bc3fSopenharmony_ci        }
223b1b8bc3fSopenharmony_ci
224b1b8bc3fSopenharmony_ci        if (map.Write(key, val, BPF_ANY) != 0) {
225b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("WriteBpfMap: map write failed");
226b1b8bc3fSopenharmony_ci            return -1;
227b1b8bc3fSopenharmony_ci        }
228b1b8bc3fSopenharmony_ci
229b1b8bc3fSopenharmony_ci        return 0;
230b1b8bc3fSopenharmony_ci    }
231b1b8bc3fSopenharmony_ci
232b1b8bc3fSopenharmony_ci    NetsysBpfNetFirewall();
233b1b8bc3fSopenharmony_ci
234b1b8bc3fSopenharmony_ci    static void StartConntrackGcThread(void);
235b1b8bc3fSopenharmony_ci
236b1b8bc3fSopenharmony_ci    static void RingBufferListenThread(void);
237b1b8bc3fSopenharmony_ci
238b1b8bc3fSopenharmony_ci    void StopConntrackGc();
239b1b8bc3fSopenharmony_ci
240b1b8bc3fSopenharmony_ci    static int HandleEvent(void *ctx, void *data, size_t len);
241b1b8bc3fSopenharmony_ci
242b1b8bc3fSopenharmony_ci    static void HandleTupleEvent(TupleEvent *ev);
243b1b8bc3fSopenharmony_ci
244b1b8bc3fSopenharmony_ci    static void HandleInterceptEvent(InterceptEvent *ev);
245b1b8bc3fSopenharmony_ci
246b1b8bc3fSopenharmony_ci    static void HandleDebugEvent(DebugEvent *ev);
247b1b8bc3fSopenharmony_ci
248b1b8bc3fSopenharmony_ci    bool ShouldSkipNotify(sptr<InterceptRecord> record);
249b1b8bc3fSopenharmony_ci
250b1b8bc3fSopenharmony_ci    void NotifyInterceptEvent(InterceptEvent *info);
251b1b8bc3fSopenharmony_ci
252b1b8bc3fSopenharmony_ci    static void ConntrackGcTask();
253b1b8bc3fSopenharmony_ci
254b1b8bc3fSopenharmony_ci    void ClearBpfFirewallRules(NetFirewallRuleDirection direction);
255b1b8bc3fSopenharmony_ci
256b1b8bc3fSopenharmony_ci    void WriteSrcIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
257b1b8bc3fSopenharmony_ci
258b1b8bc3fSopenharmony_ci    void WriteSrcIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
259b1b8bc3fSopenharmony_ci
260b1b8bc3fSopenharmony_ci    void WriteDstIpv4BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
261b1b8bc3fSopenharmony_ci
262b1b8bc3fSopenharmony_ci    void WriteDstIpv6BpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
263b1b8bc3fSopenharmony_ci
264b1b8bc3fSopenharmony_ci    void WriteSrcPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
265b1b8bc3fSopenharmony_ci
266b1b8bc3fSopenharmony_ci    void WriteDstPortBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
267b1b8bc3fSopenharmony_ci
268b1b8bc3fSopenharmony_ci    void WriteProtoBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
269b1b8bc3fSopenharmony_ci
270b1b8bc3fSopenharmony_ci    void WriteAppUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
271b1b8bc3fSopenharmony_ci
272b1b8bc3fSopenharmony_ci    void WriteUidBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
273b1b8bc3fSopenharmony_ci
274b1b8bc3fSopenharmony_ci    void WriteActionBpfMap(BitmapManager &manager, NetFirewallRuleDirection direction);
275b1b8bc3fSopenharmony_ci
276b1b8bc3fSopenharmony_ci    int32_t SetBpfFirewallRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList,
277b1b8bc3fSopenharmony_ci        NetFirewallRuleDirection direction);
278b1b8bc3fSopenharmony_ci
279b1b8bc3fSopenharmony_ci    int32_t SetFirewallIpRules(const std::vector<sptr<NetFirewallIpRule>> &ruleList);
280b1b8bc3fSopenharmony_ci
281b1b8bc3fSopenharmony_ci    static std::shared_ptr<NetsysBpfNetFirewall> instance_;
282b1b8bc3fSopenharmony_ci    static bool isBpfLoaded_;
283b1b8bc3fSopenharmony_ci    static bool keepListen_;
284b1b8bc3fSopenharmony_ci    std::unique_ptr<std::thread> thread_;
285b1b8bc3fSopenharmony_ci    std::vector<sptr<NetsysNative::INetFirewallCallback>> callbacks_;
286b1b8bc3fSopenharmony_ci    sptr<InterceptRecord> oldRecord_ = nullptr;
287b1b8bc3fSopenharmony_ci    static bool keepGc_;
288b1b8bc3fSopenharmony_ci    std::unique_ptr<std::thread> gcThread_;
289b1b8bc3fSopenharmony_ci    static std::unique_ptr<BpfMapper<CtKey, CtVaule>> ctRdMap_, ctWrMap_;
290b1b8bc3fSopenharmony_ci    std::vector<sptr<NetFirewallIpRule>> firewallIpRules_;
291b1b8bc3fSopenharmony_ci};
292b1b8bc3fSopenharmony_ci} // namespace OHOS::NetManagerStandard
293b1b8bc3fSopenharmony_ci#endif /* NETMANAGER_EXT_BPF_NET_FIREWALL_H */
294