TetherController.cpp revision cf52faf90be32aab3d0c4736a95f26923227e475
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 171#define MAX_CMD_SIZE 1024 172 173int TetherController::setDnsForwarders(char **servers, int numServers) { 174 int i; 175 char daemonCmd[MAX_CMD_SIZE]; 176 177 strcpy(daemonCmd, "update_dns"); 178 int cmdLen = strlen(daemonCmd); 179 180 mDnsForwarders->clear(); 181 for (i = 0; i < numServers; i++) { 182 LOGD("setDnsForwarders(%d = '%s')", i, servers[i]); 183 184 struct in_addr a; 185 186 if (!inet_aton(servers[i], &a)) { 187 LOGE("Failed to parse DNS server '%s'", servers[i]); 188 mDnsForwarders->clear(); 189 return -1; 190 } 191 192 cmdLen += strlen(servers[i]); 193 if (cmdLen + 2 >= MAX_CMD_SIZE) { 194 LOGD("Too many DNS servers listed"); 195 break; 196 } 197 198 strcat(daemonCmd, ":"); 199 strcat(daemonCmd, servers[i]); 200 mDnsForwarders->push_back(a); 201 } 202 203 if (mDaemonFd != -1) { 204 LOGD("Sending update msg to dnsmasq [%s]", daemonCmd); 205 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) { 206 LOGE("Failed to send update command to dnsmasq (%s)", strerror(errno)); 207 mDnsForwarders->clear(); 208 return -1; 209 } 210 } 211 return 0; 212} 213 214NetAddressCollection *TetherController::getDnsForwarders() { 215 return mDnsForwarders; 216} 217 218int TetherController::tetherInterface(const char *interface) { 219 mInterfaces->push_back(strdup(interface)); 220 return 0; 221} 222 223int TetherController::untetherInterface(const char *interface) { 224 InterfaceCollection::iterator it; 225 226 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 227 if (!strcmp(interface, *it)) { 228 free(*it); 229 mInterfaces->erase(it); 230 return 0; 231 } 232 } 233 errno = ENOENT; 234 return -1; 235} 236 237InterfaceCollection *TetherController::getTetheredInterfaceList() { 238 return mInterfaces; 239} 240 241