1 /*
2 * Copyright (C) 2021 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 #include "network_interface.h"
16 #include <arpa/inet.h>
17 #include <cerrno>
18 #include <cstdlib>
19 #include <cstring>
20 #include <string>
21 #include <net/if.h>
22 #include <netdb.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <typeinfo>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "securec.h"
31 #include "wifi_logger.h"
32
33 DEFINE_WIFILOG_LABEL("WifiNetworkInterface");
34
35 namespace OHOS {
36 namespace Wifi {
IsValidInterfaceName(const std::string & interfaceName)37 bool NetworkInterface::IsValidInterfaceName(const std::string &interfaceName)
38 {
39 size_t len = interfaceName.length();
40 if (len == 0 || len > IF_NAMESIZE) {
41 return false;
42 }
43
44 if (!isalnum(interfaceName[0])) {
45 return false;
46 }
47
48 for (size_t i = 1; i < len; i++) {
49 char ch = interfaceName[i];
50 if (!isalnum(ch) && (ch != '_' && ch != '-' && ch != ':')) {
51 return false;
52 }
53 }
54
55 return true;
56 }
57
58
Dump(const std::string & interfaceName)59 void NetworkInterface::Dump(const std::string &interfaceName)
60 {
61 WIFI_LOGI("InterfaceName [%{private}s]", interfaceName.c_str());
62
63 std::vector<Ipv4Address> vecIPv4;
64 std::vector<Ipv6Address> vecIPv6;
65
66 bool ret = FetchInterfaceConfig(interfaceName, vecIPv4, vecIPv6);
67 if (!ret) {
68 WIFI_LOGI("Fetch Interface [%{private}s] failed.", interfaceName.c_str());
69 }
70
71 WIFI_LOGI("\tIPv4 size [%{private}zu]", vecIPv4.size());
72 for (const auto &item : vecIPv4) {
73 item.Dump();
74 }
75
76 WIFI_LOGI("\tIPv6 size [%{private}zu]", vecIPv6.size());
77 for (const auto &item : vecIPv6) {
78 item.Dump();
79 }
80 }
81
FetchInterfaceConfig(const std::string & interfaceName,std::vector<Ipv4Address> & vecIPv4,std::vector<Ipv6Address> & vecIPv6)82 bool NetworkInterface::FetchInterfaceConfig(
83 const std::string &interfaceName, std::vector<Ipv4Address> &vecIPv4, std::vector<Ipv6Address> &vecIPv6)
84 {
85 if (!FetchIpAddress(interfaceName, vecIPv4, vecIPv6)) {
86 WIFI_LOGE("interface [%{public}s] Fetch IP address failed.", interfaceName.c_str());
87 return false;
88 }
89 return true;
90 }
91
GetIpv4Address(const std::string & interfaceName,std::vector<Ipv4Address> & vecIPv4)92 bool NetworkInterface::GetIpv4Address(const std::string &interfaceName, std::vector<Ipv4Address> &vecIPv4)
93 {
94 std::vector<Ipv6Address> vecIPv6;
95 if (!FetchIpAddress(interfaceName, vecIPv4, vecIPv6)) {
96 WIFI_LOGE("interface [%{public}s] Fetch IP address failed.", interfaceName.c_str());
97 return false;
98 }
99 /*
100 * The ipv4 address is not set for the network interface. In this case, the
101 * ipv4 address is not updated.
102 */
103 return !(vecIPv4.empty());
104 }
105
GetAllIpv6Address(const std::string & interfaceName,std::vector<Ipv6Address> & vecIPv6)106 bool NetworkInterface::GetAllIpv6Address(const std::string &interfaceName, std::vector<Ipv6Address> &vecIPv6)
107 {
108 std::vector<Ipv4Address> vecIPv4;
109 if (!FetchIpAddress(interfaceName, vecIPv4, vecIPv6)) {
110 WIFI_LOGE("interface [%{public}s] Fetch IP address failed.", interfaceName.c_str());
111 return false;
112 }
113 return true;
114 }
115
IsExistAddressForInterface(const std::string & interfaceName,const BaseAddress & address)116 bool NetworkInterface::IsExistAddressForInterface(const std::string &interfaceName, const BaseAddress &address)
117 {
118 std::vector<Ipv4Address> vecIPv4;
119 std::vector<Ipv6Address> vecIPv6;
120 if (!FetchIpAddress(interfaceName, vecIPv4, vecIPv6)) {
121 WIFI_LOGE("interface [%{public}s] Fetch IP address failed.", interfaceName.c_str());
122 return false;
123 }
124
125 for (const auto &iter : vecIPv4) {
126 if (iter == address) {
127 return true;
128 }
129 }
130
131 for (const auto &iter : vecIPv6) {
132 if (iter == address) {
133 return true;
134 }
135 }
136
137 return false;
138 }
139
AddIpAddress(const std::string & interfaceName,const BaseAddress & ipAddress)140 bool NetworkInterface::AddIpAddress(const std::string &interfaceName, const BaseAddress &ipAddress)
141 {
142 if (!ipAddress.IsValid()) {
143 WIFI_LOGE("Add IP address [%{private}s] is not valid.", ipAddress.GetAddressWithString().c_str());
144 return false;
145 }
146
147 /* Avoid repeated add. */
148 if (IsExistAddressForInterface(interfaceName, ipAddress)) {
149 WIFI_LOGI("In interface [%{public}s], the address [%{private}s] is exist.",
150 interfaceName.c_str(),
151 ipAddress.GetAddressWithString().c_str());
152 return true;
153 }
154
155 if (!IpAddressChange(interfaceName, ipAddress, true)) {
156 WIFI_LOGE("Interface [%{public}s] add address [%{private}s] failed.",
157 interfaceName.c_str(),
158 ipAddress.GetAddressWithString().c_str());
159 return false;
160 }
161 return true;
162 }
163
DelIpAddress(const std::string & interfaceName,const BaseAddress & ipAddress)164 bool NetworkInterface::DelIpAddress(const std::string &interfaceName, const BaseAddress &ipAddress)
165 {
166 if (!ipAddress.IsValid()) {
167 WIFI_LOGE("Del IP address [%{private}s] is not valid.", ipAddress.GetAddressWithString().c_str());
168 return false;
169 }
170
171 if (!IsExistAddressForInterface(interfaceName, ipAddress)) {
172 WIFI_LOGI("In interface [%{public}s], the address [%{private}s] is not exist.",
173 interfaceName.c_str(),
174 ipAddress.GetAddressWithString().c_str());
175 return true;
176 }
177 if (!IpAddressChange(interfaceName, ipAddress, false)) {
178 WIFI_LOGE("Interface [%{public}s] del address [%{private}s] failed.",
179 interfaceName.c_str(),
180 ipAddress.GetAddressWithString().c_str());
181 return false;
182 }
183 return true;
184 }
185
ClearAllIpAddress(const std::string & interfaceName)186 bool NetworkInterface::ClearAllIpAddress(const std::string &interfaceName)
187 {
188 std::vector<Ipv4Address> vecIPv4;
189 std::vector<Ipv6Address> vecIPv6;
190 bool ret = true;
191 if (!FetchIpAddress(interfaceName, vecIPv4, vecIPv6)) {
192 return false;
193 }
194 for (auto ip4 : vecIPv4) {
195 ret &= DelIpAddress(interfaceName, ip4);
196 }
197 for (auto ip6 : vecIPv6) {
198 ret &= DelIpAddress(interfaceName, ip6);
199 }
200 if (!ret) {
201 WIFI_LOGW("Some ip del failed.");
202 }
203 return true;
204 }
205
SaveIpAddress(const struct ifaddrs & ifa,std::vector<Ipv4Address> & vecIPv4,std::vector<Ipv6Address> & vecIPv6)206 bool NetworkInterface::SaveIpAddress(
207 const struct ifaddrs &ifa, std::vector<Ipv4Address> &vecIPv4, std::vector<Ipv6Address> &vecIPv6)
208 {
209 int ret = 0;
210 char host[NI_MAXHOST] = {0}; /* IP address storage */
211 char mask[NI_MAXHOST] = {0}; /* mask storage */
212 int family = ifa.ifa_addr->sa_family;
213 /* For an AF_INET* interface address, display the address */
214 if (family == AF_INET || family == AF_INET6) {
215 ret = getnameinfo(ifa.ifa_addr,
216 (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
217 host,
218 NI_MAXHOST,
219 nullptr,
220 0,
221 NI_NUMERICHOST);
222 if (ret != 0) {
223 WIFI_LOGE("getnameinfo() failed: %{public}s\n", gai_strerror(ret));
224 return false;
225 }
226 ret = getnameinfo(ifa.ifa_netmask,
227 (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6),
228 mask,
229 NI_MAXHOST,
230 nullptr,
231 0,
232 NI_NUMERICHOST);
233 if (ret != 0) {
234 WIFI_LOGE("getnameinfo() failed: %{public}s\n", gai_strerror(ret));
235 return false;
236 }
237 /* For an IPv6 address, the suffix %wlan0 exists. */
238 char *sepNum = strchr(host, '%');
239 if (sepNum != nullptr) {
240 *sepNum = '\0';
241 }
242 if (family == AF_INET) {
243 vecIPv4.push_back(Ipv4Address::Create(host, mask));
244 } else if (family == AF_INET6) {
245 vecIPv6.push_back(Ipv6Address::Create(host, mask));
246 }
247 }
248 return true;
249 }
250
FetchIpAddress(const std::string & interfaceName,std::vector<Ipv4Address> & vecipv4,std::vector<Ipv6Address> & vecIPv6)251 bool NetworkInterface::FetchIpAddress(
252 const std::string &interfaceName, std::vector<Ipv4Address> &vecipv4, std::vector<Ipv6Address> &vecIPv6)
253 {
254 struct ifaddrs *ifaddr = nullptr;
255 struct ifaddrs *ifa = nullptr;
256 bool ret = false;
257 int n = 0;
258
259 if (getifaddrs(&ifaddr) == -1) {
260 WIFI_LOGE("getifaddrs failed, error is %{public}d", errno);
261 return false;
262 }
263
264 for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) {
265 if (ifa->ifa_addr == nullptr) {
266 continue;
267 }
268 /*
269 * Display interface name and family (including symbolic
270 * form of the latter for the common families)
271 */
272 if (strncmp(interfaceName.c_str(), ifa->ifa_name, IF_NAMESIZE) != 0 && !interfaceName.empty()) {
273 continue;
274 }
275 ret |= SaveIpAddress(*ifa, vecipv4, vecIPv6);
276 }
277
278 freeifaddrs(ifaddr);
279 return ret;
280 }
281
FetchApOrP2pIpAddress(const std::string & interfaceName,std::vector<Ipv4Address> & vecipv4,std::vector<Ipv6Address> & vecIPv6)282 bool NetworkInterface::FetchApOrP2pIpAddress(
283 const std::string &interfaceName, std::vector<Ipv4Address> &vecipv4, std::vector<Ipv6Address> &vecIPv6)
284 {
285 struct ifaddrs *ifaddr = nullptr;
286 struct ifaddrs *ifa = nullptr;
287 bool ret = false;
288 int n = 0;
289 constexpr int prefixInterfaceName = 3;
290 constexpr int prefixP2P = 4;
291
292 if (getifaddrs(&ifaddr) == -1) {
293 WIFI_LOGE("getifaddrs failed, error is %{public}d", errno);
294 return false;
295 }
296 for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) {
297 if (ifa->ifa_addr == nullptr) {
298 continue;
299 }
300 std::string subInterfaceName = interfaceName.substr(0, prefixInterfaceName);
301 char ifaName[prefixP2P + 1];
302 if (strncpy_s(ifaName, sizeof(ifaName), ifa->ifa_name, prefixP2P) != EOK) {
303 return false;
304 }
305 if ((subInterfaceName == "wla") && (strncmp(interfaceName.c_str(), ifa->ifa_name, IF_NAMESIZE) == 0)) {
306 continue;
307 }
308 if ((subInterfaceName == "p2p") &&
309 (strncmp("p2p0", ifa->ifa_name, IF_NAMESIZE) == 0 || strncmp("p2p-", ifaName, IF_NAMESIZE) == 0)) {
310 continue;
311 }
312 ret |= SaveIpAddress(*ifa, vecipv4, vecIPv6);
313 }
314
315 freeifaddrs(ifaddr);
316 return ret;
317 }
318
IpAddressChange(const std::string & interface,const BaseAddress & ipAddress,bool action,bool dad)319 bool NetworkInterface::IpAddressChange(
320 const std::string &interface, const BaseAddress &ipAddress, bool action, bool dad)
321 {
322 if (!ipAddress.IsValid() || ipAddress.GetFamilyType() == BaseAddress::FamilyType::FAMILY_INET6) {
323 WIFI_LOGE("bad input parameter [%{public}s][%{private}s]/[%{private}zu]to change ip.", interface.c_str(),
324 ipAddress.GetAddressWithString().c_str(), ipAddress.GetAddressPrefixLength());
325 return false;
326 }
327 std::string ipAddr;
328 std::string mask;
329 if (action) {
330 Ipv4Address ipv4 = Ipv4Address::Create(ipAddress.GetAddressWithString(), ipAddress.GetAddressPrefixLength());
331 ipAddr = ipv4.GetAddressWithString();
332 mask = ipv4.GetMaskWithString();
333 } else {
334 ipAddr = "0.0.0.0";
335 mask = "0.0.0.0";
336 }
337
338 struct ifreq ifr;
339 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
340 strncpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), interface.c_str(), interface.length()) != EOK) {
341 return false;
342 }
343
344 int fd = socket(AF_INET, SOCK_DGRAM, 0);
345 if (fd < 0) {
346 return false;
347 }
348
349 struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
350 sin->sin_family = AF_INET;
351 if (inet_aton(ipAddr.c_str(), &(sin->sin_addr)) < 0) {
352 close(fd);
353 return false;
354 }
355 if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) {
356 close(fd);
357 WIFI_LOGE("ioctl set ip address failed, error is: %{public}d.", errno);
358 return false;
359 }
360 if (inet_aton(mask.c_str(), &(sin->sin_addr)) < 0) {
361 close(fd);
362 return false;
363 }
364 if (ioctl(fd, SIOCSIFNETMASK, &ifr) < 0) {
365 close(fd);
366 WIFI_LOGE("ioctl set mask address failed, error is: %{public}d.", errno);
367 return false;
368 }
369 close(fd);
370 return true;
371 }
372
WriteDataToFile(const std::string & fileName,const std::string & content)373 bool NetworkInterface::WriteDataToFile(const std::string &fileName, const std::string &content)
374 {
375 int fd = open(fileName.c_str(), O_WRONLY | O_CLOEXEC);
376 if (fd < 0) {
377 WIFI_LOGE("open %{public}s fail, error: %{public}d", fileName.c_str(), errno);
378 return false;
379 }
380
381 if (static_cast<size_t>(write(fd, content.c_str(), content.length())) != content.length()) {
382 WIFI_LOGE("write content [%{public}s] to file [%{public}s] failed. error: %{public}d.",
383 content.c_str(), fileName.c_str(), errno);
384 close(fd);
385 return false;
386 }
387 close(fd);
388 return true;
389 }
390 } // namespace Wifi
391 } // namespace OHOS
392