TetherController.cpp revision ff2c0d8c13457e43f0d4bf06d3177271aac104c1
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 33 34#include "TetherController.h" 35 36TetherController::TetherController() { 37 mInterfaces = new InterfaceCollection(); 38 mDnsForwarders = new NetAddressCollection(); 39 mDaemonFd = -1; 40 mDaemonPid = 0; 41} 42 43TetherController::~TetherController() { 44 InterfaceCollection::iterator it; 45 46 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 47 free(*it); 48 } 49 mInterfaces->clear(); 50 51 mDnsForwarders->clear(); 52} 53 54int TetherController::setIpFwdEnabled(bool enable) { 55 56 LOGD("Setting IP forward enable = %d", enable); 57 int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY); 58 if (fd < 0) { 59 LOGE("Failed to open ip_forward (%s)", strerror(errno)); 60 return -1; 61 } 62 63 if (write(fd, (enable ? "1" : "0"), 1) != 1) { 64 LOGE("Failed to write ip_forward (%s)", strerror(errno)); 65 close(fd); 66 return -1; 67 } 68 close(fd); 69 return 0; 70} 71 72bool TetherController::getIpFwdEnabled() { 73 int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY); 74 75 if (fd < 0) { 76 LOGE("Failed to open ip_forward (%s)", strerror(errno)); 77 return false; 78 } 79 80 char enabled; 81 if (read(fd, &enabled, 1) != 1) { 82 LOGE("Failed to read ip_forward (%s)", strerror(errno)); 83 close(fd); 84 return -1; 85 } 86 87 close(fd); 88 return (enabled == '1' ? true : false); 89} 90 91int TetherController::startTethering(int num_addrs, struct in_addr* addrs) { 92 if (mDaemonPid != 0) { 93 LOGE("Tethering already started"); 94 errno = EBUSY; 95 return -1; 96 } 97 98 LOGD("Starting tethering services"); 99 100 pid_t pid; 101 int pipefd[2]; 102 103 if (pipe(pipefd) < 0) { 104 LOGE("pipe failed (%s)", strerror(errno)); 105 return -1; 106 } 107 108 /* 109 * TODO: Create a monitoring thread to handle and restart 110 * the daemon if it exits prematurely 111 */ 112 if ((pid = fork()) < 0) { 113 LOGE("fork failed (%s)", strerror(errno)); 114 close(pipefd[0]); 115 close(pipefd[1]); 116 return -1; 117 } 118 119 if (!pid) { 120 close(pipefd[1]); 121 if (pipefd[0] != STDIN_FILENO) { 122 if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { 123 LOGE("dup2 failed (%s)", strerror(errno)); 124 return -1; 125 } 126 close(pipefd[0]); 127 } 128 129 int num_processed_args = 4 + (num_addrs/2) + 1; // 1 null for termination 130 char **args = (char **)malloc(sizeof(char *) * num_processed_args); 131 args[num_processed_args - 1] = NULL; 132 args[0] = (char *)"/system/bin/dnsmasq"; 133 args[1] = (char *)"--no-daemon"; 134 args[2] = (char *)"--no-resolv"; 135 args[3] = (char *)"--no-poll"; 136 137 int nextArg = 4; 138 for (int addrIndex=0; addrIndex < num_addrs;) { 139 char *start = strdup(inet_ntoa(addrs[addrIndex++])); 140 char *end = strdup(inet_ntoa(addrs[addrIndex++])); 141 asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end); 142 } 143 144 if (execv(args[0], args)) { 145 LOGE("execl failed (%s)", strerror(errno)); 146 } 147 LOGE("Should never get here!"); 148 free(args); 149 return 0; 150 } else { 151 close(pipefd[0]); 152 mDaemonPid = pid; 153 mDaemonFd = pipefd[1]; 154 LOGD("Tethering services running"); 155 } 156 157 return 0; 158} 159 160int TetherController::stopTethering() { 161 162 if (mDaemonPid == 0) { 163 LOGE("Tethering already stopped"); 164 return 0; 165 } 166 167 LOGD("Stopping tethering services"); 168 169 kill(mDaemonPid, SIGTERM); 170 waitpid(mDaemonPid, NULL, 0); 171 mDaemonPid = 0; 172 close(mDaemonFd); 173 mDaemonFd = -1; 174 LOGD("Tethering services stopped"); 175 return 0; 176} 177 178bool TetherController::isTetheringStarted() { 179 return (mDaemonPid == 0 ? false : true); 180} 181 182#define MAX_CMD_SIZE 1024 183 184int TetherController::setDnsForwarders(char **servers, int numServers) { 185 int i; 186 char daemonCmd[MAX_CMD_SIZE]; 187 188 strcpy(daemonCmd, "update_dns"); 189 int cmdLen = strlen(daemonCmd); 190 191 mDnsForwarders->clear(); 192 for (i = 0; i < numServers; i++) { 193 LOGD("setDnsForwarders(%d = '%s')", i, servers[i]); 194 195 struct in_addr a; 196 197 if (!inet_aton(servers[i], &a)) { 198 LOGE("Failed to parse DNS server '%s'", servers[i]); 199 mDnsForwarders->clear(); 200 return -1; 201 } 202 203 cmdLen += strlen(servers[i]); 204 if (cmdLen + 2 >= MAX_CMD_SIZE) { 205 LOGD("Too many DNS servers listed"); 206 break; 207 } 208 209 strcat(daemonCmd, ":"); 210 strcat(daemonCmd, servers[i]); 211 mDnsForwarders->push_back(a); 212 } 213 214 if (mDaemonFd != -1) { 215 LOGD("Sending update msg to dnsmasq [%s]", daemonCmd); 216 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) { 217 LOGE("Failed to send update command to dnsmasq (%s)", strerror(errno)); 218 mDnsForwarders->clear(); 219 return -1; 220 } 221 } 222 return 0; 223} 224 225NetAddressCollection *TetherController::getDnsForwarders() { 226 return mDnsForwarders; 227} 228 229int TetherController::tetherInterface(const char *interface) { 230 mInterfaces->push_back(strdup(interface)); 231 return 0; 232} 233 234int TetherController::untetherInterface(const char *interface) { 235 InterfaceCollection::iterator it; 236 237 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 238 if (!strcmp(interface, *it)) { 239 free(*it); 240 mInterfaces->erase(it); 241 return 0; 242 } 243 } 244 errno = ENOENT; 245 return -1; 246} 247 248InterfaceCollection *TetherController::getTetheredInterfaceList() { 249 return mInterfaces; 250} 251