TetherController.cpp revision 18737845d3c6a60edd6f75ac441a1b3fed6d66a7
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(struct in_addr dhcpStart, struct in_addr dhcpEnd) { 90 91 if (mDaemonPid != 0) { 92 LOGE("Tethering already started"); 93 errno = EBUSY; 94 return -1; 95 } 96 97 LOGD("Starting tethering services"); 98 99 pid_t pid; 100 int pipefd[2]; 101 102 if (pipe(pipefd) < 0) { 103 LOGE("pipe failed (%s)", strerror(errno)); 104 return -1; 105 } 106 107 /* 108 * TODO: Create a monitoring thread to handle and restart 109 * the daemon if it exits prematurely 110 */ 111 if ((pid = fork()) < 0) { 112 LOGE("fork failed (%s)", strerror(errno)); 113 close(pipefd[0]); 114 close(pipefd[1]); 115 return -1; 116 } 117 118 if (!pid) { 119 close(pipefd[1]); 120 if (pipefd[0] != STDIN_FILENO) { 121 if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { 122 LOGE("dup2 failed (%s)", strerror(errno)); 123 return -1; 124 } 125 close(pipefd[0]); 126 } 127 char *start = strdup(inet_ntoa(dhcpStart)); 128 char *end = strdup(inet_ntoa(dhcpEnd)); 129 char *range; 130 131 asprintf(&range, "--dhcp-range=%s,%s,1h", start, end); 132 133 if (execl("/system/bin/dnsmasq", "/system/bin/dnsmasq", "--no-daemon", "--no-resolv", 134 "--no-poll", "--no-hosts", range, (char *) NULL)) { 135 LOGE("execl failed (%s)", strerror(errno)); 136 } 137 LOGE("Should never get here!"); 138 return 0; 139 } else { 140 close(pipefd[0]); 141 mDaemonPid = pid; 142 mDaemonFd = pipefd[1]; 143 LOGD("Tethering services running"); 144 } 145 146 return 0; 147} 148 149int TetherController::stopTethering() { 150 151 if (mDaemonPid == 0) { 152 LOGE("Tethering already stopped"); 153 return 0; 154 } 155 156 LOGD("Stopping tethering services"); 157 158 kill(mDaemonPid, SIGTERM); 159 waitpid(mDaemonPid, NULL, 0); 160 mDaemonPid = 0; 161 close(mDaemonFd); 162 mDaemonFd = -1; 163 LOGD("Tethering services stopped"); 164 return 0; 165} 166 167bool TetherController::isTetheringStarted() { 168 return (mDaemonPid == 0 ? false : true); 169} 170 171int TetherController::setDnsForwarders(char **servers, int numServers) { 172 int i; 173 char daemonCmd[1024]; 174 175 strcpy(daemonCmd, "update_dns"); 176 177 mDnsForwarders->clear(); 178 for (i = 0; i < numServers; i++) { 179 LOGD("setDnsForwarders(%d = '%s')", i, servers[i]); 180 181 struct in_addr a; 182 183 if (!inet_aton(servers[i], &a)) { 184 LOGE("Failed to parse DNS server '%s'", servers[i]); 185 mDnsForwarders->clear(); 186 return -1; 187 } 188 strcat(daemonCmd, ":"); 189 strcat(daemonCmd, servers[i]); 190 mDnsForwarders->push_back(a); 191 } 192 193 if (mDaemonFd != -1) { 194 LOGD("Sending update msg to dnsmasq [%s]", daemonCmd); 195 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) { 196 LOGE("Failed to send update command to dnsmasq (%s)", strerror(errno)); 197 mDnsForwarders->clear(); 198 return -1; 199 } 200 } 201 return 0; 202} 203 204NetAddressCollection *TetherController::getDnsForwarders() { 205 return mDnsForwarders; 206} 207 208int TetherController::tetherInterface(const char *interface) { 209 mInterfaces->push_back(strdup(interface)); 210 return 0; 211} 212 213int TetherController::untetherInterface(const char *interface) { 214 InterfaceCollection::iterator it; 215 216 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 217 if (!strcmp(interface, *it)) { 218 free(*it); 219 mInterfaces->erase(it); 220 return 0; 221 } 222 } 223 errno = ENOENT; 224 return -1; 225} 226 227InterfaceCollection *TetherController::getTetheredInterfaceList() { 228 return mInterfaces; 229} 230 231