OSDN Git Service

am c2203765: (-s ours) Reconcile with jb-mr1-release - do not merge
[android-x86/system-netd.git] / TetherController.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 <stdlib.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <string.h>
21
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29
30 #define LOG_TAG "TetherController"
31 #include <cutils/log.h>
32 #include <cutils/properties.h>
33
34 #include "TetherController.h"
35
36 TetherController::TetherController() {
37     mInterfaces = new InterfaceCollection();
38     mDnsForwarders = new NetAddressCollection();
39     mDaemonFd = -1;
40     mDaemonPid = 0;
41     mDhcpcdPid = 0;
42 }
43
44 TetherController::~TetherController() {
45     InterfaceCollection::iterator it;
46
47     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
48         free(*it);
49     }
50     mInterfaces->clear();
51
52     mDnsForwarders->clear();
53 }
54
55 int TetherController::setIpFwdEnabled(bool enable) {
56
57     ALOGD("Setting IP forward enable = %d", enable);
58
59     // In BP tools mode, do not disable IP forwarding
60     char bootmode[PROPERTY_VALUE_MAX] = {0};
61     property_get("ro.bootmode", bootmode, "unknown");
62     if ((enable == false) && (0 == strcmp("bp-tools", bootmode))) {
63         return 0;
64     }
65
66     int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY);
67     if (fd < 0) {
68         ALOGE("Failed to open ip_forward (%s)", strerror(errno));
69         return -1;
70     }
71
72     if (write(fd, (enable ? "1" : "0"), 1) != 1) {
73         ALOGE("Failed to write ip_forward (%s)", strerror(errno));
74         close(fd);
75         return -1;
76     }
77     close(fd);
78     return 0;
79 }
80
81 bool TetherController::getIpFwdEnabled() {
82     int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY);
83
84     if (fd < 0) {
85         ALOGE("Failed to open ip_forward (%s)", strerror(errno));
86         return false;
87     }
88
89     char enabled;
90     if (read(fd, &enabled, 1) != 1) {
91         ALOGE("Failed to read ip_forward (%s)", strerror(errno));
92         close(fd);
93         return -1;
94     }
95
96     close(fd);
97     return (enabled  == '1' ? true : false);
98 }
99
100 int TetherController::startTethering(int num_addrs, struct in_addr* addrs) {
101     if (mDaemonPid != 0) {
102         ALOGE("Tethering already started");
103         errno = EBUSY;
104         return -1;
105     }
106
107     ALOGD("Starting tethering services");
108
109     pid_t pid;
110     int pipefd[2];
111
112     if (pipe(pipefd) < 0) {
113         ALOGE("pipe failed (%s)", strerror(errno));
114         return -1;
115     }
116
117     /*
118      * TODO: Create a monitoring thread to handle and restart
119      * the daemon if it exits prematurely
120      */
121     if ((pid = fork()) < 0) {
122         ALOGE("fork failed (%s)", strerror(errno));
123         close(pipefd[0]);
124         close(pipefd[1]);
125         return -1;
126     }
127
128     if (!pid) {
129         close(pipefd[1]);
130         if (pipefd[0] != STDIN_FILENO) {
131             if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
132                 ALOGE("dup2 failed (%s)", strerror(errno));
133                 return -1;
134             }
135             close(pipefd[0]);
136         }
137
138         int num_processed_args = 7 + (num_addrs/2) + 1; // 1 null for termination
139         char **args = (char **)malloc(sizeof(char *) * num_processed_args);
140         args[num_processed_args - 1] = NULL;
141         args[0] = (char *)"/system/bin/dnsmasq";
142         args[1] = (char *)"--keep-in-foreground";
143         args[2] = (char *)"--no-resolv";
144         args[3] = (char *)"--no-poll";
145         // TODO: pipe through metered status from ConnService
146         args[4] = (char *)"--dhcp-option-force=43,ANDROID_METERED";
147         args[5] = (char *)"--pid-file";
148         args[6] = (char *)"";
149
150         int nextArg = 7;
151         for (int addrIndex=0; addrIndex < num_addrs;) {
152             char *start = strdup(inet_ntoa(addrs[addrIndex++]));
153             char *end = strdup(inet_ntoa(addrs[addrIndex++]));
154             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
155         }
156
157         if (execv(args[0], args)) {
158             ALOGE("execl failed (%s)", strerror(errno));
159         }
160         ALOGE("Should never get here!");
161         _exit(-1);
162     } else {
163         close(pipefd[0]);
164         mDaemonPid = pid;
165         mDaemonFd = pipefd[1];
166         ALOGD("Tethering services running");
167     }
168
169     return 0;
170 }
171
172 int TetherController::stopTethering() {
173
174     if (mDaemonPid == 0) {
175         ALOGE("Tethering already stopped");
176         return 0;
177     }
178
179     ALOGD("Stopping tethering services");
180
181     kill(mDaemonPid, SIGTERM);
182     waitpid(mDaemonPid, NULL, 0);
183     mDaemonPid = 0;
184     close(mDaemonFd);
185     mDaemonFd = -1;
186     ALOGD("Tethering services stopped");
187     return 0;
188 }
189
190 // TODO(BT) remove
191 int TetherController::startReverseTethering(const char* iface) {
192     if (mDhcpcdPid != 0) {
193         ALOGE("Reverse tethering already started");
194         errno = EBUSY;
195         return -1;
196     }
197
198     ALOGD("TetherController::startReverseTethering, Starting reverse tethering");
199
200     /*
201      * TODO: Create a monitoring thread to handle and restart
202      * the daemon if it exits prematurely
203      */
204     //cleanup the dhcp result
205     char dhcp_result_name[64];
206     snprintf(dhcp_result_name, sizeof(dhcp_result_name) - 1, "dhcp.%s.result", iface);
207     property_set(dhcp_result_name, "");
208
209     pid_t pid;
210     if ((pid = fork()) < 0) {
211         ALOGE("fork failed (%s)", strerror(errno));
212         return -1;
213     }
214
215     if (!pid) {
216
217         char *args[10];
218         int argc = 0;
219         args[argc++] = "/system/bin/dhcpcd";
220         char host_name[128];
221         if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0'))
222         {
223             args[argc++] = "-h";
224             args[argc++] = host_name;
225         }
226         args[argc++] = (char*)iface;
227         args[argc] = NULL;
228         if (execv(args[0], args)) {
229             ALOGE("startReverseTethering, execv failed (%s)", strerror(errno));
230         }
231         ALOGE("startReverseTethering, Should never get here!");
232         // TODO(BT) inform parent of the failure.
233         //          Parent process need wait for child to report error status
234         //          before it set mDhcpcdPid and return 0.
235         _exit(-1);
236     } else {
237         mDhcpcdPid = pid;
238         ALOGD("Reverse Tethering running, pid:%d", pid);
239     }
240     return 0;
241 }
242
243 // TODO(BT) remove
244 int TetherController::stopReverseTethering() {
245
246     if (mDhcpcdPid == 0) {
247         ALOGE("Tethering already stopped");
248         return 0;
249     }
250
251     ALOGD("Stopping tethering services");
252
253     kill(mDhcpcdPid, SIGTERM);
254     waitpid(mDhcpcdPid, NULL, 0);
255     mDhcpcdPid = 0;
256     ALOGD("Tethering services stopped");
257     return 0;
258 }
259 bool TetherController::isTetheringStarted() {
260     return (mDaemonPid == 0 ? false : true);
261 }
262
263 #define MAX_CMD_SIZE 1024
264
265 int TetherController::setDnsForwarders(char **servers, int numServers) {
266     int i;
267     char daemonCmd[MAX_CMD_SIZE];
268
269     strcpy(daemonCmd, "update_dns");
270     int cmdLen = strlen(daemonCmd);
271
272     mDnsForwarders->clear();
273     for (i = 0; i < numServers; i++) {
274         ALOGD("setDnsForwarders(%d = '%s')", i, servers[i]);
275
276         struct in_addr a;
277
278         if (!inet_aton(servers[i], &a)) {
279             ALOGE("Failed to parse DNS server '%s'", servers[i]);
280             mDnsForwarders->clear();
281             return -1;
282         }
283
284         cmdLen += (strlen(servers[i]) + 1);
285         if (cmdLen + 1 >= MAX_CMD_SIZE) {
286             ALOGD("Too many DNS servers listed");
287             break;
288         }
289
290         strcat(daemonCmd, ":");
291         strcat(daemonCmd, servers[i]);
292         mDnsForwarders->push_back(a);
293     }
294
295     if (mDaemonFd != -1) {
296         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
297         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
298             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
299             mDnsForwarders->clear();
300             return -1;
301         }
302     }
303     return 0;
304 }
305
306 NetAddressCollection *TetherController::getDnsForwarders() {
307     return mDnsForwarders;
308 }
309
310 int TetherController::tetherInterface(const char *interface) {
311     mInterfaces->push_back(strdup(interface));
312     return 0;
313 }
314
315 int TetherController::untetherInterface(const char *interface) {
316     InterfaceCollection::iterator it;
317
318     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
319         if (!strcmp(interface, *it)) {
320             free(*it);
321             mInterfaces->erase(it);
322             return 0;
323         }
324     }
325     errno = ENOENT;
326     return -1;
327 }
328
329 InterfaceCollection *TetherController::getTetheredInterfaceList() {
330     return mInterfaces;
331 }