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 = 7 + (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 *)"--keep-in-foreground";
    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         args[5] = (char *)"--pid-file";
    147         args[6] = (char *)"";
    148 
    149         int nextArg = 7;
    150         for (int addrIndex=0; addrIndex < num_addrs;) {
    151             char *start = strdup(inet_ntoa(addrs[addrIndex++]));
    152             char *end = strdup(inet_ntoa(addrs[addrIndex++]));
    153             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
    154         }
    155 
    156         if (execv(args[0], args)) {
    157             ALOGE("execl failed (%s)", strerror(errno));
    158         }
    159         ALOGE("Should never get here!");
    160         _exit(-1);
    161     } else {
    162         close(pipefd[0]);
    163         mDaemonPid = pid;
    164         mDaemonFd = pipefd[1];
    165         applyDnsInterfaces();
    166         ALOGD("Tethering services running");
    167     }
    168 
    169     return 0;
    170 }
    171 
    172 int TetherController::stopTethering() {
    173 
    174     if (mDaemonPid == 0) {
    175         ALOGE("Tethering already stopped");
    176         return 0;
    177     }
    178 
    179     ALOGD("Stopping tethering services");
    180 
    181     kill(mDaemonPid, SIGTERM);
    182     waitpid(mDaemonPid, NULL, 0);
    183     mDaemonPid = 0;
    184     close(mDaemonFd);
    185     mDaemonFd = -1;
    186     ALOGD("Tethering services stopped");
    187     return 0;
    188 }
    189 
    190 bool TetherController::isTetheringStarted() {
    191     return (mDaemonPid == 0 ? false : true);
    192 }
    193 
    194 #define MAX_CMD_SIZE 1024
    195 
    196 int TetherController::setDnsForwarders(char **servers, int numServers) {
    197     int i;
    198     char daemonCmd[MAX_CMD_SIZE];
    199 
    200     strcpy(daemonCmd, "update_dns");
    201     int cmdLen = strlen(daemonCmd);
    202 
    203     mDnsForwarders->clear();
    204     for (i = 0; i < numServers; i++) {
    205         ALOGD("setDnsForwarders(%d = '%s')", i, servers[i]);
    206 
    207         struct in_addr a;
    208 
    209         if (!inet_aton(servers[i], &a)) {
    210             ALOGE("Failed to parse DNS server '%s'", servers[i]);
    211             mDnsForwarders->clear();
    212             return -1;
    213         }
    214 
    215         cmdLen += (strlen(servers[i]) + 1);
    216         if (cmdLen + 1 >= MAX_CMD_SIZE) {
    217             ALOGD("Too many DNS servers listed");
    218             break;
    219         }
    220 
    221         strcat(daemonCmd, ":");
    222         strcat(daemonCmd, servers[i]);
    223         mDnsForwarders->push_back(a);
    224     }
    225 
    226     if (mDaemonFd != -1) {
    227         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
    228         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
    229             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
    230             mDnsForwarders->clear();
    231             return -1;
    232         }
    233     }
    234     return 0;
    235 }
    236 
    237 NetAddressCollection *TetherController::getDnsForwarders() {
    238     return mDnsForwarders;
    239 }
    240 
    241 int TetherController::applyDnsInterfaces() {
    242     int i;
    243     char daemonCmd[MAX_CMD_SIZE];
    244 
    245     strcpy(daemonCmd, "update_ifaces");
    246     int cmdLen = strlen(daemonCmd);
    247     InterfaceCollection::iterator it;
    248     bool haveInterfaces = false;
    249 
    250     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
    251         cmdLen += (strlen(*it) + 1);
    252         if (cmdLen + 1 >= MAX_CMD_SIZE) {
    253             ALOGD("Too many DNS ifaces listed");
    254             break;
    255         }
    256 
    257         strcat(daemonCmd, ":");
    258         strcat(daemonCmd, *it);
    259         haveInterfaces = true;
    260     }
    261 
    262     if ((mDaemonFd != -1) && haveInterfaces) {
    263         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
    264         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
    265             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
    266             return -1;
    267         }
    268     }
    269     return 0;
    270 }
    271 
    272 int TetherController::tetherInterface(const char *interface) {
    273     ALOGD("tetherInterface(%s)", interface);
    274     mInterfaces->push_back(strdup(interface));
    275 
    276     if (applyDnsInterfaces()) {
    277         InterfaceCollection::iterator it;
    278         for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
    279             if (!strcmp(interface, *it)) {
    280                 free(*it);
    281                 mInterfaces->erase(it);
    282                 break;
    283             }
    284         }
    285         return -1;
    286     } else {
    287         return 0;
    288     }
    289 }
    290 
    291 int TetherController::untetherInterface(const char *interface) {
    292     InterfaceCollection::iterator it;
    293 
    294     ALOGD("untetherInterface(%s)", interface);
    295 
    296     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
    297         if (!strcmp(interface, *it)) {
    298             free(*it);
    299             mInterfaces->erase(it);
    300 
    301             return applyDnsInterfaces();
    302         }
    303     }
    304     errno = ENOENT;
    305     return -1;
    306 }
    307 
    308 InterfaceCollection *TetherController::getTetheredInterfaceList() {
    309     return mInterfaces;
    310 }
    311