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
42namespace {
43
44const char BP_TOOLS_MODE[] = "bp-tools";
45const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
46const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
47const char SEPARATOR[] = "|";
48
49bool 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
66bool 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
74void 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
81bool 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
90namespace android {
91namespace net {
92
93TetherController::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
104TetherController::~TetherController() {
105    mInterfaces.clear();
106    mDnsForwarders.clear();
107    mForwardingRequests.clear();
108}
109
110bool 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
119bool 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
127bool TetherController::disableForwarding(const char* requester) {
128    mForwardingRequests.erase(requester);
129    return setIpFwdEnabled();
130}
131
132size_t TetherController::forwardingRequestCount() {
133    return mForwardingRequests.size();
134}
135
136#define TETHER_START_CONST_ARG        10
137
138int 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
221int 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
239bool TetherController::isTetheringStarted() {
240    return (mDaemonPid == 0 ? false : true);
241}
242
243#define MAX_CMD_SIZE 1024
244
245int 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
296unsigned TetherController::getDnsNetId() {
297    return mDnsNetId;
298}
299
300const std::list<std::string> &TetherController::getDnsForwarders() const {
301    return mDnsForwarders;
302}
303
304bool 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
333int 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
355int 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
370const std::list<std::string> &TetherController::getTetheredInterfaceList() const {
371    return mInterfaces;
372}
373
374}  // namespace net
375}  // namespace android
376