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