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 } 355