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