diff options
42 files changed, 1517 insertions, 390 deletions
diff --git a/nexus/Android.mk b/nexus/Android.mk index 61240d5..1c4a394 100644 --- a/nexus/Android.mk +++ b/nexus/Android.mk @@ -23,10 +23,12 @@ LOCAL_SRC_FILES:= \ WifiNetwork.cpp \ OpenVpnController.cpp \ InterfaceConfig.cpp \ + PropertyManager.cpp \ + SupplicantState.cpp LOCAL_MODULE:= nexus -LOCAL_C_INCLUDES := $(KERNEL_HEADERS) +LOCAL_C_INCLUDES := $(KERNEL_HEADERS) -I../../../frameworks/base/include/ LOCAL_CFLAGS := diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp index e2edc77..e8de7f5 100644 --- a/nexus/CommandListener.cpp +++ b/nexus/CommandListener.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) ErrorCode::CommandOkay8 The Android Open Source Project + * 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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> @@ -26,6 +27,7 @@ #include "CommandListener.h" #include "Controller.h" +#include "Property.h" #include "NetworkManager.h" #include "WifiController.h" #include "VpnController.h" @@ -35,31 +37,32 @@ CommandListener::CommandListener() : FrameworkListener("nexus") { registerCmd(new WifiScanResultsCmd()); registerCmd(new WifiListNetworksCmd()); - registerCmd(new WifiAddNetworkCmd()); + registerCmd(new WifiCreateNetworkCmd()); registerCmd(new WifiRemoveNetworkCmd()); registerCmd(new GetCmd()); registerCmd(new SetCmd()); + registerCmd(new ListCmd()); } - + /* ------------- * Wifi Commands * ------------ */ -CommandListener::WifiAddNetworkCmd::WifiAddNetworkCmd() : - NexusCommand("wifi_add_network") { -} - -int CommandListener::WifiAddNetworkCmd::runCommand(SocketClient *cli, char *data) { +CommandListener::WifiCreateNetworkCmd::WifiCreateNetworkCmd() : + NexusCommand("wifi_create_network") { +} + +int CommandListener::WifiCreateNetworkCmd::runCommand(SocketClient *cli, char *data) { NetworkManager *nm = NetworkManager::Instance(); WifiController *wc = (WifiController *) nm->findController("WIFI"); - int networkId; + WifiNetwork *wn; - if ((networkId = wc->addNetwork()) < 0) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to add network", true); + if (!(wn = wc->createNetwork())) + cli->sendMsg(ErrorCode::OperationFailed, "Failed to create network", true); else { char tmp[128]; - sprintf(tmp, "Added network id %d.", networkId); + sprintf(tmp, "Created network id %d.", wn->getNetworkId()); cli->sendMsg(ErrorCode::CommandOkay, tmp, false); } return 0; @@ -67,8 +70,8 @@ int CommandListener::WifiAddNetworkCmd::runCommand(SocketClient *cli, char *data CommandListener::WifiRemoveNetworkCmd::WifiRemoveNetworkCmd() : NexusCommand("wifi_remove_network") { -} - +} + int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, char *data) { NetworkManager *nm = NetworkManager::Instance(); WifiController *wc = (WifiController *) nm->findController("WIFI"); @@ -83,7 +86,7 @@ int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, char *d CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() : NexusCommand("wifi_scan_results") { -} +} int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli, char *data) { NetworkManager *nm = NetworkManager::Instance(); @@ -92,7 +95,7 @@ int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli, char *dat ScanResultCollection *src = wc->createScanResults(); ScanResultCollection::iterator it; char buffer[256]; - + for(it = src->begin(); it != src->end(); ++it) { sprintf(buffer, "%s:%u:%d:%s:%s", (*it)->getBssid(), (*it)->getFreq(), (*it)->getLevel(), @@ -103,13 +106,13 @@ int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli, char *dat } delete src; - cli->sendMsg(ErrorCode::CommandOkay, "Scan results complete", false); + cli->sendMsg(ErrorCode::CommandOkay, "Scan results complete.", false); return 0; } CommandListener::WifiListNetworksCmd::WifiListNetworksCmd() : NexusCommand("wifi_list_networks") { -} +} int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, char *data) { NetworkManager *nm = NetworkManager::Instance(); @@ -118,12 +121,11 @@ int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, char *da WifiNetworkCollection *src = wc->createNetworkList(); WifiNetworkCollection::iterator it; char buffer[256]; - + for(it = src->begin(); it != src->end(); ++it) { sprintf(buffer, "%d:%s", (*it)->getNetworkId(), (*it)->getSsid()); cli->sendMsg(ErrorCode::WifiNetworkList, buffer, false); delete (*it); - it = src->erase(it); } delete src; @@ -140,34 +142,31 @@ int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, char *da * ---------------- */ CommandListener::GetCmd::GetCmd() : NexusCommand("get") { -} +} int CommandListener::GetCmd::runCommand(SocketClient *cli, char *data) { - char *bword; - char *last; - char propname[32]; + char *next = data; + char *propname; - if (!(bword = strtok_r(data, ":", &last))) + if (!(propname = strsep(&next, ":"))) goto out_inval; - - strncpy(propname, bword, sizeof(propname)); - char pb[255]; + char pb[Property::NameMaxSize + 6]; snprintf(pb, sizeof(pb), "%s:", propname); - if (!NetworkManager::Instance()->getProperty(propname, - &pb[strlen(pb)], - sizeof(pb) - strlen(pb))) { + if (!NetworkManager::Instance()->getPropMngr()->get(propname, + &pb[strlen(pb)], + sizeof(pb) - strlen(pb))) { goto out_inval; } - cli->sendMsg(ErrorCode::VariableRead, pb, false); + cli->sendMsg(ErrorCode::PropertyRead, pb, false); cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false); return 0; out_inval: errno = EINVAL; - cli->sendMsg(ErrorCode::CommandParameterError, "Failed to get variable.", true); + cli->sendMsg(ErrorCode::CommandParameterError, "Failed to read property.", true); return 0; } @@ -178,8 +177,8 @@ CommandListener::SetCmd::SetCmd() : int CommandListener::SetCmd::runCommand(SocketClient *cli, char *data) { char *bword; char *last; - char propname[32]; - char propval[250]; + char propname[Property::NameMaxSize]; + char propval[Property::ValueMaxSize]; if (!(bword = strtok_r(data, ":", &last))) goto out_inval; @@ -191,7 +190,7 @@ int CommandListener::SetCmd::runCommand(SocketClient *cli, char *data) { strncpy(propval, bword, sizeof(propval)); - if (NetworkManager::Instance()->setProperty(propname, propval)) + if (NetworkManager::Instance()->getPropMngr()->set(propname, propval)) goto out_inval; cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false); @@ -208,5 +207,39 @@ CommandListener::ListCmd::ListCmd() : } int CommandListener::ListCmd::runCommand(SocketClient *cli, char *data) { + android::List<char *> *pc; + + if (!(pc = NetworkManager::Instance()->getPropMngr()->createPropertyList())) { + errno = ENODATA; + cli->sendMsg(ErrorCode::CommandParameterError, "Failed to list properties.", true); + return 0; + } + + android::List<char *>::iterator it; + + for (it = pc->begin(); it != pc->end(); ++it) { + char p_v[Property::ValueMaxSize]; + + if (!NetworkManager::Instance()->getPropMngr()->get((*it), + p_v, + sizeof(p_v))) { + LOGW("Failed to get %s (%s)", (*it), strerror(errno)); + } + + char *buf; + if (asprintf(&buf, "%s:%s", (*it), p_v) < 0) { + LOGE("Failed to allocate memory"); + free((*it)); + continue; + } + cli->sendMsg(ErrorCode::PropertyList, buf, false); + free(buf); + + free((*it)); + } + + delete pc; + + cli->sendMsg(ErrorCode::CommandOkay, "Properties list complete.", false); return 0; } diff --git a/nexus/CommandListener.h b/nexus/CommandListener.h index b44d3ec..b57c25f 100644 --- a/nexus/CommandListener.h +++ b/nexus/CommandListener.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _COMMANDLISTENER_H__ #define _COMMANDLISTENER_H__ @@ -40,10 +41,10 @@ private: int runCommand(SocketClient *c, char *data); }; - class WifiAddNetworkCmd : public NexusCommand { + class WifiCreateNetworkCmd : public NexusCommand { public: - WifiAddNetworkCmd(); - virtual ~WifiAddNetworkCmd() {} + WifiCreateNetworkCmd(); + virtual ~WifiCreateNetworkCmd() {} int runCommand(SocketClient *c, char *data); }; diff --git a/nexus/Controller.cpp b/nexus/Controller.cpp index 133e796..9d4ff3c 100644 --- a/nexus/Controller.cpp +++ b/nexus/Controller.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -33,13 +34,17 @@ extern "C" int init_module(void *, unsigned int, const char *); extern "C" int delete_module(const char *, unsigned int); -Controller::Controller(const char *name, const char *prefix) { - mName = name; - mPropertyPrefix = prefix; - mProperties = new PropertyCollection(); +Controller::Controller(const char *name, PropertyManager *propMngr) { + mPropMngr = propMngr; + mName = strdup(name); + mBoundInterface = NULL; +} - mEnabled = false; - registerProperty("enable"); +Controller::~Controller() { + if (mBoundInterface) + free(mBoundInterface); + if (mName) + free(mName); } int Controller::start() { @@ -50,65 +55,16 @@ int Controller::stop() { return 0; } -const PropertyCollection & Controller::getProperties() { - return *mProperties; -} - -int Controller::setProperty(const char *name, char *value) { - if (!strcmp(name, "enable")) { - int en = atoi(value); - int rc; - - rc = (en ? enable() : disable()); - - if (!rc) - mEnabled = en; - - return rc; - } - +int Controller::set(const char *name, const char *value) { errno = ENOENT; return -1; } -const char *Controller::getProperty(const char *name, char *buffer, size_t maxsize) { - if (!strcmp(name, "enable")) { - snprintf(buffer, maxsize, "%d", mEnabled); - return buffer; - } - +const char *Controller::get(const char *name, char *buffer, size_t maxsize) { errno = ENOENT; return NULL; } -int Controller::registerProperty(const char *name) { - PropertyCollection::iterator it; - - for (it = mProperties->begin(); it != mProperties->end(); ++it) { - if (!strcmp(name, (*it))) { - errno = EADDRINUSE; - LOGE("Failed to register property (%s)", strerror(errno)); - return -1; - } - } - - mProperties->push_back(name); - return 0; -} - -int Controller::unregisterProperty(const char *name) { - PropertyCollection::iterator it; - - for (it = mProperties->begin(); it != mProperties->end(); ++it) { - if (!strcmp(name, (*it))) { - mProperties->erase(it); - return 0; - } - } - errno = ENOENT; - return -1; -} - int Controller::loadKernelModule(char *modpath, const char *args) { void *module; unsigned int size; @@ -137,7 +93,7 @@ int Controller::unloadKernelModule(const char *modtag) { } if (rc != 0) { - LOGW("Unable to unload kernel driver '%s' (%s)", modtag, + LOGW("Unable to unload kernel driver '%s' (%s)", modtag, strerror(errno)); } return rc; @@ -203,3 +159,16 @@ bail: close(fd); return buffer; } + +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 ae37426..9137f9a 100644 --- a/nexus/Controller.h +++ b/nexus/Controller.h @@ -13,51 +13,59 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _CONTROLLER_H #define _CONTROLLER_H #include <unistd.h> #include <sys/types.h> -#include "../../../frameworks/base/include/utils/List.h" +#include <utils/List.h> + +class PropertyManager; -#include "PropertyCollection.h" +#include "PropertyManager.h" +#include "IPropertyProvider.h" -class Controller { +class Controller : public IPropertyProvider { private: - const char *mName; - const char *mPropertyPrefix; - PropertyCollection *mProperties; - bool mEnabled; + /* + * Name of this controller - WIFI/VPN/USBNET/BTNET/BTDUN/LOOP/etc + */ + char *mName; + + /* + * Name of the system ethernet interface which this controller is + * bound to. + */ + char *mBoundInterface; + +protected: + PropertyManager *mPropMngr; public: - Controller(const char *name, const char *prefix); - virtual ~Controller() {} + Controller(const char *name, PropertyManager *propMngr); + virtual ~Controller(); virtual int start(); virtual int stop(); - virtual const PropertyCollection &getProperties(); - virtual int setProperty(const char *name, char *value); - virtual const char *getProperty(const char *name, char *buffer, size_t maxsize); - const char *getName() { return mName; } - const char *getPropertyPrefix() { return mPropertyPrefix; } + 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); int unloadKernelModule(const char *modtag); - - int registerProperty(const char *name); - int unregisterProperty(const char *name); + int bindInterface(const char *ifname); + int unbindInterface(const char *ifname); private: void *loadFile(char *filename, unsigned int *_size); - - virtual int enable() = 0; - virtual int disable() = 0; - }; typedef android::List<Controller *> ControllerCollection; diff --git a/nexus/ErrorCode.h b/nexus/ErrorCode.h index 57c99c2..414dd2c 100644 --- a/nexus/ErrorCode.h +++ b/nexus/ErrorCode.h @@ -26,8 +26,9 @@ public: static const int WifiScanResult = 125; static const int WifiNetworkList = 126; - static const int VariableRead = 127; - static const int VariableWrite = 128; + static const int PropertyRead = 127; + static const int PropertySet = 128; + static const int PropertyList = 129; // 200 series - Requested action has been successfully completed static const int CommandOkay = 200; diff --git a/nexus/IPropertyProvider.h b/nexus/IPropertyProvider.h new file mode 100644 index 0000000..17ad5f8 --- /dev/null +++ b/nexus/IPropertyProvider.h @@ -0,0 +1,33 @@ +/* + * 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 _IPROPERTY_PROVIDER_H +#define _IPROPERTY_PROVIDER_H + +#include <unistd.h> +#include <sys/types.h> + +#include <utils/List.h> + +class IPropertyProvider { +public: + virtual int set(const char *name, const char *value) = 0; + virtual const char *get(const char *name, char *buffer, size_t max) = 0; +}; + +typedef android::List<IPropertyProvider *> IPropertyProviderCollection; + +#endif diff --git a/nexus/InterfaceConfig.cpp b/nexus/InterfaceConfig.cpp index 89936f8..66861d0 100644 --- a/nexus/InterfaceConfig.cpp +++ b/nexus/InterfaceConfig.cpp @@ -14,47 +14,59 @@ * limitations under the License. */ +#include <stdlib.h> #include <string.h> #define LOG_TAG "InterfaceConfig" #include <cutils/log.h> #include "InterfaceConfig.h" +#include "NetworkManager.h" -InterfaceConfig::InterfaceConfig(const char *name) { - mName = strdup(name); +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() { - free(mName); + unregisterProperties(); + free(mPropPrefix); } -InterfaceConfig::InterfaceConfig(const char *name, const char *ip, const char *nm, +InterfaceConfig::InterfaceConfig(const char *prop_prefix, + const char *ip, const char *nm, const char *gw, const char *dns1, const char *dns2, const char *dns3) { - mName = strdup(name); + mPropPrefix = strdup(prop_prefix); mUseDhcp = false; if (!inet_aton(ip, &mIp)) LOGW("Unable to parse ip (%s)", ip); - if (!inet_aton(nm, &mIp)) + if (!inet_aton(nm, &mNetmask)) LOGW("Unable to parse netmask (%s)", nm); - if (!inet_aton(gw, &mIp)) + if (!inet_aton(gw, &mGateway)) LOGW("Unable to parse gateway (%s)", gw); - if (!inet_aton(dns1, &mIp)) + if (!inet_aton(dns1, &mDns1)) LOGW("Unable to parse dns1 (%s)", dns1); - if (!inet_aton(dns2, &mIp)) + if (!inet_aton(dns2, &mDns2)) LOGW("Unable to parse dns2 (%s)", dns2); - if (!inet_aton(dns3, &mIp)) + if (!inet_aton(dns3, &mDns3)) LOGW("Unable to parse dns3 (%s)", dns3); + registerProperties(); } -InterfaceConfig::InterfaceConfig(const char *name, const struct in_addr *ip, +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) { - mName = strdup(name); + mPropPrefix = strdup(prop_prefix); mUseDhcp = false; memcpy(&mIp, ip, sizeof(struct in_addr)); @@ -63,5 +75,95 @@ InterfaceConfig::InterfaceConfig(const char *name, const struct in_addr *ip, memcpy(&mDns1, dns1, sizeof(struct in_addr)); memcpy(&mDns2, dns2, sizeof(struct in_addr)); memcpy(&mDns3, dns3, sizeof(struct in_addr)); + registerProperties(); +} + +int InterfaceConfig::registerProperties() { + for (const char **p = InterfaceConfig::PropertyNames; *p != '\0'; p++) { + char *tmp; + asprintf(&tmp, "%s.if.%s", mPropPrefix, *p); + + if (NetworkManager::Instance()->getPropMngr()->registerProperty(tmp, + this)) { + free(tmp); + return -1; + } + free(tmp); + } + 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); + } + 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; + } + + 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 1426e99..d97f20b 100644 --- a/nexus/InterfaceConfig.h +++ b/nexus/InterfaceConfig.h @@ -17,12 +17,21 @@ #ifndef _INTERFACE_CONFIG_H #define _INTERFACE_CONFIG_H +#include <unistd.h> +#include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> -class InterfaceConfig { +#include "IPropertyProvider.h" + +class PropertyManager; + +class InterfaceConfig : public IPropertyProvider { +public: + static const char *PropertyNames[]; + private: - char *mName; + char *mPropPrefix; bool mUseDhcp; struct in_addr mIp; struct in_addr mNetmask; @@ -32,19 +41,23 @@ private: struct in_addr mDns3; public: - InterfaceConfig(const char *name); - InterfaceConfig(const char *name, const char *ip, const char *nm, + 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 *name, const struct in_addr *ip, + 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); virtual ~InterfaceConfig(); + + int set(const char *name, const char *value); + const char *get(const char *name, char *buffer, size_t maxsize); - const char *getName() const { return mName; } bool getUseDhcp() const { return mUseDhcp; } const struct in_addr &getIp() const { return mIp; } const struct in_addr &getNetmask() const { return mNetmask; } @@ -52,6 +65,10 @@ public: const struct in_addr &getDns1() const { return mDns1; } const struct in_addr &getDns2() const { return mDns2; } const struct in_addr &getDns3() const { return mDns3; } + +private: + int registerProperties(); + int unregisterProperties(); }; diff --git a/nexus/LoopController.cpp b/nexus/LoopController.cpp index 400d279..a86202a 100644 --- a/nexus/LoopController.cpp +++ b/nexus/LoopController.cpp @@ -13,20 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <errno.h> #include "LoopController.h" +#include "PropertyManager.h" -LoopController::LoopController() : - Controller("LOOP", "loop") { +LoopController::LoopController(PropertyManager *propmngr) : + Controller("LOOP", propmngr) { } -int LoopController::enable() { - errno = ENOSYS; - return -1; +int LoopController::set(const char *name, const char *value) { + return Controller::set(name, value); } -int LoopController::disable() { - errno = ENOSYS; - return -1; +const char *LoopController::get(const char *name, char *buffer, size_t maxsize) { + return Controller::get(name, buffer, maxsize); } + diff --git a/nexus/LoopController.h b/nexus/LoopController.h index d047f87..bb8314f 100644 --- a/nexus/LoopController.h +++ b/nexus/LoopController.h @@ -13,19 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _LOOP_CONTROLLER_H #define _LOOP_CONTROLLER_H #include "Controller.h" + class LoopController : public Controller { public: - LoopController(); + LoopController(PropertyManager *propmngr); virtual ~LoopController() {} -private: - int enable(); - int disable(); + int set(const char *name, const char *value); + const char *get(const char *name, char *buffer, size_t maxsize); }; #endif diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp index 49b0210..f4ae88f 100644 --- a/nexus/NetworkManager.cpp +++ b/nexus/NetworkManager.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdio.h> #include <errno.h> @@ -27,13 +28,17 @@ NetworkManager *NetworkManager::sInstance = NULL; NetworkManager *NetworkManager::Instance() { if (!sInstance) - sInstance = new NetworkManager(); + sInstance = new NetworkManager(new PropertyManager()); return sInstance; } -NetworkManager::NetworkManager() { +NetworkManager::NetworkManager(PropertyManager *propMngr) { mBroadcaster = NULL; mControllers = new ControllerCollection(); + mPropMngr = propMngr; +} + +NetworkManager::~NetworkManager() { } int NetworkManager::run() { @@ -55,7 +60,7 @@ int NetworkManager::startControllers() { for (i = mControllers->begin(); i != mControllers->end(); ++i) { int irc = (*i)->start(); LOGD("Controller '%s' start rc = %d", (*i)->getName(), irc); - if (irc && !rc) + if (irc && !rc) rc = irc; } return rc; @@ -68,7 +73,7 @@ int NetworkManager::stopControllers() { for (i = mControllers->begin(); i != mControllers->end(); ++i) { int irc = (*i)->stop(); LOGD("Controller '%s' stop rc = %d", (*i)->getName(), irc); - if (irc && !rc) + if (irc && !rc) rc = irc; } return rc; @@ -84,75 +89,8 @@ Controller *NetworkManager::findController(const char *name) { return NULL; } -int NetworkManager::setProperty(const char *name, char *value) { - char *tmp = strdup(name); - char *next = tmp; - char *prefix; - char *rest; - ControllerCollection::iterator it; - - if (!(prefix = strsep(&next, "."))) - goto out_inval; - - rest = next; - - if (!strncasecmp(prefix, "netman", 6)) { - errno = ENOSYS; - return -1; - } - - for (it = mControllers->begin(); it != mControllers->end(); ++it) { - if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) { - return (*it)->setProperty(rest, value); - } - } - - errno = ENOENT; - return -1; - -out_inval: - errno = EINVAL; - return -1; -} - -const char *NetworkManager::getProperty(const char *name, char *buffer, - size_t maxsize) { - char *tmp = strdup(name); - char *next = tmp; - char *prefix; - char *rest; - ControllerCollection::iterator it; - - if (!(prefix = strsep(&next, "."))) - goto out_inval; - - rest = next; - - if (!strncasecmp(prefix, "netman", 6)) { - errno = ENOSYS; - return NULL; - } - - for (it = mControllers->begin(); it != mControllers->end(); ++it) { - if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) { - return (*it)->getProperty(rest, buffer, maxsize); - } - } - - errno = ENOENT; - return NULL; - -out_inval: - errno = EINVAL; - return NULL; -} - -const PropertyCollection &NetworkManager::getProperties() { - return *mProperties; -} - int NetworkManager::onInterfaceStart(Controller *c, const InterfaceConfig *cfg) { - LOGD("Interface %s started by controller %s", cfg->getName(), c->getName()); + LOGD("Interface %s started by controller %s", c->getBoundInterface(), c->getName()); // Look up the interface diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h index e8564ca..e75382d 100644 --- a/nexus/NetworkManager.h +++ b/nexus/NetworkManager.h @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _NETWORKMANAGER_H #define _NETWORKMANAGER_H #include <sysutils/SocketListener.h> #include "Controller.h" -#include "PropertyCollection.h" + +#include "PropertyManager.h" class InterfaceConfig; @@ -30,10 +32,10 @@ private: private: ControllerCollection *mControllers; SocketListener *mBroadcaster; - PropertyCollection *mProperties; + PropertyManager *mPropMngr; public: - virtual ~NetworkManager() {} + virtual ~NetworkManager(); int run(); @@ -41,22 +43,17 @@ public: Controller *findController(const char *name); - const PropertyCollection &getProperties(); - int setProperty(const char *name, char *value); - const char *getProperty(const char *name, char *buffer, size_t maxsize); - void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } SocketListener *getBroadcaster() { return mBroadcaster; } + PropertyManager *getPropMngr() { return mPropMngr; } static NetworkManager *Instance(); private: int startControllers(); int stopControllers(); - int registerProperty(const char *name); - int unregisterProperty(const char *name); - NetworkManager(); + NetworkManager(PropertyManager *propMngr); public: /* diff --git a/nexus/NexusCommand.cpp b/nexus/NexusCommand.cpp index 92bb1c3..541eeeb 100644 --- a/nexus/NexusCommand.cpp +++ b/nexus/NexusCommand.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "NexusCommand.h" NexusCommand::NexusCommand(const char *cmd) : diff --git a/nexus/NexusCommand.h b/nexus/NexusCommand.h index 1482998..a7f944a 100644 --- a/nexus/NexusCommand.h +++ b/nexus/NexusCommand.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _NEXUS_COMMAND_H #define _NEXUS_COMMAND_H diff --git a/nexus/OpenVpnController.cpp b/nexus/OpenVpnController.cpp index 1934024..4c144a4 100644 --- a/nexus/OpenVpnController.cpp +++ b/nexus/OpenVpnController.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <errno.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -24,13 +25,13 @@ #include <sysutils/ServiceManager.h> #include "OpenVpnController.h" +#include "PropertyManager.h" #define DAEMON_PROP_NAME "vpn.openvpn.status" - #define DAEMON_CONFIG_FILE "/data/misc/openvpn/openvpn.conf" -OpenVpnController::OpenVpnController() : - VpnController() { +OpenVpnController::OpenVpnController(PropertyManager *propmngr) : + VpnController(propmngr) { mServiceManager = new ServiceManager(); } @@ -49,8 +50,8 @@ int OpenVpnController::stop() { int OpenVpnController::enable() { char svc[PROPERTY_VALUE_MAX]; char tmp[64]; - - if (!getProperty("vpn.gateway", tmp, sizeof(tmp))) { + + if (!mPropMngr->get("vpn.gateway", tmp, sizeof(tmp))) { LOGE("Error reading property 'vpn.gateway' (%s)", strerror(errno)); return -1; } diff --git a/nexus/OpenVpnController.h b/nexus/OpenVpnController.h index 439e18a..323c44c 100644 --- a/nexus/OpenVpnController.h +++ b/nexus/OpenVpnController.h @@ -17,6 +17,7 @@ #ifndef _OPEN_VPN_CONTROLLER_H #define _OPEN_VPN_CONTROLLER_H +#include "PropertyManager.h" #include "VpnController.h" class ServiceManager; @@ -26,7 +27,7 @@ private: ServiceManager *mServiceManager; public: - OpenVpnController(); + OpenVpnController(PropertyManager *propmngr); virtual ~OpenVpnController(); int start(); diff --git a/nexus/PropertyCollection.h b/nexus/Property.h index 4be1cf0..198f722 100644 --- a/nexus/PropertyCollection.h +++ b/nexus/Property.h @@ -14,12 +14,8 @@ * limitations under the License. */ -#ifndef _PROPERTY_COLLECTION_H -#define _PROPERTY_COLLECTION_H - -#include "../../../frameworks/base/include/utils/List.h" - -typedef android::List<const char *> PropertyCollection; - -#endif - +class Property { +public: + static const int NameMaxSize = 128; + static const int ValueMaxSize = 255; +}; diff --git a/nexus/PropertyManager.cpp b/nexus/PropertyManager.cpp new file mode 100644 index 0000000..3366bab --- /dev/null +++ b/nexus/PropertyManager.cpp @@ -0,0 +1,122 @@ +/* + * 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. + */ + +#define LOG_TAG "PropertyManager" + +#include <cutils/log.h> + +#include "PropertyManager.h" + +PropertyManager::PropertyManager() { + mPropertyPairs = new PropertyPairCollection(); + pthread_mutex_init(&mLock, NULL); +} + +PropertyManager::~PropertyManager() { + delete mPropertyPairs; +} + +int PropertyManager::registerProperty(const char *name, IPropertyProvider *pp) { + PropertyPairCollection::iterator 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)", strerror(errno)); + pthread_mutex_unlock(&mLock); + return -1; + } + } + mPropertyPairs->push_back(new PropertyPair(name, pp)); + pthread_mutex_unlock(&mLock); + return 0; +} + +int PropertyManager::unregisterProperty(const char *name) { + PropertyPairCollection::iterator it; + +// LOGD("unregisterProperty(%s)", name); + pthread_mutex_lock(&mLock); + for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) { + if (!strcmp(name, (*it)->getName())) { + delete ((*it)); + mPropertyPairs->erase(it); + pthread_mutex_unlock(&mLock); + return 0; + } + } + pthread_mutex_unlock(&mLock); + errno = ENOENT; + return -1; +} + +/* + * IPropertyManager methods + */ + +int PropertyManager::set(const char *name, const char *value) { + PropertyPairCollection::iterator it; + + 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); + } + } + 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); + } + } + pthread_mutex_unlock(&mLock); + errno = ENOENT; + return NULL; +} + +android::List<char *> *PropertyManager::createPropertyList() { + android::List<char *> *c = new android::List<char *>(); + + PropertyPairCollection::iterator it; + + pthread_mutex_lock(&mLock); + for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) + c->push_back(strdup((*it)->getName())); + 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 new file mode 100644 index 0000000..10d0b2a --- /dev/null +++ b/nexus/PropertyManager.h @@ -0,0 +1,57 @@ +/* + * 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 _PROPERTY_MANAGER_H +#define _PROPERTY_MANAGER_H + +#include <errno.h> +#include <pthread.h> + +#include <utils/List.h> + +#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<PropertyPair *> PropertyPairCollection; + +class PropertyManager { + PropertyPairCollection *mPropertyPairs; + pthread_mutex_t mLock; + +public: + PropertyManager(); + virtual ~PropertyManager(); + int registerProperty(const char *name, IPropertyProvider *pp); + int unregisterProperty(const char *name); + android::List<char *> *createPropertyList(); + + int set(const char *name, const char *value); + const char *get(const char *name, char *buffer, size_t max); +}; + +#endif diff --git a/nexus/ScanResult.cpp b/nexus/ScanResult.cpp index dc7599a..e9a286c 100644 --- a/nexus/ScanResult.cpp +++ b/nexus/ScanResult.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdlib.h> #include <ctype.h> @@ -42,7 +43,7 @@ ScanResult::ScanResult(char *rawResult) { mFreq = atoi(tmp); ++q; - // LEVEL + // LEVEL for (p = q; *q != '\t'; ++q); strncpy(tmp, p, (q - p)); tmp[q-p] = '\0'; @@ -60,7 +61,7 @@ ScanResult::ScanResult(char *rawResult) { // haven't had time to dig into it ... if (*q == '\t') q++; - + for (p = q; *q != '\t'; ++q) { if (*q == '\0') break; diff --git a/nexus/ScanResult.h b/nexus/ScanResult.h index f70a1a9..68ad0f0 100644 --- a/nexus/ScanResult.h +++ b/nexus/ScanResult.h @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _SCAN_RESULT_H #define _SCAN_RESULT_H #include <sys/types.h> -#include "../../../frameworks/base/include/utils/List.h" +#include <utils/List.h> class ScanResult { char *mBssid; diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp index 6737d91..e69f2c0 100644 --- a/nexus/Supplicant.cpp +++ b/nexus/Supplicant.cpp @@ -32,8 +32,10 @@ #include "SupplicantState.h" #include "SupplicantEvent.h" #include "ScanResult.h" +#include "PropertyManager.h" #include "NetworkManager.h" #include "ErrorCode.h" +#include "WifiController.h" #include "libwpa_client/wpa_ctrl.h" @@ -43,21 +45,29 @@ #define SUPP_CONFIG_TEMPLATE "/system/etc/wifi/wpa_supplicant.conf" #define SUPP_CONFIG_FILE "/data/misc/wifi/wpa_supplicant.conf" -Supplicant::Supplicant() { +Supplicant::Supplicant(WifiController *wc, PropertyManager *propmngr) { + mController = wc; + mPropMngr = propmngr; + mInterfaceName = NULL; mCtrl = NULL; mMonitor = NULL; mListener = NULL; - + mState = SupplicantState::UNKNOWN; mServiceManager = new ServiceManager(); mLatestScanResults = new ScanResultCollection(); pthread_mutex_init(&mLatestScanResultsLock, NULL); + + mNetworks = new WifiNetworkCollection(); + pthread_mutex_init(&mNetworksLock, NULL); } Supplicant::~Supplicant() { delete mServiceManager; + if (mInterfaceName) + free(mInterfaceName); } int Supplicant::start() { @@ -65,7 +75,7 @@ int Supplicant::start() { if (setupConfig()) { LOGW("Unable to setup supplicant.conf"); } - + if (mServiceManager->start(SUPPLICANT_SERVICE_NAME)) { LOGE("Error starting supplicant (%s)", strerror(errno)); return -1; @@ -76,11 +86,20 @@ int Supplicant::start() { LOGE("Error connecting to supplicant (%s)\n", strerror(errno)); return -1; } + + if (retrieveInterfaceName()) { + LOGE("Error retrieving interface name (%s)\n", strerror(errno)); + return -1; + } + + mPropMngr->registerProperty("wifi.supplicant.state", this); return 0; } int Supplicant::stop() { + mPropMngr->unregisterProperty("wifi.supplicant.state"); + if (mListener->stopListener()) { LOGW("Unable to stop supplicant listener (%s)", strerror(errno)); return -1; @@ -106,13 +125,55 @@ bool Supplicant::isStarted() { return mServiceManager->isRunning(SUPPLICANT_SERVICE_NAME); } -int Supplicant::connectToSupplicant() { - if (!isStarted()) { - LOGE("Supplicant not running, cannot connect"); +int Supplicant::refreshNetworkList() { + char *reply; + size_t len = 4096; + + if (!(reply = (char *) malloc(len))) { + errno = ENOMEM; + return -1; + } + + if (sendCommand("LIST_NETWORKS", reply, &len)) { + free(reply); return -1; } - mCtrl = wpa_ctrl_open("tiwlan0"); + char *linep; + char *linep_next = NULL; + + if (!strtok_r(reply, "\n", &linep_next)) { + LOGW("Malformatted network list\n"); + } else { + pthread_mutex_lock(&mNetworksLock); + if (!mNetworks->empty()) { + WifiNetworkCollection::iterator i; + + for (i = mNetworks->begin(); i !=mNetworks->end(); ++i) + delete *i; + mNetworks->clear(); + } + + while((linep = strtok_r(NULL, "\n", &linep_next))) { + WifiNetwork *wn = new WifiNetwork(mController, this, linep); + mNetworks->push_back(wn); + if (wn->refresh()) + LOGW("Unable to refresh network id %d", wn->getNetworkId()); + } + + LOGD("Loaded %d networks\n", mNetworks->size()); + pthread_mutex_unlock(&mNetworksLock); + } + + free(reply); + return 0; +} + +int Supplicant::connectToSupplicant() { + if (!isStarted()) + LOGW("Supplicant service not running"); + + mCtrl = wpa_ctrl_open("tiwlan0"); // XXX: if (mCtrl == NULL) { LOGE("Unable to open connection to supplicant on \"%s\": %s", "tiwlan0", strerror(errno)); @@ -132,7 +193,7 @@ int Supplicant::connectToSupplicant() { } mListener = new SupplicantListener(this, mMonitor); - + if (mListener->startListener()) { LOGE("Error - unable to start supplicant listener"); stop(); @@ -151,20 +212,17 @@ int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) // 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)) { - LOGW("sendCommand(): <- '%s'", reply); + strcpy(reply, "FAIL"); errno = EIO; return -1; } - if (!strncmp(cmd, "PING", 4) || - !strncmp(cmd, "SCAN_RESULTS", 12)) - reply[*reply_len] = '\0'; - -// LOGD("sendCommand(): <- '%s'", reply); +// LOGD("sendCommand(): <- '%s'", reply); return 0; } @@ -187,6 +245,22 @@ int Supplicant::triggerScan(bool active) { return 0; } +int Supplicant::set(const char *name, const char *value) { + const char *n = name + strlen("wifi.supplicant."); + + errno = -EROFS; + return -1; +} + +const char *Supplicant::get(const char *name, char *buffer, size_t max) { + const char *n = name + strlen("wifi.supplicant."); + + if (!strcasecmp(n, "state")) + return SupplicantState::toString(mState, buffer, max); + errno = ENOENT; + return NULL; +} + int Supplicant::onConnectedEvent(SupplicantEvent *evt) { LOGD("onConnectedEvent(%s)", evt->getEvent()); return 0; @@ -237,12 +311,12 @@ int Supplicant::onScanResultsEvent(SupplicantEvent *evt) { char *reply; if (!(reply = (char *) malloc(4096))) { - errno = -ENOMEM; + errno = ENOMEM; return -1; } size_t len = 4096; - + if (sendCommand("SCAN_RESULTS", reply, &len)) { LOGW("onScanResultsEvent(%s): Error getting scan results (%s)", evt->getEvent(), strerror(errno)); @@ -272,7 +346,7 @@ int Supplicant::onScanResultsEvent(SupplicantEvent *evt) { while((linep = strtok_r(NULL, "\n", &linep_next))) mLatestScanResults->push_back(new ScanResult(linep)); - + char tmp[128]; sprintf(tmp, "Scan results ready (%d)", mLatestScanResults->size()); NetworkManager::Instance()->getBroadcaster()-> @@ -323,43 +397,78 @@ ScanResultCollection *Supplicant::createLatestScanResults() { ScanResultCollection::iterator i; pthread_mutex_lock(&mLatestScanResultsLock); - for (i = mLatestScanResults->begin(); i != mLatestScanResults->end(); ++i) { + for (i = mLatestScanResults->begin(); i != mLatestScanResults->end(); ++i) d->push_back((*i)->clone()); - } pthread_mutex_unlock(&mLatestScanResultsLock); return d; } -WifiNetworkCollection *Supplicant::createNetworkList() { - WifiNetworkCollection *d = new WifiNetworkCollection(); - return d; -} - -int Supplicant::addNetwork() { - char reply[32]; +WifiNetwork *Supplicant::createNetwork() { + char reply[255]; size_t len = sizeof(reply) -1; - memset(reply, 0, sizeof(reply)); if (sendCommand("ADD_NETWORK", reply, &len)) - return -1; + return NULL; + + if (reply[strlen(reply) -1] == '\n') + reply[strlen(reply) -1] = '\0'; - return atoi(reply); + WifiNetwork *wn = new WifiNetwork(mController, this, atoi(reply)); + pthread_mutex_lock(&mNetworksLock); + mNetworks->push_back(wn); + pthread_mutex_unlock(&mNetworksLock); + return wn; } -int Supplicant::removeNetwork(int networkId) { +int Supplicant::removeNetwork(WifiNetwork *wn) { char req[64]; - sprintf(req, "REMOVE_NETWORK %d", networkId); + sprintf(req, "REMOVE_NETWORK %d", wn->getNetworkId()); char reply[32]; size_t len = sizeof(reply) -1; - memset(reply, 0, sizeof(reply)); - + if (sendCommand(req, reply, &len)) return -1; + + pthread_mutex_lock(&mNetworksLock); + WifiNetworkCollection::iterator it; + for (it = mNetworks->begin(); it != mNetworks->end(); ++it) { + if ((*it) == wn) { + mNetworks->erase(it); + break; + } + } + pthread_mutex_unlock(&mNetworksLock); return 0; } +WifiNetwork *Supplicant::lookupNetwork(int networkId) { + pthread_mutex_lock(&mNetworksLock); + WifiNetworkCollection::iterator it; + for (it = mNetworks->begin(); it != mNetworks->end(); ++it) { + if ((*it)->getNetworkId() == networkId) { + pthread_mutex_unlock(&mNetworksLock); + return *it; + } + } + pthread_mutex_unlock(&mNetworksLock); + errno = ENOENT; + return NULL; +} + +WifiNetworkCollection *Supplicant::createNetworkList() { + WifiNetworkCollection *d = new WifiNetworkCollection(); + WifiNetworkCollection::iterator i; + + pthread_mutex_lock(&mNetworksLock); + for (i = mNetworks->begin(); i != mNetworks->end(); ++i) + d->push_back((*i)->clone()); + + pthread_mutex_unlock(&mNetworksLock); + return d; +} + int Supplicant::setupConfig() { char buf[2048]; int srcfd, destfd; @@ -407,3 +516,60 @@ int Supplicant::setupConfig() { } return 0; } + +int Supplicant::setNetworkVar(int networkId, const char *var, const char *val) { + char reply[255]; + size_t len = sizeof(reply) -1; + + char *tmp; + asprintf(&tmp, "SET_NETWORK %d %s \"%s\"", networkId, var, val); + if (sendCommand(tmp, reply, &len)) { + free(tmp); + return -1; + } + free(tmp); + return 0; +} + +const char *Supplicant::getNetworkVar(int networkId, const char *var, + char *buffer, size_t max) { + size_t len = max - 1; + char *tmp; + + asprintf(&tmp, "GET_NETWORK %d %s", networkId, var); + if (sendCommand(tmp, buffer, &len)) { + free(tmp); + return NULL; + } + free(tmp); + return buffer; +} + +int Supplicant::enableNetwork(int networkId, bool enabled) { + char req[64]; + + if (enabled) + sprintf(req, "ENABLE_NETWORK %d", networkId); + else + sprintf(req, "DISABLE_NETWORK %d", networkId); + + char reply[16]; + size_t len = sizeof(reply) -1; + + if (sendCommand(req, reply, &len)) + return -1; + return 0; +} + + +int Supplicant::retrieveInterfaceName() { + char reply[255]; + size_t len = sizeof(reply) -1; + + if (sendCommand("INTERFACES", reply, &len)) + return -1; + + reply[strlen(reply)-1] = '\0'; + mInterfaceName = strdup(reply); + return 0; +} diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h index 2ea0892..34ecdcf 100644 --- a/nexus/Supplicant.h +++ b/nexus/Supplicant.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _SUPPLICANT_H #define _SUPPLICANT_H @@ -20,25 +21,35 @@ struct wpa_ctrl; class SupplicantListener; class SupplicantEvent; class ServiceManager; +class PropertyManager; +class Controller; +class WifiController; #include <pthread.h> #include "ScanResult.h" #include "WifiNetwork.h" +#include "IPropertyProvider.h" -class Supplicant { +class Supplicant : public IPropertyProvider { private: struct wpa_ctrl *mCtrl; struct wpa_ctrl *mMonitor; SupplicantListener *mListener; int mState; ServiceManager *mServiceManager; + PropertyManager *mPropMngr; + WifiController *mController; + char *mInterfaceName; ScanResultCollection *mLatestScanResults; pthread_mutex_t mLatestScanResultsLock; - + + WifiNetworkCollection *mNetworks; + pthread_mutex_t mNetworksLock; + public: - Supplicant(); + Supplicant(WifiController *wc, PropertyManager *propmngr); virtual ~Supplicant(); int start(); @@ -48,12 +59,23 @@ public: int triggerScan(bool active); ScanResultCollection *createLatestScanResults(); - int addNetwork(); - int removeNetwork(int networkId); + WifiNetwork *createNetwork(); + WifiNetwork *lookupNetwork(int networkId); + int removeNetwork(WifiNetwork *net); WifiNetworkCollection *createNetworkList(); + int refreshNetworkList(); + + int setNetworkVar(int networkId, const char *var, const char *value); + const char *getNetworkVar(int networkid, const char *var, char *buffer, + size_t max); + int enableNetwork(int networkId, bool enabled); int getState() { return mState; } + Controller *getController() { return (Controller *) mController; } + const char *getInterfaceName() { return mInterfaceName; } + int set(const char *name, const char *value); + const char *get(const char *name, char *buffer, size_t max); // XXX: Extract these into an interface // handlers for SupplicantListener @@ -76,6 +98,7 @@ private: int connectToSupplicant(); int sendCommand(const char *cmd, char *reply, size_t *reply_len); int setupConfig(); + int retrieveInterfaceName(); }; #endif diff --git a/nexus/SupplicantEvent.cpp b/nexus/SupplicantEvent.cpp index 5c0944a..2e6d665 100644 --- a/nexus/SupplicantEvent.cpp +++ b/nexus/SupplicantEvent.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdlib.h> #define LOG_TAG "SupplicantEvent" diff --git a/nexus/SupplicantEvent.h b/nexus/SupplicantEvent.h index 86ce8cb..2dc6722 100644 --- a/nexus/SupplicantEvent.h +++ b/nexus/SupplicantEvent.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _SUPPLICANT_EVENT_H #define _SUPPLICANT_EVENT_H diff --git a/nexus/SupplicantListener.cpp b/nexus/SupplicantListener.cpp index 76e9945..852eeb2 100644 --- a/nexus/SupplicantListener.cpp +++ b/nexus/SupplicantListener.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <errno.h> #include <sys/types.h> #include <pthread.h> @@ -85,7 +86,7 @@ bool SupplicantListener::onDataAvailable(SocketClient *cli) { } delete evt; - + if (rc) { LOGW("Handler %d (%s) error: %s", evt->getType(), evt->getEvent(), strerror(errno)); return false; diff --git a/nexus/SupplicantListener.h b/nexus/SupplicantListener.h index 95bad9a..680a523 100644 --- a/nexus/SupplicantListener.h +++ b/nexus/SupplicantListener.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _SUPPLICANTLISTENER_H__ #define _SUPPLICANTLISTENER_H__ diff --git a/nexus/SupplicantState.cpp b/nexus/SupplicantState.cpp new file mode 100644 index 0000000..a16d370 --- /dev/null +++ b/nexus/SupplicantState.cpp @@ -0,0 +1,49 @@ +/* + * 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 <stdio.h> + +#define LOG_TAG "SupplicantState" +#include <cutils/log.h> + +#include "SupplicantState.h" + +char *SupplicantState::toString(int val, char *buffer, int max) { + if (val == SupplicantState::UNKNOWN) + strncpy(buffer, "Unknown", max); + else if (val == SupplicantState::DISCONNECTED) + strncpy(buffer, "Disconnected", max); + else if (val == SupplicantState::INACTIVE) + strncpy(buffer, "Inactive", max); + else if (val == SupplicantState::SCANNING) + strncpy(buffer, "Scanning", max); + else if (val == SupplicantState::ASSOCIATING) + strncpy(buffer, "Associating", max); + else if (val == SupplicantState::ASSOCIATED) + strncpy(buffer, "Associated", max); + else if (val == SupplicantState::FOURWAY_HANDSHAKE) + strncpy(buffer, "Fourway Handshake", max); + else if (val == SupplicantState::GROUP_HANDSHAKE) + strncpy(buffer, "Group Handshake", max); + else if (val == SupplicantState::COMPLETED) + strncpy(buffer, "Completed", max); + else if (val == SupplicantState::IDLE) + strncpy(buffer, "Idle", max); + else + strncpy(buffer, "(internal error)", max); + + return buffer; +} diff --git a/nexus/SupplicantState.h b/nexus/SupplicantState.h index e85dcb5..6882f0c 100644 --- a/nexus/SupplicantState.h +++ b/nexus/SupplicantState.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _SUPPLICANT_STATE_H #define _SUPPLICANT_STATE_H @@ -28,6 +29,8 @@ public: static const int GROUP_HANDSHAKE = 6; static const int COMPLETED = 7; static const int IDLE = 8; + + static char *toString(int val, char *buffer, int max); }; #endif diff --git a/nexus/TiwlanWifiController.cpp b/nexus/TiwlanWifiController.cpp index 27c972b..307c48c 100644 --- a/nexus/TiwlanWifiController.cpp +++ b/nexus/TiwlanWifiController.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdlib.h> #include <fcntl.h> #include <errno.h> @@ -22,14 +23,15 @@ #define LOG_TAG "TiwlanWifiController" #include <cutils/log.h> +#include "PropertyManager.h" #include "TiwlanWifiController.h" #define DRIVER_PROP_NAME "wlan.driver.status" extern "C" int sched_yield(void); -TiwlanWifiController::TiwlanWifiController(char *modpath, char *modname, char *modargs) : - WifiController(modpath, modname, modargs) { +TiwlanWifiController::TiwlanWifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs) : + WifiController(propmngr, modpath, modname, modargs) { } int TiwlanWifiController::powerUp() { diff --git a/nexus/TiwlanWifiController.h b/nexus/TiwlanWifiController.h index f17ef51..d3ebe88 100644 --- a/nexus/TiwlanWifiController.h +++ b/nexus/TiwlanWifiController.h @@ -13,14 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _TIWLAN_WIFI_CONTROLLER_H #define _TIWLAN_WIFI_CONTROLLER_H +#include "PropertyManager.h" #include "WifiController.h" class TiwlanWifiController : public WifiController { public: - TiwlanWifiController(char *modpath, char *modname, char *modargs); + TiwlanWifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs); virtual ~TiwlanWifiController() {} virtual int powerUp(); diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp index d3bc216..1246703 100644 --- a/nexus/VpnController.cpp +++ b/nexus/VpnController.cpp @@ -16,55 +16,61 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> +#include "PropertyManager.h" #include "VpnController.h" -VpnController::VpnController() : - Controller("VPN", "vpn") { - registerProperty("gateway"); +VpnController::VpnController(PropertyManager *propmngr) : + Controller("VPN", propmngr) { + mEnabled = false; + propmngr->registerProperty("vpn.enabled", this); + propmngr->registerProperty("vpn.gateway", this); } int VpnController::start() { - errno = ENOSYS; - return -1; + return 0; } int VpnController::stop() { - errno = ENOSYS; - return -1; + return 0; } -int VpnController::enable() { - errno = ENOSYS; - return -1; -} +int VpnController::set(const char *name, const char *value) { + if (!strcmp(name, "vpn.enabled")) { + int en = atoi(value); + int rc; -int VpnController::disable() { - errno = ENOSYS; - return -1; -} + if (en == mEnabled) + return 0; + rc = (en ? enable() : disable()); -int VpnController::setProperty(const char *name, char *value) { - if (!strcmp(name, "gateway")) { + if (!rc) + mEnabled = en; + return rc; + } if (!strcmp(name, "vpn.gateway")) { if (!inet_aton(value, &mVpnGateway)) { errno = EINVAL; return -1; } return 0; - } + } - return Controller::setProperty(name, value); + return Controller::set(name, value); } -const char *VpnController::getProperty(const char *name, char *buffer, size_t maxsize) { - if (!strcmp(name, "gateway")) { +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::getProperty(name, buffer, maxsize); + return Controller::get(name, buffer, maxsize); } diff --git a/nexus/VpnController.h b/nexus/VpnController.h index 0a93990..b36856f 100644 --- a/nexus/VpnController.h +++ b/nexus/VpnController.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _VPN_CONTROLLER_H #define _VPN_CONTROLLER_H @@ -21,25 +22,25 @@ #include "Controller.h" class VpnController : public Controller { + bool mEnabled; /* * Gateway of the VPN server to connect to */ struct in_addr mVpnGateway; public: - VpnController(); + VpnController(PropertyManager *propmngr); virtual ~VpnController() {} virtual int start(); virtual int stop(); - virtual int setProperty(const char *name, char *value); - virtual const char *getProperty(const char *name, char *buffer, - size_t maxlen); + virtual int set(const char *name, const char *value); + virtual const char *get(const char *name, char *buffer, size_t maxlen); -private: - virtual int enable(); - virtual int disable(); +protected: + virtual int enable() = 0; + virtual int disable() = 0; }; diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp index 72207ce..3d06806 100644 --- a/nexus/WifiController.cpp +++ b/nexus/WifiController.cpp @@ -26,18 +26,21 @@ #include "WifiScanner.h" #include "NetworkManager.h" #include "ErrorCode.h" +#include "WifiNetwork.h" -WifiController::WifiController(char *modpath, char *modname, char *modargs) : - Controller("WIFI", "wifi") { +WifiController::WifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs) : + Controller("WIFI", propmngr) { strncpy(mModulePath, modpath, sizeof(mModulePath)); strncpy(mModuleName, modname, sizeof(mModuleName)); strncpy(mModuleArgs, modargs, sizeof(mModuleArgs)); - mSupplicant = new Supplicant(); + mSupplicant = new Supplicant(this, propmngr); mScanner = new WifiScanner(mSupplicant, 10); mCurrentScanMode = 0; - registerProperty("scanmode"); + mEnabled = false; + + propmngr->registerProperty("wifi.enabled", this); } int WifiController::start() { @@ -82,6 +85,17 @@ int WifiController::enable() { } } + if (Controller::bindInterface(mSupplicant->getInterfaceName())) { + LOGE("Error binding interface (%s)", strerror(errno)); + goto out_unloadmodule; + } + + if (mSupplicant->refreshNetworkList()) + LOGW("Error getting list of networks (%s)", strerror(errno)); + + mPropMngr->registerProperty("wifi.scanmode", this); + mPropMngr->registerProperty("wifi.interface", this); + return 0; out_unloadmodule: @@ -106,13 +120,14 @@ void WifiController::sendStatusBroadcast(const char *msg) { int WifiController::disable() { + mPropMngr->unregisterProperty("wifi.scanmode"); if (mSupplicant->isStarted()) { sendStatusBroadcast("STOPPING_SUPPLICANT"); if (mSupplicant->stop()) { LOGE("Supplicant stop failed (%s)", strerror(errno)); return -1; } - } else + } else LOGW("disable(): Supplicant not running?"); if (mModuleName[0] != '\0' && isKernelModuleLoaded(mModuleName)) { @@ -155,36 +170,60 @@ int WifiController::setScanMode(uint32_t mode) { return rc; } -int WifiController::addNetwork() { - return mSupplicant->addNetwork(); +WifiNetwork *WifiController::createNetwork() { + WifiNetwork *wn = mSupplicant->createNetwork(); + return wn; } int WifiController::removeNetwork(int networkId) { - return mSupplicant->removeNetwork(networkId); + WifiNetwork *wn = mSupplicant->lookupNetwork(networkId); + + if (!wn) + return -1; + return mSupplicant->removeNetwork(wn); } ScanResultCollection *WifiController::createScanResults() { return mSupplicant->createLatestScanResults(); } -// XXX: This should be a const list WifiNetworkCollection *WifiController::createNetworkList() { return mSupplicant->createNetworkList(); } -int WifiController::setProperty(const char *name, char *value) { - if (!strcmp(name, "scanmode")) +int WifiController::set(const char *name, const char *value) { + int rc; + + if (!strcmp(name, "wifi.enabled")) { + int en = atoi(value); + + 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)); - - return Controller::setProperty(name, value); + else + return Controller::set(name, value); + return rc; } -const char *WifiController::getProperty(const char *name, char *buffer, size_t maxsize) { - if (!strcmp(name, "scanmode")) { +const char *WifiController::get(const char *name, char *buffer, size_t maxsize) { + + 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); - return buffer; - } + else + return Controller::get(name, buffer, maxsize); - return Controller::getProperty(name, buffer, maxsize); + return buffer; } diff --git a/nexus/WifiController.h b/nexus/WifiController.h index a70fb5b..b2f4530 100644 --- a/nexus/WifiController.h +++ b/nexus/WifiController.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef _WIFI_CONTROLLER_H #define _WIFI_CONTROLLER_H @@ -46,21 +47,21 @@ private: char mModuleArgs[255]; uint32_t mCurrentScanMode; WifiScanner *mScanner; + bool mEnabled; public: - WifiController(char *modpath, char *modname, char *modargs); + WifiController(PropertyManager *propmngr, char *modpath, char *modname, char *modargs); virtual ~WifiController() {} int start(); int stop(); - int addNetwork(); + WifiNetwork *createNetwork(); int removeNetwork(int networkId); WifiNetworkCollection *createNetworkList(); - virtual int setProperty(const char *name, char *value); - virtual const char *getProperty(const char *name, char *buffer, - size_t maxlen); + virtual int set(const char *name, const char *value); + virtual const char *get(const char *name, char *buffer, size_t maxlen); ScanResultCollection *createScanResults(); @@ -71,6 +72,7 @@ public: Supplicant *getSupplicant() { return mSupplicant; } protected: + // Move this crap into a 'driver' virtual int powerUp() = 0; virtual int powerDown() = 0; virtual int loadFirmware(); @@ -78,13 +80,11 @@ protected: virtual bool isFirmwareLoaded() = 0; virtual bool isPoweredUp() = 0; - void sendStatusBroadcast(const char *msg); - private: + void sendStatusBroadcast(const char *msg); int setScanMode(uint32_t mode); int enable(); int disable(); - }; #endif diff --git a/nexus/WifiNetwork.cpp b/nexus/WifiNetwork.cpp index ef013c0..1f53a20 100644 --- a/nexus/WifiNetwork.cpp +++ b/nexus/WifiNetwork.cpp @@ -16,14 +16,93 @@ #include <errno.h> #include <string.h> +#include <stdlib.h> #include <sys/types.h> +#define LOG_TAG "WifiNetwork" +#include <cutils/log.h> + +#include "NetworkManager.h" #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 +} + +WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, const char *data) { + mController = c; + mSuppl = suppl; + + char *tmp = strdup(data); + char *next = tmp; + char *id; + char *ssid; + char *bssid; + char *flags; + + if (!(id = strsep(&next, "\t"))) + LOGE("Failed to extract network id"); + if (!(ssid = strsep(&next, "\t"))) + LOGE("Failed to extract ssid"); + if (!(bssid = strsep(&next, "\t"))) + LOGE("Failed to extract bssid"); + if (!(flags = strsep(&next, "\t"))) + LOGE("Failed to extract flags"); + + // LOGD("id '%s', ssid '%s', bssid '%s', flags '%s'", id, ssid, bssid, + // flags ? flags :"null"); + + if (id) + mNetid = atoi(id); + if (ssid) + mSsid = strdup(ssid); + if (bssid) + mBssid = strdup(bssid); + + mPsk = NULL; + memset(mWepKeys, 0, sizeof(mWepKeys)); + mDefaultKeyIndex = -1; + mPriority = -1; + mHiddenSsid = NULL; + mAllowedKeyManagement = 0; + mAllowedProtocols = 0; + mAllowedAuthAlgorithms = 0; + mAllowedPairwiseCiphers = 0; + mAllowedGroupCiphers = 0; + mEnabled = true; + + if (flags && flags[0] != '\0') { + if (!strcmp(flags, "[DISABLED]")) + mEnabled = false; + else + LOGW("Unsupported flags '%s'", flags); + } -WifiNetwork::WifiNetwork(Supplicant *suppl) { + char *tmp2; + asprintf(&tmp2, "wifi.net.%d", mNetid); + mIfaceCfg = new InterfaceConfig(tmp2); + free(tmp2); + + registerProperties(); + free(tmp); +} + +WifiNetwork::WifiNetwork(WifiController *c, Supplicant *suppl, int networkId) { + mController = c; mSuppl = suppl; - mNetid = -1; + mNetid = networkId; mSsid = NULL; mBssid = NULL; mPsk = NULL; @@ -36,9 +115,45 @@ WifiNetwork::WifiNetwork(Supplicant *suppl) { mAllowedAuthAlgorithms = 0; mAllowedPairwiseCiphers = 0; mAllowedGroupCiphers = 0; + mEnabled = false; + + char *tmp2; + asprintf(&tmp2, "wifi.net.%d", mNetid); + mIfaceCfg = new InterfaceConfig(tmp2); + free(tmp2); + + registerProperties(); +} + +WifiNetwork *WifiNetwork::clone() { + WifiNetwork *r = new WifiNetwork(); + + r->mSuppl = mSuppl; + r->mNetid = mNetid; + + if (mSsid) + r->mSsid = strdup(mSsid); + if (mBssid) + r->mBssid = strdup(mBssid); + if (mPsk) + r->mPsk = strdup(mPsk); + + r->mController = mController; + memcpy(r->mWepKeys, mWepKeys, sizeof(mWepKeys)); + r->mDefaultKeyIndex = mDefaultKeyIndex; + r->mPriority = mPriority; + if (mHiddenSsid) + r->mHiddenSsid = strdup(mHiddenSsid); + r->mAllowedKeyManagement = mAllowedKeyManagement; + r->mAllowedProtocols = mAllowedProtocols; + r->mAllowedAuthAlgorithms = mAllowedAuthAlgorithms; + r->mAllowedPairwiseCiphers = mAllowedPairwiseCiphers; + r->mAllowedGroupCiphers = mAllowedGroupCiphers; + return r; } WifiNetwork::~WifiNetwork() { + unregisterProperties(); if (mSsid) free(mSsid); if (mBssid) @@ -49,61 +164,423 @@ WifiNetwork::~WifiNetwork() { if (mWepKeys[i]) free(mWepKeys[i]); } + if (mHiddenSsid) free(mHiddenSsid); + if (mIfaceCfg) + delete(mIfaceCfg); } -int WifiNetwork::setSsid(char *ssid) { - errno = ENOSYS; +int WifiNetwork::refresh() { + char buffer[255]; + size_t len; + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "psk", buffer, len)) + mPsk = strdup(buffer); + + for (int i = 0; i < 4; i++) { + char *name; + + asprintf(&name, "wep_key%d", i); + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, name, buffer, len)) + mWepKeys[i] = strdup(buffer); + free(name); + } + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "wep_tx_keyidx", buffer, len)) + mDefaultKeyIndex = atoi(buffer); + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "priority", buffer, len)) + mPriority = atoi(buffer); + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "scan_ssid", buffer, len)) + mHiddenSsid = strdup(buffer); + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "key_mgmt", buffer, len)) { + // TODO + } + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "proto", buffer, len)) { + // TODO + } + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "auth_alg", buffer, len)) { + // TODO + } + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "pairwise", buffer, len)) { + // TODO + } + + len = sizeof(buffer); + if (mSuppl->getNetworkVar(mNetid, "group", buffer, len)) { + // TODO + } + + return 0; +out_err: + LOGE("Refresh failed (%s)",strerror(errno)); return -1; } -int WifiNetwork::setBssid(char *bssid) { - errno = ENOSYS; +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 = 0; + 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; } -int WifiNetwork::setPsk(char *psk) { - errno = ENOSYS; - 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, "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::setWepKey(int idx, char *key) { - errno = ENOSYS; - return -1; +int WifiNetwork::setSsid(const char *ssid) { + if (mSuppl->setNetworkVar(mNetid, "ssid", ssid)) + return -1; + if (mSsid) + free(mSsid); + mSsid = strdup(ssid); + return 0; +} + +int WifiNetwork::setBssid(const char *bssid) { + if (mSuppl->setNetworkVar(mNetid, "bssid", bssid)) + return -1; + if (mBssid) + free(mBssid); + mBssid = strdup(bssid); + return 0; +} + +int WifiNetwork::setPsk(const char *psk) { + if (mSuppl->setNetworkVar(mNetid, "psk", psk)) + return -1; + + if (mPsk) + free(mPsk); + mPsk = strdup(psk); + return 0; +} + +int WifiNetwork::setWepKey(int idx, const char *key) { + char *name; + + asprintf(&name, "wep_key%d", idx); + int rc = mSuppl->setNetworkVar(mNetid, name, key); + free(name); + + if (rc) + return -1; + + if (mWepKeys[idx]) + free(mWepKeys[idx]); + mWepKeys[idx] = strdup(key); + return 0; } int WifiNetwork::setDefaultKeyIndex(int idx) { - errno = ENOSYS; - return -1; + char val[16]; + sprintf(val, "%d", idx); + if (mSuppl->setNetworkVar(mNetid, "wep_tx_keyidx", val)) + return -1; + + mDefaultKeyIndex = idx; + return 0; } -int WifiNetwork::setPriority(int idx) { - errno = ENOSYS; - return -1; +int WifiNetwork::setPriority(int priority) { + char val[16]; + sprintf(val, "%d", priority); + if (mSuppl->setNetworkVar(mNetid, "priority", val)) + return -1; + + mPriority = priority; + return 0; } -int WifiNetwork::setHiddenSsid(char *ssid) { - errno = ENOSYS; - return -1; +int WifiNetwork::setHiddenSsid(const char *ssid) { + if (mSuppl->setNetworkVar(mNetid, "scan_ssid", ssid)) + return -1; + + if (mHiddenSsid) + free(mHiddenSsid); + mHiddenSsid = strdup(ssid); + return 0; } int WifiNetwork::setAllowedKeyManagement(uint32_t mask) { - errno = ENOSYS; - return -1; + char accum[255]; + + 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 (mSuppl->setNetworkVar(mNetid, "key_mgmt", accum)) + return -1; + mAllowedKeyManagement = mask; + return 0; } int WifiNetwork::setAllowedProtocols(uint32_t mask) { - errno = ENOSYS; - return -1; + char accum[255]; + + accum[0] = '\0'; + + if (mask & SecurityProtocolMask::WPA) + strcpy(accum, "WPA "); + + if (mask & SecurityProtocolMask::RSN) + strcat(accum, "RSN"); + + if (mSuppl->setNetworkVar(mNetid, "proto", accum)) + return -1; + mAllowedProtocols = mask; + return 0; +} + +int WifiNetwork::setAllowedAuthAlgorithms(uint32_t mask) { + char accum[255]; + + accum[0] = '\0'; + + if (mask & AuthenticationAlgorithmMask::OPEN) + strcpy(accum, "OPEN "); + + if (mask & AuthenticationAlgorithmMask::SHARED) + strcat(accum, "SHARED "); + + if (mask & AuthenticationAlgorithmMask::LEAP) + strcat(accum, "LEAP "); + + if (mSuppl->setNetworkVar(mNetid, "auth_alg", accum)) + return -1; + + mAllowedAuthAlgorithms = mask; + return 0; } int WifiNetwork::setAllowedPairwiseCiphers(uint32_t mask) { - errno = ENOSYS; - return -1; + char accum[255]; + + if (mask == PairwiseCiphersMask::NONE) + strcpy(accum, "NONE"); + else { + if (mask & PairwiseCiphersMask::TKIP) + strcat(accum, "TKIP "); + if (mask & PairwiseCiphersMask::CCMP) + strcat(accum, "CCMP "); + } + + if (mSuppl->setNetworkVar(mNetid, "pairwise", accum)) + return -1; + + mAllowedPairwiseCiphers = mask; + return 0; } int WifiNetwork::setAllowedGroupCiphers(uint32_t mask) { - errno = ENOSYS; - return -1; + char accum[255]; + + if (mask & GroupCiphersMask::WEP40) + strcat(accum, "WEP40 "); + if (mask & GroupCiphersMask::WEP104) + strcat(accum, "WEP104 "); + if (mask & GroupCiphersMask::TKIP) + strcat(accum, "TKIP "); + if (mask & GroupCiphersMask::CCMP) + strcat(accum, "CCMP "); + + if (mSuppl->setNetworkVar(mNetid, "group", accum)) + return -1; + mAllowedGroupCiphers = mask; + return 0; +} + +int WifiNetwork::setEnabled(bool enabled) { + if (mSuppl->enableNetwork(mNetid, enabled)) + return -1; + + mEnabled = 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); + + if (NetworkManager::Instance()->getPropMngr()->registerProperty(tmp, + this)) { + free(tmp); + return -1; + } + free(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); + + if (NetworkManager::Instance()->getPropMngr()->unregisterProperty(tmp)) + LOGW("Unable to remove property '%s' (%s)", tmp, strerror(errno)); + free(tmp); + } + return 0; } diff --git a/nexus/WifiNetwork.h b/nexus/WifiNetwork.h index 1354730..bdffa8b 100644 --- a/nexus/WifiNetwork.h +++ b/nexus/WifiNetwork.h @@ -19,7 +19,7 @@ #include <sys/types.h> -#include "../../../frameworks/base/include/utils/List.h" +#include <utils/List.h> class KeyManagementMask { public: @@ -43,14 +43,14 @@ public: static const uint32_t LEAP = 0x04; }; -class PairwiseCipherMask { +class PairwiseCiphersMask { public: static const uint32_t NONE = 0x00; static const uint32_t TKIP = 0x01; static const uint32_t CCMP = 0x02; }; -class GroupCipherMask { +class GroupCiphersMask { public: static const uint32_t WEP40 = 0x01; static const uint32_t WEP104 = 0x02; @@ -59,9 +59,20 @@ public: }; class Supplicant; +class InterfaceConfig; +class Controller; +class WifiController; -class WifiNetwork { +#include "IPropertyProvider.h" + +class WifiNetwork : public IPropertyProvider{ +public: + static const char *PropertyNames[]; + +private: Supplicant *mSuppl; + InterfaceConfig *mIfaceCfg; + WifiController *mController; /* * Unique network id - normally provided by supplicant @@ -138,10 +149,24 @@ class WifiNetwork { */ uint32_t mAllowedGroupCiphers; + /* + * Set if this Network is enabled + */ + bool mEnabled; + +private: + WifiNetwork(); + int registerProperties(); + int unregisterProperties(); + public: - WifiNetwork(Supplicant *suppl); + WifiNetwork(WifiController *c, Supplicant *suppl, int networkId); + WifiNetwork(WifiController *c, Supplicant *suppl, const char *data); + virtual ~WifiNetwork(); + WifiNetwork *clone(); + int getNetworkId() { return mNetid; } const char *getSsid() { return mSsid; } const char *getBssid() { return mBssid; } @@ -155,18 +180,30 @@ public: uint32_t getAllowedAuthAlgorithms() { return mAllowedAuthAlgorithms; } uint32_t getAllowedPairwiseCiphers() { return mAllowedPairwiseCiphers; } uint32_t getAllowedGroupCiphers() { return mAllowedGroupCiphers; } + bool getEnabled() { return mEnabled; } + Controller *getController() { return (Controller *) mController; } - int setSsid(char *ssid); - int setBssid(char *bssid); - int setPsk(char *psk); - int setWepKey(int idx, char *key); + 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); + int setPsk(const char *psk); + int setWepKey(int idx, const char *key); int setDefaultKeyIndex(int idx); int setPriority(int pri); - int setHiddenSsid(char *ssid); + 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); + + // XXX:Should this really be exposed?.. meh + int refresh(); }; typedef android::List<WifiNetwork *> WifiNetworkCollection; diff --git a/nexus/WifiScanner.cpp b/nexus/WifiScanner.cpp index 048e784..bdfa497 100644 --- a/nexus/WifiScanner.cpp +++ b/nexus/WifiScanner.cpp @@ -1,3 +1,19 @@ +/* + * 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 <stdlib.h> #include <sys/socket.h> #include <sys/select.h> diff --git a/nexus/WifiScanner.h b/nexus/WifiScanner.h index 4406e9f..92822e9 100644 --- a/nexus/WifiScanner.h +++ b/nexus/WifiScanner.h @@ -1,3 +1,19 @@ +/* + * 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 _WIFISCANNER_H #define _WIFISCANNER_H diff --git a/nexus/main.cpp b/nexus/main.cpp index 0aec3e5..e460d42 100644 --- a/nexus/main.cpp +++ b/nexus/main.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdlib.h> #include <errno.h> @@ -39,10 +40,10 @@ int main() { nm->setBroadcaster((SocketListener *) cl); - nm->attachController(new LoopController()); - nm->attachController(new TiwlanWifiController("/system/lib/modules/wlan.ko", "wlan", "")); + nm->attachController(new LoopController(nm->getPropMngr())); + nm->attachController(new TiwlanWifiController(nm->getPropMngr(), "/system/lib/modules/wlan.ko", "wlan", "")); // nm->attachController(new AndroidL2TPVpnController()); - nm->attachController(new OpenVpnController()); + nm->attachController(new OpenVpnController(nm->getPropMngr())); if (NetworkManager::Instance()->run()) { @@ -56,7 +57,7 @@ int main() { } // XXX: we'll use the main thread for the NetworkManager eventually - + while(1) { sleep(1000); } diff --git a/nexus/nexctl.c b/nexus/nexctl.c index 4ad73c4..cfebbf0 100644 --- a/nexus/nexctl.c +++ b/nexus/nexctl.c @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <stdio.h> #include <stdlib.h> #include <unistd.h> |