OSDN Git Service

dbbd933b17b9a1ab15e4ac517759a6e60ea7daf4
[android-x86/system-netd.git] / server / 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 <netdb.h>
21 #include <string.h>
22
23 #include <sys/socket.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
30
31 #define LOG_TAG "TetherController"
32 #include <cutils/log.h>
33 #include <cutils/properties.h>
34
35 #include "Fwmark.h"
36 #include "NetdConstants.h"
37 #include "Permission.h"
38 #include "TetherController.h"
39
40 namespace {
41
42 static const char BP_TOOLS_MODE[] = "bp-tools";
43 static const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
44 static const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
45 static const char SEPARATOR[] = "|";
46
47 bool writeToFile(const char* filename, const char* value) {
48     int fd = open(filename, O_WRONLY);
49     if (fd < 0) {
50         ALOGE("Failed to open %s: %s", filename, strerror(errno));
51         return false;
52     }
53
54     const ssize_t len = strlen(value);
55     if (write(fd, value, len) != len) {
56         ALOGE("Failed to write %s to %s: %s", value, filename, strerror(errno));
57         close(fd);
58         return false;
59     }
60     close(fd);
61     return true;
62 }
63
64 bool inBpToolsMode() {
65     // In BP tools mode, do not disable IP forwarding
66     char bootmode[PROPERTY_VALUE_MAX] = {0};
67     property_get("ro.bootmode", bootmode, "unknown");
68     return !strcmp(BP_TOOLS_MODE, bootmode);
69 }
70
71 }  // namespace
72
73 TetherController::TetherController() {
74     mInterfaces = new InterfaceCollection();
75     mDnsNetId = 0;
76     mDnsForwarders = new NetAddressCollection();
77     mDaemonFd = -1;
78     mDaemonPid = 0;
79     if (inBpToolsMode()) {
80         enableForwarding(BP_TOOLS_MODE);
81     } else {
82         setIpFwdEnabled();
83     }
84 }
85
86 TetherController::~TetherController() {
87     InterfaceCollection::iterator it;
88
89     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
90         free(*it);
91     }
92     mInterfaces->clear();
93
94     mDnsForwarders->clear();
95     mForwardingRequests.clear();
96 }
97
98 bool TetherController::setIpFwdEnabled() {
99     bool success = true;
100     const char* value = mForwardingRequests.empty() ? "0" : "1";
101     ALOGD("Setting IP forward enable = %s", value);
102     success &= writeToFile(IPV4_FORWARDING_PROC_FILE, value);
103     success &= writeToFile(IPV6_FORWARDING_PROC_FILE, value);
104     return success;
105 }
106
107 bool TetherController::enableForwarding(const char* requester) {
108     // Don't return an error if this requester already requested forwarding. Only return errors for
109     // things that the caller caller needs to care about, such as "couldn't write to the file to
110     // enable forwarding".
111     mForwardingRequests.insert(requester);
112     return setIpFwdEnabled();
113 }
114
115 bool TetherController::disableForwarding(const char* requester) {
116     mForwardingRequests.erase(requester);
117     return setIpFwdEnabled();
118 }
119
120 size_t TetherController::forwardingRequestCount() {
121     return mForwardingRequests.size();
122 }
123
124 #define TETHER_START_CONST_ARG        8
125
126 int TetherController::startTethering(int num_addrs, char **dhcp_ranges) {
127     if (mDaemonPid != 0) {
128         ALOGE("Tethering already started");
129         errno = EBUSY;
130         return -1;
131     }
132
133     ALOGD("Starting tethering services");
134
135     pid_t pid;
136     int pipefd[2];
137
138     if (pipe(pipefd) < 0) {
139         ALOGE("pipe failed (%s)", strerror(errno));
140         return -1;
141     }
142
143     /*
144      * TODO: Create a monitoring thread to handle and restart
145      * the daemon if it exits prematurely
146      */
147     if ((pid = fork()) < 0) {
148         ALOGE("fork failed (%s)", strerror(errno));
149         close(pipefd[0]);
150         close(pipefd[1]);
151         return -1;
152     }
153
154     if (!pid) {
155         close(pipefd[1]);
156         if (pipefd[0] != STDIN_FILENO) {
157             if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
158                 ALOGE("dup2 failed (%s)", strerror(errno));
159                 return -1;
160             }
161             close(pipefd[0]);
162         }
163
164         int num_processed_args = TETHER_START_CONST_ARG + (num_addrs/2) + 1;
165         char **args = (char **)malloc(sizeof(char *) * num_processed_args);
166         args[num_processed_args - 1] = NULL;
167         args[0] = (char *)"/system/bin/dnsmasq";
168         args[1] = (char *)"--keep-in-foreground";
169         args[2] = (char *)"--no-resolv";
170         args[3] = (char *)"--no-poll";
171         args[4] = (char *)"--dhcp-authoritative";
172         // TODO: pipe through metered status from ConnService
173         args[5] = (char *)"--dhcp-option-force=43,ANDROID_METERED";
174         args[6] = (char *)"--pid-file";
175         args[7] = (char *)"";
176
177         int nextArg = TETHER_START_CONST_ARG;
178         for (int addrIndex = 0; addrIndex < num_addrs; addrIndex += 2) {
179             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h",
180                      dhcp_ranges[addrIndex], dhcp_ranges[addrIndex+1]);
181         }
182
183         if (execv(args[0], args)) {
184             ALOGE("execl failed (%s)", strerror(errno));
185         }
186         ALOGE("Should never get here!");
187         _exit(-1);
188     } else {
189         close(pipefd[0]);
190         mDaemonPid = pid;
191         mDaemonFd = pipefd[1];
192         applyDnsInterfaces();
193         ALOGD("Tethering services running");
194     }
195
196     return 0;
197 }
198
199 int TetherController::stopTethering() {
200
201     if (mDaemonPid == 0) {
202         ALOGE("Tethering already stopped");
203         return 0;
204     }
205
206     ALOGD("Stopping tethering services");
207
208     kill(mDaemonPid, SIGTERM);
209     waitpid(mDaemonPid, NULL, 0);
210     mDaemonPid = 0;
211     close(mDaemonFd);
212     mDaemonFd = -1;
213     ALOGD("Tethering services stopped");
214     return 0;
215 }
216
217 bool TetherController::isTetheringStarted() {
218     return (mDaemonPid == 0 ? false : true);
219 }
220
221 #define MAX_CMD_SIZE 1024
222
223 int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) {
224     int i;
225     char daemonCmd[MAX_CMD_SIZE];
226
227     Fwmark fwmark;
228     fwmark.netId = netId;
229     fwmark.explicitlySelected = true;
230     fwmark.protectedFromVpn = true;
231     fwmark.permission = PERMISSION_SYSTEM;
232
233     snprintf(daemonCmd, sizeof(daemonCmd), "update_dns%s0x%x", SEPARATOR, fwmark.intValue);
234     int cmdLen = strlen(daemonCmd);
235
236     mDnsForwarders->clear();
237     for (i = 0; i < numServers; i++) {
238         ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
239
240         addrinfo *res, hints = { .ai_flags = AI_NUMERICHOST };
241         int ret = getaddrinfo(servers[i], NULL, &hints, &res);
242         freeaddrinfo(res);
243         if (ret) {
244             ALOGE("Failed to parse DNS server '%s'", servers[i]);
245             mDnsForwarders->clear();
246             errno = EINVAL;
247             return -1;
248         }
249
250         cmdLen += (strlen(servers[i]) + 1);
251         if (cmdLen + 1 >= MAX_CMD_SIZE) {
252             ALOGD("Too many DNS servers listed");
253             break;
254         }
255
256         strcat(daemonCmd, SEPARATOR);
257         strcat(daemonCmd, servers[i]);
258         mDnsForwarders->push_back(servers[i]);
259     }
260
261     mDnsNetId = netId;
262     if (mDaemonFd != -1) {
263         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
264         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
265             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
266             mDnsForwarders->clear();
267             errno = EREMOTEIO;
268             return -1;
269         }
270     }
271     return 0;
272 }
273
274 unsigned TetherController::getDnsNetId() {
275     return mDnsNetId;
276 }
277
278 NetAddressCollection *TetherController::getDnsForwarders() {
279     return mDnsForwarders;
280 }
281
282 int TetherController::applyDnsInterfaces() {
283     char daemonCmd[MAX_CMD_SIZE];
284
285     strcpy(daemonCmd, "update_ifaces");
286     int cmdLen = strlen(daemonCmd);
287     InterfaceCollection::iterator it;
288     bool haveInterfaces = false;
289
290     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
291         cmdLen += (strlen(*it) + 1);
292         if (cmdLen + 1 >= MAX_CMD_SIZE) {
293             ALOGD("Too many DNS ifaces listed");
294             break;
295         }
296
297         strcat(daemonCmd, SEPARATOR);
298         strcat(daemonCmd, *it);
299         haveInterfaces = true;
300     }
301
302     if ((mDaemonFd != -1) && haveInterfaces) {
303         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
304         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
305             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
306             return -1;
307         }
308     }
309     return 0;
310 }
311
312 int TetherController::tetherInterface(const char *interface) {
313     ALOGD("tetherInterface(%s)", interface);
314     if (!isIfaceName(interface)) {
315         errno = ENOENT;
316         return -1;
317     }
318     mInterfaces->push_back(strdup(interface));
319
320     if (applyDnsInterfaces()) {
321         InterfaceCollection::iterator it;
322         for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
323             if (!strcmp(interface, *it)) {
324                 free(*it);
325                 mInterfaces->erase(it);
326                 break;
327             }
328         }
329         return -1;
330     } else {
331         return 0;
332     }
333 }
334
335 int TetherController::untetherInterface(const char *interface) {
336     InterfaceCollection::iterator it;
337
338     ALOGD("untetherInterface(%s)", interface);
339
340     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
341         if (!strcmp(interface, *it)) {
342             free(*it);
343             mInterfaces->erase(it);
344
345             return applyDnsInterfaces();
346         }
347     }
348     errno = ENOENT;
349     return -1;
350 }
351
352 InterfaceCollection *TetherController::getTetheredInterfaceList() {
353     return mInterfaces;
354 }