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 39namespace { 40 41static const char BP_TOOLS_MODE[] = "bp-tools"; 42static const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward"; 43static const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding"; 44 45bool 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 62bool 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 71TetherController::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 84TetherController::~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 96bool 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 105bool 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 113bool TetherController::disableForwarding(const char* requester) { 114 mForwardingRequests.erase(requester); 115 return setIpFwdEnabled(); 116} 117 118size_t TetherController::forwardingRequestCount() { 119 return mForwardingRequests.size(); 120} 121 122#define TETHER_START_CONST_ARG 8 123 124int 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 200int 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 218bool TetherController::isTetheringStarted() { 219 return (mDaemonPid == 0 ? false : true); 220} 221 222#define MAX_CMD_SIZE 1024 223 224int 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 272unsigned TetherController::getDnsNetId() { 273 return mDnsNetId; 274} 275 276NetAddressCollection *TetherController::getDnsForwarders() { 277 return mDnsForwarders; 278} 279 280int 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 310int 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 333int 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 350InterfaceCollection *TetherController::getTetheredInterfaceList() { 351 return mInterfaces; 352} 353