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     mDhcpcdPid = 0;
     42 }
     43 
     44 TetherController::~TetherController() {
     45     InterfaceCollection::iterator it;
     46 
     47     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
     48         free(*it);
     49     }
     50     mInterfaces->clear();
     51 
     52     mDnsForwarders->clear();
     53 }
     54 
     55 int TetherController::setIpFwdEnabled(bool enable) {
     56 
     57     ALOGD("Setting IP forward enable = %d", enable);
     58 
     59     // In BP tools mode, do not disable IP forwarding
     60     char bootmode[PROPERTY_VALUE_MAX] = {0};
     61     property_get("ro.bootmode", bootmode, "unknown");
     62     if ((enable == false) && (0 == strcmp("bp-tools", bootmode))) {
     63         return 0;
     64     }
     65 
     66     int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY);
     67     if (fd < 0) {
     68         ALOGE("Failed to open ip_forward (%s)", strerror(errno));
     69         return -1;
     70     }
     71 
     72     if (write(fd, (enable ? "1" : "0"), 1) != 1) {
     73         ALOGE("Failed to write ip_forward (%s)", strerror(errno));
     74         close(fd);
     75         return -1;
     76     }
     77     close(fd);
     78     return 0;
     79 }
     80 
     81 bool TetherController::getIpFwdEnabled() {
     82     int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY);
     83 
     84     if (fd < 0) {
     85         ALOGE("Failed to open ip_forward (%s)", strerror(errno));
     86         return false;
     87     }
     88 
     89     char enabled;
     90     if (read(fd, &enabled, 1) != 1) {
     91         ALOGE("Failed to read ip_forward (%s)", strerror(errno));
     92         close(fd);
     93         return -1;
     94     }
     95 
     96     close(fd);
     97     return (enabled  == '1' ? true : false);
     98 }
     99 
    100 int TetherController::startTethering(int num_addrs, struct in_addr* addrs) {
    101     if (mDaemonPid != 0) {
    102         ALOGE("Tethering already started");
    103         errno = EBUSY;
    104         return -1;
    105     }
    106 
    107     ALOGD("Starting tethering services");
    108 
    109     pid_t pid;
    110     int pipefd[2];
    111 
    112     if (pipe(pipefd) < 0) {
    113         ALOGE("pipe failed (%s)", strerror(errno));
    114         return -1;
    115     }
    116 
    117     /*
    118      * TODO: Create a monitoring thread to handle and restart
    119      * the daemon if it exits prematurely
    120      */
    121     if ((pid = fork()) < 0) {
    122         ALOGE("fork failed (%s)", strerror(errno));
    123         close(pipefd[0]);
    124         close(pipefd[1]);
    125         return -1;
    126     }
    127 
    128     if (!pid) {
    129         close(pipefd[1]);
    130         if (pipefd[0] != STDIN_FILENO) {
    131             if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
    132                 ALOGE("dup2 failed (%s)", strerror(errno));
    133                 return -1;
    134             }
    135             close(pipefd[0]);
    136         }
    137 
    138         int num_processed_args = 7 + (num_addrs/2) + 1; // 1 null for termination
    139         char **args = (char **)malloc(sizeof(char *) * num_processed_args);
    140         args[num_processed_args - 1] = NULL;
    141         args[0] = (char *)"/system/bin/dnsmasq";
    142         args[1] = (char *)"--keep-in-foreground";
    143         args[2] = (char *)"--no-resolv";
    144         args[3] = (char *)"--no-poll";
    145         // TODO: pipe through metered status from ConnService
    146         args[4] = (char *)"--dhcp-option-force=43,ANDROID_METERED";
    147         args[5] = (char *)"--pid-file";
    148         args[6] = (char *)"";
    149 
    150         int nextArg = 7;
    151         for (int addrIndex=0; addrIndex < num_addrs;) {
    152             char *start = strdup(inet_ntoa(addrs[addrIndex++]));
    153             char *end = strdup(inet_ntoa(addrs[addrIndex++]));
    154             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
    155         }
    156 
    157         if (execv(args[0], args)) {
    158             ALOGE("execl failed (%s)", strerror(errno));
    159         }
    160         ALOGE("Should never get here!");
    161         free(args);
    162         return 0;
    163     } else {
    164         close(pipefd[0]);
    165         mDaemonPid = pid;
    166         mDaemonFd = pipefd[1];
    167         ALOGD("Tethering services running");
    168     }
    169 
    170     return 0;
    171 }
    172 
    173 int TetherController::stopTethering() {
    174 
    175     if (mDaemonPid == 0) {
    176         ALOGE("Tethering already stopped");
    177         return 0;
    178     }
    179 
    180     ALOGD("Stopping tethering services");
    181 
    182     kill(mDaemonPid, SIGTERM);
    183     waitpid(mDaemonPid, NULL, 0);
    184     mDaemonPid = 0;
    185     close(mDaemonFd);
    186     mDaemonFd = -1;
    187     ALOGD("Tethering services stopped");
    188     return 0;
    189 }
    190 
    191 // TODO(BT) remove
    192 int TetherController::startReverseTethering(const char* iface) {
    193     if (mDhcpcdPid != 0) {
    194         ALOGE("Reverse tethering already started");
    195         errno = EBUSY;
    196         return -1;
    197     }
    198 
    199     ALOGD("TetherController::startReverseTethering, Starting reverse tethering");
    200 
    201     /*
    202      * TODO: Create a monitoring thread to handle and restart
    203      * the daemon if it exits prematurely
    204      */
    205     //cleanup the dhcp result
    206     char dhcp_result_name[64];
    207     snprintf(dhcp_result_name, sizeof(dhcp_result_name) - 1, "dhcp.%s.result", iface);
    208     property_set(dhcp_result_name, "");
    209 
    210     pid_t pid;
    211     if ((pid = fork()) < 0) {
    212         ALOGE("fork failed (%s)", strerror(errno));
    213         return -1;
    214     }
    215 
    216     if (!pid) {
    217 
    218         char *args[10];
    219         int argc = 0;
    220         args[argc++] = "/system/bin/dhcpcd";
    221         char host_name[128];
    222         if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0'))
    223         {
    224             args[argc++] = "-h";
    225             args[argc++] = host_name;
    226         }
    227         args[argc++] = (char*)iface;
    228         args[argc] = NULL;
    229         if (execv(args[0], args)) {
    230             ALOGE("startReverseTethering, execv failed (%s)", strerror(errno));
    231         }
    232         ALOGE("startReverseTethering, Should never get here!");
    233         // TODO(BT) inform parent of the failure.
    234         //          Parent process need wait for child to report error status
    235         //          before it set mDhcpcdPid and return 0.
    236         exit(-1);
    237     } else {
    238         mDhcpcdPid = pid;
    239         ALOGD("Reverse Tethering running, pid:%d", pid);
    240     }
    241     return 0;
    242 }
    243 
    244 // TODO(BT) remove
    245 int TetherController::stopReverseTethering() {
    246 
    247     if (mDhcpcdPid == 0) {
    248         ALOGE("Tethering already stopped");
    249         return 0;
    250     }
    251 
    252     ALOGD("Stopping tethering services");
    253 
    254     kill(mDhcpcdPid, SIGTERM);
    255     waitpid(mDhcpcdPid, NULL, 0);
    256     mDhcpcdPid = 0;
    257     ALOGD("Tethering services stopped");
    258     return 0;
    259 }
    260 bool TetherController::isTetheringStarted() {
    261     return (mDaemonPid == 0 ? false : true);
    262 }
    263 
    264 #define MAX_CMD_SIZE 1024
    265 
    266 int TetherController::setDnsForwarders(char **servers, int numServers) {
    267     int i;
    268     char daemonCmd[MAX_CMD_SIZE];
    269 
    270     strcpy(daemonCmd, "update_dns");
    271     int cmdLen = strlen(daemonCmd);
    272 
    273     mDnsForwarders->clear();
    274     for (i = 0; i < numServers; i++) {
    275         ALOGD("setDnsForwarders(%d = '%s')", i, servers[i]);
    276 
    277         struct in_addr a;
    278 
    279         if (!inet_aton(servers[i], &a)) {
    280             ALOGE("Failed to parse DNS server '%s'", servers[i]);
    281             mDnsForwarders->clear();
    282             return -1;
    283         }
    284 
    285         cmdLen += (strlen(servers[i]) + 1);
    286         if (cmdLen + 1 >= MAX_CMD_SIZE) {
    287             ALOGD("Too many DNS servers listed");
    288             break;
    289         }
    290 
    291         strcat(daemonCmd, ":");
    292         strcat(daemonCmd, servers[i]);
    293         mDnsForwarders->push_back(a);
    294     }
    295 
    296     if (mDaemonFd != -1) {
    297         ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
    298         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
    299             ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
    300             mDnsForwarders->clear();
    301             return -1;
    302         }
    303     }
    304     return 0;
    305 }
    306 
    307 NetAddressCollection *TetherController::getDnsForwarders() {
    308     return mDnsForwarders;
    309 }
    310 
    311 int TetherController::tetherInterface(const char *interface) {
    312     mInterfaces->push_back(strdup(interface));
    313     return 0;
    314 }
    315 
    316 int TetherController::untetherInterface(const char *interface) {
    317     InterfaceCollection::iterator it;
    318 
    319     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
    320         if (!strcmp(interface, *it)) {
    321             free(*it);
    322             mInterfaces->erase(it);
    323             return 0;
    324         }
    325     }
    326     errno = ENOENT;
    327     return -1;
    328 }
    329 
    330 InterfaceCollection *TetherController::getTetheredInterfaceList() {
    331     return mInterfaces;
    332 }
    333