TetherController.cpp revision ff2c0d8c13457e43f0d4bf06d3177271aac104c1
19d10b341a0ba46f108cb96e46691197d778cbc06San Mehat/* 29d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * Copyright (C) 2008 The Android Open Source Project 39d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * 49d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 59d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * you may not use this file except in compliance with the License. 69d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * You may obtain a copy of the License at 79d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * 89d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * http://www.apache.org/licenses/LICENSE-2.0 99d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * 109d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * Unless required by applicable law or agreed to in writing, software 119d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 129d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * See the License for the specific language governing permissions and 149d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * limitations under the License. 159d10b341a0ba46f108cb96e46691197d778cbc06San Mehat */ 169d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 179d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include <stdlib.h> 189d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include <errno.h> 1918737845d3c6a60edd6f75ac441a1b3fed6d66a7San Mehat#include <fcntl.h> 20ff2c0d8c13457e43f0d4bf06d3177271aac104c1Olivier Bailly#include <string.h> 2118737845d3c6a60edd6f75ac441a1b3fed6d66a7San Mehat 229d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include <sys/socket.h> 239d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include <sys/stat.h> 2418737845d3c6a60edd6f75ac441a1b3fed6d66a7San Mehat#include <sys/types.h> 2518737845d3c6a60edd6f75ac441a1b3fed6d66a7San Mehat#include <sys/wait.h> 2618737845d3c6a60edd6f75ac441a1b3fed6d66a7San Mehat 279d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include <netinet/in.h> 289d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include <arpa/inet.h> 299d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 309d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#define LOG_TAG "TetherController" 319d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include <cutils/log.h> 329d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 339d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 349d10b341a0ba46f108cb96e46691197d778cbc06San Mehat#include "TetherController.h" 359d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 369d10b341a0ba46f108cb96e46691197d778cbc06San MehatTetherController::TetherController() { 379d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mInterfaces = new InterfaceCollection(); 389d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDnsForwarders = new NetAddressCollection(); 399d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDaemonFd = -1; 409d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDaemonPid = 0; 419d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 429d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 439d10b341a0ba46f108cb96e46691197d778cbc06San MehatTetherController::~TetherController() { 449d10b341a0ba46f108cb96e46691197d778cbc06San Mehat InterfaceCollection::iterator it; 459d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 469d10b341a0ba46f108cb96e46691197d778cbc06San Mehat for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 479d10b341a0ba46f108cb96e46691197d778cbc06San Mehat free(*it); 489d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 499d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mInterfaces->clear(); 509d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 519d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDnsForwarders->clear(); 529d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 539d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 549d10b341a0ba46f108cb96e46691197d778cbc06San Mehatint TetherController::setIpFwdEnabled(bool enable) { 559d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 569d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGD("Setting IP forward enable = %d", enable); 579d10b341a0ba46f108cb96e46691197d778cbc06San Mehat int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY); 589d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (fd < 0) { 599d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Failed to open ip_forward (%s)", strerror(errno)); 609d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 619d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 629d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 639d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (write(fd, (enable ? "1" : "0"), 1) != 1) { 649d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Failed to write ip_forward (%s)", strerror(errno)); 6537dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt close(fd); 669d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 679d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 689d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(fd); 699d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 709d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 719d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 729d10b341a0ba46f108cb96e46691197d778cbc06San Mehatbool TetherController::getIpFwdEnabled() { 739d10b341a0ba46f108cb96e46691197d778cbc06San Mehat int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY); 749d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 759d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (fd < 0) { 769d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Failed to open ip_forward (%s)", strerror(errno)); 779d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return false; 789d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 799d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 809d10b341a0ba46f108cb96e46691197d778cbc06San Mehat char enabled; 819d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (read(fd, &enabled, 1) != 1) { 829d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Failed to read ip_forward (%s)", strerror(errno)); 8337dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt close(fd); 849d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 859d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 869d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 879d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(fd); 889d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return (enabled == '1' ? true : false); 899d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 909d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 913208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwaltint TetherController::startTethering(int num_addrs, struct in_addr* addrs) { 929d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (mDaemonPid != 0) { 939d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Tethering already started"); 949d10b341a0ba46f108cb96e46691197d778cbc06San Mehat errno = EBUSY; 959d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 969d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 979d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 989d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGD("Starting tethering services"); 999d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1009d10b341a0ba46f108cb96e46691197d778cbc06San Mehat pid_t pid; 1019d10b341a0ba46f108cb96e46691197d778cbc06San Mehat int pipefd[2]; 1029d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1039d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (pipe(pipefd) < 0) { 1049d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("pipe failed (%s)", strerror(errno)); 1059d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 1069d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 1079d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1089d10b341a0ba46f108cb96e46691197d778cbc06San Mehat /* 1099d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * TODO: Create a monitoring thread to handle and restart 1109d10b341a0ba46f108cb96e46691197d778cbc06San Mehat * the daemon if it exits prematurely 1119d10b341a0ba46f108cb96e46691197d778cbc06San Mehat */ 1129d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if ((pid = fork()) < 0) { 1139d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("fork failed (%s)", strerror(errno)); 1149d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(pipefd[0]); 1159d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(pipefd[1]); 1169d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 1179d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 1189d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1199d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (!pid) { 1209d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(pipefd[1]); 1219d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (pipefd[0] != STDIN_FILENO) { 1229d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { 1239d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("dup2 failed (%s)", strerror(errno)); 1249d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 1259d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 1269d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(pipefd[0]); 1279d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 1289d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1293208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt int num_processed_args = 4 + (num_addrs/2) + 1; // 1 null for termination 1303208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt char **args = (char **)malloc(sizeof(char *) * num_processed_args); 1313208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt args[num_processed_args - 1] = NULL; 1323208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt args[0] = (char *)"/system/bin/dnsmasq"; 1333208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt args[1] = (char *)"--no-daemon"; 1343208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt args[2] = (char *)"--no-resolv"; 1353208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt args[3] = (char *)"--no-poll"; 1363208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt 1373208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt int nextArg = 4; 1383208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt for (int addrIndex=0; addrIndex < num_addrs;) { 1393208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt char *start = strdup(inet_ntoa(addrs[addrIndex++])); 1403208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt char *end = strdup(inet_ntoa(addrs[addrIndex++])); 1413208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end); 1423208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt } 1439d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1443208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt if (execv(args[0], args)) { 1459d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("execl failed (%s)", strerror(errno)); 1469d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 1479d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Should never get here!"); 1483208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt free(args); 1499d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 1509d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } else { 1519d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(pipefd[0]); 1529d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDaemonPid = pid; 1539d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDaemonFd = pipefd[1]; 1549d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGD("Tethering services running"); 1559d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 1569d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1579d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 1589d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 1599d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1609d10b341a0ba46f108cb96e46691197d778cbc06San Mehatint TetherController::stopTethering() { 1619d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1629d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (mDaemonPid == 0) { 1639d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Tethering already stopped"); 1649d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 1659d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 1669d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1679d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGD("Stopping tethering services"); 1689d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1699d10b341a0ba46f108cb96e46691197d778cbc06San Mehat kill(mDaemonPid, SIGTERM); 17018737845d3c6a60edd6f75ac441a1b3fed6d66a7San Mehat waitpid(mDaemonPid, NULL, 0); 1719d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDaemonPid = 0; 1729d10b341a0ba46f108cb96e46691197d778cbc06San Mehat close(mDaemonFd); 1739d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDaemonFd = -1; 17418737845d3c6a60edd6f75ac441a1b3fed6d66a7San Mehat LOGD("Tethering services stopped"); 1759d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 1769d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 1779d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1789d10b341a0ba46f108cb96e46691197d778cbc06San Mehatbool TetherController::isTetheringStarted() { 1799d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return (mDaemonPid == 0 ? false : true); 1809d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 1819d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 182cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root#define MAX_CMD_SIZE 1024 183cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root 1849d10b341a0ba46f108cb96e46691197d778cbc06San Mehatint TetherController::setDnsForwarders(char **servers, int numServers) { 1859d10b341a0ba46f108cb96e46691197d778cbc06San Mehat int i; 186cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root char daemonCmd[MAX_CMD_SIZE]; 1879d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1889d10b341a0ba46f108cb96e46691197d778cbc06San Mehat strcpy(daemonCmd, "update_dns"); 189cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root int cmdLen = strlen(daemonCmd); 1909d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1919d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDnsForwarders->clear(); 1929d10b341a0ba46f108cb96e46691197d778cbc06San Mehat for (i = 0; i < numServers; i++) { 1939d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGD("setDnsForwarders(%d = '%s')", i, servers[i]); 1949d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1959d10b341a0ba46f108cb96e46691197d778cbc06San Mehat struct in_addr a; 1969d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 1979d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (!inet_aton(servers[i], &a)) { 1989d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Failed to parse DNS server '%s'", servers[i]); 1999d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDnsForwarders->clear(); 2009d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 2019d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 202cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root 203cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root cmdLen += strlen(servers[i]); 204cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root if (cmdLen + 2 >= MAX_CMD_SIZE) { 205cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root LOGD("Too many DNS servers listed"); 206cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root break; 207cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root } 208cf52faf90be32aab3d0c4736a95f26923227e475Kenny Root 2099d10b341a0ba46f108cb96e46691197d778cbc06San Mehat strcat(daemonCmd, ":"); 2109d10b341a0ba46f108cb96e46691197d778cbc06San Mehat strcat(daemonCmd, servers[i]); 2119d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDnsForwarders->push_back(a); 2129d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 2139d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 2149d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (mDaemonFd != -1) { 2159d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGD("Sending update msg to dnsmasq [%s]", daemonCmd); 2169d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) { 2179d10b341a0ba46f108cb96e46691197d778cbc06San Mehat LOGE("Failed to send update command to dnsmasq (%s)", strerror(errno)); 2189d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mDnsForwarders->clear(); 2199d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 2209d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 2219d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 2229d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 2239d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 2249d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 2259d10b341a0ba46f108cb96e46691197d778cbc06San MehatNetAddressCollection *TetherController::getDnsForwarders() { 2269d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return mDnsForwarders; 2279d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 2289d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 2299d10b341a0ba46f108cb96e46691197d778cbc06San Mehatint TetherController::tetherInterface(const char *interface) { 2309d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mInterfaces->push_back(strdup(interface)); 2319d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 2329d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 2339d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 2349d10b341a0ba46f108cb96e46691197d778cbc06San Mehatint TetherController::untetherInterface(const char *interface) { 2359d10b341a0ba46f108cb96e46691197d778cbc06San Mehat InterfaceCollection::iterator it; 2369d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 2379d10b341a0ba46f108cb96e46691197d778cbc06San Mehat for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) { 2389d10b341a0ba46f108cb96e46691197d778cbc06San Mehat if (!strcmp(interface, *it)) { 2399d10b341a0ba46f108cb96e46691197d778cbc06San Mehat free(*it); 2409d10b341a0ba46f108cb96e46691197d778cbc06San Mehat mInterfaces->erase(it); 2419d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return 0; 2429d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 2439d10b341a0ba46f108cb96e46691197d778cbc06San Mehat } 2449d10b341a0ba46f108cb96e46691197d778cbc06San Mehat errno = ENOENT; 2459d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return -1; 2469d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 2479d10b341a0ba46f108cb96e46691197d778cbc06San Mehat 2489d10b341a0ba46f108cb96e46691197d778cbc06San MehatInterfaceCollection *TetherController::getTetheredInterfaceList() { 2499d10b341a0ba46f108cb96e46691197d778cbc06San Mehat return mInterfaces; 2509d10b341a0ba46f108cb96e46691197d778cbc06San Mehat} 251