blob: f0d40efd44c6243aa6394360d3e1be9c75fbeb81 [file] [log] [blame]
Christopher Wileyeb2afa52016-06-20 11:05:17 -07001/*
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
Christopher Wileyddf9ccd2016-06-24 11:14:37 -070017#include "wifi_system/interface_tool.h"
Christopher Wileyeb2afa52016-06-20 11:05:17 -070018
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
Christopher Wiley04d8e4e2016-07-29 17:31:09 -070025#include <android-base/logging.h>
Christopher Wileyeb2afa52016-06-20 11:05:17 -070026#include <android-base/unique_fd.h>
Christopher Wileyeb2afa52016-06-20 11:05:17 -070027
28namespace android {
29namespace wifi_system {
30namespace {
31
32const char kWlan0InterfaceName[] = "wlan0";
33
Christopher Wiley047c9cc2016-09-22 16:03:22 -070034bool 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
Christopher Wileyeb2afa52016-06-20 11:05:17 -070051} // namespace
52
Christopher Wiley047c9cc2016-09-22 16:03:22 -070053bool 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
Christopher Wileyddf9ccd2016-06-24 11:14:37 -070069bool InterfaceTool::SetUpState(const char* if_name, bool request_up) {
Christopher Wiley833ec7e2016-08-02 11:26:10 -070070 base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
Christopher Wileyeb2afa52016-06-20 11:05:17 -070071 if (sock.get() < 0) {
Christopher Wiley04d8e4e2016-07-29 17:31:09 -070072 LOG(ERROR) << "Failed to open socket to set up/down state ("
73 << strerror(errno) << ")";
Christopher Wileyeb2afa52016-06-20 11:05:17 -070074 return false;
75 }
76
77 struct ifreq ifr;
Christopher Wiley047c9cc2016-09-22 16:03:22 -070078 if (!GetIfState(if_name, sock.get(), &ifr)) {
79 return false; // logging done internally
Christopher Wileyeb2afa52016-06-20 11:05:17 -070080 }
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) {
Christopher Wiley04d8e4e2016-07-29 17:31:09 -070094 LOG(ERROR) << "Could not set interface flags for " << if_name
95 << " (" << strerror(errno) << ")";
Christopher Wileyeb2afa52016-06-20 11:05:17 -070096 return false;
97 }
98
99 return true;
100}
101
Christopher Wileyddf9ccd2016-06-24 11:14:37 -0700102bool InterfaceTool::SetWifiUpState(bool request_up) {
103 return SetUpState(kWlan0InterfaceName, request_up);
Christopher Wileyeb2afa52016-06-20 11:05:17 -0700104}
105
106} // namespace wifi_system
107} // namespace android