OSDN Git Service

Merge "Changed format of interface class acitivity message."
[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         free(args);
162         return 0;
163     } else {
164         close(pipefd[0]);
165         mDaemonPid = pid;
166         mDaemonFd = pipefd[1];
167         ALOGD("Tethering services running");
168     }
169
170     return 0;
171 }
172
173 int TetherController::stopTethering() {
174
175     if (mDaemonPid == 0) {
176         ALOGE("Tethering already stopped");
177         return 0;
178     }
179
180     ALOGD("Stopping tethering services");
181
182     kill(mDaemonPid, SIGTERM);
183     waitpid(mDaemonPid, NULL, 0);
184     mDaemonPid = 0;
185     close(mDaemonFd);
186     mDaemonFd = -1;
187     ALOGD("Tethering services stopped");
188     return 0;
189 }
190
191 // TODO(BT) remove
192 int TetherController::startReverseTethering(const char* iface) {
193     if (mDhcpcdPid != 0) {
194         ALOGE("Reverse tethering already started");
195         errno = EBUSY;
196         return -1;
197     }
198
199     ALOGD("TetherController::startReverseTethering, Starting reverse tethering");
200
201     /*
202      * TODO: Create a monitoring thread to handle and restart
203      * the daemon if it exits prematurely
204      */
205     //cleanup the dhcp result
206     char dhcp_result_name[64];
207     snprintf(dhcp_result_name, sizeof(dhcp_result_name) - 1, "dhcp.%s.result", iface);
208     property_set(dhcp_result_name, "");
209
210     pid_t pid;
211     if ((pid = fork()) < 0) {
212         ALOGE("fork failed (%s)", strerror(errno));
213         return -1;
214     }
215
216     if (!pid) {
217
218         char *args[10];
219         int argc = 0;
220         args[argc++] = "/system/bin/dhcpcd";
221         char host_name[128];
222         if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0'))
223         {
224             args[argc++] = "-h";
225             args[argc++] = host_name;
226         }
227         args[argc++] = (char*)iface;
228         args[argc] = NULL;
229         if (execv(args[0], args)) {
230             ALOGE("startReverseTethering, execv failed (%s)", strerror(errno));
231         }
232         ALOGE("startReverseTethering, Should never get here!");
233         // TODO(BT) inform parent of the failure.
234         //          Parent process need wait for child to report error status
235         //          before it set mDhcpcdPid and return 0.
236         exit(-1);
237     } else {
238         mDhcpcdPid = pid;
239         ALOGD("Reverse Tethering running, pid:%d", pid);
240     }
241     return 0;
242 }
243
244 // TODO(BT) remove
245 int TetherController::stopReverseTethering() {
246
247     if (mDhcpcdPid == 0) {
248         ALOGE("Tethering already stopped");
249         return 0;
250     }
251
252     ALOGD("Stopping tethering services");
253
254     kill(mDhcpcdPid, SIGTERM);
255     waitpid(mDhcpcdPid, NULL, 0);
256     mDhcpcdPid = 0;
257     ALOGD("Tethering services stopped");
258     return 0;
259 }
260 bool TetherController::isTetheringStarted() {
261     return (mDaemonPid == 0 ? false : true);
262 }
263
264 #define MAX_CMD_SIZE 1024
265
266 int TetherController::setDnsForwarders(char **servers, int numServers) {
267     int i;
268     char daemonCmd[MAX_CMD_SIZE];
269
270     strcpy(daemonCmd, "update_dns");
271     int cmdLen = strlen(daemonCmd);
272
273     mDnsForwarders->clear();
274     for (i = 0; i < numServers; i++) {
275         ALOGD("setDnsForwarders(%d = '%s')", i, servers[i]);
276
277         struct in_addr a;
278
279         if (!inet_aton(servers[i], &a)) {
280             ALOGE("Failed to parse DNS server '%s'", servers[i]);
281             mDnsForwarders->clear();
282             return -1;
283         }
284
285         cmdLen += strlen(servers[i]);
286         if (cmdLen + 2 >= MAX_CMD_SIZE) {
287             ALOGD("Too many DNS servers listed");
288             break;
289         }
290
291         strcat(daemonCmd, ":");
292         strcat(daemonCmd, servers[i]);
293         mDnsForwarders->push_back(a);
294     }
295
296     if (mDaemonFd != -1) {
297         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
298         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
299             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
300             mDnsForwarders->clear();
301             return -1;
302         }
303     }
304     return 0;
305 }
306
307 NetAddressCollection *TetherController::getDnsForwarders() {
308     return mDnsForwarders;
309 }
310
311 int TetherController::tetherInterface(const char *interface) {
312     mInterfaces->push_back(strdup(interface));
313     return 0;
314 }
315
316 int TetherController::untetherInterface(const char *interface) {
317     InterfaceCollection::iterator it;
318
319     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
320         if (!strcmp(interface, *it)) {
321             free(*it);
322             mInterfaces->erase(it);
323             return 0;
324         }
325     }
326     errno = ENOENT;
327     return -1;
328 }
329
330 InterfaceCollection *TetherController::getTetheredInterfaceList() {
331     return mInterfaces;
332 }