OSDN Git Service

Don\'t use framework permission strings for netd permissions. am: 5c8c42e90f am:...
[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        9
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         args[8] = (char *)"-z";  // OPT_NOWILD
177
178         int nextArg = TETHER_START_CONST_ARG;
179         for (int addrIndex = 0; addrIndex < num_addrs; addrIndex += 2) {
180             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h",
181                      dhcp_ranges[addrIndex], dhcp_ranges[addrIndex+1]);
182         }
183
184         if (execv(args[0], args)) {
185             ALOGE("execl failed (%s)", strerror(errno));
186         }
187         ALOGE("Should never get here!");
188         _exit(-1);
189     } else {
190         close(pipefd[0]);
191         mDaemonPid = pid;
192         mDaemonFd = pipefd[1];
193         applyDnsInterfaces();
194         ALOGD("Tethering services running");
195     }
196
197     return 0;
198 }
199
200 int TetherController::stopTethering() {
201
202     if (mDaemonPid == 0) {
203         ALOGE("Tethering already stopped");
204         return 0;
205     }
206
207     ALOGD("Stopping tethering services");
208
209     kill(mDaemonPid, SIGTERM);
210     waitpid(mDaemonPid, NULL, 0);
211     mDaemonPid = 0;
212     close(mDaemonFd);
213     mDaemonFd = -1;
214     ALOGD("Tethering services stopped");
215     return 0;
216 }
217
218 bool TetherController::isTetheringStarted() {
219     return (mDaemonPid == 0 ? false : true);
220 }
221
222 #define MAX_CMD_SIZE 1024
223
224 int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) {
225     int i;
226     char daemonCmd[MAX_CMD_SIZE];
227
228     Fwmark fwmark;
229     fwmark.netId = netId;
230     fwmark.explicitlySelected = true;
231     fwmark.protectedFromVpn = true;
232     fwmark.permission = PERMISSION_SYSTEM;
233
234     snprintf(daemonCmd, sizeof(daemonCmd), "update_dns%s0x%x", SEPARATOR, fwmark.intValue);
235     int cmdLen = strlen(daemonCmd);
236
237     mDnsForwarders->clear();
238     for (i = 0; i < numServers; i++) {
239         ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
240
241         addrinfo *res, hints = { .ai_flags = AI_NUMERICHOST };
242         int ret = getaddrinfo(servers[i], NULL, &hints, &res);
243         freeaddrinfo(res);
244         if (ret) {
245             ALOGE("Failed to parse DNS server '%s'", servers[i]);
246             mDnsForwarders->clear();
247             errno = EINVAL;
248             return -1;
249         }
250
251         cmdLen += (strlen(servers[i]) + 1);
252         if (cmdLen + 1 >= MAX_CMD_SIZE) {
253             ALOGD("Too many DNS servers listed");
254             break;
255         }
256
257         strcat(daemonCmd, SEPARATOR);
258         strcat(daemonCmd, servers[i]);
259         mDnsForwarders->push_back(servers[i]);
260     }
261
262     mDnsNetId = netId;
263     if (mDaemonFd != -1) {
264         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
265         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
266             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
267             mDnsForwarders->clear();
268             errno = EREMOTEIO;
269             return -1;
270         }
271     }
272     return 0;
273 }
274
275 unsigned TetherController::getDnsNetId() {
276     return mDnsNetId;
277 }
278
279 NetAddressCollection *TetherController::getDnsForwarders() {
280     return mDnsForwarders;
281 }
282
283 int TetherController::applyDnsInterfaces() {
284     char daemonCmd[MAX_CMD_SIZE];
285
286     strcpy(daemonCmd, "update_ifaces");
287     int cmdLen = strlen(daemonCmd);
288     InterfaceCollection::iterator it;
289     bool haveInterfaces = false;
290
291     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
292         cmdLen += (strlen(*it) + 1);
293         if (cmdLen + 1 >= MAX_CMD_SIZE) {
294             ALOGD("Too many DNS ifaces listed");
295             break;
296         }
297
298         strcat(daemonCmd, SEPARATOR);
299         strcat(daemonCmd, *it);
300         haveInterfaces = true;
301     }
302
303     if ((mDaemonFd != -1) && haveInterfaces) {
304         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
305         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
306             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
307             return -1;
308         }
309     }
310     return 0;
311 }
312
313 int TetherController::tetherInterface(const char *interface) {
314     ALOGD("tetherInterface(%s)", interface);
315     if (!isIfaceName(interface)) {
316         errno = ENOENT;
317         return -1;
318     }
319     mInterfaces->push_back(strdup(interface));
320
321     if (applyDnsInterfaces()) {
322         InterfaceCollection::iterator it;
323         for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
324             if (!strcmp(interface, *it)) {
325                 free(*it);
326                 mInterfaces->erase(it);
327                 break;
328             }
329         }
330         return -1;
331     } else {
332         return 0;
333     }
334 }
335
336 int TetherController::untetherInterface(const char *interface) {
337     InterfaceCollection::iterator it;
338
339     ALOGD("untetherInterface(%s)", interface);
340
341     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
342         if (!strcmp(interface, *it)) {
343             free(*it);
344             mInterfaces->erase(it);
345
346             return applyDnsInterfaces();
347         }
348     }
349     errno = ENOENT;
350     return -1;
351 }
352
353 InterfaceCollection *TetherController::getTetheredInterfaceList() {
354     return mInterfaces;
355 }