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 
     21 #include <sys/socket.h>
     22 #include <sys/stat.h>
     23 #include <sys/types.h>
     24 #include <sys/wait.h>
     25 
     26 #include <netinet/in.h>
     27 #include <arpa/inet.h>
     28 
     29 #define LOG_TAG "TetherController"
     30 #include <cutils/log.h>
     31 
     32 
     33 #include "TetherController.h"
     34 
     35 TetherController::TetherController() {
     36     mInterfaces = new InterfaceCollection();
     37     mDnsForwarders = new NetAddressCollection();
     38     mDaemonFd = -1;
     39     mDaemonPid = 0;
     40 }
     41 
     42 TetherController::~TetherController() {
     43     InterfaceCollection::iterator it;
     44 
     45     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
     46         free(*it);
     47     }
     48     mInterfaces->clear();
     49 
     50     mDnsForwarders->clear();
     51 }
     52 
     53 int TetherController::setIpFwdEnabled(bool enable) {
     54 
     55     LOGD("Setting IP forward enable = %d", enable);
     56     int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY);
     57     if (fd < 0) {
     58         LOGE("Failed to open ip_forward (%s)", strerror(errno));
     59         return -1;
     60     }
     61 
     62     if (write(fd, (enable ? "1" : "0"), 1) != 1) {
     63         LOGE("Failed to write ip_forward (%s)", strerror(errno));
     64         close(fd);
     65         return -1;
     66     }
     67     close(fd);
     68     return 0;
     69 }
     70 
     71 bool TetherController::getIpFwdEnabled() {
     72     int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY);
     73 
     74     if (fd < 0) {
     75         LOGE("Failed to open ip_forward (%s)", strerror(errno));
     76         return false;
     77     }
     78 
     79     char enabled;
     80     if (read(fd, &enabled, 1) != 1) {
     81         LOGE("Failed to read ip_forward (%s)", strerror(errno));
     82         close(fd);
     83         return -1;
     84     }
     85 
     86     close(fd);
     87     return (enabled  == '1' ? true : false);
     88 }
     89 
     90 int TetherController::startTethering(int num_addrs, struct in_addr* addrs) {
     91     if (mDaemonPid != 0) {
     92         LOGE("Tethering already started");
     93         errno = EBUSY;
     94         return -1;
     95     }
     96 
     97     LOGD("Starting tethering services");
     98 
     99     pid_t pid;
    100     int pipefd[2];
    101 
    102     if (pipe(pipefd) < 0) {
    103         LOGE("pipe failed (%s)", strerror(errno));
    104         return -1;
    105     }
    106 
    107     /*
    108      * TODO: Create a monitoring thread to handle and restart
    109      * the daemon if it exits prematurely
    110      */
    111     if ((pid = fork()) < 0) {
    112         LOGE("fork failed (%s)", strerror(errno));
    113         close(pipefd[0]);
    114         close(pipefd[1]);
    115         return -1;
    116     }
    117 
    118     if (!pid) {
    119         close(pipefd[1]);
    120         if (pipefd[0] != STDIN_FILENO) {
    121             if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
    122                 LOGE("dup2 failed (%s)", strerror(errno));
    123                 return -1;
    124             }
    125             close(pipefd[0]);
    126         }
    127 
    128         int num_processed_args = 4 + (num_addrs/2) + 1; // 1 null for termination
    129         char **args = (char **)malloc(sizeof(char *) * num_processed_args);
    130         args[num_processed_args - 1] = NULL;
    131         args[0] = (char *)"/system/bin/dnsmasq";
    132         args[1] = (char *)"--no-daemon";
    133         args[2] = (char *)"--no-resolv";
    134         args[3] = (char *)"--no-poll";
    135 
    136         int nextArg = 4;
    137         for (int addrIndex=0; addrIndex < num_addrs;) {
    138             char *start = strdup(inet_ntoa(addrs[addrIndex++]));
    139             char *end = strdup(inet_ntoa(addrs[addrIndex++]));
    140             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
    141         }
    142 
    143         if (execv(args[0], args)) {
    144             LOGE("execl failed (%s)", strerror(errno));
    145         }
    146         LOGE("Should never get here!");
    147         free(args);
    148         return 0;
    149     } else {
    150         close(pipefd[0]);
    151         mDaemonPid = pid;
    152         mDaemonFd = pipefd[1];
    153         LOGD("Tethering services running");
    154     }
    155 
    156     return 0;
    157 }
    158 
    159 int TetherController::stopTethering() {
    160 
    161     if (mDaemonPid == 0) {
    162         LOGE("Tethering already stopped");
    163         return 0;
    164     }
    165 
    166     LOGD("Stopping tethering services");
    167 
    168     kill(mDaemonPid, SIGTERM);
    169     waitpid(mDaemonPid, NULL, 0);
    170     mDaemonPid = 0;
    171     close(mDaemonFd);
    172     mDaemonFd = -1;
    173     LOGD("Tethering services stopped");
    174     return 0;
    175 }
    176 
    177 bool TetherController::isTetheringStarted() {
    178     return (mDaemonPid == 0 ? false : true);
    179 }
    180 
    181 #define MAX_CMD_SIZE 1024
    182 
    183 int TetherController::setDnsForwarders(char **servers, int numServers) {
    184     int i;
    185     char daemonCmd[MAX_CMD_SIZE];
    186 
    187     strcpy(daemonCmd, "update_dns");
    188     int cmdLen = strlen(daemonCmd);
    189 
    190     mDnsForwarders->clear();
    191     for (i = 0; i < numServers; i++) {
    192         LOGD("setDnsForwarders(%d = '%s')", i, servers[i]);
    193 
    194         struct in_addr a;
    195 
    196         if (!inet_aton(servers[i], &a)) {
    197             LOGE("Failed to parse DNS server '%s'", servers[i]);
    198             mDnsForwarders->clear();
    199             return -1;
    200         }
    201 
    202         cmdLen += strlen(servers[i]);
    203         if (cmdLen + 2 >= MAX_CMD_SIZE) {
    204             LOGD("Too many DNS servers listed");
    205             break;
    206         }
    207 
    208         strcat(daemonCmd, ":");
    209         strcat(daemonCmd, servers[i]);
    210         mDnsForwarders->push_back(a);
    211     }
    212 
    213     if (mDaemonFd != -1) {
    214         LOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
    215         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
    216             LOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
    217             mDnsForwarders->clear();
    218             return -1;
    219         }
    220     }
    221     return 0;
    222 }
    223 
    224 NetAddressCollection *TetherController::getDnsForwarders() {
    225     return mDnsForwarders;
    226 }
    227 
    228 int TetherController::tetherInterface(const char *interface) {
    229     mInterfaces->push_back(strdup(interface));
    230     return 0;
    231 }
    232 
    233 int TetherController::untetherInterface(const char *interface) {
    234     InterfaceCollection::iterator it;
    235 
    236     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
    237         if (!strcmp(interface, *it)) {
    238             free(*it);
    239             mInterfaces->erase(it);
    240             return 0;
    241         }
    242     }
    243     errno = ENOENT;
    244     return -1;
    245 }
    246 
    247 InterfaceCollection *TetherController::getTetheredInterfaceList() {
    248     return mInterfaces;
    249 }
    250