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