1b1b8bc3fSopenharmony_ci/*
2b1b8bc3fSopenharmony_ci * Copyright (c) 2023 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 <cerrno>
17b1b8bc3fSopenharmony_ci#include <fcntl.h>
18b1b8bc3fSopenharmony_ci#include <filesystem>
19b1b8bc3fSopenharmony_ci#include <functional>
20b1b8bc3fSopenharmony_ci#include <iostream>
21b1b8bc3fSopenharmony_ci#include <linux/bpf.h>
22b1b8bc3fSopenharmony_ci#include <linux/if_ether.h>
23b1b8bc3fSopenharmony_ci#include <arpa/inet.h>
24b1b8bc3fSopenharmony_ci#include <map>
25b1b8bc3fSopenharmony_ci#include <memory.h>
26b1b8bc3fSopenharmony_ci#include <string>
27b1b8bc3fSopenharmony_ci#include <sys/mount.h>
28b1b8bc3fSopenharmony_ci#include <sys/resource.h>
29b1b8bc3fSopenharmony_ci#include <sys/syscall.h>
30b1b8bc3fSopenharmony_ci#include <unistd.h>
31b1b8bc3fSopenharmony_ci#include <vector>
32b1b8bc3fSopenharmony_ci
33b1b8bc3fSopenharmony_ci#include "bpf_def.h"
34b1b8bc3fSopenharmony_ci#include "bpf_loader.h"
35b1b8bc3fSopenharmony_ci#include "elf_types.hpp"
36b1b8bc3fSopenharmony_ci#include "elfio.hpp"
37b1b8bc3fSopenharmony_ci#include "elfio_relocation.hpp"
38b1b8bc3fSopenharmony_ci#include "net_manager_constants.h"
39b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h"
40b1b8bc3fSopenharmony_ci#include "securec.h"
41b1b8bc3fSopenharmony_ci
42b1b8bc3fSopenharmony_ci#define DEFINE_SECTION_NAME(name) \
43b1b8bc3fSopenharmony_ci    {                             \
44b1b8bc3fSopenharmony_ci        name, strlen(name)        \
45b1b8bc3fSopenharmony_ci    }
46b1b8bc3fSopenharmony_ci
47b1b8bc3fSopenharmony_ci#define DEFINE_PROG_TYPE(progName, progType) \
48b1b8bc3fSopenharmony_ci    {                                        \
49b1b8bc3fSopenharmony_ci        progName, progType                   \
50b1b8bc3fSopenharmony_ci    }
51b1b8bc3fSopenharmony_ci#define DEFINE_ATTACH_TYPE(progName, attachType, needExpectedAttach) \
52b1b8bc3fSopenharmony_ci    {                                                               \
53b1b8bc3fSopenharmony_ci        progName, attachType, needExpectedAttach                    \
54b1b8bc3fSopenharmony_ci    }
55b1b8bc3fSopenharmony_ci
56b1b8bc3fSopenharmony_cinamespace OHOS::NetManagerStandard {
57b1b8bc3fSopenharmony_cistatic constexpr const char *BPF_DIR = "/sys/fs/bpf";
58b1b8bc3fSopenharmony_cistatic constexpr const char *CGROUP_DIR = "/sys/fs/cgroup";
59b1b8bc3fSopenharmony_cistatic constexpr const char *MAPS_DIR = "/sys/fs/bpf/netsys/maps";
60b1b8bc3fSopenharmony_cistatic constexpr const char *PROGS_DIR = "/sys/fs/bpf/netsys/progs";
61b1b8bc3fSopenharmony_ci
62b1b8bc3fSopenharmony_ci// There is no limit to the size of SECTION_NAMES.
63b1b8bc3fSopenharmony_cistatic const struct SectionName {
64b1b8bc3fSopenharmony_ci    const char *sectionName;
65b1b8bc3fSopenharmony_ci    size_t sectionNameLength;
66b1b8bc3fSopenharmony_ci} SECTION_NAMES[] = {
67b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("kprobe/"),
68b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("kretprobe/"),
69b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("tracepoint/"),
70b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("raw_tracepoint/"),
71b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("xdp"),
72b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("perf_event/"),
73b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("socket"),
74b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("cgroup/"),
75b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("sockops"),
76b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("sk_skb"),
77b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("sk_msg"),
78b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("cgroup_skb"),
79b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("xdp_packet_parser"),
80b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("schedcls"),
81b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("classifier"),
82b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("cgroup_sock"),
83b1b8bc3fSopenharmony_ci    DEFINE_SECTION_NAME("cgroup_addr"),
84b1b8bc3fSopenharmony_ci};
85b1b8bc3fSopenharmony_ci
86b1b8bc3fSopenharmony_cistatic const constexpr struct {
87b1b8bc3fSopenharmony_ci    const char *event;
88b1b8bc3fSopenharmony_ci    bpf_prog_type progType;
89b1b8bc3fSopenharmony_ci} PROG_TYPES[] = {
90b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("socket", BPF_PROG_TYPE_SOCKET_FILTER),
91b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("cgroup_skb", BPF_PROG_TYPE_CGROUP_SKB),
92b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("xdp", BPF_PROG_TYPE_XDP),
93b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("xdp_packet_parser", BPF_PROG_TYPE_XDP),
94b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("schedcls", BPF_PROG_TYPE_SCHED_CLS),
95b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("classifier", BPF_PROG_TYPE_SCHED_CLS),
96b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("cgroup_sock", BPF_PROG_TYPE_CGROUP_SOCK),
97b1b8bc3fSopenharmony_ci    DEFINE_PROG_TYPE("cgroup_addr", BPF_PROG_TYPE_CGROUP_SOCK_ADDR),
98b1b8bc3fSopenharmony_ci};
99b1b8bc3fSopenharmony_ci
100b1b8bc3fSopenharmony_cistatic const constexpr struct {
101b1b8bc3fSopenharmony_ci    const char *progName;
102b1b8bc3fSopenharmony_ci    bpf_attach_type attachType;
103b1b8bc3fSopenharmony_ci    bool needExpectedAttach;
104b1b8bc3fSopenharmony_ci} PROG_ATTACH_TYPES[] = {
105b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_sock_inet_create_socket", BPF_CGROUP_INET_SOCK_CREATE, false),
106b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_sock_inet_release_socket", BPF_CGROUP_INET_SOCK_RELEASE, true),
107b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_skb_uid_ingress", BPF_CGROUP_INET_INGRESS, false),
108b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_skb_uid_egress", BPF_CGROUP_INET_EGRESS, false),
109b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_addr_bind4", BPF_CGROUP_INET4_BIND, true),
110b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_addr_bind6", BPF_CGROUP_INET6_BIND, true),
111b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_addr_connect4", BPF_CGROUP_INET4_CONNECT, true),
112b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_addr_connect6", BPF_CGROUP_INET6_CONNECT, true),
113b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_addr_sendmsg4", BPF_CGROUP_UDP4_SENDMSG, true),
114b1b8bc3fSopenharmony_ci    DEFINE_ATTACH_TYPE("cgroup_addr_sendmsg6", BPF_CGROUP_UDP6_SENDMSG, true),
115b1b8bc3fSopenharmony_ci};
116b1b8bc3fSopenharmony_ci
117b1b8bc3fSopenharmony_ciint32_t g_sockFd = -1;
118b1b8bc3fSopenharmony_ci
119b1b8bc3fSopenharmony_cistruct BpfMapData {
120b1b8bc3fSopenharmony_ci    BpfMapData() : fd(0)
121b1b8bc3fSopenharmony_ci    {
122b1b8bc3fSopenharmony_ci        if (memset_s(&def, sizeof(def), 0, sizeof(def)) != EOK) {
123b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("memset_s error");
124b1b8bc3fSopenharmony_ci        }
125b1b8bc3fSopenharmony_ci    }
126b1b8bc3fSopenharmony_ci
127b1b8bc3fSopenharmony_ci    int32_t fd;
128b1b8bc3fSopenharmony_ci    std::string name;
129b1b8bc3fSopenharmony_ci    bpf_map_def def{};
130b1b8bc3fSopenharmony_ci};
131b1b8bc3fSopenharmony_ci
132b1b8bc3fSopenharmony_citemplate <typename type> inline uint64_t PtrToU64(const type ptr)
133b1b8bc3fSopenharmony_ci{
134b1b8bc3fSopenharmony_ci    return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr));
135b1b8bc3fSopenharmony_ci}
136b1b8bc3fSopenharmony_ci
137b1b8bc3fSopenharmony_ciinline bool EndsWith(const std::string &str, const std::string &searchFor)
138b1b8bc3fSopenharmony_ci{
139b1b8bc3fSopenharmony_ci    if (searchFor.size() > str.size()) {
140b1b8bc3fSopenharmony_ci        return false;
141b1b8bc3fSopenharmony_ci    }
142b1b8bc3fSopenharmony_ci
143b1b8bc3fSopenharmony_ci    std::string source = str.substr(str.size() - searchFor.size(), searchFor.size());
144b1b8bc3fSopenharmony_ci    return source == searchFor;
145b1b8bc3fSopenharmony_ci}
146b1b8bc3fSopenharmony_ci
147b1b8bc3fSopenharmony_ciinline int32_t SysBpf(bpf_cmd cmd, bpf_attr *attr, uint32_t size)
148b1b8bc3fSopenharmony_ci{
149b1b8bc3fSopenharmony_ci    return static_cast<int32_t>(syscall(__NR_bpf, cmd, attr, size));
150b1b8bc3fSopenharmony_ci}
151b1b8bc3fSopenharmony_ci
152b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjGet(const std::string &pathName, uint32_t fileFlags)
153b1b8bc3fSopenharmony_ci{
154b1b8bc3fSopenharmony_ci    bpf_attr attr = {};
155b1b8bc3fSopenharmony_ci    if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) {
156b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
157b1b8bc3fSopenharmony_ci    }
158b1b8bc3fSopenharmony_ci    attr.pathname = PtrToU64(pathName.c_str());
159b1b8bc3fSopenharmony_ci    attr.file_flags = fileFlags;
160b1b8bc3fSopenharmony_ci    return SysBpf(BPF_OBJ_GET, &attr, sizeof(attr));
161b1b8bc3fSopenharmony_ci}
162b1b8bc3fSopenharmony_ci
163b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjPin(int32_t fd, const std::string &pathName)
164b1b8bc3fSopenharmony_ci{
165b1b8bc3fSopenharmony_ci    bpf_attr attr = {};
166b1b8bc3fSopenharmony_ci
167b1b8bc3fSopenharmony_ci    if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) {
168b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
169b1b8bc3fSopenharmony_ci    }
170b1b8bc3fSopenharmony_ci    attr.pathname = PtrToU64(pathName.c_str());
171b1b8bc3fSopenharmony_ci    if (fd < 0) {
172b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
173b1b8bc3fSopenharmony_ci    }
174b1b8bc3fSopenharmony_ci    attr.bpf_fd = static_cast<uint32_t>(fd);
175b1b8bc3fSopenharmony_ci
176b1b8bc3fSopenharmony_ci    return SysBpf(BPF_OBJ_PIN, &attr, sizeof(attr));
177b1b8bc3fSopenharmony_ci}
178b1b8bc3fSopenharmony_ci
179b1b8bc3fSopenharmony_ciinline int32_t SysBpfProgLoad(bpf_attr *attr, uint32_t size)
180b1b8bc3fSopenharmony_ci{
181b1b8bc3fSopenharmony_ci    int32_t fd = SysBpf(BPF_PROG_LOAD, attr, size);
182b1b8bc3fSopenharmony_ci    while (fd < 0 && errno == EAGAIN) {
183b1b8bc3fSopenharmony_ci        fd = SysBpf(BPF_PROG_LOAD, attr, size);
184b1b8bc3fSopenharmony_ci    }
185b1b8bc3fSopenharmony_ci
186b1b8bc3fSopenharmony_ci    return fd;
187b1b8bc3fSopenharmony_ci}
188b1b8bc3fSopenharmony_ci
189b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjDetach(bpf_attach_type type, const int progFd, const int cgFd)
190b1b8bc3fSopenharmony_ci{
191b1b8bc3fSopenharmony_ci    bpf_attr attr = {};
192b1b8bc3fSopenharmony_ci
193b1b8bc3fSopenharmony_ci    if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) {
194b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
195b1b8bc3fSopenharmony_ci    }
196b1b8bc3fSopenharmony_ci    attr.target_fd = cgFd;
197b1b8bc3fSopenharmony_ci    attr.attach_bpf_fd = progFd;
198b1b8bc3fSopenharmony_ci    attr.attach_type = type;
199b1b8bc3fSopenharmony_ci
200b1b8bc3fSopenharmony_ci    return SysBpf(BPF_PROG_DETACH, &attr, sizeof(attr));
201b1b8bc3fSopenharmony_ci}
202b1b8bc3fSopenharmony_ci
203b1b8bc3fSopenharmony_ciinline int32_t SysBpfObjAttach(bpf_attach_type type, const int progFd, const int cgFd)
204b1b8bc3fSopenharmony_ci{
205b1b8bc3fSopenharmony_ci    bpf_attr attr = {};
206b1b8bc3fSopenharmony_ci
207b1b8bc3fSopenharmony_ci    if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) {
208b1b8bc3fSopenharmony_ci        return NETMANAGER_ERROR;
209b1b8bc3fSopenharmony_ci    }
210b1b8bc3fSopenharmony_ci    attr.target_fd = cgFd;
211b1b8bc3fSopenharmony_ci    attr.attach_bpf_fd = progFd;
212b1b8bc3fSopenharmony_ci    attr.attach_type = type;
213b1b8bc3fSopenharmony_ci    attr.attach_flags = BPF_F_ALLOW_MULTI;
214b1b8bc3fSopenharmony_ci
215b1b8bc3fSopenharmony_ci    return SysBpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
216b1b8bc3fSopenharmony_ci}
217b1b8bc3fSopenharmony_ci
218b1b8bc3fSopenharmony_ciinline bool MatchSecName(const std::string &name)
219b1b8bc3fSopenharmony_ci{
220b1b8bc3fSopenharmony_ci    auto matchFunc = [name](const SectionName &sec) -> bool {
221b1b8bc3fSopenharmony_ci        if (name.size() < sec.sectionNameLength) {
222b1b8bc3fSopenharmony_ci            return false;
223b1b8bc3fSopenharmony_ci        }
224b1b8bc3fSopenharmony_ci        return memcmp(name.c_str(), sec.sectionName, sec.sectionNameLength) == 0;
225b1b8bc3fSopenharmony_ci    };
226b1b8bc3fSopenharmony_ci    auto size = sizeof(SECTION_NAMES) / sizeof(SectionName);
227b1b8bc3fSopenharmony_ci    return std::any_of(SECTION_NAMES, SECTION_NAMES + size, matchFunc);
228b1b8bc3fSopenharmony_ci}
229b1b8bc3fSopenharmony_ci
230b1b8bc3fSopenharmony_ciinline int32_t UnPin(const std::string &path)
231b1b8bc3fSopenharmony_ci{
232b1b8bc3fSopenharmony_ci    return unlink(path.c_str());
233b1b8bc3fSopenharmony_ci}
234b1b8bc3fSopenharmony_ci
235b1b8bc3fSopenharmony_ciclass ElfLoader {
236b1b8bc3fSopenharmony_cipublic:
237b1b8bc3fSopenharmony_ci    explicit ElfLoader(std::string path) : path_(std::move(path)), kernVersion_(0) {}
238b1b8bc3fSopenharmony_ci
239b1b8bc3fSopenharmony_ci    ElfLoadError Unload() const
240b1b8bc3fSopenharmony_ci    {
241b1b8bc3fSopenharmony_ci        const struct {
242b1b8bc3fSopenharmony_ci            uint32_t index;
243b1b8bc3fSopenharmony_ci            const char *infoMsg;
244b1b8bc3fSopenharmony_ci            std::function<ElfLoadError()> fun;
245b1b8bc3fSopenharmony_ci            const char *errorMsg;
246b1b8bc3fSopenharmony_ci        } funList[]{
247b1b8bc3fSopenharmony_ci            {1, "path is valid", isPathValid_, "path is not valid"},
248b1b8bc3fSopenharmony_ci            {2, "load elf file ok", loadElfFile_, "load elf file failed"},
249b1b8bc3fSopenharmony_ci            {3, "load elf map section ok", loadElfMapsSection_, "load elf map section failed"},
250b1b8bc3fSopenharmony_ci            {4, "delete maps ok", deleteMaps_, "delete maps failed"},
251b1b8bc3fSopenharmony_ci            {5, "unload progs ok", unloadProgs_, "unload progs ok"},
252b1b8bc3fSopenharmony_ci        };
253b1b8bc3fSopenharmony_ci
254b1b8bc3fSopenharmony_ci        for (const auto &fun : funList) {
255b1b8bc3fSopenharmony_ci            auto ret = fun.fun();
256b1b8bc3fSopenharmony_ci            if (ret != ELF_LOAD_ERR_NONE) {
257b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("error msg is %{public}s", fun.errorMsg);
258b1b8bc3fSopenharmony_ci                return static_cast<ElfLoadError>(ret);
259b1b8bc3fSopenharmony_ci            }
260b1b8bc3fSopenharmony_ci            NETNATIVE_LOGI("the %{public}u step: %{public}s", fun.index, fun.infoMsg);
261b1b8bc3fSopenharmony_ci        }
262b1b8bc3fSopenharmony_ci
263b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
264b1b8bc3fSopenharmony_ci    }
265b1b8bc3fSopenharmony_ci
266b1b8bc3fSopenharmony_ci    ElfLoadError Load() const
267b1b8bc3fSopenharmony_ci    {
268b1b8bc3fSopenharmony_ci        const struct {
269b1b8bc3fSopenharmony_ci            uint32_t index;
270b1b8bc3fSopenharmony_ci            const char *infoMsg;
271b1b8bc3fSopenharmony_ci            std::function<ElfLoadError()> fun;
272b1b8bc3fSopenharmony_ci            const char *errorMsg;
273b1b8bc3fSopenharmony_ci        } funList[]{
274b1b8bc3fSopenharmony_ci            {1, "path is valid", isPathValid_, "path is not valid"},
275b1b8bc3fSopenharmony_ci            {2, "make directories fs ok", makeDirectories, "make directories fs failed"},
276b1b8bc3fSopenharmony_ci            {3, "load elf file ok", loadElfFile_, "load elf file failed"},
277b1b8bc3fSopenharmony_ci            {4, "version is valid", isVersionValid_, "version is not valid"},
278b1b8bc3fSopenharmony_ci            {5, "set license and version ok", setLicenseAndVersion_, "set license and version failed"},
279b1b8bc3fSopenharmony_ci            {6, "load elf map section ok", loadElfMapsSection_, "load elf map section failed"},
280b1b8bc3fSopenharmony_ci            {7, "set rlimit ok", setRlimit_, "set rlimit failed"},
281b1b8bc3fSopenharmony_ci            {8, "create maps ok", createMaps_, "create maps failed"},
282b1b8bc3fSopenharmony_ci            {9, "parse relocation ok", parseRelocation_, "parse relocation failed"},
283b1b8bc3fSopenharmony_ci            {10, "load progs ok", loadProgs_, "load progs failed"},
284b1b8bc3fSopenharmony_ci        };
285b1b8bc3fSopenharmony_ci        for (const auto &fun : funList) {
286b1b8bc3fSopenharmony_ci            auto ret = fun.fun();
287b1b8bc3fSopenharmony_ci            if (ret != ELF_LOAD_ERR_NONE) {
288b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("error msg is %{public}s", fun.errorMsg);
289b1b8bc3fSopenharmony_ci                return static_cast<ElfLoadError>(ret);
290b1b8bc3fSopenharmony_ci            }
291b1b8bc3fSopenharmony_ci            NETNATIVE_LOGI("the %{public}u step: %{public}s", fun.index, fun.infoMsg);
292b1b8bc3fSopenharmony_ci        }
293b1b8bc3fSopenharmony_ci
294b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
295b1b8bc3fSopenharmony_ci    }
296b1b8bc3fSopenharmony_ci
297b1b8bc3fSopenharmony_ciprivate:
298b1b8bc3fSopenharmony_ci    bool CheckPath()
299b1b8bc3fSopenharmony_ci    {
300b1b8bc3fSopenharmony_ci        if (path_.empty() || !std::filesystem::exists(path_) || std::filesystem::is_directory(path_)) {
301b1b8bc3fSopenharmony_ci            return false;
302b1b8bc3fSopenharmony_ci        }
303b1b8bc3fSopenharmony_ci
304b1b8bc3fSopenharmony_ci        return true;
305b1b8bc3fSopenharmony_ci    }
306b1b8bc3fSopenharmony_ci
307b1b8bc3fSopenharmony_ci    bool IsPathValid()
308b1b8bc3fSopenharmony_ci    {
309b1b8bc3fSopenharmony_ci        if (!CheckPath()) {
310b1b8bc3fSopenharmony_ci            return false;
311b1b8bc3fSopenharmony_ci        }
312b1b8bc3fSopenharmony_ci        return EndsWith(path_, ".o");
313b1b8bc3fSopenharmony_ci    }
314b1b8bc3fSopenharmony_ci
315b1b8bc3fSopenharmony_ci    bool LoadElfFile()
316b1b8bc3fSopenharmony_ci    {
317b1b8bc3fSopenharmony_ci        return elfIo_.load(path_);
318b1b8bc3fSopenharmony_ci    }
319b1b8bc3fSopenharmony_ci
320b1b8bc3fSopenharmony_ci    bool IsVersionValid()
321b1b8bc3fSopenharmony_ci    {
322b1b8bc3fSopenharmony_ci        return elfIo_.get_version() == ELFIO::EV_CURRENT;
323b1b8bc3fSopenharmony_ci    }
324b1b8bc3fSopenharmony_ci
325b1b8bc3fSopenharmony_ci    static bool SetRlimit()
326b1b8bc3fSopenharmony_ci    {
327b1b8bc3fSopenharmony_ci        rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
328b1b8bc3fSopenharmony_ci        return setrlimit(RLIMIT_MEMLOCK, &r) >= 0;
329b1b8bc3fSopenharmony_ci    }
330b1b8bc3fSopenharmony_ci
331b1b8bc3fSopenharmony_ci    static bool IsMounted(const std::string &dir)
332b1b8bc3fSopenharmony_ci    {
333b1b8bc3fSopenharmony_ci        std::ifstream ifs("/proc/mounts", std::ios::in);
334b1b8bc3fSopenharmony_ci        if (!ifs.is_open()) {
335b1b8bc3fSopenharmony_ci            return false;
336b1b8bc3fSopenharmony_ci        }
337b1b8bc3fSopenharmony_ci
338b1b8bc3fSopenharmony_ci        std::string s;
339b1b8bc3fSopenharmony_ci        while (std::getline(ifs, s)) {
340b1b8bc3fSopenharmony_ci            if (s.find(dir) != std::string::npos) {
341b1b8bc3fSopenharmony_ci                ifs.close();
342b1b8bc3fSopenharmony_ci                return true;
343b1b8bc3fSopenharmony_ci            }
344b1b8bc3fSopenharmony_ci        }
345b1b8bc3fSopenharmony_ci        ifs.close();
346b1b8bc3fSopenharmony_ci        return false;
347b1b8bc3fSopenharmony_ci    }
348b1b8bc3fSopenharmony_ci
349b1b8bc3fSopenharmony_ci    static bool MakeDir(const std::string &dir)
350b1b8bc3fSopenharmony_ci    {
351b1b8bc3fSopenharmony_ci        if (std::filesystem::exists(dir) && std::filesystem::is_directory(dir)) {
352b1b8bc3fSopenharmony_ci            return true;
353b1b8bc3fSopenharmony_ci        }
354b1b8bc3fSopenharmony_ci        if (!std::filesystem::exists(dir)) {
355b1b8bc3fSopenharmony_ci            if (!std::filesystem::create_directories(std::filesystem::path(dir))) {
356b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("filesystem make dir err %{public}d", errno);
357b1b8bc3fSopenharmony_ci                return false;
358b1b8bc3fSopenharmony_ci            }
359b1b8bc3fSopenharmony_ci            return true;
360b1b8bc3fSopenharmony_ci        }
361b1b8bc3fSopenharmony_ci        if (!std::filesystem::is_directory(dir)) {
362b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("%{public}s is a file", dir.c_str());
363b1b8bc3fSopenharmony_ci            return false;
364b1b8bc3fSopenharmony_ci        }
365b1b8bc3fSopenharmony_ci        return true;
366b1b8bc3fSopenharmony_ci    }
367b1b8bc3fSopenharmony_ci
368b1b8bc3fSopenharmony_ci    static bool MakeDirectories()
369b1b8bc3fSopenharmony_ci    {
370b1b8bc3fSopenharmony_ci        if (IsMounted(BPF_DIR) && std::filesystem::exists(MAPS_DIR) && std::filesystem::is_directory(MAPS_DIR) &&
371b1b8bc3fSopenharmony_ci            std::filesystem::exists(PROGS_DIR) && std::filesystem::is_directory(PROGS_DIR)) {
372b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("%{public}s", "bpf directories are exists");
373b1b8bc3fSopenharmony_ci            return true;
374b1b8bc3fSopenharmony_ci        }
375b1b8bc3fSopenharmony_ci        if (!IsMounted(BPF_DIR) && mount(BPF_DIR, BPF_DIR, "bpf", MS_RELATIME, nullptr) < 0) {
376b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("mount bpf fs failed: errno = %{public}d", errno);
377b1b8bc3fSopenharmony_ci            return false;
378b1b8bc3fSopenharmony_ci        }
379b1b8bc3fSopenharmony_ci        if (!MakeDir(MAPS_DIR)) {
380b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("can not make dir: %{public}s", MAPS_DIR);
381b1b8bc3fSopenharmony_ci            return false;
382b1b8bc3fSopenharmony_ci        }
383b1b8bc3fSopenharmony_ci        if (!MakeDir(PROGS_DIR)) {
384b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("can not make dir: %{public}s", PROGS_DIR);
385b1b8bc3fSopenharmony_ci            return false;
386b1b8bc3fSopenharmony_ci        }
387b1b8bc3fSopenharmony_ci
388b1b8bc3fSopenharmony_ci        if (!IsMounted(CGROUP_DIR) && mount(CGROUP_DIR, CGROUP_DIR, "cgroup2", MS_RELATIME, nullptr) < 0) {
389b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("mount cgroup fs failed: errno = %{public}d", errno);
390b1b8bc3fSopenharmony_ci            return false;
391b1b8bc3fSopenharmony_ci        }
392b1b8bc3fSopenharmony_ci        return true;
393b1b8bc3fSopenharmony_ci    }
394b1b8bc3fSopenharmony_ci
395b1b8bc3fSopenharmony_ci    bool SetLicenseAndVersion()
396b1b8bc3fSopenharmony_ci    {
397b1b8bc3fSopenharmony_ci        return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](const auto &section) {
398b1b8bc3fSopenharmony_ci            if (section->get_name() == "license") {
399b1b8bc3fSopenharmony_ci                license_ = section->get_data();
400b1b8bc3fSopenharmony_ci                if (license_.empty()) {
401b1b8bc3fSopenharmony_ci                    return false;
402b1b8bc3fSopenharmony_ci                }
403b1b8bc3fSopenharmony_ci            } else if (section->get_name() == "version") {
404b1b8bc3fSopenharmony_ci                try {
405b1b8bc3fSopenharmony_ci                    kernVersion_ = std::stoi(section->get_data());
406b1b8bc3fSopenharmony_ci                } catch (const std::invalid_argument& e) {
407b1b8bc3fSopenharmony_ci                    NETNATIVE_LOGE("invalid_argument");
408b1b8bc3fSopenharmony_ci                    return false;
409b1b8bc3fSopenharmony_ci                } catch (const std::out_of_range& e) {
410b1b8bc3fSopenharmony_ci                    NETNATIVE_LOGE("out_of_range");
411b1b8bc3fSopenharmony_ci                    return false;
412b1b8bc3fSopenharmony_ci                }
413b1b8bc3fSopenharmony_ci                if (kernVersion_ == 0) {
414b1b8bc3fSopenharmony_ci                    return false;
415b1b8bc3fSopenharmony_ci                }
416b1b8bc3fSopenharmony_ci            }
417b1b8bc3fSopenharmony_ci
418b1b8bc3fSopenharmony_ci            return true;
419b1b8bc3fSopenharmony_ci        });
420b1b8bc3fSopenharmony_ci    }
421b1b8bc3fSopenharmony_ci
422b1b8bc3fSopenharmony_ci    std::map<ELFIO::Elf64_Addr, std::string> LoadElfMapSectionCore()
423b1b8bc3fSopenharmony_ci    {
424b1b8bc3fSopenharmony_ci        std::map<ELFIO::Elf64_Addr, std::string> mapName;
425b1b8bc3fSopenharmony_ci        for (const auto &section : elfIo_.sections) {
426b1b8bc3fSopenharmony_ci            if (section->get_type() != ELFIO::SHT_SYMTAB && section->get_type() != ELFIO::SHT_DYNSYM) {
427b1b8bc3fSopenharmony_ci                continue;
428b1b8bc3fSopenharmony_ci            }
429b1b8bc3fSopenharmony_ci            ELFIO::symbol_section_accessor symbols(elfIo_, section.get());
430b1b8bc3fSopenharmony_ci            for (ELFIO::Elf_Xword i = 0; i < symbols.get_symbols_num(); i++) {
431b1b8bc3fSopenharmony_ci                std::string name;
432b1b8bc3fSopenharmony_ci                ELFIO::Elf64_Addr value = 0;
433b1b8bc3fSopenharmony_ci                ELFIO::Elf_Xword size = 0;
434b1b8bc3fSopenharmony_ci                unsigned char bind = 0;
435b1b8bc3fSopenharmony_ci                unsigned char type = 0;
436b1b8bc3fSopenharmony_ci                ELFIO::Elf_Half elfSection = 0;
437b1b8bc3fSopenharmony_ci                unsigned char other = 0;
438b1b8bc3fSopenharmony_ci                symbols.get_symbol(i, name, value, size, bind, type, elfSection, other);
439b1b8bc3fSopenharmony_ci                if (type != ELFIO::STT_OBJECT || !EndsWith(name, "_map")) {
440b1b8bc3fSopenharmony_ci                    continue;
441b1b8bc3fSopenharmony_ci                }
442b1b8bc3fSopenharmony_ci                if (mapName.find(value) != mapName.end()) {
443b1b8bc3fSopenharmony_ci                    return {};
444b1b8bc3fSopenharmony_ci                }
445b1b8bc3fSopenharmony_ci                mapName[value] = name;
446b1b8bc3fSopenharmony_ci            }
447b1b8bc3fSopenharmony_ci        }
448b1b8bc3fSopenharmony_ci        return mapName;
449b1b8bc3fSopenharmony_ci    }
450b1b8bc3fSopenharmony_ci
451b1b8bc3fSopenharmony_ci    bool LoadElfMapsSection()
452b1b8bc3fSopenharmony_ci    {
453b1b8bc3fSopenharmony_ci        if (elfIo_.sections.size() == 0) {
454b1b8bc3fSopenharmony_ci            return false;
455b1b8bc3fSopenharmony_ci        }
456b1b8bc3fSopenharmony_ci
457b1b8bc3fSopenharmony_ci        auto it = std::find_if(elfIo_.sections.begin(), elfIo_.sections.end(),
458b1b8bc3fSopenharmony_ci                               [](const auto &section) { return section->get_name() == "maps"; });
459b1b8bc3fSopenharmony_ci        if (it == elfIo_.sections.end()) {
460b1b8bc3fSopenharmony_ci            return true;
461b1b8bc3fSopenharmony_ci        }
462b1b8bc3fSopenharmony_ci
463b1b8bc3fSopenharmony_ci        ELFIO::section *mapsSection = it->get();
464b1b8bc3fSopenharmony_ci        auto defs = reinterpret_cast<const bpf_map_def *>(mapsSection->get_data());
465b1b8bc3fSopenharmony_ci        auto mapNum = mapsSection->get_size() / sizeof(bpf_map_def);
466b1b8bc3fSopenharmony_ci        for (size_t i = 0; i < static_cast<size_t>(mapNum); i++) {
467b1b8bc3fSopenharmony_ci            BpfMapData map;
468b1b8bc3fSopenharmony_ci            map.def = defs[i];
469b1b8bc3fSopenharmony_ci            maps_.emplace_back(map);
470b1b8bc3fSopenharmony_ci        }
471b1b8bc3fSopenharmony_ci        auto mapName = LoadElfMapSectionCore();
472b1b8bc3fSopenharmony_ci        if (mapName.size() != maps_.size()) {
473b1b8bc3fSopenharmony_ci            return false;
474b1b8bc3fSopenharmony_ci        }
475b1b8bc3fSopenharmony_ci        size_t mapIndex = 0;
476b1b8bc3fSopenharmony_ci        for (const auto &[addr, name] : mapName) {
477b1b8bc3fSopenharmony_ci            maps_[mapIndex].name = name;
478b1b8bc3fSopenharmony_ci            ++mapIndex;
479b1b8bc3fSopenharmony_ci        }
480b1b8bc3fSopenharmony_ci
481b1b8bc3fSopenharmony_ci        return true;
482b1b8bc3fSopenharmony_ci    }
483b1b8bc3fSopenharmony_ci
484b1b8bc3fSopenharmony_ci    static void PrintMapAttr(const bpf_attr &attr)
485b1b8bc3fSopenharmony_ci    {
486b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("%{public}s", "BPF_MAP_CREATE:");
487b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("  .map_type    = %{public}u", attr.map_type);
488b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("  .key_size    = %{public}u", attr.key_size);
489b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("  .value_size  = %{public}u", attr.value_size);
490b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("  .max_entries = %{public}u", attr.max_entries);
491b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("  .map_flags   = %{public}u", attr.map_flags);
492b1b8bc3fSopenharmony_ci        NETNATIVE_LOGI("  .map_name    = %{public}s", attr.map_name);
493b1b8bc3fSopenharmony_ci    }
494b1b8bc3fSopenharmony_ci
495b1b8bc3fSopenharmony_ci    static int32_t BpfCreateMapNode(const BpfMapData &map)
496b1b8bc3fSopenharmony_ci    {
497b1b8bc3fSopenharmony_ci        bpf_attr attr = {};
498b1b8bc3fSopenharmony_ci        if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) {
499b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
500b1b8bc3fSopenharmony_ci        }
501b1b8bc3fSopenharmony_ci        attr.map_type = map.def.type;
502b1b8bc3fSopenharmony_ci        attr.key_size = map.def.key_size;
503b1b8bc3fSopenharmony_ci        attr.value_size = map.def.value_size;
504b1b8bc3fSopenharmony_ci        attr.max_entries = map.def.max_entries;
505b1b8bc3fSopenharmony_ci        attr.map_flags = map.def.map_flags;
506b1b8bc3fSopenharmony_ci        if (!map.name.empty()) {
507b1b8bc3fSopenharmony_ci            if (memcpy_s(attr.map_name, sizeof(attr.map_name) - 1, map.name.c_str(),
508b1b8bc3fSopenharmony_ci                         std::min<size_t>(map.name.size(), sizeof(attr.map_name) - 1)) != EOK) {
509b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("Failed copy map name %{public}s", map.name.c_str());
510b1b8bc3fSopenharmony_ci                return NETMANAGER_ERROR;
511b1b8bc3fSopenharmony_ci            }
512b1b8bc3fSopenharmony_ci        }
513b1b8bc3fSopenharmony_ci        attr.numa_node = (map.def.map_flags & static_cast<unsigned int>(BPF_F_NUMA_NODE)) ? map.def.numa_node : 0;
514b1b8bc3fSopenharmony_ci        PrintMapAttr(attr);
515b1b8bc3fSopenharmony_ci
516b1b8bc3fSopenharmony_ci        auto fd = SysBpf(BPF_MAP_CREATE, &attr, sizeof(attr));
517b1b8bc3fSopenharmony_ci        if (fd < 0) {
518b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("__NR_bpf, BPF_MAP_CREATE failed %{public}d %{public}d %{public}d", __NR_bpf, fd, errno);
519b1b8bc3fSopenharmony_ci        }
520b1b8bc3fSopenharmony_ci        return fd;
521b1b8bc3fSopenharmony_ci    }
522b1b8bc3fSopenharmony_ci
523b1b8bc3fSopenharmony_ci    bool CreateMaps()
524b1b8bc3fSopenharmony_ci    {
525b1b8bc3fSopenharmony_ci        for (auto &map : maps_) {
526b1b8bc3fSopenharmony_ci            auto fd = BpfCreateMapNode(map);
527b1b8bc3fSopenharmony_ci            if (fd < 0) {
528b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("Failed create map (%{public}s): %{public}d", map.name.c_str(), fd);
529b1b8bc3fSopenharmony_ci                return false;
530b1b8bc3fSopenharmony_ci            }
531b1b8bc3fSopenharmony_ci
532b1b8bc3fSopenharmony_ci            map.fd = fd;
533b1b8bc3fSopenharmony_ci            std::string mapPinLocation = std::string(MAPS_DIR) + "/" + map.name;
534b1b8bc3fSopenharmony_ci            if (access(mapPinLocation.c_str(), F_OK) == 0) {
535b1b8bc3fSopenharmony_ci                NETNATIVE_LOGI("map: %{public}s has already been pinned", mapPinLocation.c_str());
536b1b8bc3fSopenharmony_ci            } else {
537b1b8bc3fSopenharmony_ci                if (SysBpfObjPin(fd, mapPinLocation) < 0) {
538b1b8bc3fSopenharmony_ci                    NETNATIVE_LOGE("Failed to pin map: %{public}s, errno = %{public}d", mapPinLocation.c_str(), errno);
539b1b8bc3fSopenharmony_ci                    return false;
540b1b8bc3fSopenharmony_ci                }
541b1b8bc3fSopenharmony_ci            }
542b1b8bc3fSopenharmony_ci        }
543b1b8bc3fSopenharmony_ci        return true;
544b1b8bc3fSopenharmony_ci    }
545b1b8bc3fSopenharmony_ci
546b1b8bc3fSopenharmony_ci    bool DeleteMaps()
547b1b8bc3fSopenharmony_ci    {
548b1b8bc3fSopenharmony_ci        return std::all_of(maps_.begin(), maps_.end(), [](const auto &map) {
549b1b8bc3fSopenharmony_ci            std::string mapPinLocation = std::string(MAPS_DIR) + "/" + map.name;
550b1b8bc3fSopenharmony_ci            if (access(mapPinLocation.c_str(), F_OK) == 0) {
551b1b8bc3fSopenharmony_ci                auto ret = UnPin(mapPinLocation);
552b1b8bc3fSopenharmony_ci                return ret >= 0;
553b1b8bc3fSopenharmony_ci            }
554b1b8bc3fSopenharmony_ci            return true;
555b1b8bc3fSopenharmony_ci        });
556b1b8bc3fSopenharmony_ci    }
557b1b8bc3fSopenharmony_ci
558b1b8bc3fSopenharmony_ci    bool ApplyRelocation(bpf_insn *insn, ELFIO::section *section) const
559b1b8bc3fSopenharmony_ci    {
560b1b8bc3fSopenharmony_ci        if (insn == nullptr || section == nullptr || section->get_entry_size() == 0) {
561b1b8bc3fSopenharmony_ci            return false;
562b1b8bc3fSopenharmony_ci        }
563b1b8bc3fSopenharmony_ci
564b1b8bc3fSopenharmony_ci        auto size = section->get_size() / section->get_entry_size();
565b1b8bc3fSopenharmony_ci        if (size == 0) {
566b1b8bc3fSopenharmony_ci            return false;
567b1b8bc3fSopenharmony_ci        }
568b1b8bc3fSopenharmony_ci
569b1b8bc3fSopenharmony_ci        ELFIO::Elf64_Addr offset = 0;
570b1b8bc3fSopenharmony_ci        ELFIO::Elf64_Addr symbolValue = 0;
571b1b8bc3fSopenharmony_ci        std::string symbolName;
572b1b8bc3fSopenharmony_ci        ELFIO::Elf_Word type = 0;
573b1b8bc3fSopenharmony_ci        ELFIO::Elf_Sxword addend = 0;
574b1b8bc3fSopenharmony_ci        ELFIO::Elf_Sxword calcValue = 0;
575b1b8bc3fSopenharmony_ci        ELFIO::relocation_section_accessor relocation(elfIo_, section);
576b1b8bc3fSopenharmony_ci        for (size_t i = 0; i < size; i++) {
577b1b8bc3fSopenharmony_ci            relocation.get_entry(i, offset, symbolValue, symbolName, type, addend, calcValue);
578b1b8bc3fSopenharmony_ci            uint32_t index = offset / sizeof(bpf_insn);
579b1b8bc3fSopenharmony_ci            if (insn[index].code != (BPF_LD | BPF_IMM | BPF_DW)) {
580b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("Invalid relo for insn[%{public}u].code 0x%{public}x 0x%{public}x", index,
581b1b8bc3fSopenharmony_ci                               insn[index].code, (BPF_LD | BPF_IMM | BPF_DW));
582b1b8bc3fSopenharmony_ci                continue;
583b1b8bc3fSopenharmony_ci            }
584b1b8bc3fSopenharmony_ci
585b1b8bc3fSopenharmony_ci            size_t mapIdx;
586b1b8bc3fSopenharmony_ci            bool match = false;
587b1b8bc3fSopenharmony_ci            for (mapIdx = 0; mapIdx < maps_.size(); mapIdx++) {
588b1b8bc3fSopenharmony_ci                if (maps_[mapIdx].name == symbolName) {
589b1b8bc3fSopenharmony_ci                    match = true;
590b1b8bc3fSopenharmony_ci                    break;
591b1b8bc3fSopenharmony_ci                }
592b1b8bc3fSopenharmony_ci            }
593b1b8bc3fSopenharmony_ci            if (!match) {
594b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("Invalid relo for insn[%{public}u] no map_data match %{public}s index %{public}zu",
595b1b8bc3fSopenharmony_ci                               index, section->get_name().c_str(), i);
596b1b8bc3fSopenharmony_ci                continue;
597b1b8bc3fSopenharmony_ci            }
598b1b8bc3fSopenharmony_ci            insn[index].src_reg = BPF_PSEUDO_MAP_FD;
599b1b8bc3fSopenharmony_ci            insn[index].imm = maps_[mapIdx].fd;
600b1b8bc3fSopenharmony_ci        }
601b1b8bc3fSopenharmony_ci        return true;
602b1b8bc3fSopenharmony_ci    }
603b1b8bc3fSopenharmony_ci
604b1b8bc3fSopenharmony_ci    int32_t BpfLoadProgram(std::string &progName, bpf_prog_type type, const bpf_insn *insns, size_t insnsCnt)
605b1b8bc3fSopenharmony_ci    {
606b1b8bc3fSopenharmony_ci        if (insns == nullptr) {
607b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
608b1b8bc3fSopenharmony_ci        }
609b1b8bc3fSopenharmony_ci
610b1b8bc3fSopenharmony_ci        bpf_attr attr = {};
611b1b8bc3fSopenharmony_ci        if (memset_s(&attr, sizeof(attr), 0, sizeof(attr)) != EOK) {
612b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
613b1b8bc3fSopenharmony_ci        }
614b1b8bc3fSopenharmony_ci        attr.prog_type = type;
615b1b8bc3fSopenharmony_ci        if (kernVersion_ < 0) {
616b1b8bc3fSopenharmony_ci            return NETMANAGER_ERROR;
617b1b8bc3fSopenharmony_ci        }
618b1b8bc3fSopenharmony_ci        attr.kern_version = static_cast<uint32_t>(kernVersion_);
619b1b8bc3fSopenharmony_ci        attr.insn_cnt = static_cast<uint32_t>(insnsCnt);
620b1b8bc3fSopenharmony_ci        attr.insns = PtrToU64(insns);
621b1b8bc3fSopenharmony_ci        attr.license = PtrToU64(license_.c_str());
622b1b8bc3fSopenharmony_ci        for (const auto &prog : PROG_ATTACH_TYPES) {
623b1b8bc3fSopenharmony_ci            if (prog.progName != nullptr && progName == prog.progName) {
624b1b8bc3fSopenharmony_ci                if (prog.needExpectedAttach) {
625b1b8bc3fSopenharmony_ci                    attr.expected_attach_type = prog.attachType;
626b1b8bc3fSopenharmony_ci                }
627b1b8bc3fSopenharmony_ci                break;
628b1b8bc3fSopenharmony_ci            }
629b1b8bc3fSopenharmony_ci        }
630b1b8bc3fSopenharmony_ci
631b1b8bc3fSopenharmony_ci        return SysBpfProgLoad(&attr, sizeof(attr));
632b1b8bc3fSopenharmony_ci    }
633b1b8bc3fSopenharmony_ci
634b1b8bc3fSopenharmony_ci    static bpf_prog_type ConvertEventToProgType(const std::string &event)
635b1b8bc3fSopenharmony_ci    {
636b1b8bc3fSopenharmony_ci        for (const auto &prog : PROG_TYPES) {
637b1b8bc3fSopenharmony_ci            size_t size = strlen(prog.event);
638b1b8bc3fSopenharmony_ci            if (event.size() < size) {
639b1b8bc3fSopenharmony_ci                continue;
640b1b8bc3fSopenharmony_ci            }
641b1b8bc3fSopenharmony_ci            if (memcmp(event.c_str(), prog.event, size) == 0) {
642b1b8bc3fSopenharmony_ci                return prog.progType;
643b1b8bc3fSopenharmony_ci            }
644b1b8bc3fSopenharmony_ci        }
645b1b8bc3fSopenharmony_ci        return static_cast<bpf_prog_type>(NETMANAGER_ERROR);
646b1b8bc3fSopenharmony_ci    }
647b1b8bc3fSopenharmony_ci
648b1b8bc3fSopenharmony_ci    static bool DoAttach(int32_t progFd, const std::string &progName)
649b1b8bc3fSopenharmony_ci    {
650b1b8bc3fSopenharmony_ci        if (progName.size() < 1) {
651b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("progName is null");
652b1b8bc3fSopenharmony_ci            return false;
653b1b8bc3fSopenharmony_ci        }
654b1b8bc3fSopenharmony_ci        NETNATIVE_LOG_D("The progName = %{public}s", progName.c_str());
655b1b8bc3fSopenharmony_ci
656b1b8bc3fSopenharmony_ci        for (const auto &prog : PROG_ATTACH_TYPES) {
657b1b8bc3fSopenharmony_ci            if (prog.progName != nullptr && progName == prog.progName) {
658b1b8bc3fSopenharmony_ci                int cgroupFd = open(CGROUP_DIR, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
659b1b8bc3fSopenharmony_ci                if (cgroupFd < 0) {
660b1b8bc3fSopenharmony_ci                    NETNATIVE_LOGE("open CGROUP_DIR failed: errno = %{public}d", errno);
661b1b8bc3fSopenharmony_ci                    return false;
662b1b8bc3fSopenharmony_ci                }
663b1b8bc3fSopenharmony_ci
664b1b8bc3fSopenharmony_ci                if (SysBpfObjAttach(prog.attachType, progFd, cgroupFd) < NETSYS_SUCCESS) {
665b1b8bc3fSopenharmony_ci                    NETNATIVE_LOGE("attach %{pubic}s failed: errno = %{public}d", progName.c_str(), errno);
666b1b8bc3fSopenharmony_ci                    close(cgroupFd);
667b1b8bc3fSopenharmony_ci                    return false;
668b1b8bc3fSopenharmony_ci                }
669b1b8bc3fSopenharmony_ci
670b1b8bc3fSopenharmony_ci                close(cgroupFd);
671b1b8bc3fSopenharmony_ci                return true;
672b1b8bc3fSopenharmony_ci            }
673b1b8bc3fSopenharmony_ci        }
674b1b8bc3fSopenharmony_ci
675b1b8bc3fSopenharmony_ci        return true;
676b1b8bc3fSopenharmony_ci    }
677b1b8bc3fSopenharmony_ci
678b1b8bc3fSopenharmony_ci    static void DoDetach(const std::string &progPinLocation, const std::string &progName)
679b1b8bc3fSopenharmony_ci    {
680b1b8bc3fSopenharmony_ci        if (progName.size() < 1) {
681b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("progName is null");
682b1b8bc3fSopenharmony_ci            return;
683b1b8bc3fSopenharmony_ci        }
684b1b8bc3fSopenharmony_ci        NETNATIVE_LOG_D("The progName = %{public}s", progName.c_str());
685b1b8bc3fSopenharmony_ci
686b1b8bc3fSopenharmony_ci        for (const auto &prog : PROG_ATTACH_TYPES) {
687b1b8bc3fSopenharmony_ci            if (prog.progName != nullptr && progName == prog.progName) {
688b1b8bc3fSopenharmony_ci                int cgroupFd = open(CGROUP_DIR, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
689b1b8bc3fSopenharmony_ci                if (cgroupFd < NETSYS_SUCCESS) {
690b1b8bc3fSopenharmony_ci                    NETNATIVE_LOGE("open CGROUP_DIR failed: errno = %{public}d", errno);
691b1b8bc3fSopenharmony_ci                    return;
692b1b8bc3fSopenharmony_ci                }
693b1b8bc3fSopenharmony_ci
694b1b8bc3fSopenharmony_ci                auto progFd = SysBpfObjGet(progPinLocation, 0);
695b1b8bc3fSopenharmony_ci                if (progFd < NETSYS_SUCCESS) {
696b1b8bc3fSopenharmony_ci                    close(cgroupFd);
697b1b8bc3fSopenharmony_ci                    return;
698b1b8bc3fSopenharmony_ci                }
699b1b8bc3fSopenharmony_ci
700b1b8bc3fSopenharmony_ci                if (SysBpfObjDetach(prog.attachType, progFd, cgroupFd) < NETSYS_SUCCESS) {
701b1b8bc3fSopenharmony_ci                    NETNATIVE_LOGE("detach %{pubic}s failed: errno = %{public}d", progName.c_str(), errno);
702b1b8bc3fSopenharmony_ci                    close(cgroupFd);
703b1b8bc3fSopenharmony_ci                    return;
704b1b8bc3fSopenharmony_ci                }
705b1b8bc3fSopenharmony_ci
706b1b8bc3fSopenharmony_ci                close(cgroupFd);
707b1b8bc3fSopenharmony_ci                return;
708b1b8bc3fSopenharmony_ci            }
709b1b8bc3fSopenharmony_ci        }
710b1b8bc3fSopenharmony_ci    }
711b1b8bc3fSopenharmony_ci
712b1b8bc3fSopenharmony_ci    bool LoadProg(const std::string &event, const bpf_insn *insn, size_t insnCnt)
713b1b8bc3fSopenharmony_ci    {
714b1b8bc3fSopenharmony_ci        auto progType = ConvertEventToProgType(event);
715b1b8bc3fSopenharmony_ci        if (progType < NETSYS_SUCCESS) {
716b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("unsupported program type: %{public}s", event.c_str());
717b1b8bc3fSopenharmony_ci            return false;
718b1b8bc3fSopenharmony_ci        }
719b1b8bc3fSopenharmony_ci
720b1b8bc3fSopenharmony_ci        if (insn == nullptr) {
721b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("insn is null");
722b1b8bc3fSopenharmony_ci            return false;
723b1b8bc3fSopenharmony_ci        }
724b1b8bc3fSopenharmony_ci
725b1b8bc3fSopenharmony_ci        std::string progName = event;
726b1b8bc3fSopenharmony_ci        std::replace(progName.begin(), progName.end(), '/', '_');
727b1b8bc3fSopenharmony_ci        int32_t progFd = BpfLoadProgram(progName, progType, insn, insnCnt);
728b1b8bc3fSopenharmony_ci        if (progFd < NETSYS_SUCCESS) {
729b1b8bc3fSopenharmony_ci            NETNATIVE_LOGE("Failed to load bpf prog, error = %{public}d", errno);
730b1b8bc3fSopenharmony_ci            return false;
731b1b8bc3fSopenharmony_ci        }
732b1b8bc3fSopenharmony_ci
733b1b8bc3fSopenharmony_ci        std::string progPinLocation = std::string(PROGS_DIR) + "/" + progName;
734b1b8bc3fSopenharmony_ci        if (access(progPinLocation.c_str(), F_OK) == 0) {
735b1b8bc3fSopenharmony_ci            NETNATIVE_LOGI("prog: %{public}s has already been pinned", progPinLocation.c_str());
736b1b8bc3fSopenharmony_ci        } else {
737b1b8bc3fSopenharmony_ci            if (SysBpfObjPin(progFd, progPinLocation) < NETSYS_SUCCESS) {
738b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("Failed to pin prog: %{public}s, errno = %{public}d", progPinLocation.c_str(), errno);
739b1b8bc3fSopenharmony_ci                close(progFd);
740b1b8bc3fSopenharmony_ci                return false;
741b1b8bc3fSopenharmony_ci            }
742b1b8bc3fSopenharmony_ci        }
743b1b8bc3fSopenharmony_ci
744b1b8bc3fSopenharmony_ci        /* attach socket filter */
745b1b8bc3fSopenharmony_ci        if (progType == BPF_PROG_TYPE_SOCKET_FILTER) {
746b1b8bc3fSopenharmony_ci            if (g_sockFd < 0) {
747b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("create socket failed, %{public}d, err: %{public}d", g_sockFd, errno);
748b1b8bc3fSopenharmony_ci                close(progFd);
749b1b8bc3fSopenharmony_ci                /* return true to ignore this prog */
750b1b8bc3fSopenharmony_ci                return true;
751b1b8bc3fSopenharmony_ci            }
752b1b8bc3fSopenharmony_ci            if (setsockopt(g_sockFd, SOL_SOCKET, SO_ATTACH_BPF, &progFd, sizeof(progFd)) < 0) {
753b1b8bc3fSopenharmony_ci                NETNATIVE_LOGE("attach socket failed, err: %{public}d", errno);
754b1b8bc3fSopenharmony_ci                close(g_sockFd);
755b1b8bc3fSopenharmony_ci                g_sockFd = -1;
756b1b8bc3fSopenharmony_ci            }
757b1b8bc3fSopenharmony_ci            close(progFd);
758b1b8bc3fSopenharmony_ci            return true;
759b1b8bc3fSopenharmony_ci        } else {
760b1b8bc3fSopenharmony_ci            auto ret = DoAttach(progFd, progName);
761b1b8bc3fSopenharmony_ci            close(progFd);
762b1b8bc3fSopenharmony_ci            return ret;
763b1b8bc3fSopenharmony_ci        }
764b1b8bc3fSopenharmony_ci    }
765b1b8bc3fSopenharmony_ci
766b1b8bc3fSopenharmony_ci    bool ParseRelocation()
767b1b8bc3fSopenharmony_ci    {
768b1b8bc3fSopenharmony_ci        return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](auto &section) -> bool {
769b1b8bc3fSopenharmony_ci            if (section->get_type() != ELFIO::SHT_REL) {
770b1b8bc3fSopenharmony_ci                return true;
771b1b8bc3fSopenharmony_ci            }
772b1b8bc3fSopenharmony_ci
773b1b8bc3fSopenharmony_ci            auto info = section->get_info();
774b1b8bc3fSopenharmony_ci            auto progSec = elfIo_.sections[info];
775b1b8bc3fSopenharmony_ci            if (progSec == nullptr) {
776b1b8bc3fSopenharmony_ci                return true;
777b1b8bc3fSopenharmony_ci            }
778b1b8bc3fSopenharmony_ci
779b1b8bc3fSopenharmony_ci            if (progSec->get_type() != ELFIO::SHT_PROGBITS || ((progSec->get_flags() & ELFIO::SHF_EXECINSTR) == 0)) {
780b1b8bc3fSopenharmony_ci                return true;
781b1b8bc3fSopenharmony_ci            }
782b1b8bc3fSopenharmony_ci
783b1b8bc3fSopenharmony_ci            auto insn = reinterpret_cast<bpf_insn *>(const_cast<char *>(progSec->get_data()));
784b1b8bc3fSopenharmony_ci            if (insn == nullptr) {
785b1b8bc3fSopenharmony_ci                return false;
786b1b8bc3fSopenharmony_ci            }
787b1b8bc3fSopenharmony_ci            if (!ApplyRelocation(insn, section.get())) {
788b1b8bc3fSopenharmony_ci                return false;
789b1b8bc3fSopenharmony_ci            }
790b1b8bc3fSopenharmony_ci            return true;
791b1b8bc3fSopenharmony_ci        });
792b1b8bc3fSopenharmony_ci    }
793b1b8bc3fSopenharmony_ci
794b1b8bc3fSopenharmony_ci    bool UnloadProgs()
795b1b8bc3fSopenharmony_ci    {
796b1b8bc3fSopenharmony_ci        if (g_sockFd > 0) {
797b1b8bc3fSopenharmony_ci            close(g_sockFd);
798b1b8bc3fSopenharmony_ci            g_sockFd = -1;
799b1b8bc3fSopenharmony_ci        }
800b1b8bc3fSopenharmony_ci        return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](const auto &section) -> bool {
801b1b8bc3fSopenharmony_ci            if (!MatchSecName(section->get_name())) {
802b1b8bc3fSopenharmony_ci                return true;
803b1b8bc3fSopenharmony_ci            }
804b1b8bc3fSopenharmony_ci
805b1b8bc3fSopenharmony_ci            std::string progName = section->get_name();
806b1b8bc3fSopenharmony_ci            std::replace(progName.begin(), progName.end(), '/', '_');
807b1b8bc3fSopenharmony_ci            std::string progPinLocation = std::string(PROGS_DIR) + "/" + progName;
808b1b8bc3fSopenharmony_ci            if (access(progPinLocation.c_str(), F_OK) == 0) {
809b1b8bc3fSopenharmony_ci                DoDetach(progPinLocation, progName);
810b1b8bc3fSopenharmony_ci
811b1b8bc3fSopenharmony_ci                return UnPin(progPinLocation) < NETSYS_SUCCESS ? false : true;
812b1b8bc3fSopenharmony_ci            }
813b1b8bc3fSopenharmony_ci            return true;
814b1b8bc3fSopenharmony_ci        });
815b1b8bc3fSopenharmony_ci    }
816b1b8bc3fSopenharmony_ci
817b1b8bc3fSopenharmony_ci    bool LoadProgs()
818b1b8bc3fSopenharmony_ci    {
819b1b8bc3fSopenharmony_ci        if (g_sockFd > 0) {
820b1b8bc3fSopenharmony_ci            close(g_sockFd);
821b1b8bc3fSopenharmony_ci        }
822b1b8bc3fSopenharmony_ci        g_sockFd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
823b1b8bc3fSopenharmony_ci        return std::all_of(elfIo_.sections.begin(), elfIo_.sections.end(), [this](const auto &section) -> bool {
824b1b8bc3fSopenharmony_ci            if (!MatchSecName(section->get_name())) {
825b1b8bc3fSopenharmony_ci                return true;
826b1b8bc3fSopenharmony_ci            }
827b1b8bc3fSopenharmony_ci            return LoadProg(section->get_name(), reinterpret_cast<const bpf_insn *>(section->get_data()),
828b1b8bc3fSopenharmony_ci                            section->get_size() / sizeof(bpf_insn));
829b1b8bc3fSopenharmony_ci        });
830b1b8bc3fSopenharmony_ci    }
831b1b8bc3fSopenharmony_ci
832b1b8bc3fSopenharmony_ci    std::string path_;
833b1b8bc3fSopenharmony_ci    ELFIO::elfio elfIo_;
834b1b8bc3fSopenharmony_ci    std::string license_;
835b1b8bc3fSopenharmony_ci    int32_t kernVersion_;
836b1b8bc3fSopenharmony_ci    std::vector<BpfMapData> maps_;
837b1b8bc3fSopenharmony_ci
838b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> isPathValid_ = [this]() -> ElfLoadError {
839b1b8bc3fSopenharmony_ci        if (!IsPathValid()) {
840b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_PATH_INVALID;
841b1b8bc3fSopenharmony_ci        }
842b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
843b1b8bc3fSopenharmony_ci    };
844b1b8bc3fSopenharmony_ci
845b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> makeDirectories = []() -> ElfLoadError {
846b1b8bc3fSopenharmony_ci        if (!MakeDirectories()) {
847b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_MAKE_DIR_FAIL;
848b1b8bc3fSopenharmony_ci        }
849b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
850b1b8bc3fSopenharmony_ci    };
851b1b8bc3fSopenharmony_ci
852b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> loadElfFile_ = [this]() -> ElfLoadError {
853b1b8bc3fSopenharmony_ci        if (!LoadElfFile()) {
854b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_LOAD_FILE_FAIL;
855b1b8bc3fSopenharmony_ci        }
856b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
857b1b8bc3fSopenharmony_ci    };
858b1b8bc3fSopenharmony_ci
859b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> isVersionValid_ = [this]() -> ElfLoadError {
860b1b8bc3fSopenharmony_ci        if (!IsVersionValid()) {
861b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_GET_VERSION_FAIL;
862b1b8bc3fSopenharmony_ci        }
863b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
864b1b8bc3fSopenharmony_ci    };
865b1b8bc3fSopenharmony_ci
866b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> setLicenseAndVersion_ = [this]() -> ElfLoadError {
867b1b8bc3fSopenharmony_ci        if (!SetLicenseAndVersion()) {
868b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_SELECT_LICENSE_AND_VERSION_FAIL;
869b1b8bc3fSopenharmony_ci        }
870b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
871b1b8bc3fSopenharmony_ci    };
872b1b8bc3fSopenharmony_ci
873b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> loadElfMapsSection_ = [this]() -> ElfLoadError {
874b1b8bc3fSopenharmony_ci        if (!LoadElfMapsSection()) {
875b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_LOAD_MAP_SECTION_FAIL;
876b1b8bc3fSopenharmony_ci        }
877b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
878b1b8bc3fSopenharmony_ci    };
879b1b8bc3fSopenharmony_ci
880b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> setRlimit_ = []() -> ElfLoadError {
881b1b8bc3fSopenharmony_ci        if (!SetRlimit()) {
882b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_SET_RLIMIT_FAIL;
883b1b8bc3fSopenharmony_ci        }
884b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
885b1b8bc3fSopenharmony_ci    };
886b1b8bc3fSopenharmony_ci
887b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> createMaps_ = [this]() -> ElfLoadError {
888b1b8bc3fSopenharmony_ci        if (!CreateMaps()) {
889b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_CREATE_MAP_FAIL;
890b1b8bc3fSopenharmony_ci        }
891b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
892b1b8bc3fSopenharmony_ci    };
893b1b8bc3fSopenharmony_ci
894b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> parseRelocation_ = [this]() -> ElfLoadError {
895b1b8bc3fSopenharmony_ci        if (!ParseRelocation()) {
896b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_PARSE_RELOCATION_FAIL;
897b1b8bc3fSopenharmony_ci        }
898b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
899b1b8bc3fSopenharmony_ci    };
900b1b8bc3fSopenharmony_ci
901b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> loadProgs_ = [this]() -> ElfLoadError {
902b1b8bc3fSopenharmony_ci        if (!LoadProgs()) {
903b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_LOAD_PROGS_FAIL;
904b1b8bc3fSopenharmony_ci        }
905b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
906b1b8bc3fSopenharmony_ci    };
907b1b8bc3fSopenharmony_ci
908b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> deleteMaps_ = [this]() -> ElfLoadError {
909b1b8bc3fSopenharmony_ci        if (!DeleteMaps()) {
910b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_DELETE_MAP_FAIL;
911b1b8bc3fSopenharmony_ci        }
912b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
913b1b8bc3fSopenharmony_ci    };
914b1b8bc3fSopenharmony_ci
915b1b8bc3fSopenharmony_ci    std::function<ElfLoadError()> unloadProgs_ = [this]() -> ElfLoadError {
916b1b8bc3fSopenharmony_ci        if (!UnloadProgs()) {
917b1b8bc3fSopenharmony_ci            return ELF_LOAD_ERR_UNLOAD_PROGS_FAIL;
918b1b8bc3fSopenharmony_ci        }
919b1b8bc3fSopenharmony_ci        return ELF_LOAD_ERR_NONE;
920b1b8bc3fSopenharmony_ci    };
921b1b8bc3fSopenharmony_ci};
922b1b8bc3fSopenharmony_ci
923b1b8bc3fSopenharmony_ciElfLoadError LoadElf(const std::string &elfPath)
924b1b8bc3fSopenharmony_ci{
925b1b8bc3fSopenharmony_ci    ElfLoader loader(elfPath);
926b1b8bc3fSopenharmony_ci    return loader.Load();
927b1b8bc3fSopenharmony_ci}
928b1b8bc3fSopenharmony_ci
929b1b8bc3fSopenharmony_ciElfLoadError UnloadElf(const std::string &elfPath)
930b1b8bc3fSopenharmony_ci{
931b1b8bc3fSopenharmony_ci    ElfLoader loader(elfPath);
932b1b8bc3fSopenharmony_ci    return loader.Unload();
933b1b8bc3fSopenharmony_ci}
934b1b8bc3fSopenharmony_ci} // namespace OHOS::NetManagerStandard
935