Home | History | Annotate | Download | only in nexus
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdio.h>
     18 #include <errno.h>
     19 #include <sys/types.h>
     20 #include <sys/socket.h>
     21 #include <arpa/inet.h>
     22 #include <pthread.h>
     23 
     24 #define LOG_TAG "DhcpClient"
     25 #include <cutils/log.h>
     26 #include <cutils/properties.h>
     27 
     28 #include <sysutils/ServiceManager.h>
     29 
     30 #include <netutils/ifc.h>
     31 #include <netutils/dhcp.h>
     32 
     33 #include "DhcpClient.h"
     34 #include "DhcpState.h"
     35 #include "DhcpListener.h"
     36 #include "IDhcpEventHandlers.h"
     37 #include "Controller.h"
     38 
     39 DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) :
     40             mState(DhcpState::INIT), mHandlers(handlers) {
     41     mServiceManager = new ServiceManager();
     42     mListener = NULL;
     43     mListenerSocket = NULL;
     44     mController = NULL;
     45     mDoArpProbe = false;
     46     pthread_mutex_init(&mLock, NULL);
     47 }
     48 
     49 DhcpClient::~DhcpClient() {
     50     delete mServiceManager;
     51     if (mListener)
     52         delete mListener;
     53 }
     54 
     55 int DhcpClient::start(Controller *c) {
     56     LOGD("Starting DHCP service (arp probe = %d)", mDoArpProbe);
     57     char svc[PROPERTY_VALUE_MAX];
     58     snprintf(svc,
     59              sizeof(svc),
     60              "dhcpcd:%s%s",
     61              (!mDoArpProbe ? "-A " : ""),
     62              c->getBoundInterface());
     63 
     64     pthread_mutex_lock(&mLock);
     65 
     66     if (mController) {
     67         pthread_mutex_unlock(&mLock);
     68         errno = EBUSY;
     69         return -1;
     70     }
     71     mController = c;
     72 
     73     sockaddr_in addr;
     74     if ((mListenerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
     75         LOGE("Failed to create DHCP listener socket");
     76         pthread_mutex_unlock(&mLock);
     77         return -1;
     78     }
     79     memset(&addr, 0, sizeof(addr));
     80     addr.sin_family = AF_INET;
     81     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
     82     addr.sin_port = htons(DhcpClient::STATUS_MONITOR_PORT);
     83 
     84     if (bind(mListenerSocket, (struct sockaddr *) &addr, sizeof(addr))) {
     85         LOGE("Failed to bind DHCP listener socket");
     86         close(mListenerSocket);
     87         mListenerSocket = -1;
     88         pthread_mutex_unlock(&mLock);
     89         return -1;
     90     }
     91 
     92     if (mServiceManager->start(svc)) {
     93         LOGE("Failed to start dhcp service");
     94         pthread_mutex_unlock(&mLock);
     95         return -1;
     96     }
     97 
     98     mListener = new DhcpListener(mController, mListenerSocket, mHandlers);
     99     if (mListener->startListener()) {
    100         LOGE("Failed to start listener");
    101 #if 0
    102         mServiceManager->stop("dhcpcd");
    103         return -1;
    104 #endif
    105         delete mListener;
    106         mListener = NULL;
    107         pthread_mutex_unlock(&mLock);
    108     }
    109 
    110     pthread_mutex_unlock(&mLock);
    111     return 0;
    112 }
    113 
    114 int DhcpClient::stop() {
    115     pthread_mutex_lock(&mLock);
    116     if (!mController) {
    117         pthread_mutex_unlock(&mLock);
    118         return 0;
    119     }
    120 
    121     if (mListener) {
    122         mListener->stopListener();
    123         delete mListener;
    124         mListener = NULL;
    125     }
    126     close(mListenerSocket);
    127 
    128     if (mServiceManager->stop("dhcpcd")) {
    129         LOGW("Failed to stop DHCP service (%s)", strerror(errno));
    130         // XXX: Kill it the hard way.. but its gotta go!
    131     }
    132 
    133     mController = NULL;
    134     pthread_mutex_unlock(&mLock);
    135     return 0;
    136 }
    137 
    138 void DhcpClient::setDoArpProbe(bool probe) {
    139     mDoArpProbe = probe;
    140 }
    141