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