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