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 "InterfaceController.h" 39#include "NetworkController.h" 40#include "TetherController.h" 41 42namespace { 43 44const char BP_TOOLS_MODE[] = "bp-tools"; 45const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward"; 46const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding"; 47const char SEPARATOR[] = "|"; 48 49bool writeToFile(const char* filename, const char* value) { 50 int fd = open(filename, O_WRONLY | O_CLOEXEC); 51 if (fd < 0) { 52 ALOGE("Failed to open %s: %s", filename, strerror(errno)); 53 return false; 54 } 55 56 const ssize_t len = strlen(value); 57 if (write(fd, value, len) != len) { 58 ALOGE("Failed to write %s to %s: %s", value, filename, strerror(errno)); 59 close(fd); 60 return false; 61 } 62 close(fd); 63 return true; 64} 65 66bool configureForIPv6Router(const char *interface) { 67 return (InterfaceController::setEnableIPv6(interface, 0) == 0) 68 && (InterfaceController::setAcceptIPv6Ra(interface, 0) == 0) 69 && (InterfaceController::setAcceptIPv6Dad(interface, 0) == 0) 70 && (InterfaceController::setIPv6DadTransmits(interface, "0") == 0) 71 && (InterfaceController::setEnableIPv6(interface, 1) == 0); 72} 73 74void configureForIPv6Client(const char *interface) { 75 InterfaceController::setAcceptIPv6Ra(interface, 1); 76 InterfaceController::setAcceptIPv6Dad(interface, 1); 77 InterfaceController::setIPv6DadTransmits(interface, "1"); 78 InterfaceController::setEnableIPv6(interface, 0); 79} 80 81bool inBpToolsMode() { 82 // In BP tools mode, do not disable IP forwarding 83 char bootmode[PROPERTY_VALUE_MAX] = {0}; 84 property_get("ro.bootmode", bootmode, "unknown"); 85 return !strcmp(BP_TOOLS_MODE, bootmode); 86} 87 88} // namespace 89 90namespace android { 91namespace net { 92 93TetherController::TetherController() { 94 mDnsNetId = 0; 95 mDaemonFd = -1; 96 mDaemonPid = 0; 97 if (inBpToolsMode()) { 98 enableForwarding(BP_TOOLS_MODE); 99 } else { 100 setIpFwdEnabled(); 101 } 102} 103 104TetherController::~TetherController() { 105 mInterfaces.clear(); 106 mDnsForwarders.clear(); 107 mForwardingRequests.clear(); 108} 109 110bool TetherController::setIpFwdEnabled() { 111 bool success = true; 112 const char* value = mForwardingRequests.empty() ? "0" : "1"; 113 ALOGD("Setting IP forward enable = %s", value); 114 success &= writeToFile(IPV4_FORWARDING_PROC_FILE, value); 115 success &= writeToFile(IPV6_FORWARDING_PROC_FILE, value); 116 return success; 117} 118 119bool TetherController::enableForwarding(const char* requester) { 120 // Don't return an error if this requester already requested forwarding. Only return errors for 121 // things that the caller caller needs to care about, such as "couldn't write to the file to 122 // enable forwarding". 123 mForwardingRequests.insert(requester); 124 return setIpFwdEnabled(); 125} 126 127bool TetherController::disableForwarding(const char* requester) { 128 mForwardingRequests.erase(requester); 129 return setIpFwdEnabled(); 130} 131 132size_t TetherController::forwardingRequestCount() { 133 return mForwardingRequests.size(); 134} 135 136#define TETHER_START_CONST_ARG 10 137 138int TetherController::startTethering(int num_addrs, char **dhcp_ranges) { 139 if (mDaemonPid != 0) { 140 ALOGE("Tethering already started"); 141 errno = EBUSY; 142 return -1; 143 } 144 145 ALOGD("Starting tethering services"); 146 147 pid_t pid; 148 int pipefd[2]; 149 150 if (pipe(pipefd) < 0) { 151 ALOGE("pipe failed (%s)", strerror(errno)); 152 return -1; 153 } 154 155 /* 156 * TODO: Create a monitoring thread to handle and restart 157 * the daemon if it exits prematurely 158 */ 159 if ((pid = fork()) < 0) { 160 ALOGE("fork failed (%s)", strerror(errno)); 161 close(pipefd[0]); 162 close(pipefd[1]); 163 return -1; 164 } 165 166 if (!pid) { 167 close(pipefd[1]); 168 if (pipefd[0] != STDIN_FILENO) { 169 if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { 170 ALOGE("dup2 failed (%s)", strerror(errno)); 171 return -1; 172 } 173 close(pipefd[0]); 174 } 175 176 Fwmark fwmark; 177 fwmark.netId = NetworkController::LOCAL_NET_ID; 178 fwmark.explicitlySelected = true; 179 fwmark.protectedFromVpn = true; 180 fwmark.permission = PERMISSION_SYSTEM; 181 char markStr[UINT32_HEX_STRLEN]; 182 snprintf(markStr, sizeof(markStr), "0x%x", fwmark.intValue); 183 184 int num_processed_args = TETHER_START_CONST_ARG + (num_addrs/2) + 1; 185 char **args = (char **)malloc(sizeof(char *) * num_processed_args); 186 args[num_processed_args - 1] = NULL; 187 args[0] = (char *)"/system/bin/dnsmasq"; 188 args[1] = (char *)"--keep-in-foreground"; 189 args[2] = (char *)"--no-resolv"; 190 args[3] = (char *)"--no-poll"; 191 args[4] = (char *)"--dhcp-authoritative"; 192 // TODO: pipe through metered status from ConnService 193 args[5] = (char *)"--dhcp-option-force=43,ANDROID_METERED"; 194 args[6] = (char *)"--pid-file"; 195 args[7] = (char *)"--listen-mark"; 196 args[8] = (char *)markStr; 197 args[9] = (char *)""; 198 199 int nextArg = TETHER_START_CONST_ARG; 200 for (int addrIndex = 0; addrIndex < num_addrs; addrIndex += 2) { 201 asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", 202 dhcp_ranges[addrIndex], dhcp_ranges[addrIndex+1]); 203 } 204 205 if (execv(args[0], args)) { 206 ALOGE("execl failed (%s)", strerror(errno)); 207 } 208 ALOGE("Should never get here!"); 209 _exit(-1); 210 } else { 211 close(pipefd[0]); 212 mDaemonPid = pid; 213 mDaemonFd = pipefd[1]; 214 applyDnsInterfaces(); 215 ALOGD("Tethering services running"); 216 } 217 218 return 0; 219} 220 221int TetherController::stopTethering() { 222 223 if (mDaemonPid == 0) { 224 ALOGE("Tethering already stopped"); 225 return 0; 226 } 227 228 ALOGD("Stopping tethering services"); 229 230 kill(mDaemonPid, SIGTERM); 231 waitpid(mDaemonPid, NULL, 0); 232 mDaemonPid = 0; 233 close(mDaemonFd); 234 mDaemonFd = -1; 235 ALOGD("Tethering services stopped"); 236 return 0; 237} 238 239bool TetherController::isTetheringStarted() { 240 return (mDaemonPid == 0 ? false : true); 241} 242 243#define MAX_CMD_SIZE 1024 244 245int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) { 246 int i; 247 char daemonCmd[MAX_CMD_SIZE]; 248 249 Fwmark fwmark; 250 fwmark.netId = netId; 251 fwmark.explicitlySelected = true; 252 fwmark.protectedFromVpn = true; 253 fwmark.permission = PERMISSION_SYSTEM; 254 255 snprintf(daemonCmd, sizeof(daemonCmd), "update_dns%s0x%x", SEPARATOR, fwmark.intValue); 256 int cmdLen = strlen(daemonCmd); 257 258 mDnsForwarders.clear(); 259 for (i = 0; i < numServers; i++) { 260 ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]); 261 262 addrinfo *res, hints = { .ai_flags = AI_NUMERICHOST }; 263 int ret = getaddrinfo(servers[i], NULL, &hints, &res); 264 freeaddrinfo(res); 265 if (ret) { 266 ALOGE("Failed to parse DNS server '%s'", servers[i]); 267 mDnsForwarders.clear(); 268 errno = EINVAL; 269 return -1; 270 } 271 272 cmdLen += (strlen(servers[i]) + 1); 273 if (cmdLen + 1 >= MAX_CMD_SIZE) { 274 ALOGD("Too many DNS servers listed"); 275 break; 276 } 277 278 strcat(daemonCmd, SEPARATOR); 279 strcat(daemonCmd, servers[i]); 280 mDnsForwarders.push_back(servers[i]); 281 } 282 283 mDnsNetId = netId; 284 if (mDaemonFd != -1) { 285 ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd); 286 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) { 287 ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno)); 288 mDnsForwarders.clear(); 289 errno = EREMOTEIO; 290 return -1; 291 } 292 } 293 return 0; 294} 295 296unsigned TetherController::getDnsNetId() { 297 return mDnsNetId; 298} 299 300const std::list<std::string> &TetherController::getDnsForwarders() const { 301 return mDnsForwarders; 302} 303 304bool TetherController::applyDnsInterfaces() { 305 char daemonCmd[MAX_CMD_SIZE]; 306 307 strcpy(daemonCmd, "update_ifaces"); 308 int cmdLen = strlen(daemonCmd); 309 bool haveInterfaces = false; 310 311 for (const auto &ifname : mInterfaces) { 312 cmdLen += (ifname.size() + 1); 313 if (cmdLen + 1 >= MAX_CMD_SIZE) { 314 ALOGD("Too many DNS ifaces listed"); 315 break; 316 } 317 318 strcat(daemonCmd, SEPARATOR); 319 strcat(daemonCmd, ifname.c_str()); 320 haveInterfaces = true; 321 } 322 323 if ((mDaemonFd != -1) && haveInterfaces) { 324 ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd); 325 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) { 326 ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno)); 327 return false; 328 } 329 } 330 return true; 331} 332 333int TetherController::tetherInterface(const char *interface) { 334 ALOGD("tetherInterface(%s)", interface); 335 if (!isIfaceName(interface)) { 336 errno = ENOENT; 337 return -1; 338 } 339 340 if (!configureForIPv6Router(interface)) { 341 configureForIPv6Client(interface); 342 return -1; 343 } 344 mInterfaces.push_back(interface); 345 346 if (!applyDnsInterfaces()) { 347 mInterfaces.pop_back(); 348 configureForIPv6Client(interface); 349 return -1; 350 } else { 351 return 0; 352 } 353} 354 355int TetherController::untetherInterface(const char *interface) { 356 ALOGD("untetherInterface(%s)", interface); 357 358 for (auto it = mInterfaces.cbegin(); it != mInterfaces.cend(); ++it) { 359 if (!strcmp(interface, it->c_str())) { 360 mInterfaces.erase(it); 361 362 configureForIPv6Client(interface); 363 return applyDnsInterfaces() ? 0 : -1; 364 } 365 } 366 errno = ENOENT; 367 return -1; 368} 369 370const std::list<std::string> &TetherController::getTetheredInterfaceList() const { 371 return mInterfaces; 372} 373 374} // namespace net 375} // namespace android 376