1 /*
2  * Copyright (c) 2022 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 "traffic_manager.h"
17 
18 #include <algorithm>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <net/if.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <sys/un.h>
25 #include <unistd.h>
26 
27 #include "net_manager_native.h"
28 #include "netnative_log_wrapper.h"
29 #include "securec.h"
30 
31 namespace OHOS {
32 namespace nmd {
33 namespace {
34 constexpr const char *INTERFACE_LIST_DIR = "/sys/class/net/";
35 constexpr const char *STATISTICS = "statistics";
36 constexpr const char *RX_BYTES = "rx_bytes";
37 constexpr const char *TX_BYTES = "tx_bytes";
38 constexpr const char *RX_PACKETS = "rx_packets";
39 constexpr const char *TX_PACKETS = "tx_packets";
40 } // namespace
41 
GetInterfaceList()42 std::vector<std::string> GetInterfaceList()
43 {
44     DIR *dir(nullptr);
45     struct dirent *ptr(nullptr);
46     std::vector<std::string> ifList;
47 
48     dir = opendir(INTERFACE_LIST_DIR);
49     if (dir == nullptr) {
50         NETNATIVE_LOGE("GetInterfaceList open %{private}s failed", INTERFACE_LIST_DIR);
51         return ifList;
52     }
53 
54     ptr = readdir(dir);
55     while (ptr != nullptr) {
56         if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
57             ifList.push_back(ptr->d_name);
58         }
59         ptr = readdir(dir);
60     }
61     closedir(dir);
62 
63     return ifList;
64 }
65 
GetInterfaceTrafficByType(const std::string & path,const std::string & type)66 long GetInterfaceTrafficByType(const std::string &path, const std::string &type)
67 {
68     if (path.empty()) {
69         return -1;
70     }
71 
72     std::string trafficPath = path + type;
73 
74     char tmpPath[PATH_MAX] = {0};
75     if (!realpath(trafficPath.c_str(), tmpPath)) {
76         NETNATIVE_LOGE("file name is illegal");
77         return -1;
78     }
79 
80     int fd = open(tmpPath, 0, 0666);
81     if (fd == -1) {
82         NETNATIVE_LOGE("GetInterfaceTrafficByType open %{private}s failed", INTERFACE_LIST_DIR);
83         return -1;
84     }
85 
86     char buf[100] = {0};
87     int nread = read(fd, buf, sizeof(long));
88     if (nread == -1) {
89         NETNATIVE_LOGE("GetInterfaceTrafficByType read %{private}s failed", INTERFACE_LIST_DIR);
90         close(fd);
91         return -1;
92     }
93     close(fd);
94 
95     return atol(buf);
96 }
97 
GetAllRxTraffic()98 long TrafficManager::GetAllRxTraffic()
99 {
100     std::vector<std::string> ifNameList = GetInterfaceList();
101     if (ifNameList.empty()) {
102         return 0;
103     }
104 
105     long allRxBytes = 0;
106     for (auto iter = ifNameList.begin(); iter != ifNameList.end(); iter++) {
107         if (*iter != "lo") {
108             std::string baseTrafficPath = INTERFACE_LIST_DIR + (*iter) + "/" + STATISTICS + "/";
109             long rxBytes = GetInterfaceTrafficByType(baseTrafficPath, RX_BYTES);
110             allRxBytes += rxBytes;
111         }
112     }
113     return allRxBytes;
114 }
115 
GetAllTxTraffic()116 long TrafficManager::GetAllTxTraffic()
117 {
118     std::vector<std::string> ifNameList = GetInterfaceList();
119     if (ifNameList.empty()) {
120         return 0;
121     }
122 
123     long allTxBytes = 0;
124     for (auto iter = ifNameList.begin(); iter != ifNameList.end(); iter++) {
125         if (*iter != "lo") {
126             std::string baseTrafficPath = INTERFACE_LIST_DIR + (*iter) + "/" + STATISTICS + "/";
127             long txBytes = GetInterfaceTrafficByType(baseTrafficPath, TX_BYTES);
128             allTxBytes = allTxBytes + txBytes;
129         }
130     }
131     return allTxBytes;
132 }
133 
GetInterfaceTraffic(const std::string & ifName)134 TrafficStatsParcel TrafficManager::GetInterfaceTraffic(const std::string &ifName)
135 {
136     nmd::TrafficStatsParcel interfaceTrafficBytes = {"", 0, 0, 0, 0, 0};
137     std::vector<std::string> ifNameList = GetInterfaceList();
138     if (ifNameList.empty()) {
139         return interfaceTrafficBytes;
140     }
141     for (auto iter = ifNameList.begin(); iter != ifNameList.end(); iter++) {
142         if (ifName != *iter) {
143             continue;
144         }
145         std::string baseTrafficPath = INTERFACE_LIST_DIR + (*iter) + "/" + STATISTICS + "/";
146         long infRxBytes = GetInterfaceTrafficByType(baseTrafficPath, RX_BYTES);
147         long infRxPackets = GetInterfaceTrafficByType(baseTrafficPath, RX_PACKETS);
148         long infTxBytes = GetInterfaceTrafficByType(baseTrafficPath, TX_BYTES);
149         long infTxPackets = GetInterfaceTrafficByType(baseTrafficPath, TX_PACKETS);
150 
151         interfaceTrafficBytes.iface = ifName;
152         interfaceTrafficBytes.ifIndex = if_nametoindex(ifName.c_str());
153 
154         interfaceTrafficBytes.rxBytes = infRxBytes == -1 ? 0 : infRxBytes;
155         interfaceTrafficBytes.rxPackets = infRxPackets == -1 ? 0 : infRxPackets;
156         interfaceTrafficBytes.txBytes = infTxBytes == -1 ? 0 : infTxBytes;
157         interfaceTrafficBytes.txPackets = infTxPackets == -1 ? 0 : infTxPackets;
158     }
159     return interfaceTrafficBytes;
160 }
161 } // namespace nmd
162 } // namespace OHOS
163