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