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