• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Fwmark.h"
35 #include "NetdConstants.h"
36 #include "Permission.h"
37 #include "TetherController.h"
38 
39 namespace {
40 
41 static const char BP_TOOLS_MODE[] = "bp-tools";
42 static const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
43 static const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
44 
writeToFile(const char * filename,const char * value)45 bool writeToFile(const char* filename, const char* value) {
46     int fd = open(filename, O_WRONLY);
47     if (fd < 0) {
48         ALOGE("Failed to open %s: %s", filename, strerror(errno));
49         return false;
50     }
51 
52     const ssize_t len = strlen(value);
53     if (write(fd, value, len) != len) {
54         ALOGE("Failed to write %s to %s: %s", value, filename, strerror(errno));
55         close(fd);
56         return false;
57     }
58     close(fd);
59     return true;
60 }
61 
inBpToolsMode()62 bool inBpToolsMode() {
63     // In BP tools mode, do not disable IP forwarding
64     char bootmode[PROPERTY_VALUE_MAX] = {0};
65     property_get("ro.bootmode", bootmode, "unknown");
66     return !strcmp(BP_TOOLS_MODE, bootmode);
67 }
68 
69 }  // namespace
70 
TetherController()71 TetherController::TetherController() {
72     mInterfaces = new InterfaceCollection();
73     mDnsNetId = 0;
74     mDnsForwarders = new NetAddressCollection();
75     mDaemonFd = -1;
76     mDaemonPid = 0;
77     if (inBpToolsMode()) {
78         enableForwarding(BP_TOOLS_MODE);
79     } else {
80         setIpFwdEnabled();
81     }
82 }
83 
~TetherController()84 TetherController::~TetherController() {
85     InterfaceCollection::iterator it;
86 
87     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
88         free(*it);
89     }
90     mInterfaces->clear();
91 
92     mDnsForwarders->clear();
93     mForwardingRequests.clear();
94 }
95 
setIpFwdEnabled()96 bool TetherController::setIpFwdEnabled() {
97     bool success = true;
98     const char* value = mForwardingRequests.empty() ? "0" : "1";
99     ALOGD("Setting IP forward enable = %s", value);
100     success &= writeToFile(IPV4_FORWARDING_PROC_FILE, value);
101     success &= writeToFile(IPV6_FORWARDING_PROC_FILE, value);
102     return success;
103 }
104 
enableForwarding(const char * requester)105 bool TetherController::enableForwarding(const char* requester) {
106     // Don't return an error if this requester already requested forwarding. Only return errors for
107     // things that the caller caller needs to care about, such as "couldn't write to the file to
108     // enable forwarding".
109     mForwardingRequests.insert(requester);
110     return setIpFwdEnabled();
111 }
112 
disableForwarding(const char * requester)113 bool TetherController::disableForwarding(const char* requester) {
114     mForwardingRequests.erase(requester);
115     return setIpFwdEnabled();
116 }
117 
forwardingRequestCount()118 size_t TetherController::forwardingRequestCount() {
119     return mForwardingRequests.size();
120 }
121 
122 #define TETHER_START_CONST_ARG        8
123 
startTethering(int num_addrs,struct in_addr * addrs)124 int TetherController::startTethering(int num_addrs, struct in_addr* addrs) {
125     if (mDaemonPid != 0) {
126         ALOGE("Tethering already started");
127         errno = EBUSY;
128         return -1;
129     }
130 
131     ALOGD("Starting tethering services");
132 
133     pid_t pid;
134     int pipefd[2];
135 
136     if (pipe(pipefd) < 0) {
137         ALOGE("pipe failed (%s)", strerror(errno));
138         return -1;
139     }
140 
141     /*
142      * TODO: Create a monitoring thread to handle and restart
143      * the daemon if it exits prematurely
144      */
145     if ((pid = fork()) < 0) {
146         ALOGE("fork failed (%s)", strerror(errno));
147         close(pipefd[0]);
148         close(pipefd[1]);
149         return -1;
150     }
151 
152     if (!pid) {
153         close(pipefd[1]);
154         if (pipefd[0] != STDIN_FILENO) {
155             if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
156                 ALOGE("dup2 failed (%s)", strerror(errno));
157                 return -1;
158             }
159             close(pipefd[0]);
160         }
161 
162         int num_processed_args = TETHER_START_CONST_ARG + (num_addrs/2) + 1;
163         char **args = (char **)malloc(sizeof(char *) * num_processed_args);
164         args[num_processed_args - 1] = NULL;
165         args[0] = (char *)"/system/bin/dnsmasq";
166         args[1] = (char *)"--keep-in-foreground";
167         args[2] = (char *)"--no-resolv";
168         args[3] = (char *)"--no-poll";
169         args[4] = (char *)"--dhcp-authoritative";
170         // TODO: pipe through metered status from ConnService
171         args[5] = (char *)"--dhcp-option-force=43,ANDROID_METERED";
172         args[6] = (char *)"--pid-file";
173         args[7] = (char *)"";
174 
175         int nextArg = TETHER_START_CONST_ARG;
176         for (int addrIndex=0; addrIndex < num_addrs;) {
177             char *start = strdup(inet_ntoa(addrs[addrIndex++]));
178             char *end = strdup(inet_ntoa(addrs[addrIndex++]));
179             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
180             free(start);
181             free(end);
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 
stopTethering()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 
isTetheringStarted()218 bool TetherController::isTetheringStarted() {
219     return (mDaemonPid == 0 ? false : true);
220 }
221 
222 #define MAX_CMD_SIZE 1024
223 
setDnsForwarders(unsigned netId,char ** servers,int numServers)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:0x%x", 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         struct in_addr a;
242 
243         if (!inet_aton(servers[i], &a)) {
244             ALOGE("Failed to parse DNS server '%s'", servers[i]);
245             mDnsForwarders->clear();
246             return -1;
247         }
248 
249         cmdLen += (strlen(servers[i]) + 1);
250         if (cmdLen + 1 >= MAX_CMD_SIZE) {
251             ALOGD("Too many DNS servers listed");
252             break;
253         }
254 
255         strcat(daemonCmd, ":");
256         strcat(daemonCmd, servers[i]);
257         mDnsForwarders->push_back(a);
258     }
259 
260     mDnsNetId = netId;
261     if (mDaemonFd != -1) {
262         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
263         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
264             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
265             mDnsForwarders->clear();
266             return -1;
267         }
268     }
269     return 0;
270 }
271 
getDnsNetId()272 unsigned TetherController::getDnsNetId() {
273     return mDnsNetId;
274 }
275 
getDnsForwarders()276 NetAddressCollection *TetherController::getDnsForwarders() {
277     return mDnsForwarders;
278 }
279 
applyDnsInterfaces()280 int TetherController::applyDnsInterfaces() {
281     char daemonCmd[MAX_CMD_SIZE];
282 
283     strcpy(daemonCmd, "update_ifaces");
284     int cmdLen = strlen(daemonCmd);
285     InterfaceCollection::iterator it;
286     bool haveInterfaces = false;
287 
288     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
289         cmdLen += (strlen(*it) + 1);
290         if (cmdLen + 1 >= MAX_CMD_SIZE) {
291             ALOGD("Too many DNS ifaces listed");
292             break;
293         }
294 
295         strcat(daemonCmd, ":");
296         strcat(daemonCmd, *it);
297         haveInterfaces = true;
298     }
299 
300     if ((mDaemonFd != -1) && haveInterfaces) {
301         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
302         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
303             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
304             return -1;
305         }
306     }
307     return 0;
308 }
309 
tetherInterface(const char * interface)310 int TetherController::tetherInterface(const char *interface) {
311     ALOGD("tetherInterface(%s)", interface);
312     if (!isIfaceName(interface)) {
313         errno = ENOENT;
314         return -1;
315     }
316     mInterfaces->push_back(strdup(interface));
317 
318     if (applyDnsInterfaces()) {
319         InterfaceCollection::iterator it;
320         for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
321             if (!strcmp(interface, *it)) {
322                 free(*it);
323                 mInterfaces->erase(it);
324                 break;
325             }
326         }
327         return -1;
328     } else {
329         return 0;
330     }
331 }
332 
untetherInterface(const char * interface)333 int TetherController::untetherInterface(const char *interface) {
334     InterfaceCollection::iterator it;
335 
336     ALOGD("untetherInterface(%s)", interface);
337 
338     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
339         if (!strcmp(interface, *it)) {
340             free(*it);
341             mInterfaces->erase(it);
342 
343             return applyDnsInterfaces();
344         }
345     }
346     errno = ENOENT;
347     return -1;
348 }
349 
getTetheredInterfaceList()350 InterfaceCollection *TetherController::getTetheredInterfaceList() {
351     return mInterfaces;
352 }
353