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     ALOGD("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         ALOGE("Failed to open ip_forward (%s)", strerror(errno));
     68         return -1;
     69     }
     70 
     71     if (write(fd, (enable ? "1" : "0"), 1) != 1) {
     72         ALOGE("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         ALOGE("Failed to open ip_forward (%s)", strerror(errno));
     85         return false;
     86     }
     87 
     88     char enabled;
     89     if (read(fd, &enabled, 1) != 1) {
     90         ALOGE("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         ALOGE("Tethering already started");
    102         errno = EBUSY;
    103         return -1;
    104     }
    105 
    106     ALOGD("Starting tethering services");
    107 
    108     pid_t pid;
    109     int pipefd[2];
    110 
    111     if (pipe(pipefd) < 0) {
    112         ALOGE("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         ALOGE("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                 ALOGE("dup2 failed (%s)", strerror(errno));
    132                 return -1;
    133             }
    134             close(pipefd[0]);
    135         }
    136 
    137         int num_processed_args = 5 + (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         // TODO: pipe through metered status from ConnService
    145         args[4] = (char *)"--dhcp-option-force=43,ANDROID_METERED";
    146 
    147         int nextArg = 5;
    148         for (int addrIndex=0; addrIndex < num_addrs;) {
    149             char *start = strdup(inet_ntoa(addrs[addrIndex++]));
    150             char *end = strdup(inet_ntoa(addrs[addrIndex++]));
    151             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
    152         }
    153 
    154         if (execv(args[0], args)) {
    155             ALOGE("execl failed (%s)", strerror(errno));
    156         }
    157         ALOGE("Should never get here!");
    158         free(args);
    159         return 0;
    160     } else {
    161         close(pipefd[0]);
    162         mDaemonPid = pid;
    163         mDaemonFd = pipefd[1];
    164         ALOGD("Tethering services running");
    165     }
    166 
    167     return 0;
    168 }
    169 
    170 int TetherController::stopTethering() {
    171 
    172     if (mDaemonPid == 0) {
    173         ALOGE("Tethering already stopped");
    174         return 0;
    175     }
    176 
    177     ALOGD("Stopping tethering services");
    178 
    179     kill(mDaemonPid, SIGTERM);
    180     waitpid(mDaemonPid, NULL, 0);
    181     mDaemonPid = 0;
    182     close(mDaemonFd);
    183     mDaemonFd = -1;
    184     ALOGD("Tethering services stopped");
    185     return 0;
    186 }
    187 
    188 bool TetherController::isTetheringStarted() {
    189     return (mDaemonPid == 0 ? false : true);
    190 }
    191 
    192 #define MAX_CMD_SIZE 1024
    193 
    194 int TetherController::setDnsForwarders(char **servers, int numServers) {
    195     int i;
    196     char daemonCmd[MAX_CMD_SIZE];
    197 
    198     strcpy(daemonCmd, "update_dns");
    199     int cmdLen = strlen(daemonCmd);
    200 
    201     mDnsForwarders->clear();
    202     for (i = 0; i < numServers; i++) {
    203         ALOGD("setDnsForwarders(%d = '%s')", i, servers[i]);
    204 
    205         struct in_addr a;
    206 
    207         if (!inet_aton(servers[i], &a)) {
    208             ALOGE("Failed to parse DNS server '%s'", servers[i]);
    209             mDnsForwarders->clear();
    210             return -1;
    211         }
    212 
    213         cmdLen += strlen(servers[i]);
    214         if (cmdLen + 2 >= MAX_CMD_SIZE) {
    215             ALOGD("Too many DNS servers listed");
    216             break;
    217         }
    218 
    219         strcat(daemonCmd, ":");
    220         strcat(daemonCmd, servers[i]);
    221         mDnsForwarders->push_back(a);
    222     }
    223 
    224     if (mDaemonFd != -1) {
    225         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
    226         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
    227             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
    228             mDnsForwarders->clear();
    229             return -1;
    230         }
    231     }
    232     return 0;
    233 }
    234 
    235 NetAddressCollection *TetherController::getDnsForwarders() {
    236     return mDnsForwarders;
    237 }
    238 
    239 int TetherController::tetherInterface(const char *interface) {
    240     mInterfaces->push_back(strdup(interface));
    241     return 0;
    242 }
    243 
    244 int TetherController::untetherInterface(const char *interface) {
    245     InterfaceCollection::iterator it;
    246 
    247     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
    248         if (!strcmp(interface, *it)) {
    249             free(*it);
    250             mInterfaces->erase(it);
    251             return 0;
    252         }
    253     }
    254     errno = ENOENT;
    255     return -1;
    256 }
    257 
    258 InterfaceCollection *TetherController::getTetheredInterfaceList() {
    259     return mInterfaces;
    260 }
    261