diff --git a/nexus/Android.mk b/nexus/Android.mk index 865f58a87..cd477ef45 100644 --- a/nexus/Android.mk +++ b/nexus/Android.mk @@ -34,7 +34,8 @@ LOCAL_SRC_FILES:= \ SupplicantConnectionTimeoutEvent.cpp \ SupplicantDisconnectedEvent.cpp \ SupplicantStatus.cpp \ - TiwlanEventListener.cpp + TiwlanEventListener.cpp \ + DhcpClient.cpp DhcpListener.cpp \ LOCAL_MODULE:= nexus diff --git a/nexus/DhcpClient.cpp b/nexus/DhcpClient.cpp new file mode 100644 index 000000000..2bd9c68f1 --- /dev/null +++ b/nexus/DhcpClient.cpp @@ -0,0 +1,105 @@ +/* + * 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 "DhcpClient" +#include +#include + +#include + +#include "DhcpClient.h" +#include "DhcpState.h" +#include "DhcpListener.h" +#include "IDhcpEventHandlers.h" + +extern "C" { +int ifc_disable(const char *ifname); +int ifc_add_host_route(const char *ifname, uint32_t addr); +int ifc_remove_host_routes(const char *ifname); +int ifc_set_default_route(const char *ifname, uint32_t gateway); +int ifc_get_default_route(const char *ifname); +int ifc_remove_default_route(const char *ifname); +int ifc_reset_connections(const char *ifname); +int ifc_configure(const char *ifname, in_addr_t ipaddr, in_addr_t netmask, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2); + +int dhcp_do_request(const char *ifname, + in_addr_t *ipaddr, + in_addr_t *gateway, + in_addr_t *mask, + in_addr_t *dns1, + in_addr_t *dns2, + in_addr_t *server, + uint32_t *lease); +int dhcp_stop(const char *ifname); +int dhcp_release_lease(const char *ifname); +char *dhcp_get_errmsg(); +} + +DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) : + mState(DhcpState::STOPPED), mHandlers(handlers) { + mServiceManager = new ServiceManager(); + mListener = NULL; +} + +DhcpClient::~DhcpClient() { + delete mServiceManager; + if (mListener) + delete mListener; +} + +int DhcpClient::start(const char *interface) { + + char svc[PROPERTY_VALUE_MAX]; + snprintf(svc, sizeof(svc), "dhcpcd_ng:%s", interface); + + if (mServiceManager->start(svc)) { + LOGE("Failed to start dhcp service"); + return -1; + } + + mListener = new DhcpListener(mHandlers); + if (mListener->startListener()) { + LOGE("Failed to start listener"); +#if 0 + mServiceManager->stop("dhcpcd_ng"); + return -1; +#endif + delete mListener; + mListener = NULL; + } + + mState = DhcpState::STARTED; + + return 0; +} + +int DhcpClient::stop() { + if (mListener) { + mListener->stopListener(); + delete mListener; + mListener = NULL; + } + + if (mServiceManager->stop("dhcpcd_ng")) + LOGW("Failed to stop DHCP service (%s)", strerror(errno)); + mState = DhcpState::STOPPED; + return 0; +} diff --git a/nexus/DhcpClient.h b/nexus/DhcpClient.h new file mode 100644 index 000000000..e0a2784b5 --- /dev/null +++ b/nexus/DhcpClient.h @@ -0,0 +1,41 @@ + +/* + * 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 _DhcpClient_H +#define _DhcpClient_H + +class IDhcpEventHandlers; +class ServiceManager; +class DhcpListener; + +class DhcpClient { + int mState; + IDhcpEventHandlers *mHandlers; + ServiceManager *mServiceManager; + DhcpListener *mListener; + +public: + DhcpClient(IDhcpEventHandlers *handlers); + virtual ~DhcpClient(); + + int getState() { return mState; } + + int start(const char *interface); + int stop(); +}; + +#endif diff --git a/nexus/DhcpListener.cpp b/nexus/DhcpListener.cpp new file mode 100644 index 000000000..2d07ee85d --- /dev/null +++ b/nexus/DhcpListener.cpp @@ -0,0 +1,34 @@ +/* + * 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 "DhcpListener" +#include + +#include +#include "IDhcpEventHandlers.h" + +DhcpListener::DhcpListener(IDhcpEventHandlers *handlers) : + SocketListener("dhcp_ng", false) { + mHandlers = handlers; +} + +DhcpListener::~DhcpListener() { +} + +bool DhcpListener::onDataAvailable(SocketClient *cli) { + LOGD("onDataAvailable()"); + return true; +} diff --git a/nexus/DhcpListener.h b/nexus/DhcpListener.h new file mode 100644 index 000000000..bfc5a3771 --- /dev/null +++ b/nexus/DhcpListener.h @@ -0,0 +1,36 @@ +/* + * 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 _DhcpListener_H +#define _DhcpListener_H + +#include + +class IDhcpEventHandlers; + +class DhcpListener : public SocketListener { + IDhcpEventHandlers *mHandlers; + +public: + + DhcpListener(IDhcpEventHandlers *handlers); + virtual ~DhcpListener(); + +private: + bool onDataAvailable(SocketClient *cli); +}; + +#endif diff --git a/nexus/DhcpState.h b/nexus/DhcpState.h new file mode 100644 index 000000000..27d7c7e37 --- /dev/null +++ b/nexus/DhcpState.h @@ -0,0 +1,27 @@ +/* + * 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 _DhcpState_H +#define _DhcpState_H + +class DhcpState { +public: + static const int UNKNOWN = 0; + static const int STOPPED = 1; + static const int STARTED = 2; +}; + +#endif diff --git a/nexus/IControllerHandler.h b/nexus/IControllerHandler.h index 92d015f43..f7be39cea 100644 --- a/nexus/IControllerHandler.h +++ b/nexus/IControllerHandler.h @@ -22,8 +22,8 @@ class InterfaceConfig; class IControllerHandler { public: - virtual void onInterfaceStarted(Controller *c, const InterfaceConfig *cfg) = 0; - virtual void onInterfaceStopping(Controller *c, const char *name) = 0; + virtual void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) = 0; + virtual void onInterfaceDisconnected(Controller *c, const char *name) = 0; }; #endif diff --git a/nexus/IDhcpEventHandlers.h b/nexus/IDhcpEventHandlers.h new file mode 100644 index 000000000..3f51f645d --- /dev/null +++ b/nexus/IDhcpEventHandlers.h @@ -0,0 +1,25 @@ + +/* + * 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 _IDhcpEventHandlers_H +#define _IDhcpEventHandlers_H + +class IDhcpEventHandlers { +public: +}; + +#endif diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp index 2f13a408e..7450b951b 100644 --- a/nexus/NetworkManager.cpp +++ b/nexus/NetworkManager.cpp @@ -23,6 +23,7 @@ #include "NetworkManager.h" #include "InterfaceConfig.h" +#include "DhcpClient.h" NetworkManager *NetworkManager::sInstance = NULL; @@ -36,6 +37,7 @@ NetworkManager::NetworkManager(PropertyManager *propMngr) { mBroadcaster = NULL; mControllers = new ControllerCollection(); mPropMngr = propMngr; + mDhcp = new DhcpClient(this); } NetworkManager::~NetworkManager() { @@ -89,8 +91,8 @@ Controller *NetworkManager::findController(const char *name) { return NULL; } -void NetworkManager::onInterfaceStarted(Controller *c, const InterfaceConfig *cfg) { - LOGD("Interface %s started by controller %s", c->getBoundInterface(), c->getName()); +void NetworkManager::onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) { + LOGD("Controller %s interface %s connected", c->getName(), c->getBoundInterface()); // Look up the interface @@ -98,9 +100,9 @@ void NetworkManager::onInterfaceStarted(Controller *c, const InterfaceConfig *cf } if (cfg) { - if (cfg->getUseDhcp()) { - // Launch DHCP thread - } else { + if (cfg->getUseDhcp() && mDhcp->start(c->getBoundInterface())) { + LOGE("DHCP start failed"); + } else if (!cfg->getUseDhcp()) { // Static configuration } } else { @@ -109,6 +111,11 @@ void NetworkManager::onInterfaceStarted(Controller *c, const InterfaceConfig *cf } } -void NetworkManager::onInterfaceStopping(Controller *c, const char *name) { - LOGD("Interface %s stopped by controller %s", name, c->getName()); +void NetworkManager::onInterfaceDisconnected(Controller *c, const char *name) { + LOGD("Controller %s interface %s disconnected", c->getName(), name); + + // If we have a DHCP request out on this interface then stop it + if (1) { + mDhcp->stop(); + } } diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h index edc80c9b5..44f3417fd 100644 --- a/nexus/NetworkManager.h +++ b/nexus/NetworkManager.h @@ -22,10 +22,12 @@ #include "Controller.h" #include "PropertyManager.h" #include "IControllerHandler.h" +#include "IDhcpEventHandlers.h" class InterfaceConfig; +class DhcpClient; -class NetworkManager : public IControllerHandler { +class NetworkManager : public IControllerHandler, public IDhcpEventHandlers { private: static NetworkManager *sInstance; @@ -33,6 +35,7 @@ private: ControllerCollection *mControllers; SocketListener *mBroadcaster; PropertyManager *mPropMngr; + DhcpClient *mDhcp; public: virtual ~NetworkManager(); @@ -55,7 +58,7 @@ private: NetworkManager(PropertyManager *propMngr); - void onInterfaceStarted(Controller *c, const InterfaceConfig *cfg); - void onInterfaceStopping(Controller *c, const char *name); + void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg); + void onInterfaceDisconnected(Controller *c, const char *name); }; #endif diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp index b7bd6edad..ef5ecae17 100644 --- a/nexus/WifiController.cpp +++ b/nexus/WifiController.cpp @@ -279,33 +279,31 @@ void WifiController::onAssociatedEvent(SupplicantAssociatedEvent *evt) { void WifiController::onConnectedEvent(SupplicantConnectedEvent *evt) { LOGD("onConnectedEvent(%s, %d)", evt->getBssid(), evt->getReassociated()); - if (!evt->getReassociated()) { - SupplicantStatus *ss = mSupplicant->getStatus(); - WifiNetwork *wn; + SupplicantStatus *ss = mSupplicant->getStatus(); + WifiNetwork *wn; - if (ss->getWpaState() != SupplicantState::COMPLETED) { - char tmp[32]; + if (ss->getWpaState() != SupplicantState::COMPLETED) { + char tmp[32]; - LOGW("onConnected() with SupplicantState = %s!", - SupplicantState::toString(ss->getWpaState(), tmp, - sizeof(tmp))); - return; - } - - if (ss->getId() == -1) { - LOGW("onConnected() with id = -1!"); - return; - } - - if (!(wn = mSupplicant->lookupNetwork(ss->getId()))) { - LOGW("Error looking up connected network id %d (%s)", - ss->getId(), strerror(errno)); - return; - } - - delete ss; - mHandlers->onInterfaceStarted(this, wn->getIfaceCfg()); + LOGW("onConnected() with SupplicantState = %s!", + SupplicantState::toString(ss->getWpaState(), tmp, + sizeof(tmp))); + return; } + + if (ss->getId() == -1) { + LOGW("onConnected() with id = -1!"); + return; + } + + if (!(wn = mSupplicant->lookupNetwork(ss->getId()))) { + LOGW("Error looking up connected network id %d (%s)", + ss->getId(), strerror(errno)); + return; + } + + delete ss; + mHandlers->onInterfaceConnected(this, wn->getIfaceCfg()); } void WifiController::onScanResultsEvent(SupplicantScanResultsEvent *evt) { @@ -373,7 +371,7 @@ void WifiController::onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent * } void WifiController::onDisconnectedEvent(SupplicantDisconnectedEvent *evt) { - LOGD("onDisconnectedEvent()"); + mHandlers->onInterfaceDisconnected(this, getBoundInterface()); } #if 0