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 "bpf_ring_buffer.h"
17 #include "net_policy_client.h"
18 #include "libbpf.h"
19 #include "ffrt.h"
20 #include "ffrt_inner.h"
21
22 namespace OHOS::NetManagerStandard {
23 namespace {
24 const int RING_BUFFER_POLL_TIME_OUT_MS = -1;
25 }
26 bool NetsysBpfRingBuffer::existThread_ = true;
27
BpfMapPathNameToU64(const std::string & pathName)28 uint64_t NetsysBpfRingBuffer::BpfMapPathNameToU64(const std::string &pathName)
29 {
30 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pathName.c_str()));
31 }
32
BpfSyscall(int32_t cmd,const bpf_attr & attr)33 int32_t NetsysBpfRingBuffer::BpfSyscall(int32_t cmd, const bpf_attr &attr)
34 {
35 return static_cast<int32_t>(syscall(__NR_bpf, cmd, &attr, sizeof(attr)));
36 }
37
GetRingbufFd(const std::string & path,uint32_t fileFlags)38 int NetsysBpfRingBuffer::GetRingbufFd(const std::string &path, uint32_t fileFlags)
39 {
40 bpf_attr bpfAttr{};
41 memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr));
42 bpfAttr.pathname = BpfMapPathNameToU64(path);
43 bpfAttr.file_flags = fileFlags;
44 return BpfSyscall(BPF_OBJ_GET, bpfAttr);
45 }
46
HandleNetworkPolicyEventCallback(void * ctx,void * data,size_t data_sz)47 int NetsysBpfRingBuffer::HandleNetworkPolicyEventCallback(void *ctx, void *data, size_t data_sz)
48 {
49 NETNATIVE_LOG_D("HandleNetworkPolicyEventCallback enter");
50 int32_t *e = (int32_t*)data;
51
52 if (NetPolicyClient::GetInstance().NotifyNetAccessPolicyDiag(*e) != NETMANAGER_SUCCESS) {
53 NETNATIVE_LOGE("Notify to diag fail");
54 return RING_BUFFER_ERR_INTERNAL;
55 }
56
57 return RING_BUFFER_ERR_NONE;
58 }
59
ListenRingBufferThread(void)60 void NetsysBpfRingBuffer::ListenRingBufferThread(void)
61 {
62 auto ringbufFd = GetRingbufFd(RING_BUFFER_MAP_PATH, 0);
63 if (ringbufFd > 0) {
64 struct ring_buffer *rb = NULL;
65 int err = 0;
66 /* Set up ring buffer polling */
67 rb = ring_buffer__new(ringbufFd, HandleNetworkPolicyEventCallback, NULL, NULL);
68 if (!rb) {
69 err = -1;
70 NETNATIVE_LOGE("Bpf ring buffer new fail");
71 return;
72 }
73
74 /* Process events */
75 while (existThread_) {
76 ffrt::sync_io(ringbufFd);
77 err = ring_buffer__poll(rb, RING_BUFFER_POLL_TIME_OUT_MS);
78 if (err < 0) {
79 NETNATIVE_LOGE("Bpf ring buffer poll fail, err: %{public}d, errno: %{public}d", err, errno);
80 break;
81 }
82 }
83
84 ring_buffer__free(rb);
85 }
86
87 NETNATIVE_LOGE("Could not get bpf ring buffer map");
88 return;
89 }
90
ListenNetworkAccessPolicyEvent(void)91 void NetsysBpfRingBuffer::ListenNetworkAccessPolicyEvent(void)
92 {
93 ffrt::submit(ListenRingBufferThread, {}, {}, ffrt::task_attr().name("ListenRingBufferThread"));
94 }
95
ExistRingBufferPoll(void)96 void NetsysBpfRingBuffer::ExistRingBufferPoll(void)
97 {
98 existThread_ = false;
99 }
100 }
101