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