From c4a895b7094461c98101924cf096680bfb7856f1 Mon Sep 17 00:00:00 2001 From: San Mehat Date: Tue, 23 Jun 2009 21:10:57 -0700 Subject: [PATCH] nexus: Rollup update for nexus nexus: Change field separator from : to ' ' Signed-off-by: San Mehat nexus: Add some prototypes for stuff to come Signed-off-by: San Mehat nexus: Add some TODOs Signed-off-by: San Mehat libsysutils: Put a proper token parser into the FrameworkListener which supports minimal \ escapes and quotes Signed-off-by: San Mehat nexus: Fix a lot of bugs Signed-off-by: San Mehat libsysutils: Remove some debugging Signed-off-by: San Mehat nexus: Send broadcasts for supplicant state changes Signed-off-by: San Mehat nexus: Plumb DHCP listener state changes to NetworkManager Signed-off-by: San Mehat nexus: Make the SupplicantState strings more parsable Signed-off-by: San Mehat nexus: Broadcast a message when dhcp state changes. Signed-off-by: San Mehat nexus: Add a few new response codes Signed-off-by: San Mehat nexus: Rename ErrorCode -> ResponseCode Signed-off-by: San Mehat nexus: Add DHCP event broadcasting. Also adds the framework for tracking supplicant 'searching-for-AP' state Signed-off-by: San Mehat nexus: REmove WifiScanner Signed-off-by: San Mehat nexus: Change the way scanning works. scanmode can now be selected independantly of triggering a scan. Also adds rxfilter support Signed-off-by: San Mehat nexus: Add support for configuring bluetooth coexistence scanning and modes Signed-off-by: San Mehat nexus: use case insensitive match for property names Signed-off-by: San Mehat nexus: Rollup of a bunch of stuff: - 'list' command now takes an argument to match against - InterfaceConfig has been moved into the Controller base (for now) - DhcpClient now has some rudimentry locking - process 'ADDRINFO' messages from dhcpcd - Drop tertiary dns Signed-off-by: San Mehat nexus: Clean up some of the supplicant variable parsing and add 'wifi.current' Signed-off-by: San Mehat nexus: Add driver-stop/start, initial suspend support Signed-off-by: San Mehat nexus: Add Controller suspend/resume callbacks, as well as locking Signed-off-by: San Mehat nexus: Make ARP probing configurable for DhcpClient Signed-off-by: San Mehat nexus: Add linkspeed / rssi retrieval Signed-off-by: San Mehat nexus: Add WifiStatusPoller to track RSSI/linkspeed when associated Signed-off-by: San Mehat nexus: Disable some debugging and add 'wifi.netcount' property Signed-off-by: San Mehat nexus: Replace the hackish property system with something more flexible with namespaces Signed-off-by: San Mehat libsysutils: Fix a few bugs in SocketListener Signed-off-by: San Mehat nexus: PropertyManager: Add array support Signed-off-by: San Mehat nexus: Clean up properties Signed-off-by: San Mehat nexus: WifiController: Change name of 'CurrentNetwork' property Signed-off-by: San Mehat --- include/sysutils/SocketListener.h | 2 +- libsysutils/src/FrameworkListener.cpp | 79 +- libsysutils/src/SocketListener.cpp | 38 +- nexus/Android.mk | 24 +- nexus/CommandListener.cpp | 42 +- nexus/Controller.cpp | 13 +- nexus/Controller.h | 9 +- nexus/DhcpClient.cpp | 79 +- nexus/DhcpClient.h | 15 +- nexus/DhcpEvent.cpp | 56 ++ nexus/{IPropertyProvider.h => DhcpEvent.h} | 24 +- nexus/DhcpListener.cpp | 80 +- nexus/DhcpListener.h | 4 +- nexus/DhcpState.cpp | 80 ++ nexus/DhcpState.h | 22 +- nexus/IControllerHandler.h | 7 +- nexus/IDhcpEventHandlers.h | 8 + nexus/ISupplicantEventHandler.h | 1 + nexus/IWifiStatusPollerHandler.h | 26 + nexus/InterfaceConfig.cpp | 173 ++-- nexus/InterfaceConfig.h | 63 +- nexus/LoopController.cpp | 11 +- nexus/NetworkManager.cpp | 158 +++- nexus/NetworkManager.h | 45 +- nexus/Property.cpp | 203 +++++ nexus/Property.h | 118 ++- nexus/PropertyManager.cpp | 251 ++++-- nexus/PropertyManager.h | 36 +- nexus/{ErrorCode.h => ResponseCode.h} | 11 +- nexus/Supplicant.cpp | 268 ++++++- nexus/Supplicant.h | 19 +- nexus/SupplicantState.cpp | 20 +- nexus/TiwlanWifiController.cpp | 40 +- nexus/VpnController.cpp | 82 +- nexus/VpnController.h | 58 +- nexus/WifiController.cpp | 530 +++++++++++-- nexus/WifiController.h | 223 +++++- nexus/WifiNetwork.cpp | 874 ++++++++++++++------- nexus/WifiNetwork.h | 200 ++++- nexus/WifiStatusPoller.cpp | 104 +++ nexus/WifiStatusPoller.h | 47 ++ 41 files changed, 3282 insertions(+), 861 deletions(-) create mode 100644 nexus/DhcpEvent.cpp rename nexus/{IPropertyProvider.h => DhcpEvent.h} (63%) create mode 100644 nexus/DhcpState.cpp create mode 100644 nexus/IWifiStatusPollerHandler.h create mode 100644 nexus/Property.cpp rename nexus/{ErrorCode.h => ResponseCode.h} (84%) create mode 100644 nexus/WifiStatusPoller.cpp create mode 100644 nexus/WifiStatusPoller.h diff --git a/include/sysutils/SocketListener.h b/include/sysutils/SocketListener.h index 68dcb8f45..c7edfeb00 100644 --- a/include/sysutils/SocketListener.h +++ b/include/sysutils/SocketListener.h @@ -33,7 +33,7 @@ public: SocketListener(const char *socketNames, bool listen); SocketListener(int socketFd, bool listen); - virtual ~SocketListener() {} + virtual ~SocketListener(); int startListener(); int stopListener(); diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index e9ca8977f..4c7476501 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -56,24 +56,73 @@ void FrameworkListener::registerCmd(FrameworkCommand *cmd) { } void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { - int argc; + FrameworkCommandCollection::iterator i; + int argc = 0; char *argv[FrameworkListener::CMD_ARGS_MAX]; + char tmp[255]; + char *p = data; + char *q = tmp; + bool esc = false; + bool quote = false; + int k; - if (!index(data, '"')) { - char *next = data; - char *field; - int i; + memset(argv, 0, sizeof(argv)); + memset(tmp, 0, sizeof(tmp)); + while(*p) { + if (*p == '\\') { + if (esc) { + *q++ = '\\'; + esc = false; + } else + esc = true; + p++; + continue; + } else if (esc) { + if (*p == '"') + *q++ = '"'; + else if (*p == '\\') + *q++ = '\\'; + else { + cli->sendMsg(500, "Unsupported escape sequence", false); + goto out; + } + p++; + esc = false; + continue; + } - for (i = 0; (i < FrameworkListener::CMD_ARGS_MAX) && - (argv[i] = strsep(&next, " ")); i++); - argc = i+1; - } else { - LOGD("blehhh not supported"); - return; + if (*p == '"') { + if (quote) + quote = false; + else + quote = true; + p++; + continue; + } + + *q = *p++; + if (!quote && *q == ' ') { + *q = '\0'; + argv[argc++] = strdup(tmp); + memset(tmp, 0, sizeof(tmp)); + q = tmp; + continue; + } + q++; } - FrameworkCommandCollection::iterator i; + argv[argc++] = strdup(tmp); +#if 0 + for (k = 0; k < argc; k++) { + LOGD("arg[%d] = '%s'", k, argv[k]); + } +#endif + if (quote) { + cli->sendMsg(500, "Unclosed quotes error", false); + goto out; + } + for (i = mCommands->begin(); i != mCommands->end(); ++i) { FrameworkCommand *c = *i; @@ -81,10 +130,14 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { if (c->runCommand(cli, argc, argv)) { LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); } - return; + goto out; } } cli->sendMsg(500, "Command not recognized", false); +out: + int j; + for (j = 0; j < argc; j++) + free(argv[j]); return; } diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index 1a937c296..72e128dbb 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -45,9 +45,26 @@ SocketListener::SocketListener(int socketFd, bool listen) { mClients = new SocketClientCollection(); } +SocketListener::~SocketListener() { + if (mSocketName && mSock > -1) + close(mSock); + + if (mCtrlPipe[0] != -1) { + close(mCtrlPipe[0]); + close(mCtrlPipe[1]); + } + SocketClientCollection::iterator it; + for (it = mClients->begin(); it != mClients->end(); ++it) { + delete (*it); + it = mClients->erase(it); + } + delete mClients; +} + int SocketListener::startListener() { if (!mSocketName && mSock == -1) { + LOGE("Failed to start unbound listener"); errno = EINVAL; return -1; } else if (mSocketName) { @@ -64,11 +81,15 @@ int SocketListener::startListener() { } else if (!mListen) mClients->push_back(new SocketClient(mSock)); - if (pipe(mCtrlPipe)) + if (pipe(mCtrlPipe)) { + LOGE("pipe failed (%s)", strerror(errno)); return -1; + } - if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) + if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) { + LOGE("pthread_create (%s)", strerror(errno)); return -1; + } return 0; } @@ -88,6 +109,19 @@ int SocketListener::stopListener() { } close(mCtrlPipe[0]); close(mCtrlPipe[1]); + mCtrlPipe[0] = -1; + mCtrlPipe[1] = -1; + + if (mSocketName && mSock > -1) { + close(mSock); + mSock = -1; + } + + SocketClientCollection::iterator it; + for (it = mClients->begin(); it != mClients->end(); ++it) { + delete (*it); + it = mClients->erase(it); + } return 0; } diff --git a/nexus/Android.mk b/nexus/Android.mk index cd477ef45..f9f711086 100644 --- a/nexus/Android.mk +++ b/nexus/Android.mk @@ -7,23 +7,22 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ main.cpp \ - NetworkManager.cpp \ + NexusCommand.cpp \ CommandListener.cpp \ + Property.cpp \ + PropertyManager.cpp \ + InterfaceConfig.cpp \ + NetworkManager.cpp \ Controller.cpp \ WifiController.cpp \ - LoopController.cpp \ - NexusCommand.cpp \ TiwlanWifiController.cpp \ + TiwlanEventListener.cpp \ + WifiNetwork.cpp \ + WifiStatusPoller.cpp \ + ScanResult.cpp \ Supplicant.cpp \ SupplicantEvent.cpp \ SupplicantListener.cpp \ - VpnController.cpp \ - ScanResult.cpp \ - WifiScanner.cpp \ - WifiNetwork.cpp \ - OpenVpnController.cpp \ - InterfaceConfig.cpp \ - PropertyManager.cpp \ SupplicantState.cpp \ SupplicantEventFactory.cpp \ SupplicantConnectedEvent.cpp \ @@ -34,8 +33,11 @@ LOCAL_SRC_FILES:= \ SupplicantConnectionTimeoutEvent.cpp \ SupplicantDisconnectedEvent.cpp \ SupplicantStatus.cpp \ - TiwlanEventListener.cpp \ + OpenVpnController.cpp \ + VpnController.cpp \ + LoopController.cpp \ DhcpClient.cpp DhcpListener.cpp \ + DhcpState.cpp DhcpEvent.cpp \ LOCAL_MODULE:= nexus diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp index 8eb378bcd..5973ff510 100644 --- a/nexus/CommandListener.cpp +++ b/nexus/CommandListener.cpp @@ -31,7 +31,7 @@ #include "NetworkManager.h" #include "WifiController.h" #include "VpnController.h" -#include "ErrorCode.h" +#include "ResponseCode.h" CommandListener::CommandListener() : FrameworkListener("nexus") { @@ -60,11 +60,11 @@ int CommandListener::WifiCreateNetworkCmd::runCommand(SocketClient *cli, WifiNetwork *wn; if (!(wn = wc->createNetwork())) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to create network", true); + cli->sendMsg(ResponseCode::OperationFailed, "Failed to create network", true); else { char tmp[128]; sprintf(tmp, "Created network id %d.", wn->getNetworkId()); - cli->sendMsg(ErrorCode::CommandOkay, tmp, false); + cli->sendMsg(ResponseCode::CommandOkay, tmp, false); } return 0; } @@ -79,9 +79,9 @@ int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, WifiController *wc = (WifiController *) nm->findController("WIFI"); if (wc->removeNetwork(atoi(argv[1]))) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to remove network", true); + cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove network", true); else { - cli->sendMsg(ErrorCode::CommandOkay, "Network removed.", false); + cli->sendMsg(ResponseCode::CommandOkay, "Network removed.", false); } return 0; } @@ -100,16 +100,16 @@ int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli, char buffer[256]; for(it = src->begin(); it != src->end(); ++it) { - sprintf(buffer, "%s:%u:%d:%s:%s", + sprintf(buffer, "%s %u %d %s %s", (*it)->getBssid(), (*it)->getFreq(), (*it)->getLevel(), (*it)->getFlags(), (*it)->getSsid()); - cli->sendMsg(ErrorCode::WifiScanResult, buffer, false); + cli->sendMsg(ResponseCode::WifiScanResult, buffer, false); delete (*it); it = src->erase(it); } delete src; - cli->sendMsg(ErrorCode::CommandOkay, "Scan results complete.", false); + cli->sendMsg(ResponseCode::CommandOkay, "Scan results complete.", false); return 0; } @@ -128,12 +128,12 @@ int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, for(it = src->begin(); it != src->end(); ++it) { sprintf(buffer, "%d:%s", (*it)->getNetworkId(), (*it)->getSsid()); - cli->sendMsg(ErrorCode::WifiNetworkList, buffer, false); + cli->sendMsg(ResponseCode::WifiNetworkList, buffer, false); delete (*it); } delete src; - cli->sendMsg(ErrorCode::CommandOkay, "Network listing complete.", false); + cli->sendMsg(ResponseCode::CommandOkay, "Network listing complete.", false); return 0; } @@ -159,14 +159,14 @@ int CommandListener::GetCmd::runCommand(SocketClient *cli, int argc, char **argv char *tmp; asprintf(&tmp, "%s %s", argv[1], val); - cli->sendMsg(ErrorCode::PropertyRead, tmp, false); + cli->sendMsg(ResponseCode::PropertyRead, tmp, false); free(tmp); - cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false); + cli->sendMsg(ResponseCode::CommandOkay, "Property read.", false); return 0; out_inval: errno = EINVAL; - cli->sendMsg(ErrorCode::CommandParameterError, "Failed to read property.", true); + cli->sendMsg(ResponseCode::CommandParameterError, "Failed to read property.", true); return 0; } @@ -179,12 +179,12 @@ int CommandListener::SetCmd::runCommand(SocketClient *cli, int argc, if (NetworkManager::Instance()->getPropMngr()->set(argv[1], argv[2])) goto out_inval; - cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false); + cli->sendMsg(ResponseCode::CommandOkay, "Property set.", false); return 0; out_inval: errno = EINVAL; - cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set property.", true); + cli->sendMsg(ResponseCode::CommandParameterError, "Failed to set property.", true); return 0; } @@ -194,10 +194,14 @@ CommandListener::ListCmd::ListCmd() : int CommandListener::ListCmd::runCommand(SocketClient *cli, int argc, char **argv) { android::List *pc; + char *prefix = NULL; - if (!(pc = NetworkManager::Instance()->getPropMngr()->createPropertyList())) { + if (argc > 1) + prefix = argv[1]; + + if (!(pc = NetworkManager::Instance()->getPropMngr()->createPropertyList(prefix))) { errno = ENODATA; - cli->sendMsg(ErrorCode::CommandParameterError, "Failed to list properties.", true); + cli->sendMsg(ResponseCode::CommandParameterError, "Failed to list properties.", true); return 0; } @@ -218,7 +222,7 @@ int CommandListener::ListCmd::runCommand(SocketClient *cli, int argc, char **arg free((*it)); continue; } - cli->sendMsg(ErrorCode::PropertyList, buf, false); + cli->sendMsg(ResponseCode::PropertyList, buf, false); free(buf); free((*it)); @@ -226,6 +230,6 @@ int CommandListener::ListCmd::runCommand(SocketClient *cli, int argc, char **arg delete pc; - cli->sendMsg(ErrorCode::CommandOkay, "Properties list complete.", false); + cli->sendMsg(ResponseCode::CommandOkay, "Properties list complete.", false); return 0; } diff --git a/nexus/Controller.cpp b/nexus/Controller.cpp index 17fb51939..f6a24361c 100644 --- a/nexus/Controller.cpp +++ b/nexus/Controller.cpp @@ -30,6 +30,7 @@ #include #include "Controller.h" +#include "InterfaceConfig.h" extern "C" int init_module(void *, unsigned int, const char *); extern "C" int delete_module(const char *, unsigned int); @@ -57,16 +58,6 @@ int Controller::stop() { return 0; } -int Controller::set(const char *name, const char *value) { - errno = ENOENT; - return -1; -} - -const char *Controller::get(const char *name, char *buffer, size_t maxsize) { - errno = ENOENT; - return NULL; -} - int Controller::loadKernelModule(char *modpath, const char *args) { void *module; unsigned int size; @@ -164,13 +155,11 @@ bail: int Controller::bindInterface(const char *ifname) { mBoundInterface = strdup(ifname); - LOGD("Controller %s bound to %s", mName, ifname); return 0; } int Controller::unbindInterface(const char *ifname) { free(mBoundInterface); mBoundInterface = NULL; - LOGD("Controller %s unbound from %s", mName, ifname); return 0; } diff --git a/nexus/Controller.h b/nexus/Controller.h index af03d2e59..e7e17c51f 100644 --- a/nexus/Controller.h +++ b/nexus/Controller.h @@ -26,9 +26,8 @@ class PropertyManager; class IControllerHandler; #include "PropertyManager.h" -#include "IPropertyProvider.h" -class Controller : public IPropertyProvider { +class Controller { /* * Name of this controller - WIFI/VPN/USBNET/BTNET/BTDUN/LOOP/etc */ @@ -54,11 +53,7 @@ public: const char *getName() { return mName; } const char *getBoundInterface() { return mBoundInterface; } - - /* IPropertyProvider methods */ - virtual int set(const char *name, const char *value); - virtual const char *get(const char *name, char *buffer, size_t maxsize); - + protected: int loadKernelModule(char *modpath, const char *args); bool isKernelModuleLoaded(const char *modtag); diff --git a/nexus/DhcpClient.cpp b/nexus/DhcpClient.cpp index 2bd9c68f1..a5654d28d 100644 --- a/nexus/DhcpClient.cpp +++ b/nexus/DhcpClient.cpp @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #define LOG_TAG "DhcpClient" #include @@ -29,6 +31,7 @@ #include "DhcpState.h" #include "DhcpListener.h" #include "IDhcpEventHandlers.h" +#include "Controller.h" extern "C" { int ifc_disable(const char *ifname); @@ -54,9 +57,13 @@ char *dhcp_get_errmsg(); } DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) : - mState(DhcpState::STOPPED), mHandlers(handlers) { + mState(DhcpState::INIT), mHandlers(handlers) { mServiceManager = new ServiceManager(); mListener = NULL; + mListenerSocket = NULL; + mController = NULL; + mDoArpProbe = false; + pthread_mutex_init(&mLock, NULL); } DhcpClient::~DhcpClient() { @@ -65,41 +72,89 @@ DhcpClient::~DhcpClient() { delete mListener; } -int DhcpClient::start(const char *interface) { - +int DhcpClient::start(Controller *c) { + LOGD("Starting DHCP service (arp probe = %d)", mDoArpProbe); char svc[PROPERTY_VALUE_MAX]; - snprintf(svc, sizeof(svc), "dhcpcd_ng:%s", interface); + snprintf(svc, + sizeof(svc), + "dhcpcd:%s%s", + (!mDoArpProbe ? "-A " : ""), + c->getBoundInterface()); - if (mServiceManager->start(svc)) { - LOGE("Failed to start dhcp service"); + pthread_mutex_lock(&mLock); + + if (mController) { + pthread_mutex_unlock(&mLock); + errno = EBUSY; + return -1; + } + mController = c; + + sockaddr_in addr; + if ((mListenerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + LOGE("Failed to create DHCP listener socket"); + pthread_mutex_unlock(&mLock); + return -1; + } + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_port = htons(DhcpClient::STATUS_MONITOR_PORT); + + if (bind(mListenerSocket, (struct sockaddr *) &addr, sizeof(addr))) { + LOGE("Failed to bind DHCP listener socket"); + close(mListenerSocket); + mListenerSocket = -1; + pthread_mutex_unlock(&mLock); return -1; } - mListener = new DhcpListener(mHandlers); + if (mServiceManager->start(svc)) { + LOGE("Failed to start dhcp service"); + pthread_mutex_unlock(&mLock); + return -1; + } + + mListener = new DhcpListener(mController, mListenerSocket, mHandlers); if (mListener->startListener()) { LOGE("Failed to start listener"); #if 0 - mServiceManager->stop("dhcpcd_ng"); + mServiceManager->stop("dhcpcd"); return -1; #endif delete mListener; mListener = NULL; + pthread_mutex_unlock(&mLock); } - mState = DhcpState::STARTED; - + pthread_mutex_unlock(&mLock); return 0; } int DhcpClient::stop() { + pthread_mutex_lock(&mLock); + if (!mController) { + pthread_mutex_unlock(&mLock); + return 0; + } + if (mListener) { mListener->stopListener(); delete mListener; mListener = NULL; } + close(mListenerSocket); - if (mServiceManager->stop("dhcpcd_ng")) + if (mServiceManager->stop("dhcpcd")) { LOGW("Failed to stop DHCP service (%s)", strerror(errno)); - mState = DhcpState::STOPPED; + // XXX: Kill it the hard way.. but its gotta go! + } + + mController = NULL; + pthread_mutex_unlock(&mLock); return 0; } + +void DhcpClient::setDoArpProbe(bool probe) { + mDoArpProbe = probe; +} diff --git a/nexus/DhcpClient.h b/nexus/DhcpClient.h index e0a2784b5..42bfda073 100644 --- a/nexus/DhcpClient.h +++ b/nexus/DhcpClient.h @@ -18,23 +18,36 @@ #ifndef _DhcpClient_H #define _DhcpClient_H +#include + class IDhcpEventHandlers; class ServiceManager; class DhcpListener; +class Controller; class DhcpClient { +public: + static const int STATUS_MONITOR_PORT = 6666; + +private: int mState; IDhcpEventHandlers *mHandlers; ServiceManager *mServiceManager; DhcpListener *mListener; + int mListenerSocket; + pthread_mutex_t mLock; + Controller *mController; + bool mDoArpProbe; public: DhcpClient(IDhcpEventHandlers *handlers); virtual ~DhcpClient(); int getState() { return mState; } + bool getDoArpProbe() { return mDoArpProbe; } + void setDoArpProbe(bool probe); - int start(const char *interface); + int start(Controller *c); int stop(); }; diff --git a/nexus/DhcpEvent.cpp b/nexus/DhcpEvent.cpp new file mode 100644 index 000000000..58893f409 --- /dev/null +++ b/nexus/DhcpEvent.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "DhcpEvent" +#include + +#include "DhcpEvent.h" + +char *DhcpEvent::toString(int val, char *buffer, int max) { + if (val == DhcpEvent::UNKNOWN) + strncpy(buffer, "UNKNOWN", max); + else if (val == DhcpEvent::STOP) + strncpy(buffer, "STOP", max); + else if (val == DhcpEvent::RENEW) + strncpy(buffer, "RENEW", max); + else if (val == DhcpEvent::RELEASE) + strncpy(buffer, "RELEASE", max); + else if (val == DhcpEvent::TIMEOUT) + strncpy(buffer, "TIMEOUT", max); + else + strncpy(buffer, "(internal error)", max); + + return buffer; +} + +int DhcpEvent::parseString(const char *buffer) { + if (!strcasecmp(buffer, "UNKNOWN")) + return DhcpEvent::UNKNOWN; + else if (!strcasecmp(buffer, "STOP")) + return DhcpEvent::STOP; + else if (!strcasecmp(buffer, "RENEW")) + return DhcpEvent::RENEW; + else if (!strcasecmp(buffer, "RELEASE")) + return DhcpEvent::RELEASE; + else if (!strcasecmp(buffer, "TIMEOUT")) + return DhcpEvent::TIMEOUT; + else { + LOGW("Bad event '%s'", buffer); + return -1; + } +} diff --git a/nexus/IPropertyProvider.h b/nexus/DhcpEvent.h similarity index 63% rename from nexus/IPropertyProvider.h rename to nexus/DhcpEvent.h index 17ad5f8ce..f77834dc3 100644 --- a/nexus/IPropertyProvider.h +++ b/nexus/DhcpEvent.h @@ -14,20 +14,20 @@ * limitations under the License. */ -#ifndef _IPROPERTY_PROVIDER_H -#define _IPROPERTY_PROVIDER_H +#ifndef _DHCP_EVENT_H +#define _DHCP_EVENT_H -#include -#include - -#include - -class IPropertyProvider { +class DhcpEvent { public: - virtual int set(const char *name, const char *value) = 0; - virtual const char *get(const char *name, char *buffer, size_t max) = 0; + static const int UNKNOWN = 0; + static const int STOP = 1; + static const int RENEW = 2; + static const int RELEASE = 3; + static const int TIMEOUT = 4; + + static char *toString(int val, char *buffer, int max); + + static int parseString(const char *buffer); }; -typedef android::List IPropertyProviderCollection; - #endif diff --git a/nexus/DhcpListener.cpp b/nexus/DhcpListener.cpp index 2d07ee85d..afa68ebdb 100644 --- a/nexus/DhcpListener.cpp +++ b/nexus/DhcpListener.cpp @@ -14,21 +14,95 @@ * limitations under the License. */ +#include +#include +#include +#include + #define LOG_TAG "DhcpListener" #include #include #include "IDhcpEventHandlers.h" +#include "DhcpState.h" +#include "DhcpEvent.h" +#include "Controller.h" -DhcpListener::DhcpListener(IDhcpEventHandlers *handlers) : - SocketListener("dhcp_ng", false) { +DhcpListener::DhcpListener(Controller *c, int socket, IDhcpEventHandlers *handlers) : + SocketListener(socket, false) { mHandlers = handlers; + mController = c; } DhcpListener::~DhcpListener() { } bool DhcpListener::onDataAvailable(SocketClient *cli) { - LOGD("onDataAvailable()"); + char buffer[255]; + int rc; + + if ((rc = read(cli->getSocket(), buffer, sizeof(buffer))) < 0) { + LOGW("Error reading dhcp status msg (%s)", strerror(errno)); + return true; + } + + if (!strncmp(buffer, "STATE:", 6)) { + char *next = buffer; + char *tmp; + int i; + + for (i = 0; i < 2; i++) { + if (!(tmp = strsep(&next, ":"))) { + LOGW("Error parsing state '%s'", buffer); + return true; + } + } + + int st = DhcpState::parseString(tmp); + mHandlers->onDhcpStateChanged(mController, st); + } else if (!strncmp(buffer, "ADDRINFO:", 9)) { + char *next = buffer + 9; + struct in_addr ipaddr, netmask, gateway, broadcast, dns1, dns2; + + if (!inet_aton(strsep(&next, ":"), &ipaddr)) { + LOGW("Malformatted IP specified"); + } + if (!inet_aton(strsep(&next, ":"), &netmask)) { + LOGW("Malformatted netmask specified"); + } + if (!inet_aton(strsep(&next, ":"), &broadcast)) { + LOGW("Malformatted broadcast specified"); + } + if (!inet_aton(strsep(&next, ":"), &gateway)) { + LOGW("Malformatted gateway specified"); + } + if (!inet_aton(strsep(&next, ":"), &dns1)) { + LOGW("Malformatted dns1 specified"); + } + if (!inet_aton(strsep(&next, ":"), &dns2)) { + LOGW("Malformatted dns2 specified"); + } + mHandlers->onDhcpLeaseUpdated(mController, &ipaddr, &netmask, + &broadcast, &gateway, &dns1, &dns2); + + } else if (!strncmp(buffer, "EVENT:", 6)) { + char *next = buffer; + char *tmp; + int i; + + for (i = 0; i < 2; i++) { + if (!(tmp = strsep(&next, ":"))) { + LOGW("Error parsing event '%s'", buffer); + return true; + } + } + + int ev = DhcpEvent::parseString(tmp); + mHandlers->onDhcpEvent(mController, ev); + + } else { + LOGW("Unknown DHCP monitor msg '%s'", buffer); + } + return true; } diff --git a/nexus/DhcpListener.h b/nexus/DhcpListener.h index bfc5a3771..ca6fe3788 100644 --- a/nexus/DhcpListener.h +++ b/nexus/DhcpListener.h @@ -20,13 +20,15 @@ #include class IDhcpEventHandlers; +class Controller; class DhcpListener : public SocketListener { IDhcpEventHandlers *mHandlers; + Controller *mController; public: - DhcpListener(IDhcpEventHandlers *handlers); + DhcpListener(Controller *c, int socket, IDhcpEventHandlers *handlers); virtual ~DhcpListener(); private: diff --git a/nexus/DhcpState.cpp b/nexus/DhcpState.cpp new file mode 100644 index 000000000..c9d513581 --- /dev/null +++ b/nexus/DhcpState.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "DhcpState" +#include + +#include "DhcpState.h" + +char *DhcpState::toString(int val, char *buffer, int max) { + if (val == DhcpState::INIT) + strncpy(buffer, "INIT", max); + else if (val == DhcpState::DISCOVERING) + strncpy(buffer, "DISCOVERING", max); + else if (val == DhcpState::REQUESTING) + strncpy(buffer, "REQUESTING", max); + else if (val == DhcpState::BOUND) + strncpy(buffer, "BOUND", max); + else if (val == DhcpState::RENEWING) + strncpy(buffer, "RENEWING", max); + else if (val == DhcpState::REBINDING) + strncpy(buffer, "REBINDING", max); + else if (val == DhcpState::REBOOT) + strncpy(buffer, "REBOOT", max); + else if (val == DhcpState::RENEW_REQUESTED) + strncpy(buffer, "RENEW_REQUESTED", max); + else if (val == DhcpState::INIT_IPV4LL) + strncpy(buffer, "INIT_IPV4LL", max); + else if (val == DhcpState::PROBING) + strncpy(buffer, "PROBING", max); + else if (val == DhcpState::ANNOUNCING) + strncpy(buffer, "ANNOUNCING", max); + else + strncpy(buffer, "(internal error)", max); + + return buffer; +} + +int DhcpState::parseString(const char *buffer) { + if (!strcasecmp(buffer, "INIT")) + return DhcpState::INIT; + else if (!strcasecmp(buffer, "DISCOVERING")) + return DhcpState::DISCOVERING; + else if (!strcasecmp(buffer, "REQUESTING")) + return DhcpState::REQUESTING; + else if (!strcasecmp(buffer, "BOUND")) + return DhcpState::BOUND; + else if (!strcasecmp(buffer, "RENEWING")) + return DhcpState::RENEWING; + else if (!strcasecmp(buffer, "REBINDING")) + return DhcpState::REBINDING; + else if (!strcasecmp(buffer, "REBOOT")) + return DhcpState::REBOOT; + else if (!strcasecmp(buffer, "RENEW_REQUESTED")) + return DhcpState::INIT_IPV4LL; + else if (!strcasecmp(buffer, "INIT_IPV4LL")) + return DhcpState::INIT_IPV4LL; + else if (!strcasecmp(buffer, "PROBING")) + return DhcpState::PROBING; + else if (!strcasecmp(buffer, "ANNOUNCING")) + return DhcpState::ANNOUNCING; + else { + LOGW("Bad state '%s'", buffer); + return -1; + } +} diff --git a/nexus/DhcpState.h b/nexus/DhcpState.h index 27d7c7e37..041c5d24e 100644 --- a/nexus/DhcpState.h +++ b/nexus/DhcpState.h @@ -14,14 +14,26 @@ * limitations under the License. */ -#ifndef _DhcpState_H -#define _DhcpState_H +#ifndef _DHCP_STATE_H +#define _DHCP_STATE_H class DhcpState { public: - static const int UNKNOWN = 0; - static const int STOPPED = 1; - static const int STARTED = 2; + static const int INIT = 0; + static const int DISCOVERING = 1; + static const int REQUESTING = 2; + static const int BOUND = 3; + static const int RENEWING = 4; + static const int REBINDING = 5; + static const int REBOOT = 6; + static const int RENEW_REQUESTED = 7; + static const int INIT_IPV4LL = 8; + static const int PROBING = 9; + static const int ANNOUNCING = 10; + + static char *toString(int val, char *buffer, int max); + + static int parseString(const char *buffer); }; #endif diff --git a/nexus/IControllerHandler.h b/nexus/IControllerHandler.h index f7be39cea..3151587d1 100644 --- a/nexus/IControllerHandler.h +++ b/nexus/IControllerHandler.h @@ -22,8 +22,11 @@ class InterfaceConfig; class IControllerHandler { public: - virtual void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) = 0; - virtual void onInterfaceDisconnected(Controller *c, const char *name) = 0; + virtual ~IControllerHandler() {} + virtual void onInterfaceConnected(Controller *c) = 0; + virtual void onInterfaceDisconnected(Controller *c) = 0; + virtual void onControllerSuspending(Controller *c) = 0; + virtual void onControllerResumed(Controller *c) = 0; }; #endif diff --git a/nexus/IDhcpEventHandlers.h b/nexus/IDhcpEventHandlers.h index 3f51f645d..2568f0947 100644 --- a/nexus/IDhcpEventHandlers.h +++ b/nexus/IDhcpEventHandlers.h @@ -20,6 +20,14 @@ class IDhcpEventHandlers { public: + virtual ~IDhcpEventHandlers() {} + virtual void onDhcpStateChanged(Controller *c, int state) = 0; + virtual void onDhcpEvent(Controller *c, int event) = 0; + virtual void onDhcpLeaseUpdated(Controller *c, + struct in_addr *addr, struct in_addr *net, + struct in_addr *brd, + struct in_addr *gw, struct in_addr *dns1, + struct in_addr *dns2) = 0; }; #endif diff --git a/nexus/ISupplicantEventHandler.h b/nexus/ISupplicantEventHandler.h index b7fd17b56..1a3aa07f5 100644 --- a/nexus/ISupplicantEventHandler.h +++ b/nexus/ISupplicantEventHandler.h @@ -27,6 +27,7 @@ class SupplicantDisconnectedEvent; class ISupplicantEventHandler { public: + virtual ~ISupplicantEventHandler(){} virtual void onAssociatingEvent(SupplicantAssociatingEvent *evt) = 0; virtual void onAssociatedEvent(SupplicantAssociatedEvent *evt) = 0; virtual void onConnectedEvent(SupplicantConnectedEvent *evt) = 0; diff --git a/nexus/IWifiStatusPollerHandler.h b/nexus/IWifiStatusPollerHandler.h new file mode 100644 index 000000000..9b9494590 --- /dev/null +++ b/nexus/IWifiStatusPollerHandler.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IWIFISTATUSPOLLER_HANDLER_H +#define _IWIFISTATUSPOLLER_HANDLER_H + +class IWifiStatusPollerHandler { +public: + virtual ~IWifiStatusPollerHandler() {} + virtual void onStatusPollInterval() = 0; +}; + +#endif diff --git a/nexus/InterfaceConfig.cpp b/nexus/InterfaceConfig.cpp index 66861d02a..832cbcabd 100644 --- a/nexus/InterfaceConfig.cpp +++ b/nexus/InterfaceConfig.cpp @@ -23,147 +23,72 @@ #include "InterfaceConfig.h" #include "NetworkManager.h" -const char *InterfaceConfig::PropertyNames[] = { "dhcp", "ip", - "netmask", - "gateway", "dns1", "dns2", - "dns3", '\0' }; - -InterfaceConfig::InterfaceConfig(const char *prop_prefix) { - mPropPrefix = strdup(prop_prefix); - mUseDhcp = true; - registerProperties(); +InterfaceConfig::InterfaceConfig(bool propertiesReadOnly) { + mStaticProperties.propIp = new IPV4AddressPropertyHelper("Addr", propertiesReadOnly, &mIp); + mStaticProperties.propNetmask = new IPV4AddressPropertyHelper("Netmask", propertiesReadOnly, &mNetmask); + mStaticProperties.propGateway = new IPV4AddressPropertyHelper("Gateway", propertiesReadOnly, &mGateway); + mStaticProperties.propBroadcast = new IPV4AddressPropertyHelper("Broadcast", propertiesReadOnly, &mBroadcast); + mStaticProperties.propDns = new InterfaceDnsProperty(this, propertiesReadOnly); } InterfaceConfig::~InterfaceConfig() { - unregisterProperties(); - free(mPropPrefix); + delete mStaticProperties.propIp; + delete mStaticProperties.propNetmask; + delete mStaticProperties.propGateway; + delete mStaticProperties.propBroadcast; + delete mStaticProperties.propDns; } -InterfaceConfig::InterfaceConfig(const char *prop_prefix, - const char *ip, const char *nm, - const char *gw, const char *dns1, const char *dns2, - const char *dns3) { - mPropPrefix = strdup(prop_prefix); - mUseDhcp = false; - - if (!inet_aton(ip, &mIp)) - LOGW("Unable to parse ip (%s)", ip); - if (!inet_aton(nm, &mNetmask)) - LOGW("Unable to parse netmask (%s)", nm); - if (!inet_aton(gw, &mGateway)) - LOGW("Unable to parse gateway (%s)", gw); - if (!inet_aton(dns1, &mDns1)) - LOGW("Unable to parse dns1 (%s)", dns1); - if (!inet_aton(dns2, &mDns2)) - LOGW("Unable to parse dns2 (%s)", dns2); - if (!inet_aton(dns3, &mDns3)) - LOGW("Unable to parse dns3 (%s)", dns3); - registerProperties(); +void InterfaceConfig::setIp(struct in_addr *addr) { + memcpy(&mIp, addr, sizeof(struct in_addr)); } -InterfaceConfig::InterfaceConfig(const char *prop_prefix, - const struct in_addr *ip, - const struct in_addr *nm, const struct in_addr *gw, - const struct in_addr *dns1, const struct in_addr *dns2, - const struct in_addr *dns3) { - mPropPrefix = strdup(prop_prefix); - mUseDhcp = false; - - memcpy(&mIp, ip, sizeof(struct in_addr)); - memcpy(&mNetmask, nm, sizeof(struct in_addr)); - memcpy(&mGateway, gw, sizeof(struct in_addr)); - memcpy(&mDns1, dns1, sizeof(struct in_addr)); - memcpy(&mDns2, dns2, sizeof(struct in_addr)); - memcpy(&mDns3, dns3, sizeof(struct in_addr)); - registerProperties(); +void InterfaceConfig::setNetmask(struct in_addr *addr) { + memcpy(&mNetmask, addr, sizeof(struct in_addr)); } -int InterfaceConfig::registerProperties() { - for (const char **p = InterfaceConfig::PropertyNames; *p != '\0'; p++) { - char *tmp; - asprintf(&tmp, "%s.if.%s", mPropPrefix, *p); +void InterfaceConfig::setGateway(struct in_addr *addr) { + memcpy(&mGateway, addr, sizeof(struct in_addr)); +} - if (NetworkManager::Instance()->getPropMngr()->registerProperty(tmp, - this)) { - free(tmp); - return -1; - } - free(tmp); - } +void InterfaceConfig::setBroadcast(struct in_addr *addr) { + memcpy(&mBroadcast, addr, sizeof(struct in_addr)); +} + +void InterfaceConfig::setDns(int idx, struct in_addr *addr) { + memcpy(&mDns[idx], addr, sizeof(struct in_addr)); +} + +int InterfaceConfig::attachProperties(PropertyManager *pm, const char *nsName) { + pm->attachProperty(nsName, mStaticProperties.propIp); + pm->attachProperty(nsName, mStaticProperties.propNetmask); + pm->attachProperty(nsName, mStaticProperties.propGateway); + pm->attachProperty(nsName, mStaticProperties.propBroadcast); + pm->attachProperty(nsName, mStaticProperties.propDns); return 0; } -int InterfaceConfig::unregisterProperties() { - for (const char **p = InterfaceConfig::PropertyNames; *p != '\0'; p++) { - char *tmp; - asprintf(&tmp, "%s.if.%s", mPropPrefix, *p); - - if (NetworkManager::Instance()->getPropMngr()->unregisterProperty(tmp)) - LOGW("Unable to remove property '%s' (%s)", tmp, strerror(errno)); - free(tmp); - } +int InterfaceConfig::detachProperties(PropertyManager *pm, const char *nsName) { + pm->detachProperty(nsName, mStaticProperties.propIp); + pm->detachProperty(nsName, mStaticProperties.propNetmask); + pm->detachProperty(nsName, mStaticProperties.propGateway); + pm->detachProperty(nsName, mStaticProperties.propBroadcast); + pm->detachProperty(nsName, mStaticProperties.propDns); return 0; } -int InterfaceConfig::set(const char *name, const char *value) { - const char *n; - - for (n = &name[strlen(name)]; *n != '.'; n--); - n++; - - if (!strcasecmp(n, "name")) { - errno = EROFS; - return -1; - } else if (!strcasecmp(n, "ip") && !inet_aton(value, &mIp)) - goto out_inval; - else if (!strcasecmp(n, "dhcp")) - mUseDhcp = (atoi(value) == 0 ? false : true); - else if (!strcasecmp(n, "netmask") && !inet_aton(value, &mNetmask)) - goto out_inval; - else if (!strcasecmp(n, "gateway") && !inet_aton(value, &mGateway)) - goto out_inval; - else if (!strcasecmp(n, "dns1") && !inet_aton(value, &mDns1)) - goto out_inval; - else if (!strcasecmp(n, "dns2") && !inet_aton(value, &mDns2)) - goto out_inval; - else if (!strcasecmp(n, "dns3") && !inet_aton(value, &mDns3)) - goto out_inval; - else { - errno = ENOENT; - return -1; - } +InterfaceConfig::InterfaceDnsProperty::InterfaceDnsProperty(InterfaceConfig *c, + bool ro) : + IPV4AddressProperty("Dns", ro, 2) { + mCfg = c; +} +int InterfaceConfig::InterfaceDnsProperty::set(int idx, struct in_addr *value) { + memcpy(&mCfg->mDns[idx], value, sizeof(struct in_addr)); + return 0; +} +int InterfaceConfig::InterfaceDnsProperty::get(int idx, struct in_addr *buf) { + memcpy(buf, &mCfg->mDns[idx], sizeof(struct in_addr)); return 0; - -out_inval: - errno = EINVAL; - return -1; } -const char *InterfaceConfig::get(const char *name, char *buffer, size_t max) { - const char *n; - - for (n = &name[strlen(name)]; *n != '.'; n--); - n++; - - if (!strcasecmp(n, "ip")) - strncpy(buffer, inet_ntoa(mIp), max); - else if (!strcasecmp(n, "dhcp")) - snprintf(buffer, max, "%d", mUseDhcp); - else if (!strcasecmp(n, "netmask")) - strncpy(buffer, inet_ntoa(mNetmask), max); - else if (!strcasecmp(n, "gateway")) - strncpy(buffer, inet_ntoa(mGateway), max); - else if (!strcasecmp(n, "dns1")) - strncpy(buffer, inet_ntoa(mDns1), max); - else if (!strcasecmp(n, "dns2")) - strncpy(buffer, inet_ntoa(mDns2), max); - else if (!strcasecmp(n, "dns3")) - strncpy(buffer, inet_ntoa(mDns3), max); - else { - strncpy(buffer, "(internal error)", max); - errno = ENOENT; - return NULL; - } - return buffer; -} diff --git a/nexus/InterfaceConfig.h b/nexus/InterfaceConfig.h index d97f20b2d..3fc73909c 100644 --- a/nexus/InterfaceConfig.h +++ b/nexus/InterfaceConfig.h @@ -22,53 +22,58 @@ #include #include -#include "IPropertyProvider.h" - +#include "Property.h" class PropertyManager; -class InterfaceConfig : public IPropertyProvider { -public: - static const char *PropertyNames[]; +class InterfaceConfig { + class InterfaceDnsProperty; + friend class InterfaceConfig::InterfaceDnsProperty; + + struct { + IPV4AddressPropertyHelper *propIp; + IPV4AddressPropertyHelper *propNetmask; + IPV4AddressPropertyHelper *propGateway; + IPV4AddressPropertyHelper *propBroadcast; + InterfaceDnsProperty *propDns; + } mStaticProperties; -private: - char *mPropPrefix; - bool mUseDhcp; struct in_addr mIp; struct in_addr mNetmask; struct in_addr mGateway; - struct in_addr mDns1; - struct in_addr mDns2; - struct in_addr mDns3; + struct in_addr mBroadcast; + struct in_addr mDns[2]; public: - InterfaceConfig(const char *prop_prefix); - InterfaceConfig(const char *prop_prefix, - const char *ip, const char *nm, - const char *gw, const char *dns1, const char *dns2, - const char *dns3); - - InterfaceConfig(const char *prop_prefix, - const struct in_addr *ip, - const struct in_addr *nm, const struct in_addr *gw, - const struct in_addr *dns1, const struct in_addr *dns2, - const struct in_addr *dns3); - + InterfaceConfig(bool propertiesReadOnly); virtual ~InterfaceConfig(); int set(const char *name, const char *value); const char *get(const char *name, char *buffer, size_t maxsize); - bool getUseDhcp() const { return mUseDhcp; } const struct in_addr &getIp() const { return mIp; } const struct in_addr &getNetmask() const { return mNetmask; } const struct in_addr &getGateway() const { return mGateway; } - const struct in_addr &getDns1() const { return mDns1; } - const struct in_addr &getDns2() const { return mDns2; } - const struct in_addr &getDns3() const { return mDns3; } + const struct in_addr &getBroadcast() const { return mBroadcast; } + const struct in_addr &getDns(int idx) const { return mDns[idx]; } + + void setIp(struct in_addr *addr); + void setNetmask(struct in_addr *addr); + void setGateway(struct in_addr *addr); + void setBroadcast(struct in_addr *addr); + void setDns(int idx, struct in_addr *addr); + + int attachProperties(PropertyManager *pm, const char *nsName); + int detachProperties(PropertyManager *pm, const char *nsName); private: - int registerProperties(); - int unregisterProperties(); + + class InterfaceDnsProperty : public IPV4AddressProperty { + InterfaceConfig *mCfg; + public: + InterfaceDnsProperty(InterfaceConfig *cfg, bool ro); + int set(int idx, struct in_addr *value); + int get(int idx, struct in_addr *buffer); + }; }; diff --git a/nexus/LoopController.cpp b/nexus/LoopController.cpp index 5cfb1fecb..f8e01d7c2 100644 --- a/nexus/LoopController.cpp +++ b/nexus/LoopController.cpp @@ -21,14 +21,5 @@ LoopController::LoopController(PropertyManager *propmngr, IControllerHandler *handlers) : - Controller("LOOP", propmngr, handlers) { + Controller("loop", propmngr, handlers) { } - -int LoopController::set(const char *name, const char *value) { - return Controller::set(name, value); -} - -const char *LoopController::get(const char *name, char *buffer, size_t maxsize) { - return Controller::get(name, buffer, maxsize); -} - diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp index 7450b951b..e0df4096a 100644 --- a/nexus/NetworkManager.cpp +++ b/nexus/NetworkManager.cpp @@ -24,6 +24,9 @@ #include "NetworkManager.h" #include "InterfaceConfig.h" #include "DhcpClient.h" +#include "DhcpState.h" +#include "DhcpEvent.h" +#include "ResponseCode.h" NetworkManager *NetworkManager::sInstance = NULL; @@ -35,8 +38,9 @@ NetworkManager *NetworkManager::Instance() { NetworkManager::NetworkManager(PropertyManager *propMngr) { mBroadcaster = NULL; - mControllers = new ControllerCollection(); + mControllerBindings = new ControllerBindingCollection(); mPropMngr = propMngr; + mLastDhcpState = DhcpState::INIT; mDhcp = new DhcpClient(this); } @@ -51,17 +55,17 @@ int NetworkManager::run() { } int NetworkManager::attachController(Controller *c) { - mControllers->push_back(c); + ControllerBinding *cb = new ControllerBinding(c); + mControllerBindings->push_back(cb); return 0; } int NetworkManager::startControllers() { int rc = 0; - ControllerCollection::iterator i; + ControllerBindingCollection::iterator it; - for (i = mControllers->begin(); i != mControllers->end(); ++i) { - int irc = (*i)->start(); - LOGD("Controller '%s' start rc = %d", (*i)->getName(), irc); + for (it = mControllerBindings->begin(); it != mControllerBindings->end(); ++it) { + int irc = (*it)->getController()->start(); if (irc && !rc) rc = irc; } @@ -70,52 +74,132 @@ int NetworkManager::startControllers() { int NetworkManager::stopControllers() { int rc = 0; - ControllerCollection::iterator i; + ControllerBindingCollection::iterator it; - for (i = mControllers->begin(); i != mControllers->end(); ++i) { - int irc = (*i)->stop(); - LOGD("Controller '%s' stop rc = %d", (*i)->getName(), irc); + for (it = mControllerBindings->begin(); it != mControllerBindings->end(); ++it) { + int irc = (*it)->getController()->stop(); if (irc && !rc) rc = irc; } return rc; } -Controller *NetworkManager::findController(const char *name) { - ControllerCollection::iterator i; - for (i = mControllers->begin(); i != mControllers->end(); ++i) { - if (!strcmp((*i)->getName(), name)) - return *i; +NetworkManager::ControllerBinding *NetworkManager::lookupBinding(Controller *c) { + ControllerBindingCollection::iterator it; + + for (it = mControllerBindings->begin(); it != mControllerBindings->end(); ++it) { + if ((*it)->getController() == c) + return (*it); } - LOGW("Controller '%s' not found", name); + errno = ENOENT; return NULL; } -void NetworkManager::onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) { +Controller *NetworkManager::findController(const char *name) { + ControllerBindingCollection::iterator it; + + for (it = mControllerBindings->begin(); it != mControllerBindings->end(); ++it) { + if (!strcasecmp((*it)->getController()->getName(), name)) + return (*it)->getController(); + } + errno = ENOENT; + return NULL; +} + +void NetworkManager::onInterfaceConnected(Controller *c) { LOGD("Controller %s interface %s connected", c->getName(), c->getBoundInterface()); - // Look up the interface - - if (0) { // already started? - } - - if (cfg) { - if (cfg->getUseDhcp() && mDhcp->start(c->getBoundInterface())) { - LOGE("DHCP start failed"); - } else if (!cfg->getUseDhcp()) { - // Static configuration - } - } else { - LOGD("No InterfaceConfig for %s:%s - assuming self-managed", - c->getName(), c->getBoundInterface()); + if (mDhcp->start(c)) { + LOGE("Failed to start DHCP (%s)", strerror(errno)); + return; } } -void NetworkManager::onInterfaceDisconnected(Controller *c, const char *name) { - LOGD("Controller %s interface %s disconnected", c->getName(), name); +void NetworkManager::onInterfaceDisconnected(Controller *c) { + LOGD("Controller %s interface %s disconnected", c->getName(), + c->getBoundInterface()); - // If we have a DHCP request out on this interface then stop it - if (1) { - mDhcp->stop(); - } + mDhcp->stop(); } + +void NetworkManager::onControllerSuspending(Controller *c) { + LOGD("Controller %s interface %s suspending", c->getName(), + c->getBoundInterface()); + mDhcp->stop(); +} + +void NetworkManager::onControllerResumed(Controller *c) { + LOGD("Controller %s interface %s resumed", c->getName(), + c->getBoundInterface()); +} + +void NetworkManager::onDhcpStateChanged(Controller *c, int state) { + char tmp[255]; + char tmp2[255]; + + LOGD("onDhcpStateChanged(%s -> %s)", + DhcpState::toString(mLastDhcpState, tmp, sizeof(tmp)), + DhcpState::toString(state, tmp2, sizeof(tmp2))); + + switch(state) { + case DhcpState::BOUND: + // Refresh the 'net.xxx' for the controller + break; + case DhcpState::RENEWING: + break; + default: + break; + } + + char *tmp3; + asprintf(&tmp3, + "DHCP state changed from %d (%s) -> %d (%s)", + mLastDhcpState, + DhcpState::toString(mLastDhcpState, tmp, sizeof(tmp)), + state, + DhcpState::toString(state, tmp2, sizeof(tmp2))); + + getBroadcaster()->sendBroadcast(ResponseCode::DhcpStateChange, + tmp3, + false); + free(tmp3); + + mLastDhcpState = state; +} + +void NetworkManager::onDhcpEvent(Controller *c, int evt) { + char tmp[64]; + LOGD("onDhcpEvent(%s)", DhcpEvent::toString(evt, tmp, sizeof(tmp))); +} + +void NetworkManager::onDhcpLeaseUpdated(Controller *c, struct in_addr *addr, + struct in_addr *net, + struct in_addr *brd, + struct in_addr *gw, + struct in_addr *dns1, + struct in_addr *dns2) { + ControllerBinding *bind = lookupBinding(c); + + if (!bind->getCurrentCfg()) + bind->setCurrentCfg(new InterfaceConfig(true)); + + bind->getCurrentCfg()->setIp(addr); + bind->getCurrentCfg()->setNetmask(net); + bind->getCurrentCfg()->setGateway(gw); + bind->getCurrentCfg()->setBroadcast(brd); + bind->getCurrentCfg()->setDns(0, dns1); + bind->getCurrentCfg()->setDns(1, dns2); +} + +NetworkManager::ControllerBinding::ControllerBinding(Controller *c) : + mController(c) { +} + +void NetworkManager::ControllerBinding::setCurrentCfg(InterfaceConfig *c) { + mCurrentCfg = c; +} + +void NetworkManager::ControllerBinding::setBoundCfg(InterfaceConfig *c) { + mBoundCfg = c; +} + diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h index 44f3417fd..93702ce8d 100644 --- a/nexus/NetworkManager.h +++ b/nexus/NetworkManager.h @@ -17,6 +17,7 @@ #ifndef _NETWORKMANAGER_H #define _NETWORKMANAGER_H +#include #include #include "Controller.h" @@ -28,14 +29,33 @@ class InterfaceConfig; class DhcpClient; class NetworkManager : public IControllerHandler, public IDhcpEventHandlers { -private: static NetworkManager *sInstance; + class ControllerBinding { + Controller *mController; + InterfaceConfig *mCurrentCfg; + InterfaceConfig *mBoundCfg; + + public: + ControllerBinding(Controller *c); + virtual ~ControllerBinding() {} + + InterfaceConfig *getCurrentCfg() { return mCurrentCfg; } + InterfaceConfig *getBoundCfg() { return mCurrentCfg; } + Controller *getController() { return mController; } + + void setCurrentCfg(InterfaceConfig *cfg); + void setBoundCfg(InterfaceConfig *cfg); + }; + + typedef android::List ControllerBindingCollection; + private: - ControllerCollection *mControllers; - SocketListener *mBroadcaster; - PropertyManager *mPropMngr; - DhcpClient *mDhcp; + ControllerBindingCollection *mControllerBindings; + SocketListener *mBroadcaster; + PropertyManager *mPropMngr; + DhcpClient *mDhcp; + int mLastDhcpState; public: virtual ~NetworkManager(); @@ -57,8 +77,19 @@ private: int stopControllers(); NetworkManager(PropertyManager *propMngr); + ControllerBinding *lookupBinding(Controller *c); - void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg); - void onInterfaceDisconnected(Controller *c, const char *name); + void onInterfaceConnected(Controller *c); + void onInterfaceDisconnected(Controller *c); + void onControllerSuspending(Controller *c); + void onControllerResumed(Controller *c); + + void onDhcpStateChanged(Controller *c, int state); + void onDhcpEvent(Controller *c, int event); + void onDhcpLeaseUpdated(Controller *c, + struct in_addr *addr, struct in_addr *net, + struct in_addr *brd, + struct in_addr *gw, struct in_addr *dns1, + struct in_addr *dns2); }; #endif diff --git a/nexus/Property.cpp b/nexus/Property.cpp new file mode 100644 index 000000000..d02769d57 --- /dev/null +++ b/nexus/Property.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#define LOG_TAG "Property" + +#include + +#include "Property.h" + +Property::Property(const char *name, bool readOnly, + int type, int numElements) : + mName(name), mReadOnly(readOnly), mType(type), + mNumElements(numElements) { + if (index(name, '.')) { + LOGW("Property name %s violates namespace rules", name); + } +} + +StringProperty::StringProperty(const char *name, bool ro, int elements) : + Property(name, ro, Property::Type_STRING, elements) { +} +int StringProperty::set(int idx, int value) { + LOGE("Integer 'set' called on string property!"); + errno = EINVAL; + return -1; +} +int StringProperty::set(int idx, struct in_addr *value) { + LOGE("IpAddr 'set' called on string property!"); + errno = EINVAL; + return -1; +} +int StringProperty::get(int idx, int *buffer) { + LOGE("Integer 'get' called on string property!"); + errno = EINVAL; + return -1; +} +int StringProperty::get(int idx, struct in_addr *buffer) { + LOGE("IpAddr 'get' called on string property!"); + errno = EINVAL; + return -1; +} + +StringPropertyHelper::StringPropertyHelper(const char *name, bool ro, + char *buffer, size_t max) : + StringProperty(name, ro, 1) { + mBuffer = buffer; + mMax = max; +} + +int StringPropertyHelper::set(int idx, const char *value) { + if (idx != 0) { + LOGW("Attempt to use array index on StringPropertyHelper::set"); + errno = EINVAL; + return -1; + } + strncpy(mBuffer, value, mMax); + return 0; +} + +int StringPropertyHelper::get(int idx, char *buffer, size_t max) { + if (idx != 0) { + LOGW("Attempt to use array index on StringPropertyHelper::get"); + errno = EINVAL; + return -1; + } + strncpy(buffer, mBuffer, max); + return 0; +} + +IntegerProperty::IntegerProperty(const char *name, bool ro, int elements) : + Property(name, ro, Property::Type_INTEGER, elements) { +} + +int IntegerProperty::set(int idx, const char *value) { + LOGE("String 'set' called on integer property!"); + errno = EINVAL; + return -1; +} +int IntegerProperty::set(int idx, struct in_addr *value) { + LOGE("IpAddr 'set' called on integer property!"); + errno = EINVAL; + return -1; +} +int IntegerProperty::get(int idx, char *buffer, size_t max) { + LOGE("String 'get' called on integer property!"); + errno = EINVAL; + return -1; +} +int IntegerProperty::get(int idx, struct in_addr *buffer) { + LOGE("IpAddr 'get' called on integer property!"); + errno = EINVAL; + return -1; +} + +IntegerPropertyHelper::IntegerPropertyHelper(const char *name, bool ro, + int *buffer) : + IntegerProperty(name, ro, 1) { + mBuffer = buffer; +} + +int IntegerPropertyHelper::set(int idx, int value) { + if (idx != 0) { + LOGW("Attempt to use array index on IntegerPropertyHelper::set"); + errno = EINVAL; + return -1; + } + *mBuffer = value; + return 0; +} + +int IntegerPropertyHelper::get(int idx, int *buffer) { + if (idx != 0) { + LOGW("Attempt to use array index on IntegerPropertyHelper::get"); + errno = EINVAL; + return -1; + } + *buffer = *mBuffer; + return 0; +} + +IPV4AddressProperty::IPV4AddressProperty(const char *name, bool ro, int elements) : + Property(name, ro, Property::Type_IPV4, elements) { +} + +int IPV4AddressProperty::set(int idx, const char *value) { + LOGE("String 'set' called on ipv4 property!"); + errno = EINVAL; + return -1; +} +int IPV4AddressProperty::set(int idx, int value) { + LOGE("Integer 'set' called on ipv4 property!"); + errno = EINVAL; + return -1; +} +int IPV4AddressProperty::get(int idx, char *buffer, size_t max) { + LOGE("String 'get' called on ipv4 property!"); + errno = EINVAL; + return -1; +} +int IPV4AddressProperty::get(int idx, int *buffer) { + LOGE("Integer 'get' called on ipv4 property!"); + errno = EINVAL; + return -1; +} + +IPV4AddressPropertyHelper::IPV4AddressPropertyHelper(const char *name, bool ro, + struct in_addr *buffer) : + IPV4AddressProperty(name, ro, 1) { + mBuffer = buffer; +} + +int IPV4AddressPropertyHelper::set(int idx, struct in_addr *value) { + if (idx != 0) { + LOGW("Attempt to use array index on IPV4AddressPropertyHelper::set"); + errno = EINVAL; + return -1; + } + memcpy(mBuffer, value, sizeof(struct in_addr)); + return 0; +} + +int IPV4AddressPropertyHelper::get(int idx, struct in_addr *buffer) { + if (idx != 0) { + LOGW("Attempt to use array index on IPV4AddressPropertyHelper::get"); + errno = EINVAL; + return -1; + } + memcpy(buffer, mBuffer, sizeof(struct in_addr)); + return 0; +} + +PropertyNamespace::PropertyNamespace(const char *name) { + mName = strdup(name); + mProperties = new PropertyCollection(); +} + +PropertyNamespace::~PropertyNamespace() { + PropertyCollection::iterator it; + for (it = mProperties->begin(); it != mProperties->end();) { + delete (*it); + it = mProperties->erase(it); + } + delete mProperties; + free(mName); +} diff --git a/nexus/Property.h b/nexus/Property.h index 198f7223c..ceea2d3e3 100644 --- a/nexus/Property.h +++ b/nexus/Property.h @@ -14,8 +14,124 @@ * limitations under the License. */ +#ifndef _PROPERTY_H +#define _PROPERTY_H + +#include +#include + class Property { + const char *mName; + bool mReadOnly; + int mType; + int mNumElements; + public: - static const int NameMaxSize = 128; + static const int NameMaxSize = 128; static const int ValueMaxSize = 255; + + static const int Type_STRING = 1; + static const int Type_INTEGER = 2; + static const int Type_IPV4 = 3; + + Property(const char *name, bool ro, int type, int elements); + virtual ~Property() {} + + virtual int set(int idx, const char *value) = 0; + virtual int set(int idx, int value) = 0; + virtual int set(int idx, struct in_addr *value) = 0; + + virtual int get(int idx, char *buffer, size_t max) = 0; + virtual int get(int idx, int *buffer) = 0; + virtual int get(int idx, struct in_addr *buffer) = 0; + + int getType() { return mType; } + bool getReadOnly() { return mReadOnly; } + int getNumElements() { return mNumElements; } + const char *getName() { return mName; } }; + +class StringProperty : public Property { +public: + StringProperty(const char *name, bool ro, int elements); + virtual ~StringProperty() {} + + virtual int set(int idx, const char *value) = 0; + int set(int idx, int value); + int set(int idx, struct in_addr *value); + + virtual int get(int idx, char *buffer, size_t max) = 0; + int get(int idx, int *buffer); + int get(int idx, struct in_addr *buffer); +}; + +class StringPropertyHelper : public StringProperty { + char *mBuffer; + size_t mMax; +public: + StringPropertyHelper(const char *name, bool ro, + char *buffer, size_t max); + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); +}; + +class IntegerProperty : public Property { +public: + IntegerProperty(const char *name, bool ro, int elements); + virtual ~IntegerProperty() {} + + int set(int idx, const char *value); + virtual int set(int idx, int value) = 0; + int set(int idx, struct in_addr *value); + + int get(int idx, char *buffer, size_t max); + virtual int get(int idx, int *buffer) = 0; + int get(int idx, struct in_addr *buffer); +}; + +class IntegerPropertyHelper : public IntegerProperty { + int *mBuffer; +public: + IntegerPropertyHelper(const char *name, bool ro, int *buffer); + int set(int idx, int value); + int get(int idx, int *buffer); +}; + +class IPV4AddressProperty : public Property { +public: + IPV4AddressProperty(const char *name, bool ro, int elements); + virtual ~IPV4AddressProperty() {} + + int set(int idx, const char *value); + int set(int idx, int value); + virtual int set(int idx, struct in_addr *value) = 0; + + int get(int idx, char *buffer, size_t max); + int get(int idx, int *buffer); + virtual int get(int idx, struct in_addr *buffer) = 0; +}; + +class IPV4AddressPropertyHelper : public IPV4AddressProperty { + struct in_addr *mBuffer; +public: + IPV4AddressPropertyHelper(const char *name, bool ro, struct in_addr *buf); + int set(int idx, struct in_addr *value); + int get(int idx, struct in_addr *buffer); +}; + +typedef android::List PropertyCollection; + +class PropertyNamespace { + char *mName; + PropertyCollection *mProperties; + +public: + PropertyNamespace(const char *name); + virtual ~PropertyNamespace(); + + const char *getName() { return mName; } + PropertyCollection *getProperties() { return mProperties; } +}; + +typedef android::List PropertyNamespaceCollection; +#endif diff --git a/nexus/PropertyManager.cpp b/nexus/PropertyManager.cpp index 6faf9b830..704b2230b 100644 --- a/nexus/PropertyManager.cpp +++ b/nexus/PropertyManager.cpp @@ -14,6 +14,11 @@ * limitations under the License. */ +#include +#include +#include +#include + #define LOG_TAG "PropertyManager" #include @@ -21,103 +26,255 @@ #include "PropertyManager.h" PropertyManager::PropertyManager() { - mPropertyPairs = new PropertyPairCollection(); + mNamespaces = new PropertyNamespaceCollection(); pthread_mutex_init(&mLock, NULL); } PropertyManager::~PropertyManager() { - delete mPropertyPairs; + PropertyNamespaceCollection::iterator it; + + for (it = mNamespaces->begin(); it != mNamespaces->end();) { + delete (*it); + it = mNamespaces->erase(it); + } + delete mNamespaces; } -int PropertyManager::registerProperty(const char *name, IPropertyProvider *pp) { - PropertyPairCollection::iterator it; +PropertyNamespace *PropertyManager::lookupNamespace_UNLOCKED(const char *ns) { + PropertyNamespaceCollection::iterator ns_it; -// LOGD("registerProperty(%s)", name); - pthread_mutex_lock(&mLock); - for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) { - if (!strcmp(name, (*it)->getName())) { - errno = EADDRINUSE; - LOGE("Failed to register property %s (%s)", - name, strerror(errno)); - pthread_mutex_unlock(&mLock); - return -1; - } + for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) { + if (!strcasecmp(ns, (*ns_it)->getName())) + return (*ns_it); } - mPropertyPairs->push_back(new PropertyPair(name, pp)); + errno = ENOENT; + return NULL; +} + +Property *PropertyManager::lookupProperty_UNLOCKED(PropertyNamespace *ns, const char *name) { + PropertyCollection::iterator it; + + for (it = ns->getProperties()->begin(); + it != ns->getProperties()->end(); ++it) { + if (!strcasecmp(name, (*it)->getName())) + return (*it); + } + errno = ENOENT; + return NULL; +} + +int PropertyManager::attachProperty(const char *ns_name, Property *p) { + PropertyNamespace *ns; + + LOGD("Attaching property %s to namespace %s", p->getName(), ns_name); + pthread_mutex_lock(&mLock); + if (!(ns = lookupNamespace_UNLOCKED(ns_name))) { + LOGD("Creating namespace %s", ns_name); + ns = new PropertyNamespace(ns_name); + mNamespaces->push_back(ns); + } + + if (lookupProperty_UNLOCKED(ns, p->getName())) { + errno = EADDRINUSE; + pthread_mutex_unlock(&mLock); + LOGE("Failed to register property %s.%s (%s)", + ns_name, p->getName(), strerror(errno)); + return -1; + } + + ns->getProperties()->push_back(p); pthread_mutex_unlock(&mLock); return 0; } -int PropertyManager::unregisterProperty(const char *name) { - PropertyPairCollection::iterator it; +int PropertyManager::detachProperty(const char *ns_name, Property *p) { + PropertyNamespace *ns; -// LOGD("unregisterProperty(%s)", name); + LOGD("Detaching property %s from namespace %s", p->getName(), ns_name); pthread_mutex_lock(&mLock); - for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) { - if (!strcmp(name, (*it)->getName())) { + if (!(ns = lookupNamespace_UNLOCKED(ns_name))) { + pthread_mutex_unlock(&mLock); + LOGE("Namespace '%s' not found", ns_name); + return -1; + } + + PropertyCollection::iterator it; + + for (it = ns->getProperties()->begin(); + it != ns->getProperties()->end(); ++it) { + if (!strcasecmp(p->getName(), (*it)->getName())) { delete ((*it)); - mPropertyPairs->erase(it); + ns->getProperties()->erase(it); pthread_mutex_unlock(&mLock); return 0; } } + + LOGE("Property %s.%s not found", ns_name, p->getName()); pthread_mutex_unlock(&mLock); errno = ENOENT; return -1; } +int PropertyManager::doSet(Property *p, int idx, const char *value) { + + if (p->getReadOnly()) { + errno = EROFS; + return -1; + } + + if (p->getType() == Property::Type_STRING) { + return p->set(idx, value); + } else if (p->getType() == Property::Type_INTEGER) { + int tmp; + errno = 0; + tmp = strtol(value, (char **) NULL, 10); + if (errno) { + LOGE("Failed to convert '%s' to int", value); + errno = EINVAL; + return -1; + } + return p->set(idx, tmp); + } else if (p->getType() == Property::Type_IPV4) { + struct in_addr tmp; + if (!inet_aton(value, &tmp)) { + LOGE("Failed to convert '%s' to ipv4", value); + errno = EINVAL; + return -1; + } + return p->set(idx, &tmp); + } else { + LOGE("Property '%s' has an unknown type (%d)", p->getName(), + p->getType()); + errno = EINVAL; + return -1; + } + errno = ENOENT; + return -1; +} + +int PropertyManager::doGet(Property *p, int idx, char *buffer, size_t max) { + + if (p->getType() == Property::Type_STRING) { + if (p->get(idx, buffer, max)) { + LOGW("String property %s get failed (%s)", p->getName(), + strerror(errno)); + return -1; + } + } + else if (p->getType() == Property::Type_INTEGER) { + int tmp; + if (p->get(idx, &tmp)) { + LOGW("Integer property %s get failed (%s)", p->getName(), + strerror(errno)); + return -1; + } + snprintf(buffer, max, "%d", tmp); + } else if (p->getType() == Property::Type_IPV4) { + struct in_addr tmp; + if (p->get(idx, &tmp)) { + LOGW("IPV4 property %s get failed (%s)", p->getName(), + strerror(errno)); + return -1; + } + strncpy(buffer, inet_ntoa(tmp), max); + } else { + LOGE("Property '%s' has an unknown type (%d)", p->getName(), + p->getType()); + errno = EINVAL; + return -1; + } + return 0; +} + /* * IPropertyManager methods */ int PropertyManager::set(const char *name, const char *value) { - PropertyPairCollection::iterator it; + LOGD("set %s = '%s'", name, value); pthread_mutex_lock(&mLock); - for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) { - if (!strcmp(name, (*it)->getName())) { - pthread_mutex_unlock(&mLock); - return (*it)->getProvider()->set(name, value); + PropertyNamespaceCollection::iterator ns_it; + for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) { + PropertyCollection::iterator p_it; + for (p_it = (*ns_it)->getProperties()->begin(); + p_it != (*ns_it)->getProperties()->end(); ++p_it) { + for (int i = 0; i < (*p_it)->getNumElements(); i++) { + char fqn[255]; + char tmp[8]; + sprintf(tmp, "_%d", i); + snprintf(fqn, sizeof(fqn), "%s.%s%s", + (*ns_it)->getName(), (*p_it)->getName(), + ((*p_it)->getNumElements() > 1 ? tmp : "")); + if (!strcasecmp(name, fqn)) { + pthread_mutex_unlock(&mLock); + return doSet((*p_it), i, value); + } + } } } + + LOGE("Property %s not found", name); pthread_mutex_unlock(&mLock); errno = ENOENT; return -1; } const char *PropertyManager::get(const char *name, char *buffer, size_t max) { - PropertyPairCollection::iterator it; - - memset(buffer, 0, max); pthread_mutex_lock(&mLock); - for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) { - if (!strcmp(name, (*it)->getName())) { - pthread_mutex_unlock(&mLock); - return (*it)->getProvider()->get(name, buffer, max); + PropertyNamespaceCollection::iterator ns_it; + for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) { + PropertyCollection::iterator p_it; + for (p_it = (*ns_it)->getProperties()->begin(); + p_it != (*ns_it)->getProperties()->end(); ++p_it) { + + for (int i = 0; i < (*p_it)->getNumElements(); i++) { + char fqn[255]; + char tmp[8]; + sprintf(tmp, "_%d", i); + snprintf(fqn, sizeof(fqn), "%s.%s%s", + (*ns_it)->getName(), (*p_it)->getName(), + ((*p_it)->getNumElements() > 1 ? tmp : "")); + if (!strcasecmp(name, fqn)) { + pthread_mutex_unlock(&mLock); + if (doGet((*p_it), i, buffer, max)) + return NULL; + return buffer; + } } + } } + + LOGE("Property %s not found", name); pthread_mutex_unlock(&mLock); errno = ENOENT; return NULL; } -android::List *PropertyManager::createPropertyList() { +android::List *PropertyManager::createPropertyList(const char *prefix) { android::List *c = new android::List(); - PropertyPairCollection::iterator it; - pthread_mutex_lock(&mLock); - for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) - c->push_back(strdup((*it)->getName())); + PropertyNamespaceCollection::iterator ns_it; + for (ns_it = mNamespaces->begin(); ns_it != mNamespaces->end(); ++ns_it) { + PropertyCollection::iterator p_it; + for (p_it = (*ns_it)->getProperties()->begin(); + p_it != (*ns_it)->getProperties()->end(); ++p_it) { + for (int i = 0; i < (*p_it)->getNumElements(); i++) { + char fqn[255]; + char tmp[8]; + sprintf(tmp, "_%d", i); + snprintf(fqn, sizeof(fqn), "%s.%s%s", + (*ns_it)->getName(), (*p_it)->getName(), + ((*p_it)->getNumElements() > 1 ? tmp : "")); + if (!prefix || + (prefix && !strncasecmp(fqn, prefix, strlen(prefix)))) { + c->push_back(strdup(fqn)); + } + } + } + } pthread_mutex_unlock(&mLock); return c; } - -PropertyPair::PropertyPair(const char *name, IPropertyProvider *pp) { - mName = strdup(name); - mPp = pp; -} - -PropertyPair::~PropertyPair() { - free(mName); -} diff --git a/nexus/PropertyManager.h b/nexus/PropertyManager.h index 10d0b2aa9..af56a9c15 100644 --- a/nexus/PropertyManager.h +++ b/nexus/PropertyManager.h @@ -22,36 +22,28 @@ #include -#include "IPropertyProvider.h" - -class PropertyPair { -private: - char *mName; - IPropertyProvider *mPp; - -public: - PropertyPair(const char *name, IPropertyProvider *pp); - virtual ~PropertyPair(); - - const char *getName() { return mName; } - IPropertyProvider *getProvider() { return mPp; } -}; - -typedef android::List PropertyPairCollection; +#include "Property.h" class PropertyManager { - PropertyPairCollection *mPropertyPairs; - pthread_mutex_t mLock; + PropertyNamespaceCollection *mNamespaces; + pthread_mutex_t mLock; public: PropertyManager(); - virtual ~PropertyManager(); - int registerProperty(const char *name, IPropertyProvider *pp); - int unregisterProperty(const char *name); - android::List *createPropertyList(); + virtual ~PropertyManager(); + int attachProperty(const char *ns, Property *p); + int detachProperty(const char *ns, Property *p); + + android::List *createPropertyList(const char *prefix); int set(const char *name, const char *value); const char *get(const char *name, char *buffer, size_t max); + +private: + PropertyNamespace *lookupNamespace_UNLOCKED(const char *ns); + Property *lookupProperty_UNLOCKED(PropertyNamespace *ns, const char *name); + int doSet(Property *p, int idx, const char *value); + int doGet(Property *p, int idx, char *buffer, size_t max); }; #endif diff --git a/nexus/ErrorCode.h b/nexus/ResponseCode.h similarity index 84% rename from nexus/ErrorCode.h rename to nexus/ResponseCode.h index 414dd2c5a..4b6cac851 100644 --- a/nexus/ErrorCode.h +++ b/nexus/ResponseCode.h @@ -14,10 +14,10 @@ * limitations under the License. */ -#ifndef _ERRORCODE_H -#define _ERRORCODE_H +#ifndef _RESPONSECODE_H +#define _RESPONSECODE_H -class ErrorCode { +class ResponseCode { public: // 100 series - Requestion action was initiated; expect another reply // before proceeding with a new command. @@ -44,5 +44,10 @@ public: // 600 series - Unsolicited broadcasts static const int UnsolicitedInformational = 600; + static const int DhcpStateChange = 605; + static const int SupplicantStateChange = 610; + static const int ScanResultsReady = 615; + static const int LinkSpeedChange = 620; + static const int RssiChange = 625; }; #endif diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp index 9bb6bf2c1..6aa36e875 100644 --- a/nexus/Supplicant.cpp +++ b/nexus/Supplicant.cpp @@ -30,7 +30,6 @@ #include "Supplicant.h" #include "SupplicantListener.h" #include "NetworkManager.h" -#include "ErrorCode.h" #include "WifiController.h" #include "SupplicantStatus.h" @@ -114,6 +113,29 @@ bool Supplicant::isStarted() { return mServiceManager->isRunning(SUPPLICANT_SERVICE_NAME); } +int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) { + + if (!mCtrl) { + errno = ENOTCONN; + return -1; + } + +// LOGD("sendCommand(): -> '%s'", cmd); + + int rc; + memset(reply, 0, *reply_len); + if ((rc = wpa_ctrl_request(mCtrl, cmd, strlen(cmd), reply, reply_len, NULL)) == -2) { + errno = ETIMEDOUT; + return -1; + } else if (rc < 0 || !strncmp(reply, "FAIL", 4)) { + strcpy(reply, "FAIL"); + errno = EIO; + return -1; + } + + // LOGD("sendCommand(): <- '%s'", reply); + return 0; +} SupplicantStatus *Supplicant::getStatus() { char *reply; size_t len = 4096; @@ -162,6 +184,7 @@ int Supplicant::refreshNetworkList() { return -1; } + PropertyManager *pm = NetworkManager::Instance()->getPropMngr(); pthread_mutex_lock(&mNetworksLock); int num_added = 0; @@ -182,7 +205,9 @@ int Supplicant::refreshNetworkList() { delete new_wn; } else { num_added++; - new_wn->registerProperties(); + char new_ns[20]; + snprintf(new_ns, sizeof(new_ns), "wifi.net.%d", new_wn->getNetworkId()); + new_wn->attachProperties(pm, new_ns); mNetworks->push_back(new_wn); if (new_wn->refresh()) { LOGW("Unable to refresh network id %d (%s)", @@ -198,7 +223,9 @@ int Supplicant::refreshNetworkList() { for (i = mNetworks->begin(); i != mNetworks->end(); ++i) { if (0) { num_removed++; - (*i)->unregisterProperties(); + char del_ns[20]; + snprintf(del_ns, sizeof(del_ns), "wifi.net.%d", (*i)->getNetworkId()); + (*i)->detachProperties(pm, del_ns); delete (*i); i = mNetworks->erase(i); } @@ -247,31 +274,7 @@ int Supplicant::connectToSupplicant() { return 0; } -int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) -{ - if (!mCtrl) { - errno = ENOTCONN; - return -1; - } - -// LOGD("sendCommand(): -> '%s'", cmd); - - int rc; - memset(reply, 0, *reply_len); - if ((rc = wpa_ctrl_request(mCtrl, cmd, strlen(cmd), reply, reply_len, NULL)) == -2) { - errno = ETIMEDOUT; - return -1; - } else if (rc < 0 || !strncmp(reply, "FAIL", 4)) { - strcpy(reply, "FAIL"); - errno = EIO; - return -1; - } - -// LOGD("sendCommand(): <- '%s'", reply); - return 0; -} - -int Supplicant::triggerScan(bool active) { +int Supplicant::setScanMode(bool active) { char reply[255]; size_t len = sizeof(reply); @@ -281,10 +284,88 @@ int Supplicant::triggerScan(bool active) { strerror(errno)); return -1; } - len = sizeof(reply); + return 0; +} + +int Supplicant::triggerScan() { + char reply[255]; + size_t len = sizeof(reply); if (sendCommand("SCAN", reply, &len)) { - LOGW("triggerScan(%d): Error initiating scan", active); + LOGW("triggerScan(): Error initiating scan"); + return -1; + } + return 0; +} + +int Supplicant::getRssi(int *buffer) { + char reply[64]; + size_t len = sizeof(reply); + + if (sendCommand("DRIVER RSSI", reply, &len)) { + LOGW("Failed to get RSSI (%s)", strerror(errno)); + return -1; + } + + char *next = reply; + char *s; + for (int i = 0; i < 3; i++) { + if (!(s = strsep(&next, " "))) { + LOGE("Error parsing RSSI"); + errno = EIO; + return -1; + } + } + *buffer = atoi(s); + return 0; +} + +int Supplicant::getLinkSpeed() { + char reply[64]; + size_t len = sizeof(reply); + + if (sendCommand("DRIVER LINKSPEED", reply, &len)) { + LOGW("Failed to get LINKSPEED (%s)", strerror(errno)); + return -1; + } + + char *next = reply; + char *s; + + if (!(s = strsep(&next, " "))) { + LOGE("Error parsing LINKSPEED"); + errno = EIO; + return -1; + } + + if (!(s = strsep(&next, " "))) { + LOGE("Error parsing LINKSPEED"); + errno = EIO; + return -1; + } + return atoi(s); +} + +int Supplicant::stopDriver() { + char reply[64]; + size_t len = sizeof(reply); + + LOGD("stopDriver()"); + + if (sendCommand("DRIVER STOP", reply, &len)) { + LOGW("Failed to stop driver (%s)", strerror(errno)); + return -1; + } + return 0; +} + +int Supplicant::startDriver() { + char reply[64]; + size_t len = sizeof(reply); + + LOGD("startDriver()"); + if (sendCommand("DRIVER START", reply, &len)) { + LOGW("Failed to start driver (%s)", strerror(errno)); return -1; } return 0; @@ -301,7 +382,11 @@ WifiNetwork *Supplicant::createNetwork() { reply[strlen(reply) -1] = '\0'; WifiNetwork *wn = new WifiNetwork(mController, this, atoi(reply)); + PropertyManager *pm = NetworkManager::Instance()->getPropMngr(); pthread_mutex_lock(&mNetworksLock); + char new_ns[20]; + snprintf(new_ns, sizeof(new_ns), "wifi.net.%d", wn->getNetworkId()); + wn->attachProperties(pm, new_ns); mNetworks->push_back(wn); pthread_mutex_unlock(&mNetworksLock); return wn; @@ -411,8 +496,9 @@ int Supplicant::setNetworkVar(int networkId, const char *var, const char *val) { char reply[255]; size_t len = sizeof(reply) -1; + LOGD("netid %d, var '%s' = '%s'", networkId, var, val); char *tmp; - asprintf(&tmp, "SET_NETWORK %d %s \"%s\"", networkId, var, val); + asprintf(&tmp, "SET_NETWORK %d %s %s", networkId, var, val); if (sendCommand(tmp, reply, &len)) { free(tmp); return -1; @@ -457,6 +543,95 @@ int Supplicant::enableNetwork(int networkId, bool enabled) { return 0; } +int Supplicant::enablePacketFilter() { + char req[128]; + char reply[16]; + size_t len; + int i; + + for (i = 0; i <=3; i++) { + snprintf(req, sizeof(req), "DRIVER RXFILTER-ADD %d", i); + len = sizeof(reply); + if (sendCommand(req, reply, &len)) + return -1; + } + + len = sizeof(reply); + if (sendCommand("DRIVER RXFILTER-START", reply, &len)) + return -1; + return 0; +} + +int Supplicant::disablePacketFilter() { + char req[128]; + char reply[16]; + size_t len; + int i; + + len = sizeof(reply); + if (sendCommand("DRIVER RXFILTER-STOP", reply, &len)) + return -1; + + for (i = 3; i >=0; i--) { + snprintf(req, sizeof(req), "DRIVER RXFILTER-REMOVE %d", i); + len = sizeof(reply); + if (sendCommand(req, reply, &len)) + return -1; + } + return 0; +} + +int Supplicant::enableBluetoothCoexistenceScan() { + char req[128]; + char reply[16]; + size_t len; + int i; + + len = sizeof(reply); + if (sendCommand("DRIVER BTCOEXSCAN-START", reply, &len)) + return -1; + return 0; +} + +int Supplicant::disableBluetoothCoexistenceScan() { + char req[128]; + char reply[16]; + size_t len; + int i; + + len = sizeof(reply); + if (sendCommand("DRIVER BTCOEXSCAN-STOP", reply, &len)) + return -1; + return 0; +} + +int Supplicant::setBluetoothCoexistenceMode(int mode) { + char req[64]; + + sprintf(req, "DRIVER BTCOEXMODE %d", mode); + + char reply[16]; + size_t len = sizeof(reply) -1; + + if (sendCommand(req, reply, &len)) + return -1; + return 0; +} + +int Supplicant::setApScanMode(int mode) { + char req[64]; + +// LOGD("setApScanMode(%d)", mode); + sprintf(req, "AP_SCAN %d", mode); + + char reply[16]; + size_t len = sizeof(reply) -1; + + if (sendCommand(req, reply, &len)) + return -1; + return 0; +} + int Supplicant::retrieveInterfaceName() { char reply[255]; @@ -469,3 +644,34 @@ int Supplicant::retrieveInterfaceName() { mInterfaceName = strdup(reply); return 0; } + +int Supplicant::reconnect() { + char req[128]; + char reply[16]; + size_t len; + int i; + + len = sizeof(reply); + if (sendCommand("RECONNECT", reply, &len)) + return -1; + return 0; +} + +int Supplicant::disconnect() { + char req[128]; + char reply[16]; + size_t len; + int i; + + len = sizeof(reply); + if (sendCommand("DISCONNECT", reply, &len)) + return -1; + return 0; +} + +int Supplicant::getNetworkCount() { + pthread_mutex_lock(&mNetworksLock); + int cnt = mNetworks->size(); + pthread_mutex_unlock(&mNetworksLock); + return cnt; +} diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h index 3efbe4cd4..3900f4f7f 100644 --- a/nexus/Supplicant.h +++ b/nexus/Supplicant.h @@ -30,7 +30,6 @@ class SupplicantStatus; #include "ISupplicantEventHandler.h" class Supplicant { -private: struct wpa_ctrl *mCtrl; struct wpa_ctrl *mMonitor; SupplicantListener *mListener; @@ -50,7 +49,8 @@ public: int stop(); bool isStarted(); - int triggerScan(bool active); + int setScanMode(bool active); + int triggerScan(); WifiNetwork *createNetwork(); WifiNetwork *lookupNetwork(int networkId); @@ -63,6 +63,21 @@ public: size_t max); int enableNetwork(int networkId, bool enabled); + int disconnect(); + int reconnect(); + int reassociate(); + int setApScanMode(int mode); + int enablePacketFilter(); + int disablePacketFilter(); + int setBluetoothCoexistenceMode(int mode); + int enableBluetoothCoexistenceScan(); + int disableBluetoothCoexistenceScan(); + int stopDriver(); + int startDriver(); + int getRssi(int *buffer); + int getLinkSpeed(); + int getNetworkCount(); + SupplicantStatus *getStatus(); Controller *getController() { return (Controller *) mController; } diff --git a/nexus/SupplicantState.cpp b/nexus/SupplicantState.cpp index a16d3709e..2815430f9 100644 --- a/nexus/SupplicantState.cpp +++ b/nexus/SupplicantState.cpp @@ -23,25 +23,25 @@ char *SupplicantState::toString(int val, char *buffer, int max) { if (val == SupplicantState::UNKNOWN) - strncpy(buffer, "Unknown", max); + strncpy(buffer, "UNKNOWN", max); else if (val == SupplicantState::DISCONNECTED) - strncpy(buffer, "Disconnected", max); + strncpy(buffer, "DISCONNECTED", max); else if (val == SupplicantState::INACTIVE) - strncpy(buffer, "Inactive", max); + strncpy(buffer, "INACTIVE", max); else if (val == SupplicantState::SCANNING) - strncpy(buffer, "Scanning", max); + strncpy(buffer, "SCANNING", max); else if (val == SupplicantState::ASSOCIATING) - strncpy(buffer, "Associating", max); + strncpy(buffer, "ASSOCIATING", max); else if (val == SupplicantState::ASSOCIATED) - strncpy(buffer, "Associated", max); + strncpy(buffer, "ASSOCIATED", max); else if (val == SupplicantState::FOURWAY_HANDSHAKE) - strncpy(buffer, "Fourway Handshake", max); + strncpy(buffer, "FOURWAY_HANDSHAKE", max); else if (val == SupplicantState::GROUP_HANDSHAKE) - strncpy(buffer, "Group Handshake", max); + strncpy(buffer, "GROUP_HANDSHAKE", max); else if (val == SupplicantState::COMPLETED) - strncpy(buffer, "Completed", max); + strncpy(buffer, "COMPLETED", max); else if (val == SupplicantState::IDLE) - strncpy(buffer, "Idle", max); + strncpy(buffer, "IDLE", max); else strncpy(buffer, "(internal error)", max); diff --git a/nexus/TiwlanWifiController.cpp b/nexus/TiwlanWifiController.cpp index 61535c356..016c79074 100644 --- a/nexus/TiwlanWifiController.cpp +++ b/nexus/TiwlanWifiController.cpp @@ -51,6 +51,7 @@ int TiwlanWifiController::powerUp() { int TiwlanWifiController::powerDown() { if (mEventListener) { delete mEventListener; + shutdown(mListenerSock, SHUT_RDWR); close(mListenerSock); mListenerSock = -1; mEventListener = NULL; @@ -77,7 +78,8 @@ int TiwlanWifiController::loadFirmware() { LOGD("Firmware loaded OK"); if (startDriverEventListener()) { - LOGW("Failed to start driver event listener"); + LOGW("Failed to start driver event listener (%s)", + strerror(errno)); } return 0; @@ -95,32 +97,48 @@ int TiwlanWifiController::loadFirmware() { int TiwlanWifiController::startDriverEventListener() { struct sockaddr_in addr; - int s; - if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + if (mListenerSock != -1) { + LOGE("Listener already started!"); + errno = EBUSY; return -1; + } + + if ((mListenerSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + LOGE("socket failed (%s)", strerror(errno)); + return -1; + } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(TI_DRIVER_MSG_PORT); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - close(s); - return -1; + if (bind(mListenerSock, + (struct sockaddr *) &addr, + sizeof(addr)) < 0) { + LOGE("bind failed (%s)", strerror(errno)); + goto out_err; } - mEventListener = new TiwlanEventListener(s); + mEventListener = new TiwlanEventListener(mListenerSock); if (mEventListener->startListener()) { LOGE("Error starting driver listener (%s)", strerror(errno)); + goto out_err; + } + return 0; +out_err: + if (mEventListener) { delete mEventListener; mEventListener = NULL; - close(s); - return -1; } - mListenerSock = s; - return 0; + if (mListenerSock != -1) { + shutdown(mListenerSock, SHUT_RDWR); + close(mListenerSock); + mListenerSock = -1; + } + return -1; } bool TiwlanWifiController::isFirmwareLoaded() { diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp index add4dc39a..015710fcc 100644 --- a/nexus/VpnController.cpp +++ b/nexus/VpnController.cpp @@ -27,56 +27,66 @@ VpnController::VpnController(PropertyManager *propmngr, IControllerHandler *handlers) : - Controller("VPN", propmngr, handlers) { + Controller("vpn", propmngr, handlers) { mEnabled = false; + + mStaticProperties.propEnabled = new VpnEnabledProperty(this); + mDynamicProperties.propGateway = new IPV4AddressPropertyHelper("Gateway", + false, + &mGateway); } int VpnController::start() { - mPropMngr->registerProperty("vpn.enabled", this); + mPropMngr->attachProperty("vpn", mStaticProperties.propEnabled); return 0; } int VpnController::stop() { - mPropMngr->unregisterProperty("vpn.enabled"); + mPropMngr->detachProperty("vpn", mStaticProperties.propEnabled); return 0; } -int VpnController::set(const char *name, const char *value) { - if (!strcmp(name, "vpn.enabled")) { - int en = atoi(value); - int rc; +VpnController::VpnIntegerProperty::VpnIntegerProperty(VpnController *c, + const char *name, + bool ro, + int elements) : + IntegerProperty(name, ro, elements) { + mVc = c; +} - if (en == mEnabled) - return 0; - rc = (en ? enable() : disable()); +VpnController::VpnStringProperty::VpnStringProperty(VpnController *c, + const char *name, + bool ro, int elements) : + StringProperty(name, ro, elements) { + mVc = c; +} +VpnController::VpnIPV4AddressProperty::VpnIPV4AddressProperty(VpnController *c, + const char *name, + bool ro, int elements) : + IPV4AddressProperty(name, ro, elements) { + mVc = c; +} + +VpnController::VpnEnabledProperty::VpnEnabledProperty(VpnController *c) : + VpnIntegerProperty(c, "Enabled", false, 1) { +} +int VpnController::VpnEnabledProperty::get(int idx, int *buffer) { + *buffer = mVc->mEnabled; + return 0; +} +int VpnController::VpnEnabledProperty::set(int idx, int value) { + int rc; + if (!value) { + mVc->mPropMngr->detachProperty("vpn", mVc->mDynamicProperties.propGateway); + rc = mVc->disable(); + } else { + rc = mVc->enable(); if (!rc) { - mEnabled = en; - if (en) - mPropMngr->unregisterProperty("vpn.gateway"); - else - mPropMngr->unregisterProperty("vpn.gateway"); + mVc->mPropMngr->attachProperty("vpn", mVc->mDynamicProperties.propGateway); } - return rc; - } if (!strcmp(name, "vpn.gateway")) { - if (!inet_aton(value, &mVpnGateway)) { - errno = EINVAL; - return -1; - } - return 0; } - - return Controller::set(name, value); -} - -const char *VpnController::get(const char *name, char *buffer, size_t maxsize) { - if (!strcmp(name, "vpn.enabled")) { - snprintf(buffer, maxsize, "%d", mEnabled); - return buffer; - } if (!strcmp(name, "vpn.gateway")) { - snprintf(buffer, maxsize, "%s", inet_ntoa(mVpnGateway)); - return buffer; - } - - return Controller::get(name, buffer, maxsize); + if (!rc) + mVc->mEnabled = value; + return rc; } diff --git a/nexus/VpnController.h b/nexus/VpnController.h index 1af4d9fbc..4bd86b54d 100644 --- a/nexus/VpnController.h +++ b/nexus/VpnController.h @@ -24,11 +24,63 @@ class IControllerHandler; class VpnController : public Controller { + class VpnIntegerProperty : public IntegerProperty { + protected: + VpnController *mVc; + public: + VpnIntegerProperty(VpnController *c, const char *name, bool ro, + int elements); + virtual ~VpnIntegerProperty() {} + virtual int set(int idx, int value) = 0; + virtual int get(int idx, int *buffer) = 0; + }; + friend class VpnController::VpnIntegerProperty; + + class VpnStringProperty : public StringProperty { + protected: + VpnController *mVc; + public: + VpnStringProperty(VpnController *c, const char *name, bool ro, + int elements); + virtual ~VpnStringProperty() {} + virtual int set(int idx, const char *value) = 0; + virtual int get(int idx, char *buffer, size_t max) = 0; + }; + friend class VpnController::VpnStringProperty; + + class VpnIPV4AddressProperty : public IPV4AddressProperty { + protected: + VpnController *mVc; + public: + VpnIPV4AddressProperty(VpnController *c, const char *name, bool ro, + int elements); + virtual ~VpnIPV4AddressProperty() {} + virtual int set(int idx, struct in_addr *value) = 0; + virtual int get(int idx, struct in_addr *buffer) = 0; + }; + friend class VpnController::VpnIPV4AddressProperty; + + class VpnEnabledProperty : public VpnIntegerProperty { + public: + VpnEnabledProperty(VpnController *c); + virtual ~VpnEnabledProperty() {}; + int set(int idx, int value); + int get(int idx, int *buffer); + }; + bool mEnabled; /* * Gateway of the VPN server to connect to */ - struct in_addr mVpnGateway; + struct in_addr mGateway; + + struct { + VpnEnabledProperty *propEnabled; + } mStaticProperties; + + struct { + IPV4AddressPropertyHelper *propGateway; + } mDynamicProperties; public: VpnController(PropertyManager *propmngr, IControllerHandler *handlers); @@ -37,13 +89,9 @@ public: virtual int start(); virtual int stop(); - virtual int set(const char *name, const char *value); - virtual const char *get(const char *name, char *buffer, size_t maxlen); - protected: virtual int enable() = 0; virtual int disable() = 0; - }; #endif diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp index ef5ecae17..c218c30ad 100644 --- a/nexus/WifiController.cpp +++ b/nexus/WifiController.cpp @@ -23,9 +23,8 @@ #include "Supplicant.h" #include "WifiController.h" -#include "WifiScanner.h" #include "NetworkManager.h" -#include "ErrorCode.h" +#include "ResponseCode.h" #include "WifiNetwork.h" #include "ISupplicantEventHandler.h" #include "SupplicantState.h" @@ -37,11 +36,12 @@ #include "SupplicantStateChangeEvent.h" #include "SupplicantConnectionTimeoutEvent.h" #include "SupplicantDisconnectedEvent.h" +#include "WifiStatusPoller.h" WifiController::WifiController(PropertyManager *mPropMngr, IControllerHandler *handlers, char *modpath, char *modname, char *modargs) : - Controller("WIFI", mPropMngr, handlers) { + Controller("wifi", mPropMngr, handlers) { strncpy(mModulePath, modpath, sizeof(mModulePath)); strncpy(mModuleName, modname, sizeof(mModuleName)); strncpy(mModuleArgs, modargs, sizeof(mModuleArgs)); @@ -49,22 +49,59 @@ WifiController::WifiController(PropertyManager *mPropMngr, mLatestScanResults = new ScanResultCollection(); pthread_mutex_init(&mLatestScanResultsLock, NULL); - mSupplicant = new Supplicant(this, this); - mScanner = new WifiScanner(mSupplicant, 10); - mCurrentScanMode = 0; + pthread_mutex_init(&mLock, NULL); + mSupplicant = new Supplicant(this, this); + mActiveScan = false; mEnabled = false; + mScanOnly = false; + mPacketFilter = false; + mBluetoothCoexScan = false; + mBluetoothCoexMode = 0; + mCurrentlyConnectedNetworkId = -1; + mStatusPoller = new WifiStatusPoller(this); + mRssiEventThreshold = 5; + mLastLinkSpeed = 0; mSupplicantState = SupplicantState::UNKNOWN; + + mStaticProperties.propEnabled = new WifiEnabledProperty(this); + mStaticProperties.propScanOnly = new WifiScanOnlyProperty(this); + mStaticProperties.propAllowedChannels = new WifiAllowedChannelsProperty(this); + + mStaticProperties.propRssiEventThreshold = + new IntegerPropertyHelper("RssiEventThreshold", false, &mRssiEventThreshold); + + mDynamicProperties.propSupplicantState = new WifiSupplicantStateProperty(this); + mDynamicProperties.propActiveScan = new WifiActiveScanProperty(this); + mDynamicProperties.propInterface = new WifiInterfaceProperty(this); + mDynamicProperties.propSearching = new WifiSearchingProperty(this); + mDynamicProperties.propPacketFilter = new WifiPacketFilterProperty(this); + mDynamicProperties.propBluetoothCoexScan = new WifiBluetoothCoexScanProperty(this); + mDynamicProperties.propBluetoothCoexMode = new WifiBluetoothCoexModeProperty(this); + mDynamicProperties.propCurrentNetwork = new WifiCurrentNetworkProperty(this); + + mDynamicProperties.propRssi = new IntegerPropertyHelper("Rssi", true, &mLastRssi); + mDynamicProperties.propLinkSpeed = new IntegerPropertyHelper("LinkSpeed", true, &mLastLinkSpeed); + + mDynamicProperties.propSuspended = new WifiSuspendedProperty(this); + mDynamicProperties.propNetCount = new WifiNetCountProperty(this); + mDynamicProperties.propTriggerScan = new WifiTriggerScanProperty(this); } int WifiController::start() { - mPropMngr->registerProperty("wifi.enabled", this); + mPropMngr->attachProperty("wifi", mStaticProperties.propEnabled); + mPropMngr->attachProperty("wifi", mStaticProperties.propScanOnly); + mPropMngr->attachProperty("wifi", mStaticProperties.propAllowedChannels); + mPropMngr->attachProperty("wifi", mStaticProperties.propRssiEventThreshold); return 0; } int WifiController::stop() { - mPropMngr->unregisterProperty("wifi.enabled"); + mPropMngr->detachProperty("wifi", mStaticProperties.propEnabled); + mPropMngr->detachProperty("wifi", mStaticProperties.propScanOnly); + mPropMngr->detachProperty("wifi", mStaticProperties.propAllowedChannels); + mPropMngr->detachProperty("wifi", mStaticProperties.propRssiEventThreshold); return 0; } @@ -114,9 +151,21 @@ int WifiController::enable() { if (mSupplicant->refreshNetworkList()) LOGW("Error getting list of networks (%s)", strerror(errno)); - mPropMngr->registerProperty("wifi.supplicant.state", this); - mPropMngr->registerProperty("wifi.scanmode", this); - mPropMngr->registerProperty("wifi.interface", this); + LOGW("TODO: Set # of allowed regulatory channels!"); + + mPropMngr->attachProperty("wifi", mDynamicProperties.propSupplicantState); + mPropMngr->attachProperty("wifi", mDynamicProperties.propActiveScan); + mPropMngr->attachProperty("wifi", mDynamicProperties.propInterface); + mPropMngr->attachProperty("wifi", mDynamicProperties.propSearching); + mPropMngr->attachProperty("wifi", mDynamicProperties.propPacketFilter); + mPropMngr->attachProperty("wifi", mDynamicProperties.propBluetoothCoexScan); + mPropMngr->attachProperty("wifi", mDynamicProperties.propBluetoothCoexMode); + mPropMngr->attachProperty("wifi", mDynamicProperties.propCurrentNetwork); + mPropMngr->attachProperty("wifi", mDynamicProperties.propRssi); + mPropMngr->attachProperty("wifi", mDynamicProperties.propLinkSpeed); + mPropMngr->attachProperty("wifi", mDynamicProperties.propSuspended); + mPropMngr->attachProperty("wifi", mDynamicProperties.propNetCount); + mPropMngr->attachProperty("wifi", mDynamicProperties.propTriggerScan); LOGI("Enabled successfully"); return 0; @@ -135,17 +184,87 @@ out_powerdown: return -1; } +bool WifiController::getSuspended() { + pthread_mutex_lock(&mLock); + bool r = mSuspended; + pthread_mutex_unlock(&mLock); + return r; +} + +int WifiController::setSuspend(bool suspend) { + + pthread_mutex_lock(&mLock); + if (suspend == mSuspended) { + LOGW("Suspended state already = %d", suspend); + pthread_mutex_unlock(&mLock); + return 0; + } + + if (suspend) { + mHandlers->onControllerSuspending(this); + + char tmp[80]; + LOGD("Suspending from supplicant state %s", + SupplicantState::toString(mSupplicantState, + tmp, + sizeof(tmp))); + + if (mSupplicantState != SupplicantState::IDLE) { + LOGD("Forcing Supplicant disconnect"); + if (mSupplicant->disconnect()) { + LOGW("Error disconnecting (%s)", strerror(errno)); + } + } + + LOGD("Stopping Supplicant driver"); + if (mSupplicant->stopDriver()) { + LOGE("Error stopping driver (%s)", strerror(errno)); + pthread_mutex_unlock(&mLock); + return -1; + } + } else { + LOGD("Resuming"); + + if (mSupplicant->startDriver()) { + LOGE("Error resuming driver (%s)", strerror(errno)); + pthread_mutex_unlock(&mLock); + return -1; + } + // XXX: set regulatory max channels + if (mScanOnly) + mSupplicant->triggerScan(); + else + mSupplicant->reconnect(); + + mHandlers->onControllerResumed(this); + } + + mSuspended = suspend; + pthread_mutex_unlock(&mLock); + LOGD("Suspend / Resume completed"); + return 0; +} + void WifiController::sendStatusBroadcast(const char *msg) { NetworkManager::Instance()-> getBroadcaster()-> - sendBroadcast(ErrorCode::UnsolicitedInformational, msg, false); + sendBroadcast(ResponseCode::UnsolicitedInformational, msg, false); } int WifiController::disable() { - mPropMngr->unregisterProperty("wifi.scanmode"); - mPropMngr->unregisterProperty("wifi.supplicant.state"); - mPropMngr->unregisterProperty("wifi.scanmode"); + mPropMngr->detachProperty("wifi", mDynamicProperties.propSupplicantState); + mPropMngr->detachProperty("wifi", mDynamicProperties.propActiveScan); + mPropMngr->detachProperty("wifi", mDynamicProperties.propInterface); + mPropMngr->detachProperty("wifi", mDynamicProperties.propSearching); + mPropMngr->detachProperty("wifi", mDynamicProperties.propPacketFilter); + mPropMngr->detachProperty("wifi", mDynamicProperties.propBluetoothCoexScan); + mPropMngr->detachProperty("wifi", mDynamicProperties.propBluetoothCoexMode); + mPropMngr->detachProperty("wifi", mDynamicProperties.propCurrentNetwork); + mPropMngr->detachProperty("wifi", mDynamicProperties.propRssi); + mPropMngr->detachProperty("wifi", mDynamicProperties.propLinkSpeed); + mPropMngr->detachProperty("wifi", mDynamicProperties.propSuspended); + mPropMngr->detachProperty("wifi", mDynamicProperties.propNetCount); if (mSupplicant->isStarted()) { sendStatusBroadcast("Stopping WPA Supplicant"); @@ -178,35 +297,61 @@ int WifiController::loadFirmware() { return 0; } -int WifiController::setScanMode(uint32_t mode) { - int rc = 0; +int WifiController::triggerScan() { + pthread_mutex_lock(&mLock); + if (verifyNotSuspended()) { + pthread_mutex_unlock(&mLock); + return -1; + } - if (mCurrentScanMode == mode) + switch (mSupplicantState) { + case SupplicantState::DISCONNECTED: + case SupplicantState::INACTIVE: + case SupplicantState::SCANNING: + case SupplicantState::IDLE: + break; + default: + // Switch to scan only mode + mSupplicant->setApScanMode(2); + break; + } + + int rc = mSupplicant->triggerScan(); + pthread_mutex_unlock(&mLock); + return rc; +} + +int WifiController::setActiveScan(bool active) { + pthread_mutex_lock(&mLock); + if (mActiveScan == active) { + pthread_mutex_unlock(&mLock); return 0; + } + mActiveScan = active; - if (!(mode & SCAN_ENABLE_MASK)) { - if (mCurrentScanMode & SCAN_REPEAT_MASK) - mScanner->stop(); - } else if (mode & SCAN_REPEAT_MASK) - rc = mScanner->start(mode & SCAN_ACTIVE_MASK); - else - rc = mSupplicant->triggerScan(mode & SCAN_ACTIVE_MASK); - - mCurrentScanMode = mode; + int rc = mSupplicant->setScanMode(active); + pthread_mutex_unlock(&mLock); return rc; } WifiNetwork *WifiController::createNetwork() { + pthread_mutex_lock(&mLock); WifiNetwork *wn = mSupplicant->createNetwork(); + pthread_mutex_unlock(&mLock); return wn; } int WifiController::removeNetwork(int networkId) { + pthread_mutex_lock(&mLock); WifiNetwork *wn = mSupplicant->lookupNetwork(networkId); - if (!wn) + if (!wn) { + pthread_mutex_unlock(&mLock); return -1; - return mSupplicant->removeNetwork(wn); + } + int rc = mSupplicant->removeNetwork(wn); + pthread_mutex_unlock(&mLock); + return rc; } ScanResultCollection *WifiController::createScanResults() { @@ -225,45 +370,59 @@ WifiNetworkCollection *WifiController::createNetworkList() { return mSupplicant->createNetworkList(); } -int WifiController::set(const char *name, const char *value) { +int WifiController::setPacketFilter(bool enable) { int rc; - if (!strcmp(name, "wifi.enabled")) { - int en = atoi(value); + pthread_mutex_lock(&mLock); + if (enable) + rc = mSupplicant->enablePacketFilter(); + else + rc = mSupplicant->disablePacketFilter(); - if (en == mEnabled) - return 0; - rc = (en ? enable() : disable()); - if (!rc) - mEnabled = en; - } else if (!strcmp(name, "wifi.interface")) { - errno = EROFS; - return -1; - } else if (!strcmp(name, "wifi.scanmode")) - return setScanMode((uint32_t) strtoul(value, NULL, 0)); - else if (!strcmp(name, "wifi.supplicant.state")) { - errno = EROFS; - return -1; - } else - return Controller::set(name, value); + if (!rc) + mPacketFilter = enable; + pthread_mutex_unlock(&mLock); return rc; } -const char *WifiController::get(const char *name, char *buffer, size_t maxsize) { +int WifiController::setBluetoothCoexistenceScan(bool enable) { + int rc; - if (!strcmp(name, "wifi.enabled")) - snprintf(buffer, maxsize, "%d", mEnabled); - else if (!strcmp(name, "wifi.interface")) { - snprintf(buffer, maxsize, "%s", - (getBoundInterface() ? getBoundInterface() : "none")); - } else if (!strcmp(name, "wifi.scanmode")) - snprintf(buffer, maxsize, "0x%.8x", mCurrentScanMode); - else if (!strcmp(name, "wifi.supplicant.state")) - return SupplicantState::toString(mSupplicantState, buffer, maxsize); + pthread_mutex_lock(&mLock); + + if (enable) + rc = mSupplicant->enableBluetoothCoexistenceScan(); else - return Controller::get(name, buffer, maxsize); + rc = mSupplicant->disableBluetoothCoexistenceScan(); - return buffer; + if (!rc) + mBluetoothCoexScan = enable; + pthread_mutex_unlock(&mLock); + return rc; +} + +int WifiController::setScanOnly(bool scanOnly) { + pthread_mutex_lock(&mLock); + int rc = mSupplicant->setApScanMode((scanOnly ? 2 : 1)); + if (!rc) + mScanOnly = scanOnly; + if (!mSuspended) { + if (scanOnly) + mSupplicant->disconnect(); + else + mSupplicant->reconnect(); + } + pthread_mutex_unlock(&mLock); + return rc; +} + +int WifiController::setBluetoothCoexistenceMode(int mode) { + pthread_mutex_lock(&mLock); + int rc = mSupplicant->setBluetoothCoexistenceMode(mode); + if (!rc) + mBluetoothCoexMode = mode; + pthread_mutex_unlock(&mLock); + return rc; } void WifiController::onAssociatingEvent(SupplicantAssociatingEvent *evt) { @@ -296,6 +455,7 @@ void WifiController::onConnectedEvent(SupplicantConnectedEvent *evt) { return; } + mCurrentlyConnectedNetworkId = ss->getId(); if (!(wn = mSupplicant->lookupNetwork(ss->getId()))) { LOGW("Error looking up connected network id %d (%s)", ss->getId(), strerror(errno)); @@ -303,7 +463,7 @@ void WifiController::onConnectedEvent(SupplicantConnectedEvent *evt) { } delete ss; - mHandlers->onInterfaceConnected(this, wn->getIfaceCfg()); + mHandlers->onInterfaceConnected(this); } void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) { @@ -314,6 +474,10 @@ void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) { return; } + mNumScanResultsSinceLastStateChange++; + if (mNumScanResultsSinceLastStateChange >= 3) + mIsSupplicantSearching = false; + size_t len = 4096; if (mSupplicant->sendCommand("SCAN_RESULTS", reply, &len)) { @@ -346,10 +510,14 @@ void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) { while((linep = strtok_r(NULL, "\n", &linep_next))) mLatestScanResults->push_back(new ScanResult(linep)); + // Switch handling of scan results back to normal mode + mSupplicant->setApScanMode(1); + char *tmp; asprintf(&tmp, "Scan results ready (%d)", mLatestScanResults->size()); NetworkManager::Instance()->getBroadcaster()-> - sendBroadcast(ErrorCode::UnsolicitedInformational, tmp, false); + sendBroadcast(ResponseCode::ScanResultsReady, + tmp, false); free(tmp); pthread_mutex_unlock(&mLatestScanResultsLock); free(reply); @@ -359,11 +527,35 @@ void WifiController::onStateChangeEvent(SupplicantStateChangeEvent *evt) { char tmp[32]; char tmp2[32]; + if (evt->getState() == mSupplicantState) + return; + LOGD("onStateChangeEvent(%s -> %s)", SupplicantState::toString(mSupplicantState, tmp, sizeof(tmp)), SupplicantState::toString(evt->getState(), tmp2, sizeof(tmp2))); + if (evt->getState() != SupplicantState::SCANNING) { + mIsSupplicantSearching = true; + mNumScanResultsSinceLastStateChange = 0; + } + + char *tmp3; + asprintf(&tmp3, + "Supplicant state changed from %d (%s) -> %d (%s)", + mSupplicantState, tmp, evt->getState(), tmp2); + mSupplicantState = evt->getState(); + + if (mSupplicantState == SupplicantState::COMPLETED) { + mStatusPoller->start(); + } else if (mStatusPoller->isStarted()) { + mStatusPoller->stop(); + } + + NetworkManager::Instance()->getBroadcaster()-> + sendBroadcast(ResponseCode::SupplicantStateChange, + tmp3, false); + free(tmp3); } void WifiController::onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) { @@ -371,7 +563,8 @@ void WifiController::onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent * } void WifiController::onDisconnectedEvent(SupplicantDisconnectedEvent *evt) { - mHandlers->onInterfaceDisconnected(this, getBoundInterface()); + mCurrentlyConnectedNetworkId = -1; + mHandlers->onInterfaceDisconnected(this); } #if 0 @@ -411,3 +604,216 @@ void WifiController::onDriverStateEvent(SupplicantEvent *evt) { LOGD("onDriverStateEvent(%s)", evt->getEvent()); } #endif + +void WifiController::onStatusPollInterval() { + pthread_mutex_lock(&mLock); + int rssi; + if (mSupplicant->getRssi(&rssi)) { + LOGE("Failed to get rssi (%s)", strerror(errno)); + pthread_mutex_unlock(&mLock); + return; + } + + if (abs(mLastRssi - rssi) > mRssiEventThreshold) { + char *tmp3; + asprintf(&tmp3, "RSSI changed from %d -> %d", + mLastRssi, rssi); + mLastRssi = rssi; + NetworkManager::Instance()->getBroadcaster()-> + sendBroadcast(ResponseCode::RssiChange, + tmp3, false); + free(tmp3); + } + + int linkspeed = mSupplicant->getLinkSpeed(); + if (linkspeed != mLastLinkSpeed) { + char *tmp3; + asprintf(&tmp3, "Link speed changed from %d -> %d", + mLastLinkSpeed, linkspeed); + mLastLinkSpeed = linkspeed; + NetworkManager::Instance()->getBroadcaster()-> + sendBroadcast(ResponseCode::LinkSpeedChange, + tmp3, false); + free(tmp3); + + } + pthread_mutex_unlock(&mLock); +} + +int WifiController::verifyNotSuspended() { + if (mSuspended) { + errno = ESHUTDOWN; + return -1; + } + return 0; +} + +/* + * Property inner classes + */ + +WifiController::WifiIntegerProperty::WifiIntegerProperty(WifiController *c, + const char *name, + bool ro, + int elements) : + IntegerProperty(name, ro, elements) { + mWc = c; +} + +WifiController::WifiStringProperty::WifiStringProperty(WifiController *c, + const char *name, + bool ro, int elements) : + StringProperty(name, ro, elements) { + mWc = c; +} + +WifiController::WifiEnabledProperty::WifiEnabledProperty(WifiController *c) : + WifiIntegerProperty(c, "Enabled", false, 1) { +} + +int WifiController::WifiEnabledProperty::get(int idx, int *buffer) { + *buffer = mWc->mEnabled; + return 0; +} +int WifiController::WifiEnabledProperty::set(int idx, int value) { + int rc = (value ? mWc->enable() : mWc->disable()); + if (!rc) + mWc->mEnabled = value; + return rc; +} + +WifiController::WifiScanOnlyProperty::WifiScanOnlyProperty(WifiController *c) : + WifiIntegerProperty(c, "ScanOnly", false, 1) { +} +int WifiController::WifiScanOnlyProperty::get(int idx, int *buffer) { + *buffer = mWc->mScanOnly; + return 0; +} +int WifiController::WifiScanOnlyProperty::set(int idx, int value) { + return mWc->setScanOnly(value == 1); +} + +WifiController::WifiAllowedChannelsProperty::WifiAllowedChannelsProperty(WifiController *c) : + WifiIntegerProperty(c, "AllowedChannels", false, 1) { +} +int WifiController::WifiAllowedChannelsProperty::get(int idx, int *buffer) { + *buffer = mWc->mNumAllowedChannels; + return 0; +} +int WifiController::WifiAllowedChannelsProperty::set(int idx, int value) { + // XXX: IMPL + errno = ENOSYS; + return -1; +} + +WifiController::WifiSupplicantStateProperty::WifiSupplicantStateProperty(WifiController *c) : + WifiStringProperty(c, "SupplicantState", true, 1) { +} +int WifiController::WifiSupplicantStateProperty::get(int idx, char *buffer, size_t max) { + if (!SupplicantState::toString(mWc->mSupplicantState, buffer, max)) + return -1; + return 0; +} + +WifiController::WifiActiveScanProperty::WifiActiveScanProperty(WifiController *c) : + WifiIntegerProperty(c, "ActiveScan", false, 1) { +} +int WifiController::WifiActiveScanProperty::get(int idx, int *buffer) { + *buffer = mWc->mActiveScan; + return 0; +} +int WifiController::WifiActiveScanProperty::set(int idx, int value) { + return mWc->setActiveScan(value); +} + +WifiController::WifiInterfaceProperty::WifiInterfaceProperty(WifiController *c) : + WifiStringProperty(c, "Interface", true, 1) { +} +int WifiController::WifiInterfaceProperty::get(int idx, char *buffer, size_t max) { + strncpy(buffer, (mWc->getBoundInterface() ? mWc->getBoundInterface() : "none"), max); + return 0; +} + +WifiController::WifiSearchingProperty::WifiSearchingProperty(WifiController *c) : + WifiIntegerProperty(c, "Searching", true, 1) { +} +int WifiController::WifiSearchingProperty::get(int idx, int *buffer) { + *buffer = mWc->mIsSupplicantSearching; + return 0; +} + +WifiController::WifiPacketFilterProperty::WifiPacketFilterProperty(WifiController *c) : + WifiIntegerProperty(c, "PacketFilter", false, 1) { +} +int WifiController::WifiPacketFilterProperty::get(int idx, int *buffer) { + *buffer = mWc->mPacketFilter; + return 0; +} +int WifiController::WifiPacketFilterProperty::set(int idx, int value) { + return mWc->setPacketFilter(value); +} + +WifiController::WifiBluetoothCoexScanProperty::WifiBluetoothCoexScanProperty(WifiController *c) : + WifiIntegerProperty(c, "BluetoothCoexScan", false, 1) { +} +int WifiController::WifiBluetoothCoexScanProperty::get(int idx, int *buffer) { + *buffer = mWc->mBluetoothCoexScan; + return 0; +} +int WifiController::WifiBluetoothCoexScanProperty::set(int idx, int value) { + return mWc->setBluetoothCoexistenceScan(value == 1); +} + +WifiController::WifiBluetoothCoexModeProperty::WifiBluetoothCoexModeProperty(WifiController *c) : + WifiIntegerProperty(c, "BluetoothCoexMode", false, 1) { +} +int WifiController::WifiBluetoothCoexModeProperty::get(int idx, int *buffer) { + *buffer = mWc->mBluetoothCoexMode; + return 0; +} +int WifiController::WifiBluetoothCoexModeProperty::set(int idx, int value) { + return mWc->setBluetoothCoexistenceMode(value); +} + +WifiController::WifiCurrentNetworkProperty::WifiCurrentNetworkProperty(WifiController *c) : + WifiIntegerProperty(c, "CurrentlyConnectedNetworkId", true, 1) { +} +int WifiController::WifiCurrentNetworkProperty::get(int idx, int *buffer) { + *buffer = mWc->mCurrentlyConnectedNetworkId; + return 0; +} + +WifiController::WifiSuspendedProperty::WifiSuspendedProperty(WifiController *c) : + WifiIntegerProperty(c, "Suspended", false, 1) { +} +int WifiController::WifiSuspendedProperty::get(int idx, int *buffer) { + *buffer = mWc->getSuspended(); + return 0; +} +int WifiController::WifiSuspendedProperty::set(int idx, int value) { + return mWc->setSuspend(value == 1); +} + +WifiController::WifiNetCountProperty::WifiNetCountProperty(WifiController *c) : + WifiIntegerProperty(c, "NetCount", true, 1) { +} +int WifiController::WifiNetCountProperty::get(int idx, int *buffer) { + pthread_mutex_lock(&mWc->mLock); + *buffer = mWc->mSupplicant->getNetworkCount(); + pthread_mutex_unlock(&mWc->mLock); + return 0; +} + +WifiController::WifiTriggerScanProperty::WifiTriggerScanProperty(WifiController *c) : + WifiIntegerProperty(c, "TriggerScan", false, 1) { +} +int WifiController::WifiTriggerScanProperty::get(int idx, int *buffer) { + // XXX: Need action type + *buffer = 0; + return 0; +} + +int WifiController::WifiTriggerScanProperty::set(int idx, int value) { + return mWc->triggerScan(); +} + diff --git a/nexus/WifiController.h b/nexus/WifiController.h index c61d97a5a..b1524f66d 100644 --- a/nexus/WifiController.h +++ b/nexus/WifiController.h @@ -23,41 +23,207 @@ #include "ScanResult.h" #include "WifiNetwork.h" #include "ISupplicantEventHandler.h" +#include "IWifiStatusPollerHandler.h" class NetInterface; class Supplicant; -class WifiScanner; class SupplicantAssociatingEvent; class SupplicantAssociatedEvent; class SupplicantConnectedEvent; class SupplicantScanResultsEvent; class SupplicantStateChangeEvent; class SupplicantDisconnectedEvent; +class WifiStatusPoller; -class WifiController : public Controller, public ISupplicantEventHandler { -public: - static const uint32_t SCAN_ENABLE_MASK = 0x01; - static const uint32_t SCAN_ACTIVE_MASK = 0x02; - static const uint32_t SCAN_REPEAT_MASK = 0x04; +class WifiController : public Controller, + public ISupplicantEventHandler, + public IWifiStatusPollerHandler { - static const uint32_t SCANMODE_NONE = 0; - static const uint32_t SCANMODE_PASSIVE_ONESHOT = SCAN_ENABLE_MASK; - static const uint32_t SCANMODE_PASSIVE_CONTINUOUS = SCAN_ENABLE_MASK | SCAN_REPEAT_MASK; - static const uint32_t SCANMODE_ACTIVE_ONESHOT = SCAN_ENABLE_MASK | SCAN_ACTIVE_MASK; - static const uint32_t SCANMODE_ACTIVE_CONTINUOUS = SCAN_ENABLE_MASK | SCAN_ACTIVE_MASK | SCAN_REPEAT_MASK; + class WifiIntegerProperty : public IntegerProperty { + protected: + WifiController *mWc; + public: + WifiIntegerProperty(WifiController *c, const char *name, bool ro, + int elements); + virtual ~WifiIntegerProperty() {} + virtual int set(int idx, int value) = 0; + virtual int get(int idx, int *buffer) = 0; + }; + friend class WifiController::WifiIntegerProperty; + + class WifiStringProperty : public StringProperty { + protected: + WifiController *mWc; + public: + WifiStringProperty(WifiController *c, const char *name, bool ro, + int elements); + virtual ~WifiStringProperty() {} + virtual int set(int idx, const char *value) = 0; + virtual int get(int idx, char *buffer, size_t max) = 0; + }; + friend class WifiController::WifiStringProperty; + + class WifiEnabledProperty : public WifiIntegerProperty { + public: + WifiEnabledProperty(WifiController *c); + virtual ~WifiEnabledProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiScanOnlyProperty : public WifiIntegerProperty { + public: + WifiScanOnlyProperty(WifiController *c); + virtual ~WifiScanOnlyProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiAllowedChannelsProperty : public WifiIntegerProperty { + public: + WifiAllowedChannelsProperty(WifiController *c); + virtual ~WifiAllowedChannelsProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiActiveScanProperty : public WifiIntegerProperty { + public: + WifiActiveScanProperty(WifiController *c); + virtual ~WifiActiveScanProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiSearchingProperty : public WifiIntegerProperty { + public: + WifiSearchingProperty(WifiController *c); + virtual ~WifiSearchingProperty() {} + int set(int idx, int value) { return -1; } + int get(int idx, int *buffer); + }; + + class WifiPacketFilterProperty : public WifiIntegerProperty { + public: + WifiPacketFilterProperty(WifiController *c); + virtual ~WifiPacketFilterProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiBluetoothCoexScanProperty : public WifiIntegerProperty { + public: + WifiBluetoothCoexScanProperty(WifiController *c); + virtual ~WifiBluetoothCoexScanProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiBluetoothCoexModeProperty : public WifiIntegerProperty { + public: + WifiBluetoothCoexModeProperty(WifiController *c); + virtual ~WifiBluetoothCoexModeProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiCurrentNetworkProperty : public WifiIntegerProperty { + public: + WifiCurrentNetworkProperty(WifiController *c); + virtual ~WifiCurrentNetworkProperty() {} + int set(int idx, int value) { return -1; } + int get(int idx, int *buffer); + }; + + class WifiSuspendedProperty : public WifiIntegerProperty { + public: + WifiSuspendedProperty(WifiController *c); + virtual ~WifiSuspendedProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiNetCountProperty : public WifiIntegerProperty { + public: + WifiNetCountProperty(WifiController *c); + virtual ~WifiNetCountProperty() {} + int set(int idx, int value) { return -1; } + int get(int idx, int *buffer); + }; + + class WifiTriggerScanProperty : public WifiIntegerProperty { + public: + WifiTriggerScanProperty(WifiController *c); + virtual ~WifiTriggerScanProperty() {} + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiSupplicantStateProperty : public WifiStringProperty { + public: + WifiSupplicantStateProperty(WifiController *c); + virtual ~WifiSupplicantStateProperty() {} + int set(int idx, const char *value) { return -1; } + int get(int idx, char *buffer, size_t max); + }; + + class WifiInterfaceProperty : public WifiStringProperty { + public: + WifiInterfaceProperty(WifiController *c); + virtual ~WifiInterfaceProperty() {} + int set(int idx, const char *value) { return -1; } + int get(int idx, char *buffer, size_t max); + }; -private: Supplicant *mSupplicant; char mModulePath[255]; char mModuleName[64]; char mModuleArgs[255]; - uint32_t mCurrentScanMode; - WifiScanner *mScanner; int mSupplicantState; + bool mActiveScan; + bool mScanOnly; + bool mPacketFilter; + bool mBluetoothCoexScan; + int mBluetoothCoexMode; + int mCurrentlyConnectedNetworkId; + bool mSuspended; + int mLastRssi; + int mRssiEventThreshold; + int mLastLinkSpeed; + int mNumAllowedChannels; ScanResultCollection *mLatestScanResults; pthread_mutex_t mLatestScanResultsLock; + pthread_mutex_t mLock; + WifiStatusPoller *mStatusPoller; + + struct { + WifiEnabledProperty *propEnabled; + WifiScanOnlyProperty *propScanOnly; + WifiAllowedChannelsProperty *propAllowedChannels; + IntegerPropertyHelper *propRssiEventThreshold; + } mStaticProperties; + + struct { + WifiActiveScanProperty *propActiveScan; + WifiSearchingProperty *propSearching; + WifiPacketFilterProperty *propPacketFilter; + WifiBluetoothCoexScanProperty *propBluetoothCoexScan; + WifiBluetoothCoexModeProperty *propBluetoothCoexMode; + WifiCurrentNetworkProperty *propCurrentNetwork; + IntegerPropertyHelper *propRssi; + IntegerPropertyHelper *propLinkSpeed; + WifiSuspendedProperty *propSuspended; + WifiNetCountProperty *propNetCount; + WifiSupplicantStateProperty *propSupplicantState; + WifiInterfaceProperty *propInterface; + WifiTriggerScanProperty *propTriggerScan; + } mDynamicProperties; + + // True if supplicant is currently searching for a network + bool mIsSupplicantSearching; + int mNumScanResultsSinceLastStateChange; bool mEnabled; @@ -72,9 +238,6 @@ public: int removeNetwork(int networkId); WifiNetworkCollection *createNetworkList(); - virtual int set(const char *name, const char *value); - virtual const char *get(const char *name, char *buffer, size_t maxlen); - ScanResultCollection *createScanResults(); char *getModulePath() { return mModulePath; } @@ -94,18 +257,25 @@ protected: private: void sendStatusBroadcast(const char *msg); - int setScanMode(uint32_t mode); + int setActiveScan(bool active); + int triggerScan(); int enable(); int disable(); + int setSuspend(bool suspend); + bool getSuspended(); + int setBluetoothCoexistenceScan(bool enable); + int setBluetoothCoexistenceMode(int mode); + int setPacketFilter(bool enable); + int setScanOnly(bool scanOnly); // ISupplicantEventHandler methods - virtual void onAssociatingEvent(SupplicantAssociatingEvent *evt); - virtual void onAssociatedEvent(SupplicantAssociatedEvent *evt); - virtual void onConnectedEvent(SupplicantConnectedEvent *evt); - virtual void onScanResultsEvent(SupplicantScanResultsEvent *evt); - virtual void onStateChangeEvent(SupplicantStateChangeEvent *evt); - virtual void onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt); - virtual void onDisconnectedEvent(SupplicantDisconnectedEvent *evt); + void onAssociatingEvent(SupplicantAssociatingEvent *evt); + void onAssociatedEvent(SupplicantAssociatedEvent *evt); + void onConnectedEvent(SupplicantConnectedEvent *evt); + void onScanResultsEvent(SupplicantScanResultsEvent *evt); + void onStateChangeEvent(SupplicantStateChangeEvent *evt); + void onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt); + void onDisconnectedEvent(SupplicantDisconnectedEvent *evt); #if 0 virtual void onTerminatingEvent(SupplicantEvent *evt); virtual void onPasswordChangedEvent(SupplicantEvent *evt); @@ -118,6 +288,9 @@ private: virtual void onDriverStateEvent(SupplicantEvent *evt); #endif + void onStatusPollInterval(); + + int verifyNotSuspended(); }; #endif diff --git a/nexus/WifiNetwork.cpp b/nexus/WifiNetwork.cpp index 7059bd04b..6a0f6840b 100644 --- a/nexus/WifiNetwork.cpp +++ b/nexus/WifiNetwork.cpp @@ -26,17 +26,7 @@ #include "WifiNetwork.h" #include "Supplicant.h" #include "WifiController.h" -#include "InterfaceConfig.h" -const char *WifiNetwork::PropertyNames[] = { "ssid", "bssid", "psk", "wepkey.1", - "wepkey.2", "wepkey.3", "wepkey.4", - "defkeyidx", "pri", "hiddenssid", - "AllowedKeyManagement", - "AllowedProtocols", - "AllowedAuthAlgorithms", - "AllowedPairwiseCiphers", - "AllowedGroupCiphers", - "enabled", '\0' }; WifiNetwork::WifiNetwork() { // This is private to restrict copy constructors } @@ -76,11 +66,11 @@ WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, const char *data) mDefaultKeyIndex = -1; mPriority = -1; mHiddenSsid = NULL; - mAllowedKeyManagement = KeyManagementMask::UNKNOWN; - mAllowedProtocols = 0; - mAllowedAuthAlgorithms = 0; - mAllowedPairwiseCiphers = 0; - mAllowedGroupCiphers = 0; + mKeyManagement = KeyManagementMask::UNKNOWN; + mProtocols = 0; + mAuthAlgorithms = 0; + mPairwiseCiphers = 0; + mGroupCiphers = 0; mEnabled = true; if (flags && flags[0] != '\0') { @@ -90,11 +80,8 @@ WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, const char *data) LOGW("Unsupported flags '%s'", flags); } - char *tmp2; - asprintf(&tmp2, "wifi.net.%d", mNetid); - mIfaceCfg = new InterfaceConfig(tmp2); - free(tmp2); free(tmp); + createProperties(); } WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, int networkId) { @@ -108,17 +95,13 @@ WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, int networkId) { mDefaultKeyIndex = -1; mPriority = -1; mHiddenSsid = NULL; - mAllowedKeyManagement = 0; - mAllowedProtocols = 0; - mAllowedAuthAlgorithms = 0; - mAllowedPairwiseCiphers = 0; - mAllowedGroupCiphers = 0; + mKeyManagement = 0; + mProtocols = 0; + mAuthAlgorithms = 0; + mPairwiseCiphers = 0; + mGroupCiphers = 0; mEnabled = false; - - char *tmp2; - asprintf(&tmp2, "wifi.net.%d", mNetid); - mIfaceCfg = new InterfaceConfig(tmp2); - free(tmp2); + createProperties(); } WifiNetwork *WifiNetwork::clone() { @@ -140,15 +123,35 @@ WifiNetwork *WifiNetwork::clone() { r->mPriority = mPriority; if (mHiddenSsid) r->mHiddenSsid = strdup(mHiddenSsid); - r->mAllowedKeyManagement = mAllowedKeyManagement; - r->mAllowedProtocols = mAllowedProtocols; - r->mAllowedAuthAlgorithms = mAllowedAuthAlgorithms; - r->mAllowedPairwiseCiphers = mAllowedPairwiseCiphers; - r->mAllowedGroupCiphers = mAllowedGroupCiphers; + r->mKeyManagement = mKeyManagement; + r->mProtocols = mProtocols; + r->mAuthAlgorithms = mAuthAlgorithms; + r->mPairwiseCiphers = mPairwiseCiphers; + r->mGroupCiphers = mGroupCiphers; return r; } +void WifiNetwork::createProperties() { + asprintf(&mPropNamespace, "wifi.net.%d", mNetid); + + mStaticProperties.propEnabled = new WifiNetworkEnabledProperty(this); + mStaticProperties.propSsid = new WifiNetworkSsidProperty(this); + mStaticProperties.propBssid = new WifiNetworkBssidProperty(this); + mStaticProperties.propPsk = new WifiNetworkPskProperty(this); + mStaticProperties.propWepKey = new WifiNetworkWepKeyProperty(this); + mStaticProperties.propDefKeyIdx = new WifiNetworkDefaultKeyIndexProperty(this); + mStaticProperties.propPriority = new WifiNetworkPriorityProperty(this); + mStaticProperties.propKeyManagement = new WifiNetworkKeyManagementProperty(this); + mStaticProperties.propProtocols = new WifiNetworkProtocolsProperty(this); + mStaticProperties.propAuthAlgorithms = new WifiNetworkAuthAlgorithmsProperty(this); + mStaticProperties.propPairwiseCiphers = new WifiNetworkPairwiseCiphersProperty(this); + mStaticProperties.propGroupCiphers = new WifiNetworkGroupCiphersProperty(this); + mStaticProperties.propHiddenSsid = new WifiNetworkHiddenSsidProperty(this); +} + WifiNetwork::~WifiNetwork() { + if (mPropNamespace) + free(mPropNamespace); if (mSsid) free(mSsid); if (mBssid) @@ -162,13 +165,26 @@ WifiNetwork::~WifiNetwork() { if (mHiddenSsid) free(mHiddenSsid); - if (mIfaceCfg) - delete(mIfaceCfg); + + delete mStaticProperties.propEnabled; + delete mStaticProperties.propSsid; + delete mStaticProperties.propBssid; + delete mStaticProperties.propPsk; + delete mStaticProperties.propWepKey; + delete mStaticProperties.propDefKeyIdx; + delete mStaticProperties.propPriority; + delete mStaticProperties.propKeyManagement; + delete mStaticProperties.propProtocols; + delete mStaticProperties.propAuthAlgorithms; + delete mStaticProperties.propPairwiseCiphers; + delete mStaticProperties.propGroupCiphers; + delete mStaticProperties.propHiddenSsid; } int WifiNetwork::refresh() { char buffer[255]; size_t len; + uint32_t mask; len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "psk", buffer, len)) @@ -198,46 +214,47 @@ int WifiNetwork::refresh() { len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "key_mgmt", buffer, len)) { - if (!strcmp(buffer, "NONE")) - setAllowedKeyManagement(KeyManagementMask::NONE); - else if (index(buffer, ' ')) { - char *next = buffer; - char *token; - uint32_t mask = 0; - - while((token = strsep(&next, " "))) { - if (!strcmp(token, "WPA-PSK")) - mask |= KeyManagementMask::WPA_PSK; - else if (!strcmp(token, "WPA-EAP")) - mask |= KeyManagementMask::WPA_EAP; - else if (!strcmp(token, "IEE8021X")) - mask |= KeyManagementMask::IEEE8021X; - else - LOGW("Unsupported key management scheme '%s'" , token); - } - setAllowedKeyManagement(mask); - } else - LOGE("Unsupported key management '%s'", buffer); + if (WifiNetwork::parseKeyManagementMask(buffer, &mask)) { + LOGE("Error parsing key_mgmt (%s)", strerror(errno)); + } else { + mKeyManagement = mask; + } } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "proto", buffer, len)) { - // TODO + if (WifiNetwork::parseProtocolsMask(buffer, &mask)) { + LOGE("Error parsing proto (%s)", strerror(errno)); + } else { + mProtocols = mask; + } } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "auth_alg", buffer, len)) { - // TODO + if (WifiNetwork::parseAuthAlgorithmsMask(buffer, &mask)) { + LOGE("Error parsing auth_alg (%s)", strerror(errno)); + } else { + mAuthAlgorithms = mask; + } } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "pairwise", buffer, len)) { - // TODO + if (WifiNetwork::parsePairwiseCiphersMask(buffer, &mask)) { + LOGE("Error parsing pairwise (%s)", strerror(errno)); + } else { + mPairwiseCiphers = mask; + } } len = sizeof(buffer); if (mSuppl->getNetworkVar(mNetid, "group", buffer, len)) { - // TODO + if (WifiNetwork::parseGroupCiphersMask(buffer, &mask)) { + LOGE("Error parsing group (%s)", strerror(errno)); + } else { + mGroupCiphers = mask; + } } return 0; @@ -246,179 +263,10 @@ out_err: return -1; } -int WifiNetwork::set(const char *name, const char *value) { - char *n_tmp = strdup(name + strlen("wifi.net.")); - char *n_next = n_tmp; - char *n_local; - char *n_rest; - int rc = 0; - - if (!strsep(&n_next, ".")) // skip net id - goto out_inval; - - if (!(n_local = strsep(&n_next, "."))) - goto out_inval; - - n_rest = n_next; - -// LOGD("set(): var '%s'(%s / %s) = %s", name, n_local, n_rest, value); - if (!strcasecmp(n_local, "enabled")) - rc = setEnabled(atoi(value)); - else if (!strcmp(n_local, "ssid")) - rc = setSsid(value); - else if (!strcasecmp(n_local, "bssid")) - rc = setBssid(value); - else if (!strcasecmp(n_local, "psk")) - rc = setPsk(value); - else if (!strcasecmp(n_local, "wepkey")) - rc = setWepKey(atoi(n_rest) -1, value); - else if (!strcasecmp(n_local, "defkeyidx")) - rc = setDefaultKeyIndex(atoi(value)); - else if (!strcasecmp(n_local, "pri")) - rc = setPriority(atoi(value)); - else if (!strcasecmp(n_local, "hiddenssid")) - rc = setHiddenSsid(value); - else if (!strcasecmp(n_local, "AllowedKeyManagement")) { - uint32_t mask = 0; - bool none = false; - char *v_tmp = strdup(value); - char *v_next = v_tmp; - char *v_token; - - while((v_token = strsep(&v_next, " "))) { - if (!strcasecmp(v_token, "NONE")) { - mask = KeyManagementMask::NONE; - none = true; - } else if (!none) { - if (!strcasecmp(v_token, "WPA_PSK")) - mask |= KeyManagementMask::WPA_PSK; - else if (!strcasecmp(v_token, "WPA_EAP")) - mask |= KeyManagementMask::WPA_EAP; - else if (!strcasecmp(v_token, "IEEE8021X")) - mask |= KeyManagementMask::IEEE8021X; - else { - errno = EINVAL; - rc = -1; - free(v_tmp); - goto out; - } - } else { - errno = EINVAL; - rc = -1; - free(v_tmp); - goto out; - } - } - free(v_tmp); - } else if (!strcasecmp(n_local, "AllowedProtocols")) { - // TODO - } else if (!strcasecmp(n_local, "AllowedPairwiseCiphers")) { - // TODO - } else if (!strcasecmp(n_local, "AllowedAuthAlgorithms")) { - // TODO - } else if (!strcasecmp(n_local, "AllowedGroupCiphers")) { - // TODO - } else { - errno = ENOENT; - free(n_tmp); - return -1; - } - -out: - free(n_tmp); - return rc; - -out_inval: - errno = EINVAL; - free(n_tmp); - return -1; -} - -const char *WifiNetwork::get(const char *name, char *buffer, size_t maxsize) { - char *n_tmp = strdup(name + strlen("wifi.net.")); - char *n_next = n_tmp; - char *n_local; - char fc[64]; - char rc[128]; - - if (!strsep(&n_next, ".")) // skip net id - goto out_inval; - - if (!(n_local = strsep(&n_next, "."))) - goto out_inval; - - - strncpy(fc, n_local, sizeof(fc)); - rc[0] = '\0'; - if (n_next) - strncpy(rc, n_next, sizeof(rc)); - - free(n_tmp); - - if (!strcasecmp(fc, "enabled")) - snprintf(buffer, maxsize, "%d", getEnabled()); - else if (!strcasecmp(fc, "ssid")) { - strncpy(buffer, - getSsid() ? getSsid() : "none", - maxsize); - } else if (!strcasecmp(fc, "bssid")) { - strncpy(buffer, - getBssid() ? getBssid() : "none", - maxsize); - } else if (!strcasecmp(fc, "psk")) { - strncpy(buffer, - getPsk() ? getPsk() : "none", - maxsize); - } else if (!strcasecmp(fc, "wepkey")) { - strncpy(buffer, - getWepKey(atoi(rc)-1) ? getWepKey(atoi(rc)-1) : "none", - maxsize); - } else if (!strcasecmp(fc, "defkeyidx")) - snprintf(buffer, maxsize, "%d", getDefaultKeyIndex()); - else if (!strcasecmp(fc, "pri")) - snprintf(buffer, maxsize, "%d", getPriority()); - else if (!strcasecmp(fc, "AllowedKeyManagement")) { - if (getAllowedKeyManagement() == KeyManagementMask::NONE) - strncpy(buffer, "NONE", maxsize); - else { - char tmp[80] = { '\0' }; - - if (getAllowedKeyManagement() & KeyManagementMask::WPA_PSK) - strcat(tmp, "WPA_PSK "); - if (getAllowedKeyManagement() & KeyManagementMask::WPA_EAP) - strcat(tmp, "WPA_EAP "); - if (getAllowedKeyManagement() & KeyManagementMask::IEEE8021X) - strcat(tmp, "IEEE8021X"); - if (tmp[0] == '\0') { - strncpy(buffer, "(internal error)", maxsize); - errno = ENOENT; - return NULL; - } - if (tmp[strlen(tmp)] == ' ') - tmp[strlen(tmp)] = '\0'; - - strncpy(buffer, tmp, maxsize); - } - } else if (!strcasecmp(fc, "hiddenssid")) { - strncpy(buffer, - getHiddenSsid() ? getHiddenSsid() : "none", - maxsize); - } else { - strncpy(buffer, "(internal error)", maxsize); - errno = ENOENT; - return NULL; - } - - return buffer; - -out_inval: - errno = EINVAL; - free(n_tmp); - return NULL; -} - int WifiNetwork::setSsid(const char *ssid) { - if (mSuppl->setNetworkVar(mNetid, "ssid", ssid)) + char tmp[255]; + snprintf(tmp, sizeof(tmp), "\"%s\"", ssid); + if (mSuppl->setNetworkVar(mNetid, "ssid", tmp)) return -1; if (mSsid) free(mSsid); @@ -436,7 +284,9 @@ int WifiNetwork::setBssid(const char *bssid) { } int WifiNetwork::setPsk(const char *psk) { - if (mSuppl->setNetworkVar(mNetid, "psk", psk)) + char tmp[255]; + snprintf(tmp, sizeof(tmp), "\"%s\"", psk); + if (mSuppl->setNetworkVar(mNetid, "psk", tmp)) return -1; if (mPsk) @@ -491,28 +341,34 @@ int WifiNetwork::setHiddenSsid(const char *ssid) { return 0; } -int WifiNetwork::setAllowedKeyManagement(uint32_t mask) { - char accum[255]; +int WifiNetwork::setKeyManagement(uint32_t mask) { + char accum[64] = {'\0'}; if (mask == KeyManagementMask::NONE) strcpy(accum, "NONE"); else { - if (mask & KeyManagementMask::WPA_PSK) - strcat(accum, "WPA_PSK "); - if (mask & KeyManagementMask::WPA_EAP) - strcat(accum, "WPA_EAP "); - if (mask & KeyManagementMask::IEEE8021X) - strcat(accum, "IEEE8021X "); + if (mask & KeyManagementMask::WPA_PSK) + strcat(accum, "WPA-PSK"); + if (mask & KeyManagementMask::WPA_EAP) { + if (accum[0] != '\0') + strcat(accum, " "); + strcat(accum, "WPA-EAP"); + } + if (mask & KeyManagementMask::IEEE8021X) { + if (accum[0] != '\0') + strcat(accum, " "); + strcat(accum, "IEEE8021X"); + } } if (mSuppl->setNetworkVar(mNetid, "key_mgmt", accum)) return -1; - mAllowedKeyManagement = mask; + mKeyManagement = mask; return 0; } -int WifiNetwork::setAllowedProtocols(uint32_t mask) { - char accum[255]; +int WifiNetwork::setProtocols(uint32_t mask) { + char accum[64]; accum[0] = '\0'; @@ -524,15 +380,18 @@ int WifiNetwork::setAllowedProtocols(uint32_t mask) { if (mSuppl->setNetworkVar(mNetid, "proto", accum)) return -1; - mAllowedProtocols = mask; + mProtocols = mask; return 0; } -int WifiNetwork::setAllowedAuthAlgorithms(uint32_t mask) { - char accum[255]; +int WifiNetwork::setAuthAlgorithms(uint32_t mask) { + char accum[64]; accum[0] = '\0'; + if (mask == 0) + strcpy(accum, ""); + if (mask & AuthenticationAlgorithmMask::OPEN) strcpy(accum, "OPEN "); @@ -545,12 +404,14 @@ int WifiNetwork::setAllowedAuthAlgorithms(uint32_t mask) { if (mSuppl->setNetworkVar(mNetid, "auth_alg", accum)) return -1; - mAllowedAuthAlgorithms = mask; + mAuthAlgorithms = mask; return 0; } -int WifiNetwork::setAllowedPairwiseCiphers(uint32_t mask) { - char accum[255]; +int WifiNetwork::setPairwiseCiphers(uint32_t mask) { + char accum[64]; + + accum[0] = '\0'; if (mask == PairwiseCiphersMask::NONE) strcpy(accum, "NONE"); @@ -564,12 +425,14 @@ int WifiNetwork::setAllowedPairwiseCiphers(uint32_t mask) { if (mSuppl->setNetworkVar(mNetid, "pairwise", accum)) return -1; - mAllowedPairwiseCiphers = mask; + mPairwiseCiphers = mask; return 0; } -int WifiNetwork::setAllowedGroupCiphers(uint32_t mask) { - char accum[255]; +int WifiNetwork::setGroupCiphers(uint32_t mask) { + char accum[64]; + + accum[0] = '\0'; if (mask & GroupCiphersMask::WEP40) strcat(accum, "WEP40 "); @@ -582,7 +445,7 @@ int WifiNetwork::setAllowedGroupCiphers(uint32_t mask) { if (mSuppl->setNetworkVar(mNetid, "group", accum)) return -1; - mAllowedGroupCiphers = mask; + mGroupCiphers = mask; return 0; } @@ -594,7 +457,7 @@ int WifiNetwork::setEnabled(bool enabled) { errno = EAGAIN; return -1; } - if (getAllowedKeyManagement() == KeyManagementMask::UNKNOWN) { + if (getKeyManagement() == KeyManagementMask::UNKNOWN) { LOGE("Cannot enable network when KeyManagement is not set"); errno = EAGAIN; return -1; @@ -608,29 +471,500 @@ int WifiNetwork::setEnabled(bool enabled) { return 0; } -int WifiNetwork::registerProperties() { - for (const char **p = WifiNetwork::PropertyNames; *p != '\0'; p++) { - char *tmp; - asprintf(&tmp, "wifi.net.%d.%s", mNetid, *p); +int WifiNetwork::attachProperties(PropertyManager *pm, const char *nsName) { + pm->attachProperty(nsName, mStaticProperties.propSsid); + pm->attachProperty(nsName, mStaticProperties.propBssid); + pm->attachProperty(nsName, mStaticProperties.propPsk); + pm->attachProperty(nsName, mStaticProperties.propWepKey); + pm->attachProperty(nsName, mStaticProperties.propDefKeyIdx); + pm->attachProperty(nsName, mStaticProperties.propPriority); + pm->attachProperty(nsName, mStaticProperties.propKeyManagement); + pm->attachProperty(nsName, mStaticProperties.propProtocols); + pm->attachProperty(nsName, mStaticProperties.propAuthAlgorithms); + pm->attachProperty(nsName, mStaticProperties.propPairwiseCiphers); + pm->attachProperty(nsName, mStaticProperties.propGroupCiphers); + pm->attachProperty(nsName, mStaticProperties.propHiddenSsid); + pm->attachProperty(nsName, mStaticProperties.propEnabled); + return 0; +} - if (NetworkManager::Instance()->getPropMngr()->registerProperty(tmp, - this)) { - free(tmp); +int WifiNetwork::detachProperties(PropertyManager *pm, const char *nsName) { + pm->detachProperty(nsName, mStaticProperties.propEnabled); + pm->detachProperty(nsName, mStaticProperties.propSsid); + pm->detachProperty(nsName, mStaticProperties.propBssid); + pm->detachProperty(nsName, mStaticProperties.propPsk); + pm->detachProperty(nsName, mStaticProperties.propWepKey); + pm->detachProperty(nsName, mStaticProperties.propDefKeyIdx); + pm->detachProperty(nsName, mStaticProperties.propPriority); + pm->detachProperty(nsName, mStaticProperties.propKeyManagement); + pm->detachProperty(nsName, mStaticProperties.propProtocols); + pm->detachProperty(nsName, mStaticProperties.propAuthAlgorithms); + pm->detachProperty(nsName, mStaticProperties.propPairwiseCiphers); + pm->detachProperty(nsName, mStaticProperties.propGroupCiphers); + pm->detachProperty(nsName, mStaticProperties.propHiddenSsid); + return 0; +} + +int WifiNetwork::parseKeyManagementMask(const char *buffer, uint32_t *mask) { + bool none = false; + char *v_tmp = strdup(buffer); + char *v_next = v_tmp; + char *v_token; + +// LOGD("parseKeyManagementMask(%s)", buffer); + *mask = 0; + + while((v_token = strsep(&v_next, " "))) { + if (!strcasecmp(v_token, "NONE")) { + *mask = KeyManagementMask::NONE; + none = true; + } else if (!none) { + if (!strcasecmp(v_token, "WPA-PSK")) + *mask |= KeyManagementMask::WPA_PSK; + else if (!strcasecmp(v_token, "WPA-EAP")) + *mask |= KeyManagementMask::WPA_EAP; + else if (!strcasecmp(v_token, "IEEE8021X")) + *mask |= KeyManagementMask::IEEE8021X; + else { + LOGW("Invalid KeyManagementMask value '%s'", v_token); + errno = EINVAL; + free(v_tmp); + return -1; + } + } else { + LOGW("KeyManagementMask value '%s' when NONE", v_token); + errno = EINVAL; + free(v_tmp); return -1; } - free(tmp); } + free(v_tmp); return 0; } -int WifiNetwork::unregisterProperties() { - for (const char **p = WifiNetwork::PropertyNames; *p != '\0'; p++) { - char *tmp; - asprintf(&tmp, "wifi.net.%d.%s", mNetid, *p); +int WifiNetwork::parseProtocolsMask(const char *buffer, uint32_t *mask) { + bool none = false; + char *v_tmp = strdup(buffer); + char *v_next = v_tmp; + char *v_token; - if (NetworkManager::Instance()->getPropMngr()->unregisterProperty(tmp)) - LOGW("Unable to remove property '%s' (%s)", tmp, strerror(errno)); - free(tmp); +// LOGD("parseProtocolsMask(%s)", buffer); + *mask = 0; + while((v_token = strsep(&v_next, " "))) { + if (!strcasecmp(v_token, "WPA")) + *mask |= SecurityProtocolMask::WPA; + else if (!strcasecmp(v_token, "RSN")) + *mask |= SecurityProtocolMask::RSN; + else { + LOGW("Invalid ProtocolsMask value '%s'", v_token); + errno = EINVAL; + free(v_tmp); + return -1; + } + } + + free(v_tmp); + return 0; +} + +int WifiNetwork::parseAuthAlgorithmsMask(const char *buffer, uint32_t *mask) { + bool none = false; + char *v_tmp = strdup(buffer); + char *v_next = v_tmp; + char *v_token; + +// LOGD("parseAuthAlgorithmsMask(%s)", buffer); + + *mask = 0; + if (buffer[0] == '\0') + return 0; + + while((v_token = strsep(&v_next, " "))) { + if (!strcasecmp(v_token, "OPEN")) + *mask |= AuthenticationAlgorithmMask::OPEN; + else if (!strcasecmp(v_token, "SHARED")) + *mask |= AuthenticationAlgorithmMask::SHARED; + else if (!strcasecmp(v_token, "LEAP")) + *mask |= AuthenticationAlgorithmMask::LEAP; + else { + LOGW("Invalid AuthAlgorithmsMask value '%s'", v_token); + errno = EINVAL; + free(v_tmp); + return -1; + } + } + free(v_tmp); + return 0; +} + +int WifiNetwork::parsePairwiseCiphersMask(const char *buffer, uint32_t *mask) { + bool none = false; + char *v_tmp = strdup(buffer); + char *v_next = v_tmp; + char *v_token; + +// LOGD("parsePairwiseCiphersMask(%s)", buffer); + + *mask = 0; + while((v_token = strsep(&v_next, " "))) { + if (!strcasecmp(v_token, "NONE")) { + *mask = PairwiseCiphersMask::NONE; + none = true; + } else if (!none) { + if (!strcasecmp(v_token, "TKIP")) + *mask |= PairwiseCiphersMask::TKIP; + else if (!strcasecmp(v_token, "CCMP")) + *mask |= PairwiseCiphersMask::CCMP; + else { + LOGW("PairwiseCiphersMask value '%s' when NONE", v_token); + errno = EINVAL; + free(v_tmp); + return -1; + } + } else { + LOGW("Invalid PairwiseCiphersMask value '%s'", v_token); + errno = EINVAL; + free(v_tmp); + return -1; + } + } + free(v_tmp); + return 0; +} + +int WifiNetwork::parseGroupCiphersMask(const char *buffer, uint32_t *mask) { + bool none = false; + char *v_tmp = strdup(buffer); + char *v_next = v_tmp; + char *v_token; + +// LOGD("parseGroupCiphersMask(%s)", buffer); + + *mask = 0; + while((v_token = strsep(&v_next, " "))) { + if (!strcasecmp(v_token, "WEP40")) + *mask |= GroupCiphersMask::WEP40; + else if (!strcasecmp(v_token, "WEP104")) + *mask |= GroupCiphersMask::WEP104; + else if (!strcasecmp(v_token, "TKIP")) + *mask |= GroupCiphersMask::TKIP; + else if (!strcasecmp(v_token, "CCMP")) + *mask |= GroupCiphersMask::CCMP; + else { + LOGW("Invalid GroupCiphersMask value '%s'", v_token); + errno = EINVAL; + free(v_tmp); + return -1; + } + } + free(v_tmp); + return 0; +} + +WifiNetwork::WifiNetworkIntegerProperty::WifiNetworkIntegerProperty(WifiNetwork *wn, + const char *name, + bool ro, + int elements) : + IntegerProperty(name, ro, elements) { + mWn = wn; +} + +WifiNetwork::WifiNetworkStringProperty::WifiNetworkStringProperty(WifiNetwork *wn, + const char *name, + bool ro, int elements) : + StringProperty(name, ro, elements) { + mWn = wn; +} + +WifiNetwork::WifiNetworkEnabledProperty::WifiNetworkEnabledProperty(WifiNetwork *wn) : + WifiNetworkIntegerProperty(wn, "Enabled", false, 1) { +} + +int WifiNetwork::WifiNetworkEnabledProperty::get(int idx, int *buffer) { + *buffer = mWn->mEnabled; + return 0; +} +int WifiNetwork::WifiNetworkEnabledProperty::set(int idx, int value) { + return mWn->setEnabled(value == 1); +} + +WifiNetwork::WifiNetworkSsidProperty::WifiNetworkSsidProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "Ssid", false, 1) { +} + +int WifiNetwork::WifiNetworkSsidProperty::get(int idx, char *buffer, size_t max) { + strncpy(buffer, + mWn->getSsid() ? mWn->getSsid() : "none", + max); + return 0; +} +int WifiNetwork::WifiNetworkSsidProperty::set(int idx, const char *value) { + return mWn->setSsid(value); +} + +WifiNetwork::WifiNetworkBssidProperty::WifiNetworkBssidProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "Bssid", false, 1) { +} +int WifiNetwork::WifiNetworkBssidProperty::get(int idx, char *buffer, size_t max) { + strncpy(buffer, + mWn->getBssid() ? mWn->getBssid() : "none", + max); + return 0; +} +int WifiNetwork::WifiNetworkBssidProperty::set(int idx, const char *value) { + return mWn->setBssid(value); +} + +WifiNetwork::WifiNetworkPskProperty::WifiNetworkPskProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "Psk", false, 1) { +} +int WifiNetwork::WifiNetworkPskProperty::get(int idx, char *buffer, size_t max) { + strncpy(buffer, + mWn->getPsk() ? mWn->getPsk() : "none", + max); + return 0; +} +int WifiNetwork::WifiNetworkPskProperty::set(int idx, const char *value) { + return mWn->setPsk(value); +} + +WifiNetwork::WifiNetworkWepKeyProperty::WifiNetworkWepKeyProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "WepKey", false, 4) { +} + +int WifiNetwork::WifiNetworkWepKeyProperty::get(int idx, char *buffer, size_t max) { + const char *key = mWn->getWepKey(idx); + + strncpy(buffer, (key ? key : "none"), max); + return 0; +} +int WifiNetwork::WifiNetworkWepKeyProperty::set(int idx, const char *value) { + return mWn->setWepKey(idx, value); +} + +WifiNetwork::WifiNetworkDefaultKeyIndexProperty::WifiNetworkDefaultKeyIndexProperty(WifiNetwork *wn) : + WifiNetworkIntegerProperty(wn, "DefaultKeyIndex", false, 1) { +} +int WifiNetwork::WifiNetworkDefaultKeyIndexProperty::get(int idx, int *buffer) { + *buffer = mWn->getDefaultKeyIndex(); + return 0; +} +int WifiNetwork::WifiNetworkDefaultKeyIndexProperty::set(int idx, int value) { + return mWn->setDefaultKeyIndex(value); +} + +WifiNetwork::WifiNetworkPriorityProperty::WifiNetworkPriorityProperty(WifiNetwork *wn) : + WifiNetworkIntegerProperty(wn, "Priority", false, 1) { +} +int WifiNetwork::WifiNetworkPriorityProperty::get(int idx, int *buffer) { + *buffer = mWn->getPriority(); + return 0; +} +int WifiNetwork::WifiNetworkPriorityProperty::set(int idx, int value) { + return mWn->setPriority(value); +} + +WifiNetwork::WifiNetworkKeyManagementProperty::WifiNetworkKeyManagementProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "KeyManagement", false, 1) { +} +int WifiNetwork::WifiNetworkKeyManagementProperty::get(int idx, char *buffer, size_t max) { + + if (mWn->getKeyManagement() == KeyManagementMask::NONE) + strncpy(buffer, "NONE", max); + else { + char tmp[80] = { '\0' }; + + if (mWn->getKeyManagement() & KeyManagementMask::WPA_PSK) + strcat(tmp, "WPA-PSK"); + if (mWn->getKeyManagement() & KeyManagementMask::WPA_EAP) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "WPA-EAP"); + } + if (mWn->getKeyManagement() & KeyManagementMask::IEEE8021X) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "IEEE8021X"); + } + if (tmp[0] == '\0') { + strncpy(buffer, "(internal error)", max); + errno = ENOENT; + return -1; + } + if (tmp[strlen(tmp)] == ' ') + tmp[strlen(tmp)] = '\0'; + + strncpy(buffer, tmp, max); } return 0; } +int WifiNetwork::WifiNetworkKeyManagementProperty::set(int idx, const char *value) { + uint32_t mask; + if (mWn->parseKeyManagementMask(value, &mask)) + return -1; + return mWn->setKeyManagement(mask); +} + +WifiNetwork::WifiNetworkProtocolsProperty::WifiNetworkProtocolsProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "Protocols", false, 1) { +} +int WifiNetwork::WifiNetworkProtocolsProperty::get(int idx, char *buffer, size_t max) { + char tmp[80] = { '\0' }; + + if (mWn->getProtocols() & SecurityProtocolMask::WPA) + strcat(tmp, "WPA"); + if (mWn->getProtocols() & SecurityProtocolMask::RSN) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "RSN"); + } + + if (tmp[0] == '\0') { + strncpy(buffer, "(internal error)", max); + errno = ENOENT; + return NULL; + } + if (tmp[strlen(tmp)] == ' ') + tmp[strlen(tmp)] = '\0'; + + strncpy(buffer, tmp, max); + return 0; +} +int WifiNetwork::WifiNetworkProtocolsProperty::set(int idx, const char *value) { + uint32_t mask; + if (mWn->parseProtocolsMask(value, &mask)) + return -1; + return mWn->setProtocols(mask); +} + +WifiNetwork::WifiNetworkAuthAlgorithmsProperty::WifiNetworkAuthAlgorithmsProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "AuthAlgorithms", false, 1) { +} +int WifiNetwork::WifiNetworkAuthAlgorithmsProperty::get(int idx, char *buffer, size_t max) { + char tmp[80] = { '\0' }; + + if (mWn->getAuthAlgorithms() == 0) { + strncpy(buffer, "NONE", max); + return 0; + } + + if (mWn->getAuthAlgorithms() & AuthenticationAlgorithmMask::OPEN) + strcat(tmp, "OPEN"); + if (mWn->getAuthAlgorithms() & AuthenticationAlgorithmMask::SHARED) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "SHARED"); + } + if (mWn->getAuthAlgorithms() & AuthenticationAlgorithmMask::LEAP) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "LEAP"); + } + + if (tmp[0] == '\0') { + strncpy(buffer, "(internal error)", max); + errno = ENOENT; + return NULL; + } + if (tmp[strlen(tmp)] == ' ') + tmp[strlen(tmp)] = '\0'; + + strncpy(buffer, tmp, max); + return 0; +} +int WifiNetwork::WifiNetworkAuthAlgorithmsProperty::set(int idx, const char *value) { + uint32_t mask; + if (mWn->parseAuthAlgorithmsMask(value, &mask)) + return -1; + return mWn->setAuthAlgorithms(mask); +} + +WifiNetwork::WifiNetworkPairwiseCiphersProperty::WifiNetworkPairwiseCiphersProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "PairwiseCiphers", false, 1) { +} +int WifiNetwork::WifiNetworkPairwiseCiphersProperty::get(int idx, char *buffer, size_t max) { + if (mWn->getPairwiseCiphers() == PairwiseCiphersMask::NONE) + strncpy(buffer, "NONE", max); + else { + char tmp[80] = { '\0' }; + + if (mWn->getPairwiseCiphers() & PairwiseCiphersMask::TKIP) + strcat(tmp, "TKIP"); + if (mWn->getPairwiseCiphers() & PairwiseCiphersMask::CCMP) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "CCMP"); + } + if (tmp[0] == '\0') { + strncpy(buffer, "(internal error)", max); + errno = ENOENT; + return NULL; + } + if (tmp[strlen(tmp)] == ' ') + tmp[strlen(tmp)] = '\0'; + + strncpy(buffer, tmp, max); + } + return 0; +} +int WifiNetwork::WifiNetworkPairwiseCiphersProperty::set(int idx, const char *value) { + uint32_t mask; + if (mWn->parsePairwiseCiphersMask(value, &mask)) + return -1; + return mWn->setPairwiseCiphers(mask); +} + +WifiNetwork::WifiNetworkGroupCiphersProperty::WifiNetworkGroupCiphersProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "GroupCiphers", false, 1) { +} +int WifiNetwork::WifiNetworkGroupCiphersProperty::get(int idx, char *buffer, size_t max) { + char tmp[80] = { '\0' }; + + if (mWn->getGroupCiphers() & GroupCiphersMask::WEP40) + strcat(tmp, "WEP40"); + if (mWn->getGroupCiphers() & GroupCiphersMask::WEP104) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "WEP104"); + } + if (mWn->getGroupCiphers() & GroupCiphersMask::TKIP) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "TKIP"); + } + if (mWn->getGroupCiphers() & GroupCiphersMask::CCMP) { + if (tmp[0] != '\0') + strcat(tmp, " "); + strcat(tmp, "CCMP"); + } + + if (tmp[0] == '\0') { + strncpy(buffer, "(internal error)", max); + errno = ENOENT; + return -1; + } + if (tmp[strlen(tmp)] == ' ') + tmp[strlen(tmp)] = '\0'; + + strncpy(buffer, tmp, max); + return 0; +} +int WifiNetwork::WifiNetworkGroupCiphersProperty::set(int idx, const char *value) { + uint32_t mask; + if (mWn->parseGroupCiphersMask(value, &mask)) + return -1; + return mWn->setGroupCiphers(mask); +} + +WifiNetwork::WifiNetworkHiddenSsidProperty::WifiNetworkHiddenSsidProperty(WifiNetwork *wn) : + WifiNetworkStringProperty(wn, "HiddenSsid", false, 1) { +} +int WifiNetwork::WifiNetworkHiddenSsidProperty::get(int idx, char *buffer, size_t max) { + const char *scan_ssid = mWn->getHiddenSsid(); + + strncpy(buffer, (scan_ssid ? scan_ssid : "none"), max); + return 0; +} +int WifiNetwork::WifiNetworkHiddenSsidProperty::set(int idx, const char *value) { + return mWn->setHiddenSsid(value); +} diff --git a/nexus/WifiNetwork.h b/nexus/WifiNetwork.h index c2f5d235a..15ec647ea 100644 --- a/nexus/WifiNetwork.h +++ b/nexus/WifiNetwork.h @@ -21,6 +21,10 @@ #include +#include "Property.h" + +class PropertyManager; + class KeyManagementMask { public: static const uint32_t UNKNOWN = 0; @@ -60,19 +64,140 @@ public: }; class Supplicant; -class InterfaceConfig; class Controller; class WifiController; -#include "IPropertyProvider.h" +class WifiNetwork { + class WifiNetworkIntegerProperty : public IntegerProperty { + protected: + WifiNetwork *mWn; + public: + WifiNetworkIntegerProperty(WifiNetwork *wn, const char *name, bool ro, + int elements); + virtual ~WifiNetworkIntegerProperty() {} + virtual int set(int idx, int value) = 0; + virtual int get(int idx, int *buffer) = 0; + }; + friend class WifiNetwork::WifiNetworkIntegerProperty; -class WifiNetwork : public IPropertyProvider{ -public: - static const char *PropertyNames[]; + class WifiNetworkStringProperty : public StringProperty { + protected: + WifiNetwork *mWn; + public: + WifiNetworkStringProperty(WifiNetwork *wn, const char *name, bool ro, + int elements); + virtual ~WifiNetworkStringProperty() {} + virtual int set(int idx, const char *value) = 0; + virtual int get(int idx, char *buffer, size_t max) = 0; + }; + friend class WifiNetwork::WifiNetworkStringProperty; + + class WifiNetworkEnabledProperty : public WifiNetworkIntegerProperty { + public: + WifiNetworkEnabledProperty(WifiNetwork *wn); + virtual ~WifiNetworkEnabledProperty() {}; + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiNetworkPriorityProperty : public WifiNetworkIntegerProperty { + public: + WifiNetworkPriorityProperty(WifiNetwork *wn); + virtual ~WifiNetworkPriorityProperty() {}; + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiNetworkDefaultKeyIndexProperty : public WifiNetworkIntegerProperty { + public: + WifiNetworkDefaultKeyIndexProperty(WifiNetwork *wn); + virtual ~WifiNetworkDefaultKeyIndexProperty() {}; + int set(int idx, int value); + int get(int idx, int *buffer); + }; + + class WifiNetworkSsidProperty : public WifiNetworkStringProperty { + public: + WifiNetworkSsidProperty(WifiNetwork *wn); + virtual ~WifiNetworkSsidProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkBssidProperty : public WifiNetworkStringProperty { + public: + WifiNetworkBssidProperty(WifiNetwork *wn); + virtual ~WifiNetworkBssidProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkPskProperty : public WifiNetworkStringProperty { + public: + WifiNetworkPskProperty(WifiNetwork *wn); + virtual ~WifiNetworkPskProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkKeyManagementProperty : public WifiNetworkStringProperty { + public: + WifiNetworkKeyManagementProperty(WifiNetwork *wn); + virtual ~WifiNetworkKeyManagementProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkAuthAlgorithmsProperty : public WifiNetworkStringProperty { + public: + WifiNetworkAuthAlgorithmsProperty(WifiNetwork *wn); + virtual ~WifiNetworkAuthAlgorithmsProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkProtocolsProperty : public WifiNetworkStringProperty { + public: + WifiNetworkProtocolsProperty(WifiNetwork *wn); + virtual ~WifiNetworkProtocolsProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkWepKeyProperty : public WifiNetworkStringProperty { + public: + WifiNetworkWepKeyProperty(WifiNetwork *wn); + virtual ~WifiNetworkWepKeyProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkPairwiseCiphersProperty : public WifiNetworkStringProperty { + public: + WifiNetworkPairwiseCiphersProperty(WifiNetwork *wn); + virtual ~WifiNetworkPairwiseCiphersProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkGroupCiphersProperty : public WifiNetworkStringProperty { + public: + WifiNetworkGroupCiphersProperty(WifiNetwork *wn); + virtual ~WifiNetworkGroupCiphersProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; + + class WifiNetworkHiddenSsidProperty : public WifiNetworkStringProperty { + public: + WifiNetworkHiddenSsidProperty(WifiNetwork *wn); + virtual ~WifiNetworkHiddenSsidProperty() {}; + int set(int idx, const char *value); + int get(int idx, char *buffer, size_t max); + }; private: Supplicant *mSuppl; - InterfaceConfig *mIfaceCfg; WifiController *mController; /* @@ -128,33 +253,49 @@ private: /* * The set of key management protocols supported by this configuration. */ - uint32_t mAllowedKeyManagement; + uint32_t mKeyManagement; /* * The set of security protocols supported by this configuration. */ - uint32_t mAllowedProtocols; + uint32_t mProtocols; /* * The set of authentication protocols supported by this configuration. */ - uint32_t mAllowedAuthAlgorithms; + uint32_t mAuthAlgorithms; /* * The set of pairwise ciphers for WPA supported by this configuration. */ - uint32_t mAllowedPairwiseCiphers; + uint32_t mPairwiseCiphers; /* * The set of group ciphers for WPA supported by this configuration. */ - uint32_t mAllowedGroupCiphers; + uint32_t mGroupCiphers; /* * Set if this Network is enabled */ bool mEnabled; + char *mPropNamespace; + struct { + WifiNetworkEnabledProperty *propEnabled; + WifiNetworkSsidProperty *propSsid; + WifiNetworkBssidProperty *propBssid; + WifiNetworkPskProperty *propPsk; + WifiNetworkWepKeyProperty *propWepKey; + WifiNetworkDefaultKeyIndexProperty *propDefKeyIdx; + WifiNetworkPriorityProperty *propPriority; + WifiNetworkKeyManagementProperty *propKeyManagement; + WifiNetworkProtocolsProperty *propProtocols; + WifiNetworkAuthAlgorithmsProperty *propAuthAlgorithms; + WifiNetworkPairwiseCiphersProperty *propPairwiseCiphers; + WifiNetworkGroupCiphersProperty *propGroupCiphers; + WifiNetworkHiddenSsidProperty *propHiddenSsid; + } mStaticProperties; private: WifiNetwork(); @@ -165,8 +306,8 @@ public: virtual ~WifiNetwork(); WifiNetwork *clone(); - int registerProperties(); - int unregisterProperties(); + int attachProperties(PropertyManager *pm, const char *nsName); + int detachProperties(PropertyManager *pm, const char *nsName); int getNetworkId() { return mNetid; } const char *getSsid() { return mSsid; } @@ -176,19 +317,14 @@ public: int getDefaultKeyIndex() { return mDefaultKeyIndex; } int getPriority() { return mPriority; } const char *getHiddenSsid() { return mHiddenSsid; } - uint32_t getAllowedKeyManagement() { return mAllowedKeyManagement; } - uint32_t getAllowedProtocols() { return mAllowedProtocols; } - uint32_t getAllowedAuthAlgorithms() { return mAllowedAuthAlgorithms; } - uint32_t getAllowedPairwiseCiphers() { return mAllowedPairwiseCiphers; } - uint32_t getAllowedGroupCiphers() { return mAllowedGroupCiphers; } + uint32_t getKeyManagement() { return mKeyManagement; } + uint32_t getProtocols() { return mProtocols; } + uint32_t getAuthAlgorithms() { return mAuthAlgorithms; } + uint32_t getPairwiseCiphers() { return mPairwiseCiphers; } + uint32_t getGroupCiphers() { return mGroupCiphers; } bool getEnabled() { return mEnabled; } Controller *getController() { return (Controller *) mController; } - int set(const char *name, const char *value); - const char *get(const char *name, char *buffer, size_t maxsize); - - InterfaceConfig *getIfaceCfg() { return mIfaceCfg; } - int setEnabled(bool enabled); int setSsid(const char *ssid); int setBssid(const char *bssid); @@ -197,14 +333,22 @@ public: int setDefaultKeyIndex(int idx); int setPriority(int pri); int setHiddenSsid(const char *ssid); - int setAllowedKeyManagement(uint32_t mask); - int setAllowedProtocols(uint32_t mask); - int setAllowedAuthAlgorithms(uint32_t mask); - int setAllowedPairwiseCiphers(uint32_t mask); - int setAllowedGroupCiphers(uint32_t mask); + int setKeyManagement(uint32_t mask); + int setProtocols(uint32_t mask); + int setAuthAlgorithms(uint32_t mask); + int setPairwiseCiphers(uint32_t mask); + int setGroupCiphers(uint32_t mask); // XXX:Should this really be exposed?.. meh int refresh(); + +private: + int parseKeyManagementMask(const char *buffer, uint32_t *mask); + int parseProtocolsMask(const char *buffer, uint32_t *mask); + int parseAuthAlgorithmsMask(const char *buffer, uint32_t *mask); + int parsePairwiseCiphersMask(const char *buffer, uint32_t *mask); + int parseGroupCiphersMask(const char *buffer, uint32_t *mask); + void createProperties(); }; typedef android::List WifiNetworkCollection; diff --git a/nexus/WifiStatusPoller.cpp b/nexus/WifiStatusPoller.cpp new file mode 100644 index 000000000..cf717337e --- /dev/null +++ b/nexus/WifiStatusPoller.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_TAG "WifiStatusPoller" +#include + +#include "WifiStatusPoller.h" +#include "IWifiStatusPollerHandler.h" + + +WifiStatusPoller::WifiStatusPoller(IWifiStatusPollerHandler *handler) : + mHandlers(handler) { + mPollingInterval = 5; + mStarted = false; +} + +int WifiStatusPoller::start() { + + if (pipe(mCtrlPipe)) + return -1; + + if (pthread_create(&mThread, NULL, WifiStatusPoller::threadStart, this)) + return -1; + + return 0; +} + +int WifiStatusPoller::stop() { + char c = 0; + + if (write(mCtrlPipe[1], &c, 1) != 1) { + LOGE("Error writing to control pipe (%s)", strerror(errno)); + return -1; + } + + void *ret; + if (pthread_join(mThread, &ret)) { + LOGE("Error joining to listener thread (%s)", strerror(errno)); + return -1; + } + close(mCtrlPipe[0]); + close(mCtrlPipe[1]); + return 0; +} + +void *WifiStatusPoller::threadStart(void *obj) { + WifiStatusPoller *me = reinterpret_cast(obj); + + me->mStarted = true; + LOGD("Starting"); + me->run(); + me->mStarted = false; + LOGD("Stopping"); + pthread_exit(NULL); + return NULL; +} + +void WifiStatusPoller::run() { + + while(1) { + struct timeval to; + fd_set read_fds; + int rc = 0; + int max = 0; + + FD_ZERO(&read_fds); + to.tv_usec = 0; + to.tv_sec = mPollingInterval; + + FD_SET(mCtrlPipe[0], &read_fds); + max = mCtrlPipe[0]; + + if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) { + LOGE("select failed (%s)", strerror(errno)); + sleep(1); + continue; + } else if (!rc) { + mHandlers->onStatusPollInterval(); + } + if (FD_ISSET(mCtrlPipe[0], &read_fds)) + break; + } +} diff --git a/nexus/WifiStatusPoller.h b/nexus/WifiStatusPoller.h new file mode 100644 index 000000000..202bbbf00 --- /dev/null +++ b/nexus/WifiStatusPoller.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WIFI_STATUS_POLLER_H +#define _WIFI_STATUS_POLLER_H + +#include + +class IWifiStatusPollerHandler; + +class WifiStatusPoller { + pthread_t mThread; + int mCtrlPipe[2]; + int mPollingInterval; + IWifiStatusPollerHandler *mHandlers; + bool mStarted; + +public: + WifiStatusPoller(IWifiStatusPollerHandler *handler); + virtual ~WifiStatusPoller() {} + + int start(); + int stop(); + bool isStarted() { return mStarted; } + + void setPollingInterval(int interval); + int getPollingInterval() { return mPollingInterval; } + +private: + static void *threadStart(void *obj); + void run(); +}; + +#endif