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