• 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 <netinet/in.h>
20 #include <sys/socket.h>
21 /* We need linux/if.h for flags like IFF_UP.  Sadly, it forward declares
22    struct sockaddr and must be included after sys/socket.h. */
23 #include <linux/if.h>
24 
25 #include <android-base/logging.h>
26 #include <android-base/unique_fd.h>
27 
28 namespace android {
29 namespace wifi_system {
30 namespace {
31 
32 const char kWlan0InterfaceName[] = "wlan0";
33 
GetIfState(const char * if_name,int sock,struct ifreq * ifr)34 bool GetIfState(const char* if_name, int sock, struct ifreq* ifr) {
35   memset(ifr, 0, sizeof(*ifr));
36   if (strlcpy(ifr->ifr_name, if_name, sizeof(ifr->ifr_name)) >=
37       sizeof(ifr->ifr_name)) {
38     LOG(ERROR) << "Interface name is too long: " << if_name;
39     return false;
40   }
41 
42   if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCGIFFLAGS, ifr)) != 0) {
43     LOG(ERROR) << "Could not read interface state for " << if_name
44                << " (" << strerror(errno) << ")";
45     return false;
46   }
47 
48   return true;
49 }
50 
51 }  // namespace
52 
GetUpState(const char * if_name)53 bool InterfaceTool::GetUpState(const char* if_name) {
54   base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
55   if (sock.get() < 0) {
56     LOG(ERROR) << "Failed to open socket to set up/down state ("
57                << strerror(errno) << ")";
58     return false;
59   }
60 
61   struct ifreq ifr;
62   if (!GetIfState(if_name, sock.get(), &ifr)) {
63     return false;  // logging done internally
64   }
65 
66   return ifr.ifr_flags & IFF_UP;
67 }
68 
SetUpState(const char * if_name,bool request_up)69 bool InterfaceTool::SetUpState(const char* if_name, bool request_up) {
70   base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
71   if (sock.get() < 0) {
72     LOG(ERROR) << "Failed to open socket to set up/down state ("
73                << strerror(errno) << ")";
74     return false;
75   }
76 
77   struct ifreq ifr;
78   if (!GetIfState(if_name, sock.get(), &ifr)) {
79     return false;  // logging done internally
80   }
81 
82   const bool currently_up = ifr.ifr_flags & IFF_UP;
83   if (currently_up == request_up) {
84     return true;
85   }
86 
87   if (request_up) {
88     ifr.ifr_flags |= IFF_UP;
89   } else {
90     ifr.ifr_flags &= ~IFF_UP;
91   }
92 
93   if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCSIFFLAGS, &ifr)) != 0) {
94     LOG(ERROR) << "Could not set interface flags for " << if_name
95                << " (" << strerror(errno) << ")";
96     return false;
97   }
98 
99   return true;
100 }
101 
SetWifiUpState(bool request_up)102 bool InterfaceTool::SetWifiUpState(bool request_up) {
103   return SetUpState(kWlan0InterfaceName, request_up);
104 }
105 
106 }  // namespace wifi_system
107 }  // namespace android
108