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