• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "wifi_system/interface_tool.h"
18 
19 #include <net/if.h>
20 #include <net/if_arp.h>
21 #include <netinet/in.h>
22 #include <sys/socket.h>
23 
24 #include <linux/if_bridge.h>
25 #include <string.h>
26 
27 #include <linux/ethtool.h>
28 /* We need linux/if.h for flags like IFF_UP.  Sadly, it forward declares
29    struct sockaddr and must be included after sys/socket.h. */
30 #include <linux/if.h>
31 
32 #include <android-base/logging.h>
33 #include <android-base/unique_fd.h>
34 
35 #define IFNAMSIZ    16
36 
37 namespace android {
38 namespace wifi_system {
39 namespace {
40 
41 const char kWlan0InterfaceName[] = "wlan0";
42 
GetIfState(const char * if_name,int sock,struct ifreq * ifr)43 bool GetIfState(const char* if_name, int sock, struct ifreq* ifr) {
44   memset(ifr, 0, sizeof(*ifr));
45   if (strlcpy(ifr->ifr_name, if_name, sizeof(ifr->ifr_name)) >=
46       sizeof(ifr->ifr_name)) {
47     LOG(ERROR) << "Interface name is too long: " << if_name;
48     return false;
49   }
50 
51   if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCGIFFLAGS, ifr)) != 0) {
52     LOG(ERROR) << "Could not read interface state for " << if_name
53                << " (" << strerror(errno) << ")";
54     return false;
55   }
56 
57   return true;
58 }
59 
60 }  // namespace
61 
GetUpState(const char * if_name)62 bool InterfaceTool::GetUpState(const char* if_name) {
63   base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
64   if (sock.get() < 0) {
65     LOG(ERROR) << "Failed to open socket to set up/down state ("
66                << strerror(errno) << ")";
67     return false;
68   }
69 
70   struct ifreq ifr;
71   if (!GetIfState(if_name, sock.get(), &ifr)) {
72     return false;  // logging done internally
73   }
74 
75   return ifr.ifr_flags & IFF_UP;
76 }
77 
SetUpState(const char * if_name,bool request_up)78 bool InterfaceTool::SetUpState(const char* if_name, bool request_up) {
79   base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
80   if (sock.get() < 0) {
81     LOG(ERROR) << "Failed to open socket to set up/down state ("
82                << strerror(errno) << ")";
83     return false;
84   }
85 
86   struct ifreq ifr;
87   if (!GetIfState(if_name, sock.get(), &ifr)) {
88     return false;  // logging done internally
89   }
90 
91   const bool currently_up = ifr.ifr_flags & IFF_UP;
92   if (currently_up == request_up) {
93     return true;
94   }
95 
96   if (request_up) {
97     ifr.ifr_flags |= IFF_UP;
98   } else {
99     ifr.ifr_flags &= ~IFF_UP;
100   }
101 
102   if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCSIFFLAGS, &ifr)) != 0) {
103     LOG(ERROR) << "Could not set interface flags for " << if_name
104                << " (" << strerror(errno) << ")";
105     return false;
106   }
107 
108   return true;
109 }
110 
SetWifiUpState(bool request_up)111 bool InterfaceTool::SetWifiUpState(bool request_up) {
112   return SetUpState(kWlan0InterfaceName, request_up);
113 }
114 
SetMacAddress(const char * if_name,const std::array<uint8_t,ETH_ALEN> & new_address)115 bool InterfaceTool::SetMacAddress(const char* if_name,
116     const std::array<uint8_t, ETH_ALEN>& new_address) {
117   struct ifreq ifr;
118   static_assert(ETH_ALEN <= sizeof(ifr.ifr_hwaddr.sa_data),
119     "new address is too long");
120 
121   base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
122   if (sock.get() < 0) {
123     LOG(ERROR) << "Failed to open socket to set MAC address ("
124                << strerror(errno) << ")";
125     return false;
126   }
127 
128   if (!GetIfState(if_name, sock.get(), &ifr)) {
129     return false;  // logging done internally
130   }
131 
132   memset(&ifr.ifr_hwaddr, 0, sizeof(ifr.ifr_hwaddr));
133   ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
134   memcpy(ifr.ifr_hwaddr.sa_data, new_address.data(), new_address.size());
135   if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCSIFHWADDR, &ifr)) != 0) {
136     LOG(ERROR) << "Could not set interface MAC address for " << if_name
137                << " (" << strerror(errno) << ")";
138     return false;
139   }
140 
141   return true;
142 }
143 
GetFactoryMacAddress(const char * if_name)144 std::array<uint8_t, ETH_ALEN> InterfaceTool::GetFactoryMacAddress(const char* if_name) {
145   std::array<uint8_t, ETH_ALEN> paddr = {};
146   struct ifreq ifr;
147   struct {
148     // Allocate ETH_ALEN bytes after ethtool_perm_addr.
149     struct ethtool_perm_addr epaddr;
150     uint8_t data[ETH_ALEN];
151   } epaddr_buf;
152   struct ethtool_perm_addr* epaddr = &epaddr_buf.epaddr;
153 
154   base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
155   if (sock.get() < 0) {
156     LOG(ERROR) << "Failed to open socket to get factory MAC address ("
157                << strerror(errno) << ")";
158     return paddr;
159   }
160 
161   if (!GetIfState(if_name, sock.get(), &ifr)) {
162     return paddr;  // logging done internally
163   }
164 
165   epaddr->cmd = ETHTOOL_GPERMADDR;
166   epaddr->size = ETH_ALEN;
167   ifr.ifr_data = epaddr;
168 
169   if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCETHTOOL, &ifr)) != 0) {
170     LOG(ERROR) << "Could not get factory address MAC for " << if_name
171                << " (" << strerror(errno) << ")";
172   } else if (epaddr->size == ETH_ALEN) {
173     memcpy(paddr.data(), epaddr->data, ETH_ALEN);
174   }
175   return paddr;
176 }
177 
createBridge(const std::string & br_name)178 bool InterfaceTool::createBridge(const std::string& br_name) {
179     base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
180 
181     if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCBRADDBR, br_name.c_str())) != 0) {
182         LOG(ERROR) << "Could not add bridge " << br_name.c_str()
183                    << " (" << strerror(errno) << ")";
184         return false;
185     }
186 
187     return true;
188 }
189 
deleteBridge(const std::string & br_name)190 bool InterfaceTool::deleteBridge(const std::string& br_name) {
191     base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
192 
193     if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCBRDELBR, br_name.c_str())) != 0) {
194         LOG(ERROR) << "Could not remove bridge " << br_name.c_str()
195                    << " (" << strerror(errno) << ")";
196         return false;
197     }
198     return true;
199 }
200 
addIfaceToBridge(const std::string & br_name,const std::string & if_name)201 bool InterfaceTool::addIfaceToBridge(const std::string& br_name, const std::string& if_name) {
202     struct ifreq ifr;
203     memset(&ifr, 0, sizeof(ifr));
204 
205     ifr.ifr_ifindex = if_nametoindex(if_name.c_str());
206     if (ifr.ifr_ifindex == 0) {
207         LOG(ERROR) << "Interface is not exist: " << if_name.c_str();
208         return false;
209     }
210     strlcpy(ifr.ifr_name, br_name.c_str(), IFNAMSIZ);
211 
212     base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
213     if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCBRADDIF, &ifr)) != 0) {
214         LOG(ERROR) << "Could not add interface " << if_name.c_str()
215                    << " into bridge " << ifr.ifr_name
216                    << " (" << strerror(errno) << ")";
217         return false;
218     }
219     return true;
220 }
221 
removeIfaceFromBridge(const std::string & br_name,const std::string & if_name)222 bool InterfaceTool::removeIfaceFromBridge(const std::string& br_name, const std::string& if_name) {
223     struct ifreq ifr;
224     memset(&ifr, 0, sizeof(ifr));
225 
226     ifr.ifr_ifindex = if_nametoindex(if_name.c_str());
227     if (ifr.ifr_ifindex == 0) {
228         LOG(ERROR) << "Interface is not exist: " << if_name.c_str();
229         return false;
230     }
231     strlcpy(ifr.ifr_name, br_name.c_str(), IFNAMSIZ);
232 
233     base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
234     if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCBRDELIF, &ifr)) != 0) {
235         LOG(ERROR) << "Could not remove interface " << if_name.c_str()
236                    << " from bridge " << ifr.ifr_name
237                    << " (" << strerror(errno) << ")";
238         return false;
239     }
240 
241     return true;
242 }
243 }  // namespace wifi_system
244 }  // namespace android
245