1 /*
2  * Copyright (c) 2024 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 "iface_tool.h"
17 #include <cstring>
18 #include <net/if.h>
19 #include <net/if_arp.h>
20 #include <netinet/in.h>
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <linux/if_bridge.h>
24 #include <linux/if.h>
25 #include <unistd.h>
26 #include <hdf_log.h>
27 #include "unique_fd.h"
28 #include "securec.h"
29 
30 namespace OHOS {
31 namespace HDI {
32 namespace Wlan {
33 namespace Chip {
34 namespace V1_0 {
35 const char K_WLAN0_INTERFACE_NAME[] = "wlan0";
36 const int MAC_LEN = 6;
37 const int MAC_POS_1 = 1;
38 const int MAC_POS_2 = 2;
39 const int MAC_POS_3 = 3;
40 const int MAC_POS_4 = 4;
41 const int MAC_POS_5 = 5;
42 
GetIfState(const char * ifName,int sock,struct ifreq * ifr)43 bool GetIfState(const char* ifName, int sock, struct ifreq* ifr)
44 {
45     if (memset_s(ifr, sizeof(*ifr), 0, sizeof(*ifr)) != EOK) {
46         HDF_LOGE("memset_s failed");
47         return false;
48     }
49     if (strlcpy(ifr->ifr_name, ifName, sizeof(ifr->ifr_name)) >=
50         sizeof(ifr->ifr_name)) {
51         HDF_LOGE("Interface name is too long: %{public}s", ifName);
52         return false;
53     }
54     if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCGIFFLAGS, ifr)) != 0) {
55         HDF_LOGE("Could not read interface state for %{public}s, %{public}s", ifName, strerror(errno));
56         return false;
57     }
58     return true;
59 }
60 
GetUpState(const char * ifName)61 bool IfaceTool::GetUpState(const char* ifName)
62 {
63     UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
64     if (sock.Get() < 0) {
65         HDF_LOGE("Failed to open socket to set up/down state %{public}s", strerror(errno));
66         return false;
67     }
68     struct ifreq ifr;
69     if (!GetIfState(ifName, sock.Get(), &ifr)) {
70         return false;
71     }
72     return ifr.ifr_flags & IFF_UP;
73 }
74 
SetUpState(const char * ifName,bool requestUp)75 bool IfaceTool::SetUpState(const char* ifName, bool requestUp)
76 {
77     UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
78     if (sock.Get() < 0) {
79         HDF_LOGE("Failed to open socket to set up/down state %{public}s", strerror(errno));
80         return false;
81     }
82     struct ifreq ifr;
83     if (!GetIfState(ifName, sock.Get(), &ifr)) {
84         return false;
85     }
86     const bool currentlyUp = ifr.ifr_flags & IFF_UP;
87     if (currentlyUp == requestUp) {
88         return true;
89     }
90     if (requestUp) {
91         ifr.ifr_flags |= IFF_UP;
92     } else {
93         ifr.ifr_flags &= ~IFF_UP;
94     }
95     if (TEMP_FAILURE_RETRY(ioctl(sock.Get(), SIOCSIFFLAGS, &ifr)) != 0) {
96         HDF_LOGE("Could not set interface flags for %{public}s, %{public}s", ifName, strerror(errno));
97         return false;
98     }
99     return true;
100 }
101 
SetWifiUpState(bool requestUp)102 bool IfaceTool::SetWifiUpState(bool requestUp)
103 {
104     return SetUpState(K_WLAN0_INTERFACE_NAME, requestUp);
105 }
106 
SetMacAddress(const char * ifName,const char * mac)107 bool IfaceTool::SetMacAddress(const char* ifName, const char* mac)
108 {
109     struct ifreq ifr;
110 
111     unsigned char macBin[MAC_LEN];
112     if (sscanf_s(mac, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
113         &macBin[0], &macBin[MAC_POS_1], &macBin[MAC_POS_2],
114         &macBin[MAC_POS_3], &macBin[MAC_POS_4], &macBin[MAC_POS_5]) == EOF) {
115         return false;
116     }
117     UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
118     if (sock.Get() < 0) {
119         HDF_LOGE("Failed to open socket to set MAC address %{public}s", strerror(errno));
120         return false;
121     }
122     if (!GetIfState(ifName, sock.Get(), &ifr)) {
123         return false;
124     }
125     if (memset_s(&ifr.ifr_hwaddr, sizeof(ifr.ifr_hwaddr), 0, sizeof(ifr.ifr_hwaddr)) < 0) {
126         HDF_LOGE("Failed to memset");
127     }
128     ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
129     if (memcpy_s(ifr.ifr_hwaddr.sa_data, MAC_LEN, macBin, MAC_LEN) < 0) {
130         HDF_LOGE("Failed to memcpy");
131     }
132     if (TEMP_FAILURE_RETRY(ioctl(sock.Get(), SIOCSIFHWADDR, &ifr)) != 0) {
133         HDF_LOGE("Failed to set interface MAC address for %{public}s, %{public}s",
134             ifName, strerror(errno));
135         return false;
136     }
137     return true;
138 }
139 }
140 }
141 }
142 }
143 }