OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / system / core / nexus / DhcpClient.cpp
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 "DhcpClient.h"
31 #include "DhcpState.h"
32 #include "DhcpListener.h"
33 #include "IDhcpEventHandlers.h"
34 #include "Controller.h"
35
36 extern "C" {
37 int ifc_disable(const char *ifname);
38 int ifc_add_host_route(const char *ifname, uint32_t addr);
39 int ifc_remove_host_routes(const char *ifname);
40 int ifc_set_default_route(const char *ifname, uint32_t gateway);
41 int ifc_get_default_route(const char *ifname);
42 int ifc_remove_default_route(const char *ifname);
43 int ifc_reset_connections(const char *ifname);
44 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);
45
46 int dhcp_do_request(const char *ifname,
47                     in_addr_t *ipaddr,
48                     in_addr_t *gateway,
49                     in_addr_t *mask,
50                     in_addr_t *dns1,
51                     in_addr_t *dns2,
52                     in_addr_t *server,
53                     uint32_t  *lease);
54 int dhcp_stop(const char *ifname);
55 int dhcp_release_lease(const char *ifname);
56 char *dhcp_get_errmsg();
57 }
58
59 DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) :
60             mState(DhcpState::INIT), mHandlers(handlers) {
61     mServiceManager = new ServiceManager();
62     mListener = NULL;
63     mListenerSocket = NULL;
64     mController = NULL;
65     mDoArpProbe = false;
66     pthread_mutex_init(&mLock, NULL);
67 }
68
69 DhcpClient::~DhcpClient() {
70     delete mServiceManager;
71     if (mListener)
72         delete mListener;
73 }
74
75 int DhcpClient::start(Controller *c) {
76     LOGD("Starting DHCP service (arp probe = %d)", mDoArpProbe);
77     char svc[PROPERTY_VALUE_MAX];
78     snprintf(svc,
79              sizeof(svc),
80              "dhcpcd:%s%s",
81              (!mDoArpProbe ? "-A " : ""),
82              c->getBoundInterface());
83
84     pthread_mutex_lock(&mLock);
85
86     if (mController) {
87         pthread_mutex_unlock(&mLock);
88         errno = EBUSY;
89         return -1;
90     }
91     mController = c;
92
93     sockaddr_in addr;
94     if ((mListenerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
95         LOGE("Failed to create DHCP listener socket");
96         pthread_mutex_unlock(&mLock);
97         return -1;
98     }
99     memset(&addr, 0, sizeof(addr));
100     addr.sin_family = AF_INET;
101     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
102     addr.sin_port = htons(DhcpClient::STATUS_MONITOR_PORT);
103
104     if (bind(mListenerSocket, (struct sockaddr *) &addr, sizeof(addr))) {
105         LOGE("Failed to bind DHCP listener socket");
106         close(mListenerSocket);
107         mListenerSocket = -1;
108         pthread_mutex_unlock(&mLock);
109         return -1;
110     }
111
112     if (mServiceManager->start(svc)) {
113         LOGE("Failed to start dhcp service");
114         pthread_mutex_unlock(&mLock);
115         return -1;
116     }
117
118     mListener = new DhcpListener(mController, mListenerSocket, mHandlers);
119     if (mListener->startListener()) {
120         LOGE("Failed to start listener");
121 #if 0
122         mServiceManager->stop("dhcpcd");
123         return -1;
124 #endif
125         delete mListener;
126         mListener = NULL;
127         pthread_mutex_unlock(&mLock);
128     }
129
130     pthread_mutex_unlock(&mLock);
131     return 0;
132 }
133
134 int DhcpClient::stop() {
135     pthread_mutex_lock(&mLock);
136     if (!mController) {
137         pthread_mutex_unlock(&mLock);
138         return 0;
139     }
140
141     if (mListener) {
142         mListener->stopListener();
143         delete mListener;
144         mListener = NULL;
145     }
146     close(mListenerSocket);
147
148     if (mServiceManager->stop("dhcpcd")) {
149         LOGW("Failed to stop DHCP service (%s)", strerror(errno));
150         // XXX: Kill it the hard way.. but its gotta go!
151     }
152
153     mController = NULL;
154     pthread_mutex_unlock(&mLock);
155     return 0;
156 }
157
158 void DhcpClient::setDoArpProbe(bool probe) {
159     mDoArpProbe = probe;
160 }