1 /*
2  * Copyright (c) 2022-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 #include <net/if.h>
17 #include <vector>
18 
19 #include "bpf_path.h"
20 #include "bpf_def.h"
21 #include "bpf_stats.h"
22 #include "securec.h"
23 #include "netnative_log_wrapper.h"
24 #include "net_stats_constants.h"
25 
26 namespace OHOS::NetManagerStandard {
27 namespace {
28 constexpr const char *CELLULAR_IFACE = "rmnet0";
29 constexpr const char *WIFI_IFACE = "wlan0";
30 }
GetNumberFromStatsValue(uint64_t &stats, StatsType statsType, const stats_value &value)31 int32_t NetsysBpfStats::GetNumberFromStatsValue(uint64_t &stats, StatsType statsType, const stats_value &value)
32 {
33     switch (statsType) {
34         case StatsType::STATS_TYPE_RX_BYTES:
35             stats = value.rxBytes;
36             break;
37         case StatsType::STATS_TYPE_RX_PACKETS:
38             stats = value.rxPackets;
39             break;
40         case StatsType::STATS_TYPE_TX_BYTES:
41             stats = value.txBytes;
42             break;
43         case StatsType::STATS_TYPE_TX_PACKETS:
44             stats = value.txPackets;
45             break;
46         default:
47             NETNATIVE_LOGE("invalid StatsType type %{public}d", statsType);
48             return STATS_ERR_READ_BPF_FAIL;
49     }
50     return NETSYS_SUCCESS;
51 }
52 
GetTotalStats(uint64_t &stats, StatsType statsType)53 int32_t NetsysBpfStats::GetTotalStats(uint64_t &stats, StatsType statsType)
54 {
55     stats = 0;
56     BpfMapper<iface_stats_key, iface_stats_value> ifaceStatsMap(IFACE_STATS_MAP_PATH, BPF_F_RDONLY);
57     if (!ifaceStatsMap.IsValid()) {
58         NETNATIVE_LOGE("ifaceStatsMap IsValid");
59         return STATS_ERR_INVALID_IFACE_NAME_MAP;
60     }
61 
62     iface_stats_value totalStats = {0};
63     auto keys = ifaceStatsMap.GetAllKeys();
64     for (const auto &k : keys) {
65         iface_stats_value v = {0};
66         if (ifaceStatsMap.Read(k, v) < NETSYS_SUCCESS) {
67             NETNATIVE_LOGE("Read ifaceStatsMap err");
68             return STATS_ERR_READ_BPF_FAIL;
69         }
70         totalStats.rxPackets += v.rxPackets;
71         totalStats.rxBytes += v.rxBytes;
72         totalStats.txPackets += v.txPackets;
73         totalStats.txBytes += v.txBytes;
74     }
75 
76     return GetNumberFromStatsValue(stats, statsType, totalStats);
77 }
78 
GetUidStats(uint64_t &stats, StatsType statsType, uint32_t uid)79 int32_t NetsysBpfStats::GetUidStats(uint64_t &stats, StatsType statsType, uint32_t uid)
80 {
81     stats = 0;
82     BpfMapper<app_uid_stats_key, app_uid_stats_value> appUidStatsMap(APP_UID_STATS_MAP_PATH, BPF_F_RDONLY);
83     if (!appUidStatsMap.IsValid()) {
84         return STATS_ERR_INVALID_IFACE_NAME_MAP;
85     }
86 
87     app_uid_stats_value uidStats = {0};
88     if (appUidStatsMap.Read(uid, uidStats) < 0) {
89         return STATS_ERR_READ_BPF_FAIL;
90     }
91     return GetNumberFromStatsValue(stats, statsType, uidStats);
92 }
93 
GetAllSimStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)94 int32_t NetsysBpfStats::GetAllSimStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)
95 {
96     BpfMapper<stats_key, stats_value> uidSimStatsMap(APP_UID_SIM_STATS_MAP_PATH, BPF_F_RDONLY);
97     if (!uidSimStatsMap.IsValid()) {
98         return STATS_ERR_INVALID_IFACE_NAME_MAP;
99     }
100 
101     stats.clear();
102     char if_name[IFNAME_SIZE] = {0};
103     auto keys = uidSimStatsMap.GetAllKeys();
104     for (const auto &k : keys) {
105         stats_value v = {};
106         if (uidSimStatsMap.Read(k, v) < 0) {
107             NETNATIVE_LOGE("Read uid_sim_map err");
108             return STATS_ERR_READ_BPF_FAIL;
109         }
110 
111         NetStatsInfo tempStats;
112         tempStats.uid_ = k.uId;
113         if (memset_s(if_name, sizeof(if_name), 0, sizeof(if_name)) != EOK) {
114             return STATS_ERR_READ_BPF_FAIL;
115         }
116 
117         char *pName = if_indextoname(k.ifIndex, if_name);
118         if (pName != nullptr) {
119             tempStats.iface_ = pName;
120         }
121         if (k.ifType == IFACE_TYPE_WIFI) {
122             tempStats.iface_ = WIFI_IFACE;
123         } else if (k.ifType == IFACE_TYPE_CELLULAR) {
124             tempStats.iface_ = CELLULAR_IFACE;
125         }
126         tempStats.rxBytes_ = v.rxBytes;
127         tempStats.txBytes_ = v.txBytes;
128         tempStats.rxPackets_ = v.rxPackets;
129         tempStats.txPackets_ = v.txPackets;
130         auto findRet = std::find_if(stats.begin(), stats.end(),
131                                     [&tempStats](const NetStatsInfo &info) { return info.Equals(tempStats); });
132         if (findRet == stats.end()) {
133             stats.push_back(std::move(tempStats));
134         } else {
135             *findRet += tempStats;
136         }
137     }
138 
139     return NETSYS_SUCCESS;
140 }
141 
GetAllStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)142 int32_t NetsysBpfStats::GetAllStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)
143 {
144     BpfMapper<stats_key, stats_value> uidIfaceStatsMap(APP_UID_IF_STATS_MAP_PATH, BPF_F_RDONLY);
145     if (!uidIfaceStatsMap.IsValid()) {
146         return STATS_ERR_INVALID_IFACE_NAME_MAP;
147     }
148 
149     stats.clear();
150     char if_name[IFNAME_SIZE] = {0};
151     auto keys = uidIfaceStatsMap.GetAllKeys();
152     for (const auto &k : keys) {
153         stats_value v = {};
154         if (uidIfaceStatsMap.Read(k, v) < 0) {
155             NETNATIVE_LOGE("Read ifaceStatsMap err");
156             return STATS_ERR_READ_BPF_FAIL;
157         }
158 
159         NetStatsInfo tempStats;
160         tempStats.uid_ = k.uId;
161         if (memset_s(if_name, sizeof(if_name), 0, sizeof(if_name)) != EOK) {
162             return STATS_ERR_READ_BPF_FAIL;
163         }
164 
165         char *pName = if_indextoname(k.ifIndex, if_name);
166         if (pName != nullptr) {
167             tempStats.iface_ = pName;
168         }
169         tempStats.rxBytes_ = v.rxBytes;
170         tempStats.txBytes_ = v.txBytes;
171         tempStats.rxPackets_ = v.rxPackets;
172         tempStats.txPackets_ = v.txPackets;
173         stats.emplace_back(std::move(tempStats));
174     }
175 
176     return NETSYS_SUCCESS;
177 }
178 
DeleteStatsInfo(const std::string &path, uint32_t uid)179 int32_t NetsysBpfStats::DeleteStatsInfo(const std::string &path, uint32_t uid)
180 {
181     if (path != APP_UID_IF_STATS_MAP_PATH && path != APP_UID_SIM_STATS_MAP_PATH) {
182         NETNATIVE_LOGI("DeleteStatsInfo invalid path");
183         return NETSYS_SUCCESS;
184     }
185     BpfMapper<stats_key, stats_value> uidStatsMap(path, BPF_ANY);
186     if (!uidStatsMap.IsValid()) {
187         return STATS_ERR_INVALID_IFACE_NAME_MAP;
188     }
189     auto keys = uidStatsMap.GetAllKeys();
190     for (const auto &k : keys) {
191         if (k.uId == uid) {
192             if (uidStatsMap.Delete(k) < 0) {
193                 NETNATIVE_LOGE("Delete uidStatsMap err");
194                 return STATS_ERR_WRITE_BPF_FAIL;
195             }
196         }
197     }
198     return NETSYS_SUCCESS;
199 }
200 
GetIfaceStats(uint64_t &stats, const StatsType statsType, const std::string &interfaceName)201 int32_t NetsysBpfStats::GetIfaceStats(uint64_t &stats, const StatsType statsType, const std::string &interfaceName)
202 {
203     stats = 0;
204     BpfMapper<iface_stats_key, iface_stats_value> ifaceStatsMap(IFACE_STATS_MAP_PATH, BPF_F_RDONLY);
205     if (!ifaceStatsMap.IsValid()) {
206         return STATS_ERR_INVALID_IFACE_NAME_MAP;
207     }
208 
209     auto ifIndex = if_nametoindex(interfaceName.c_str());
210     if (ifIndex <= 0) {
211         return STATS_ERR_GET_IFACE_NAME_FAILED;
212     }
213 
214     iface_stats_value ifaceStats = {0};
215     if (ifaceStatsMap.Read(ifIndex, ifaceStats) < 0) {
216         return STATS_ERR_READ_BPF_FAIL;
217     }
218     return GetNumberFromStatsValue(stats, statsType, ifaceStats);
219 }
220 
GetCookieStats(uint64_t &stats, StatsType statsType, uint64_t cookie)221 int32_t NetsysBpfStats::GetCookieStats(uint64_t &stats, StatsType statsType, uint64_t cookie)
222 {
223     NETNATIVE_LOGI("GetCookieStats start");
224     stats = 0;
225     BpfMapper<socket_cookie_stats_key, app_cookie_stats_value> appUidCookieStatsMap(APP_COOKIE_STATS_MAP_PATH,
226                                                                                     BPF_F_RDONLY);
227     if (!appUidCookieStatsMap.IsValid()) {
228         NETNATIVE_LOGE("GetCookieStats appUidCookieStatsMap is valid");
229         return NETMANAGER_ERR_INTERNAL;
230     }
231 
232     app_cookie_stats_value cookieStats = {0};
233     if (appUidCookieStatsMap.Read(cookie, cookieStats) < 0) {
234         NETNATIVE_LOGE("GetCookieStats appUidCookieStatsMap read error");
235         return NETMANAGER_ERR_INTERNAL;
236     }
237 
238     int32_t res = GetNumberFromStatsValue(stats, statsType, cookieStats);
239     if (res == STATS_ERR_READ_BPF_FAIL) {
240         NETNATIVE_LOGE("GetCookieStats GetNumberFromStatsValue error");
241         return NETMANAGER_ERR_INTERNAL;
242     }
243     return NETSYS_SUCCESS;
244 }
245 } // namespace OHOS::NetManagerStandard
246