TetherController.cpp revision 9589a4c6e0b6a5ec60c65b248e7deff2805749b2
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 "TetherController.h" 35 36TetherController::TetherController() { 37 mInterfaces = new InterfaceCollection(); 38 mDnsForwarders = new NetAddressCollection(); 39 mDaemonFd = -1; 40 mDaemonPid = 0; 41 mDhcpcdPid = 0; 42} 43 44TetherController::~TetherController() { 45 InterfaceCollection::iterator it; 46 47 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 48 free(*it); 49 } 50 mInterfaces->clear(); 51 52 mDnsForwarders->clear(); 53} 54 55int TetherController::setIpFwdEnabled(bool enable) { 56 57 ALOGD("Setting IP forward enable = %d", enable); 58 59 // In BP tools mode, do not disable IP forwarding 60 char bootmode[PROPERTY_VALUE_MAX] = {0}; 61 property_get("ro.bootmode", bootmode, "unknown"); 62 if ((enable == false) && (0 == strcmp("bp-tools", bootmode))) { 63 return 0; 64 } 65 66 int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY); 67 if (fd < 0) { 68 ALOGE("Failed to open ip_forward (%s)", strerror(errno)); 69 return -1; 70 } 71 72 if (write(fd, (enable ? "1" : "0"), 1) != 1) { 73 ALOGE("Failed to write ip_forward (%s)", strerror(errno)); 74 close(fd); 75 return -1; 76 } 77 close(fd); 78 return 0; 79} 80 81bool TetherController::getIpFwdEnabled() { 82 int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY); 83 84 if (fd < 0) { 85 ALOGE("Failed to open ip_forward (%s)", strerror(errno)); 86 return false; 87 } 88 89 char enabled; 90 if (read(fd, &enabled, 1) != 1) { 91 ALOGE("Failed to read ip_forward (%s)", strerror(errno)); 92 close(fd); 93 return -1; 94 } 95 96 close(fd); 97 return (enabled == '1' ? true : false); 98} 99 100int TetherController::startTethering(int num_addrs, struct in_addr* addrs) { 101 if (mDaemonPid != 0) { 102 ALOGE("Tethering already started"); 103 errno = EBUSY; 104 return -1; 105 } 106 107 ALOGD("Starting tethering services"); 108 109 pid_t pid; 110 int pipefd[2]; 111 112 if (pipe(pipefd) < 0) { 113 ALOGE("pipe failed (%s)", strerror(errno)); 114 return -1; 115 } 116 117 /* 118 * TODO: Create a monitoring thread to handle and restart 119 * the daemon if it exits prematurely 120 */ 121 if ((pid = fork()) < 0) { 122 ALOGE("fork failed (%s)", strerror(errno)); 123 close(pipefd[0]); 124 close(pipefd[1]); 125 return -1; 126 } 127 128 if (!pid) { 129 close(pipefd[1]); 130 if (pipefd[0] != STDIN_FILENO) { 131 if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { 132 ALOGE("dup2 failed (%s)", strerror(errno)); 133 return -1; 134 } 135 close(pipefd[0]); 136 } 137 138 int num_processed_args = 7 + (num_addrs/2) + 1; // 1 null for termination 139 char **args = (char **)malloc(sizeof(char *) * num_processed_args); 140 args[num_processed_args - 1] = NULL; 141 args[0] = (char *)"/system/bin/dnsmasq"; 142 args[1] = (char *)"--keep-in-foreground"; 143 args[2] = (char *)"--no-resolv"; 144 args[3] = (char *)"--no-poll"; 145 // TODO: pipe through metered status from ConnService 146 args[4] = (char *)"--dhcp-option-force=43,ANDROID_METERED"; 147 args[5] = (char *)"--pid-file"; 148 args[6] = (char *)""; 149 150 int nextArg = 7; 151 for (int addrIndex=0; addrIndex < num_addrs;) { 152 char *start = strdup(inet_ntoa(addrs[addrIndex++])); 153 char *end = strdup(inet_ntoa(addrs[addrIndex++])); 154 asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end); 155 } 156 157 if (execv(args[0], args)) { 158 ALOGE("execl failed (%s)", strerror(errno)); 159 } 160 ALOGE("Should never get here!"); 161 free(args); 162 return 0; 163 } else { 164 close(pipefd[0]); 165 mDaemonPid = pid; 166 mDaemonFd = pipefd[1]; 167 ALOGD("Tethering services running"); 168 } 169 170 return 0; 171} 172 173int TetherController::stopTethering() { 174 175 if (mDaemonPid == 0) { 176 ALOGE("Tethering already stopped"); 177 return 0; 178 } 179 180 ALOGD("Stopping tethering services"); 181 182 kill(mDaemonPid, SIGTERM); 183 waitpid(mDaemonPid, NULL, 0); 184 mDaemonPid = 0; 185 close(mDaemonFd); 186 mDaemonFd = -1; 187 ALOGD("Tethering services stopped"); 188 return 0; 189} 190int TetherController::startReverseTethering(const char* iface) { 191 if (mDhcpcdPid != 0) { 192 LOGE("Reverse tethering already started"); 193 errno = EBUSY; 194 return -1; 195 } 196 197 LOGD("TetherController::startReverseTethering, Starting reverse tethering"); 198 199 /* 200 * TODO: Create a monitoring thread to handle and restart 201 * the daemon if it exits prematurely 202 */ 203 //cleanup the dhcp result 204 char dhcp_result_name[64]; 205 snprintf(dhcp_result_name, sizeof(dhcp_result_name) - 1, "dhcp.%s.result", iface); 206 property_set(dhcp_result_name, ""); 207 208 pid_t pid; 209 if ((pid = fork()) < 0) { 210 LOGE("fork failed (%s)", strerror(errno)); 211 return -1; 212 } 213 214 if (!pid) { 215 216 char *args[10]; 217 int argc = 0; 218 args[argc++] = "/system/bin/dhcpcd"; 219 char host_name[128]; 220 if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0')) 221 { 222 args[argc++] = "-h"; 223 args[argc++] = host_name; 224 } 225 args[argc++] = (char*)iface; 226 args[argc] = NULL; 227 if (execv(args[0], args)) { 228 LOGE("startReverseTethering, execv failed (%s)", strerror(errno)); 229 } 230 LOGE("startReverseTethering, Should never get here!"); 231 return 0; 232 } else { 233 mDhcpcdPid = pid; 234 LOGD("Reverse Tethering running, pid:%d", pid); 235 } 236 return 0; 237} 238int TetherController::stopReverseTethering() { 239 240 if (mDhcpcdPid == 0) { 241 LOGE("Tethering already stopped"); 242 return 0; 243 } 244 245 LOGD("Stopping tethering services"); 246 247 kill(mDhcpcdPid, SIGTERM); 248 waitpid(mDhcpcdPid, NULL, 0); 249 mDhcpcdPid = 0; 250 LOGD("Tethering services stopped"); 251 return 0; 252} 253bool TetherController::isTetheringStarted() { 254 return (mDaemonPid == 0 ? false : true); 255} 256 257#define MAX_CMD_SIZE 1024 258 259int TetherController::setDnsForwarders(char **servers, int numServers) { 260 int i; 261 char daemonCmd[MAX_CMD_SIZE]; 262 263 strcpy(daemonCmd, "update_dns"); 264 int cmdLen = strlen(daemonCmd); 265 266 mDnsForwarders->clear(); 267 for (i = 0; i < numServers; i++) { 268 ALOGD("setDnsForwarders(%d = '%s')", i, servers[i]); 269 270 struct in_addr a; 271 272 if (!inet_aton(servers[i], &a)) { 273 ALOGE("Failed to parse DNS server '%s'", servers[i]); 274 mDnsForwarders->clear(); 275 return -1; 276 } 277 278 cmdLen += strlen(servers[i]); 279 if (cmdLen + 2 >= MAX_CMD_SIZE) { 280 ALOGD("Too many DNS servers listed"); 281 break; 282 } 283 284 strcat(daemonCmd, ":"); 285 strcat(daemonCmd, servers[i]); 286 mDnsForwarders->push_back(a); 287 } 288 289 if (mDaemonFd != -1) { 290 ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd); 291 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) { 292 ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno)); 293 mDnsForwarders->clear(); 294 return -1; 295 } 296 } 297 return 0; 298} 299 300NetAddressCollection *TetherController::getDnsForwarders() { 301 return mDnsForwarders; 302} 303 304int TetherController::tetherInterface(const char *interface) { 305 mInterfaces->push_back(strdup(interface)); 306 return 0; 307} 308 309int TetherController::untetherInterface(const char *interface) { 310 InterfaceCollection::iterator it; 311 312 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 313 if (!strcmp(interface, *it)) { 314 free(*it); 315 mInterfaces->erase(it); 316 return 0; 317 } 318 } 319 errno = ENOENT; 320 return -1; 321} 322 323InterfaceCollection *TetherController::getTetheredInterfaceList() { 324 return mInterfaces; 325} 326