1 /*
2  * Copyright (c) 2023 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 #ifndef CONNECTIVITY_EXT_BPF_MAPPER_H
17 #define CONNECTIVITY_EXT_BPF_MAPPER_H
18 
19 #include <cerrno>
20 #include <linux/bpf.h>
21 #include <linux/unistd.h>
22 #include <cstdint>
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <string>
26 #include <unistd.h>
27 #include <functional>
28 #include <linux/bpf.h>
29 #include <linux/if_ether.h>
30 #include <linux/unistd.h>
31 #include <memory>
32 #include <string>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <vector>
36 
37 #include "net_manager_constants.h"
38 #include "netnative_log_wrapper.h"
39 #include "securec.h"
40 
41 namespace OHOS::NetManagerStandard {
42 template <class Key, class Value> class BpfMapperImplement {
43 public:
44     BpfMapperImplement<Key, Value>() = default;
45 
GetFirstKey(const int32_t mapFd,Key & key)46     static int32_t GetFirstKey(const int32_t mapFd, Key &key)
47     {
48         bpf_attr bpfAttr{};
49         if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) {
50             return NETMANAGER_ERROR;
51         }
52         bpfAttr.map_fd = BpfFdToU32(mapFd);
53         bpfAttr.key = 0;
54         bpfAttr.next_key = BpfMapKeyToU64(key);
55         return BpfSyscall(BPF_MAP_GET_NEXT_KEY, bpfAttr);
56     }
57 
58     /**
59      * Get the Next Key From Map
60      *
61      * @param mapFd map fd
62      * @param key the key of Bpf Map
63      * @param next_key the key of Bpf Map
64      * @return int32_t return next key
65      */
GetNextKey(const int32_t mapFd,const Key & key,Key & nextKey)66     static int32_t GetNextKey(const int32_t mapFd, const Key &key, Key &nextKey)
67     {
68         bpf_attr bpfAttr{};
69         if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) {
70             return NETMANAGER_ERROR;
71         }
72         bpfAttr.map_fd = BpfFdToU32(mapFd);
73         bpfAttr.key = BpfMapKeyToU64(key);
74         bpfAttr.next_key = BpfMapKeyToU64(nextKey);
75         return BpfSyscall(BPF_MAP_GET_NEXT_KEY, bpfAttr);
76     }
77 
78     /**
79      * Bpf Syscall
80      *
81      * @param cmd which command need to execute
82      * @param attr union consists of various anonymous structures
83      * @return int32_t return the result of executing the command
84      */
BpfSyscall(int32_t cmd,const bpf_attr & attr)85     static int32_t BpfSyscall(int32_t cmd, const bpf_attr &attr)
86     {
87         return static_cast<int32_t>(syscall(__NR_bpf, cmd, &attr, sizeof(attr)));
88     }
89 
90     /**
91      * Write Value To Bpf Map
92      *
93      * @param mapFd map fd
94      * @param key the key of Bpf Map
95      * @param value the value of Bpf Map
96      * @param flags map flag
97      * @return int32_t 0:write success -1:failure
98      */
UpdateElem(const int32_t mapFd,const Key & key,const Value & value,uint64_t flags)99     static int32_t UpdateElem(const int32_t mapFd, const Key &key, const Value &value, uint64_t flags)
100     {
101         bpf_attr bpfAttr{};
102         if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) {
103             return NETMANAGER_ERROR;
104         }
105         bpfAttr.map_fd = BpfFdToU32(mapFd);
106         bpfAttr.key = BpfMapKeyToU64(key);
107         bpfAttr.value = BpfMapValueToU64(value);
108         bpfAttr.flags = flags;
109         return BpfSyscall(BPF_MAP_UPDATE_ELEM, bpfAttr);
110     }
111 
112     /**
113      * LookUp Elem From Map
114      *
115      * @param mapFd map fd
116      * @param key the key of Bpf Map
117      * @param value the value of Bpf Map
118      * @return int32_t 0:find success -1:failure
119      */
LookUpElem(const int32_t mapFd,const Key & key,const Value & value)120     static int32_t LookUpElem(const int32_t mapFd, const Key &key, const Value &value)
121     {
122         bpf_attr bpfAttr{};
123         if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) {
124             return NETMANAGER_ERROR;
125         }
126         bpfAttr.map_fd = BpfFdToU32(mapFd);
127         bpfAttr.key = BpfMapKeyToU64(key);
128         bpfAttr.value = BpfMapValueToU64(value);
129         return BpfSyscall(BPF_MAP_LOOKUP_ELEM, bpfAttr);
130     }
131 
132     /**
133      * Delete Elem From Map
134      *
135      * @param mapFd map fd
136      * @param key the key of Bpf Map
137      * @return int32_t 0:delete success -1:failure
138      */
DeleteElem(const int32_t mapFd,const Key & key)139     static int32_t DeleteElem(const int32_t mapFd, const Key &key)
140     {
141         bpf_attr bpfAttr{};
142         if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) {
143             return NETMANAGER_ERROR;
144         }
145         bpfAttr.map_fd = BpfFdToU32(mapFd);
146         bpfAttr.key = BpfMapKeyToU64(key);
147         return BpfSyscall(BPF_MAP_DELETE_ELEM, bpfAttr);
148     }
149 
150     /**
151      * Get Bpf Object By PathName
152      *
153      * @param pathName bpf map path
154      * @param fileFlags file flags
155      * @return int32_t return map file descriptor
156      */
BpfObjGet(const std::string & pathName,uint32_t fileFlags)157     static int32_t BpfObjGet(const std::string &pathName, uint32_t fileFlags)
158     {
159         bpf_attr bpfAttr{};
160         if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) {
161             return NETMANAGER_ERROR;
162         }
163         bpfAttr.pathname = BpfMapPathNameToU64(pathName);
164         bpfAttr.file_flags = fileFlags;
165         return BpfSyscall(BPF_OBJ_GET, bpfAttr);
166     }
167 
168     /**
169      * Get the Map Fd
170      *
171      * @param pathName bpf map path
172      * @param objFlags obj flags
173      * @return int32_t return map file descriptor
174      */
GetMap(const std::string & pathName,uint32_t objFlags)175     static int32_t GetMap(const std::string &pathName, uint32_t objFlags)
176     {
177         return BpfObjGet(pathName, objFlags);
178     }
179 
180 private:
BpfFdToU32(const int32_t mapFd)181     static uint32_t BpfFdToU32(const int32_t mapFd)
182     {
183         return static_cast<uint32_t>(mapFd);
184     }
185 
BpfMapPathNameToU64(const std::string & pathName)186     static uint64_t BpfMapPathNameToU64(const std::string &pathName)
187     {
188         return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pathName.c_str()));
189     }
190 
BpfMapKeyToU64(const Key & key)191     static uint64_t BpfMapKeyToU64(const Key &key)
192     {
193         return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&key));
194     }
195 
BpfMapValueToU64(const Value & value)196     static uint64_t BpfMapValueToU64(const Value &value)
197     {
198         return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&value));
199     }
200 };
201 
202 template <class Key, class Value> class BpfMapper {
203 public:
204     BpfMapper<Key, Value>() = default;
~BpfMapper()205     ~BpfMapper<Key, Value>()
206     {
207         if (mapFd_ != NETMANAGER_ERROR) {
208             close(mapFd_);
209             mapFd_ = NETMANAGER_ERROR;
210         }
211     }
212     BpfMapper<Key, Value>(const std::string &pathName, uint32_t flags)
213     {
214         mapFd_ = NETMANAGER_ERROR;
215         int32_t mapFd = BpfMapperImplement<Key, Value>::GetMap(pathName, flags);
216         if (mapFd >= 0) {
217             mapFd_ = mapFd;
218         }
219     }
220 
221     /**
222      * Is has map fd
223      *
224      * @return bool true:has map fd false:not have
225      */
IsValid()226     [[nodiscard]] bool IsValid() const
227     {
228         return mapFd_ >= 0;
229     }
230 
231     /**
232      * Read Value From Map
233      *
234      * @param key the key of map
235      * @return Value value corresponding to key
236      */
Read(const Key & key,Value & val)237     [[nodiscard]] int32_t Read(const Key &key, Value &val) const
238     {
239         Value value{};
240         if (BpfMapperImplement<Key, Value>::LookUpElem(mapFd_, key, value) < 0) {
241             return NETMANAGER_ERROR;
242         }
243         val = value;
244         return 0;
245     }
246 
247     /**
248      * WriteValue
249      *
250      * @param key the key want to write
251      * @param value the value want to write
252      * @param flags map flag
253      * @return int32_t 0 if OK
254      */
Write(const Key & key,const Value & value,uint64_t flags)255     [[nodiscard]] int32_t Write(const Key &key, const Value &value, uint64_t flags) const
256     {
257         return BpfMapperImplement<Key, Value>::UpdateElem(mapFd_, key, value, flags);
258     }
259 
260     /**
261      * Get all keys
262      *
263      * @return key of list
264      */
GetAllKeys()265     [[nodiscard]] std::vector<Key> GetAllKeys() const
266     {
267         Key key{};
268         if (BpfMapperImplement<Key, Value>::GetFirstKey(mapFd_, key) < 0) {
269             return {};
270         }
271         std::vector<Key> keys;
272         keys.emplace_back(key);
273 
274         Key nextKey{};
275         while (BpfMapperImplement<Key, Value>::GetNextKey(mapFd_, key, nextKey) >= 0) {
276             key = nextKey;
277             keys.emplace_back(key);
278         }
279         return keys;
280     }
281 
Clear(const std::vector<Key> & keys)282     [[nodiscard]] int32_t Clear(const std::vector<Key> &keys) const
283     {
284         for (const auto &k : keys) {
285             if (Delete(k) < NETSYS_SUCCESS) {
286                 return NETMANAGER_ERROR;
287             }
288         }
289         return 0;
290     }
291 
292     /**
293      * DeleteEntryFromMap
294      *
295      * @param deleteKey the key need to delete
296      * @return int32_t 0 if OK
297      */
Delete(const Key & deleteKey)298     [[nodiscard]] int32_t Delete(const Key &deleteKey) const
299     {
300         return BpfMapperImplement<Key, Value>::DeleteElem(mapFd_, deleteKey);
301     }
302 
303 private:
304     int32_t mapFd_ = NETMANAGER_ERROR;
305 };
306 } // namespace OHOS::NetManagerStandard
307 #endif /* CONNECTIVITY_EXT_BPF_MAPPER_H */
308