From 047c9cc84293f449b1ecb2d560cf10a0ecb81c4f Mon Sep 17 00:00:00 2001 From: Christopher Wiley Date: Thu, 22 Sep 2016 16:03:22 -0700 Subject: Add a helper to read the interface state This helper doesn't really distinguish between "I failed to read the state" and "state is down" but I think that if we cannot observe the interface to be up, it may as well be down. Bug: 31337216 Test: Compiles Change-Id: Id48968844fea120bc0a4c439693db58d72feb4a1 --- .../include/wifi_system/interface_tool.h | 4 +++ libwifi_system/interface_tool.cpp | 42 +++++++++++++++++----- .../include/wifi_system_test/mock_interface_tool.h | 1 + 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/libwifi_system/include/wifi_system/interface_tool.h b/libwifi_system/include/wifi_system/interface_tool.h index 2e58379a1..aabdd9a52 100644 --- a/libwifi_system/include/wifi_system/interface_tool.h +++ b/libwifi_system/include/wifi_system/interface_tool.h @@ -25,6 +25,10 @@ class InterfaceTool { InterfaceTool() = default; virtual ~InterfaceTool() = default; + // Get the interface state of |if_name|. + // Returns true iff the interface is up. + virtual bool GetUpState(const char* if_name); + // Set the interface named by |if_name| up or down. // Returns true on success, false otherwise. virtual bool SetUpState(const char* if_name, bool request_up); diff --git a/libwifi_system/interface_tool.cpp b/libwifi_system/interface_tool.cpp index af9cc0805..f0d40efd4 100644 --- a/libwifi_system/interface_tool.cpp +++ b/libwifi_system/interface_tool.cpp @@ -31,9 +31,26 @@ namespace { const char kWlan0InterfaceName[] = "wlan0"; +bool GetIfState(const char* if_name, int sock, struct ifreq* ifr) { + memset(ifr, 0, sizeof(*ifr)); + if (strlcpy(ifr->ifr_name, if_name, sizeof(ifr->ifr_name)) >= + sizeof(ifr->ifr_name)) { + LOG(ERROR) << "Interface name is too long: " << if_name; + return false; + } + + if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCGIFFLAGS, ifr)) != 0) { + LOG(ERROR) << "Could not read interface state for " << if_name + << " (" << strerror(errno) << ")"; + return false; + } + + return true; +} + } // namespace -bool InterfaceTool::SetUpState(const char* if_name, bool request_up) { +bool InterfaceTool::GetUpState(const char* if_name) { base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)); if (sock.get() < 0) { LOG(ERROR) << "Failed to open socket to set up/down state (" @@ -42,19 +59,26 @@ bool InterfaceTool::SetUpState(const char* if_name, bool request_up) { } struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - if (strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)) >= - sizeof(ifr.ifr_name)) { - LOG(ERROR) << "Interface name is too long: " << if_name; - return false; + if (!GetIfState(if_name, sock.get(), &ifr)) { + return false; // logging done internally } - if (TEMP_FAILURE_RETRY(ioctl(sock.get(), SIOCGIFFLAGS, &ifr)) != 0) { - LOG(ERROR) << "Could not read interface state for " << if_name - << " (" << strerror(errno) << ")"; + return ifr.ifr_flags & IFF_UP; +} + +bool InterfaceTool::SetUpState(const char* if_name, bool request_up) { + base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)); + if (sock.get() < 0) { + LOG(ERROR) << "Failed to open socket to set up/down state (" + << strerror(errno) << ")"; return false; } + struct ifreq ifr; + if (!GetIfState(if_name, sock.get(), &ifr)) { + return false; // logging done internally + } + const bool currently_up = ifr.ifr_flags & IFF_UP; if (currently_up == request_up) { return true; diff --git a/libwifi_system/testlib/include/wifi_system_test/mock_interface_tool.h b/libwifi_system/testlib/include/wifi_system_test/mock_interface_tool.h index 13e67807a..b9926c938 100644 --- a/libwifi_system/testlib/include/wifi_system_test/mock_interface_tool.h +++ b/libwifi_system/testlib/include/wifi_system_test/mock_interface_tool.h @@ -26,6 +26,7 @@ class MockInterfaceTool : public InterfaceTool { public: ~MockInterfaceTool() override = default; + MOCK_METHOD1(GetUpState, bool(const char* if_name)); MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up)); MOCK_METHOD1(SetWifiUpState, bool(bool request_up)); -- cgit v1.2.3