19ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat/*
29ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * Copyright (C) 2008 The Android Open Source Project
39ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat *
49ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * Licensed under the Apache License, Version 2.0 (the "License");
59ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * you may not use this file except in compliance with the License.
69ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * You may obtain a copy of the License at
79ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat *
89ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat *      http://www.apache.org/licenses/LICENSE-2.0
99ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat *
109ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * Unless required by applicable law or agreed to in writing, software
119ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * distributed under the License is distributed on an "AS IS" BASIS,
129ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * See the License for the specific language governing permissions and
149ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat * limitations under the License.
159ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat */
169ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
17baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#define LOG_NDEBUG 0
180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
199ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <stdlib.h>
209ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <errno.h>
219ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <sys/socket.h>
229ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <sys/stat.h>
23001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand#include <sys/wait.h>
249ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <fcntl.h>
259ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <netinet/in.h>
269ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <arpa/inet.h>
27ff2c0d8c13457e43f0d4bf06d3177271aac104c1Olivier Bailly#include <string.h>
28ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau#include <cutils/properties.h>
299ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
309ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#define LOG_TAG "NatController"
319ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <cutils/log.h>
32001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand#include <logwrap/logwrap.h>
339ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
349ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include "NatController.h"
35c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt#include "NetdConstants.h"
3687475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran#include "RouteController.h"
379ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
388e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
39e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitticonst char* NatController::LOCAL_MANGLE_FORWARD = "natctrl_mangle_FORWARD";
408e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
41baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallconst char* NatController::LOCAL_TETHER_COUNTERS_CHAIN = "natctrl_tether_counters";
428e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
4387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram RamachandranNatController::NatController() {
449ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
469ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() {
479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
489ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
494ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrallstruct CommandsAndArgs {
504ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    /* The array size doesn't really matter as the compiler will barf if too many initializers are specified. */
514ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    const char *cmd[32];
524ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    bool checkRes;
534ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall};
544ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall
55001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchandint NatController::runCmd(int argc, const char **argv) {
5611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
58001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
59baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
60baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#if !LOG_NDEBUG
61baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    std::string full_cmd = argv[0];
62baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    argc--; argv++;
63baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /*
64baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * HACK: Sometimes runCmd() is called with a ridcously large value (32)
65baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * and it works because the argv[] contains a NULL after the last
66baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * true argv. So here we use the NULL argv[] to terminate when the argc
67baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * is horribly wrong, and argc for the normal cases.
68baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     */
69baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    for (; argc && argv[0]; argc--, argv++) {
70baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        full_cmd += " ";
71baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        full_cmd += argv[0];
72baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
73baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    ALOGV("runCmd(%s) res=%d", full_cmd.c_str(), res);
74baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#endif
7511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
769ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
779ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
780031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint NatController::setupIptablesHooks() {
79baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    int res;
80baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    res = setDefaults();
81baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (res < 0) {
82baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return res;
83baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
84baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
85baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    struct CommandsAndArgs defaultCommands[] = {
86baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        /*
876b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * First chain is for tethering counters.
88baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * This chain is reached via --goto, and then RETURNS.
896b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         *
906b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * Second chain is used to limit downstream mss to the upstream pmtu
916b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * so we don't end up fragmenting every large packet tethered devices
926b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * send.  Note this feature requires kernel support with flag
936b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * CONFIG_NETFILTER_XT_TARGET_TCPMSS=y, which not all builds will have,
946b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * so the final rule is allowed to fail.
956b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * Bug 17629786 asks to make the failure more obvious, or even fatal
966b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao         * so that all builds eventually gain the performance improvement.
97baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         */
98baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-F", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
99baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-X", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
100baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-N", LOCAL_TETHER_COUNTERS_CHAIN,}, 1},
101e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti        {{IPTABLES_PATH, "-t", "mangle", "-A", LOCAL_MANGLE_FORWARD, "-p", "tcp", "--tcp-flags",
1026b6f22fac4c33fcd349aaf6970bbdc191db752a3Gordon Gao                "SYN", "SYN", "-j", "TCPMSS", "--clamp-mss-to-pmtu"}, 0},
103baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    };
104baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE(defaultCommands); cmdNum++) {
105baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        if (runCmd(ARRAY_SIZE(defaultCommands[cmdNum].cmd), defaultCommands[cmdNum].cmd) &&
106baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            defaultCommands[cmdNum].checkRes) {
107baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                return -1;
108baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        }
109baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
110f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    ifacePairList.clear();
111baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
1120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
1130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint NatController::setDefaults() {
116baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /*
117baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * The following only works because:
118baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     *  - the defaultsCommands[].cmd array is padded with NULL, and
119baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     *  - the 1st argc of runCmd() will just be the max for the CommandsAndArgs[].cmd, and
120baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     *  - internally it will be memcopied to an array and terminated with a NULL.
121baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     */
1224ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    struct CommandsAndArgs defaultCommands[] = {
123baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-F", LOCAL_FORWARD,}, 1},
124baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-A", LOCAL_FORWARD, "-j", "DROP"}, 1},
125baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-t", "nat", "-F", LOCAL_NAT_POSTROUTING}, 1},
126001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
1274ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE(defaultCommands); cmdNum++) {
1284ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        if (runCmd(ARRAY_SIZE(defaultCommands[cmdNum].cmd), defaultCommands[cmdNum].cmd) &&
1294ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall            defaultCommands[cmdNum].checkRes) {
1304ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall                return -1;
1314ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        }
1324ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    }
133fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
134fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    natCount = 0;
1354ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
1369ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return 0;
1379ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
1389ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
13987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandranint NatController::enableNat(const char* intIface, const char* extIface) {
140baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
141baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
14269261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
143fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
144fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
145fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
1469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
147baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
148baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (!strcmp(intIface, extIface)) {
149baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
150baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        errno = EINVAL;
151baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return -1;
152baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
153baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
154fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    // add this if we are the first added nat
155659692a56cca02822a43b792baba2632d39eb739JP Abgrall    if (natCount == 0) {
156001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        const char *cmd[] = {
157001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                IPTABLES_PATH,
158001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-t",
159001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "nat",
160001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-A",
161baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                LOCAL_NAT_POSTROUTING,
162001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-o",
163001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                extIface,
164001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-j",
165001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "MASQUERADE"
166001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        };
167001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        if (runCmd(ARRAY_SIZE(cmd), cmd)) {
16887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran            ALOGE("Error setting postroute rule: iface=%s", extIface);
169fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // unwind what's been done, but don't care about success - what more could we do?
170fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            setDefaults();
171fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            return -1;
172fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
173fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
174fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
175659692a56cca02822a43b792baba2632d39eb739JP Abgrall    if (setForwardRules(true, intIface, extIface) != 0) {
176659692a56cca02822a43b792baba2632d39eb739JP Abgrall        ALOGE("Error setting forward rules");
177659692a56cca02822a43b792baba2632d39eb739JP Abgrall        if (natCount == 0) {
178659692a56cca02822a43b792baba2632d39eb739JP Abgrall            setDefaults();
179659692a56cca02822a43b792baba2632d39eb739JP Abgrall        }
180659692a56cca02822a43b792baba2632d39eb739JP Abgrall        errno = ENODEV;
181659692a56cca02822a43b792baba2632d39eb739JP Abgrall        return -1;
182659692a56cca02822a43b792baba2632d39eb739JP Abgrall    }
183659692a56cca02822a43b792baba2632d39eb739JP Abgrall
184659692a56cca02822a43b792baba2632d39eb739JP Abgrall    /* Always make sure the drop rule is at the end */
185659692a56cca02822a43b792baba2632d39eb739JP Abgrall    const char *cmd1[] = {
186659692a56cca02822a43b792baba2632d39eb739JP Abgrall            IPTABLES_PATH,
187659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-D",
188baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
189659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-j",
190659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "DROP"
191659692a56cca02822a43b792baba2632d39eb739JP Abgrall    };
192659692a56cca02822a43b792baba2632d39eb739JP Abgrall    runCmd(ARRAY_SIZE(cmd1), cmd1);
193659692a56cca02822a43b792baba2632d39eb739JP Abgrall    const char *cmd2[] = {
194659692a56cca02822a43b792baba2632d39eb739JP Abgrall            IPTABLES_PATH,
195659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-A",
196baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
197659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-j",
198659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "DROP"
199659692a56cca02822a43b792baba2632d39eb739JP Abgrall    };
200659692a56cca02822a43b792baba2632d39eb739JP Abgrall    runCmd(ARRAY_SIZE(cmd2), cmd2);
201659692a56cca02822a43b792baba2632d39eb739JP Abgrall
20287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (int ret = RouteController::enableTethering(intIface, extIface)) {
20387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        ALOGE("failed to add tethering rule for iif=%s oif=%s", intIface, extIface);
2048b3b91c6cad577e2928a29073fc962c57ef75af5Sreeram Ramachandran        if (natCount == 0) {
2058b3b91c6cad577e2928a29073fc962c57ef75af5Sreeram Ramachandran            setDefaults();
2068b3b91c6cad577e2928a29073fc962c57ef75af5Sreeram Ramachandran        }
20787475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        errno = -ret;
20887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        return -1;
20987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    }
21087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran
211659692a56cca02822a43b792baba2632d39eb739JP Abgrall    natCount++;
212fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
213fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
214fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
215f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrallbool NatController::checkTetherCountingRuleExist(const char *pair_name) {
216f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    std::list<std::string>::iterator it;
217f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
218f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    for (it = ifacePairList.begin(); it != ifacePairList.end(); it++) {
219f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        if (*it == pair_name) {
220f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            /* We already have this counter */
221f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            return true;
222f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        }
223f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    }
224f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    return false;
225f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall}
226f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
227baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallint NatController::setTetherCountingRules(bool add, const char *intIface, const char *extIface) {
228baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
229baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /* We only ever add tethering quota rules so that they stick. */
230baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (!add) {
231baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return 0;
232baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
23356afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran    char *pair_name;
234f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    asprintf(&pair_name, "%s_%s", intIface, extIface);
235f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
236f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    if (checkTetherCountingRuleExist(pair_name)) {
237f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
238baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return 0;
239baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
240baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    const char *cmd2b[] = {
241baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            IPTABLES_PATH,
242baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-A",
243baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN,
244baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-i",
245baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            intIface,
246baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-o",
247baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            extIface,
248baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-j",
249baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall          "RETURN"
250baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    };
251baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
252baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (runCmd(ARRAY_SIZE(cmd2b), cmd2b) && add) {
253f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
254baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return -1;
255baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
256f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    ifacePairList.push_front(pair_name);
257f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    free(pair_name);
258f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
259f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    asprintf(&pair_name, "%s_%s", extIface, intIface);
260f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    if (checkTetherCountingRuleExist(pair_name)) {
261f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
262baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return 0;
263baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
264baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
265baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    const char *cmd3b[] = {
266baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            IPTABLES_PATH,
267baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-A",
268baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN,
269baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-i",
270baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            extIface,
271baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-o",
272baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            intIface,
273baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-j",
274baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "RETURN"
275baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    };
276baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
277baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (runCmd(ARRAY_SIZE(cmd3b), cmd3b) && add) {
278baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        // unwind what's been done, but don't care about success - what more could we do?
279f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
280baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return -1;
281baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
282f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    ifacePairList.push_front(pair_name);
283f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    free(pair_name);
284baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    return 0;
285baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall}
286baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
287baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallint NatController::setForwardRules(bool add, const char *intIface, const char *extIface) {
288001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd1[] = {
289001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IPTABLES_PATH,
290001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            add ? "-A" : "-D",
291baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
292001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-i",
293001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            extIface,
294001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-o",
295001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            intIface,
296001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-m",
297001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "state",
298001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "--state",
299001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "ESTABLISHED,RELATED",
300baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-g",
301baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN
302001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
303001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    int rc = 0;
304001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
305001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
3069ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
3079ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
3089ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
309001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd2[] = {
310001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IPTABLES_PATH,
311001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            add ? "-A" : "-D",
312baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
313001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-i",
314001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            intIface,
315001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-o",
316001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            extIface,
317001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-m",
318001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "state",
319001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "--state",
320001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "INVALID",
321001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-j",
322001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "DROP"
323001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
324001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
325001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd3[] = {
326001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IPTABLES_PATH,
327001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            add ? "-A" : "-D",
328baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
329001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-i",
330001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            intIface,
331001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-o",
332001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            extIface,
333baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-g",
334baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN
335001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
336001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
337001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
338f7bf29c8a37d65e132a4dceb7c5a4200ed5c3d79Robert Greenwalt        // bail on error, but only if adding
339001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        rc = -1;
340001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        goto err_invalid_drop;
341ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    }
342ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
343001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
344210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        // unwind what's been done, but don't care about success - what more could we do?
345001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        rc = -1;
346001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        goto err_return;
3479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
3480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
349baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (setTetherCountingRules(add, intIface, extIface) && add) {
350baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        rc = -1;
351baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        goto err_return;
352baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
353baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
354fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
355001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
356001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchanderr_return:
357001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    cmd2[1] = "-D";
358001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    runCmd(ARRAY_SIZE(cmd2), cmd2);
359001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchanderr_invalid_drop:
360001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    cmd1[1] = "-D";
361001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    runCmd(ARRAY_SIZE(cmd1), cmd1);
362001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    return rc;
363fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
3649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
36587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandranint NatController::disableNat(const char* intIface, const char* extIface) {
36669261cb65186e27dfbdc1e3eec796437f9968ff9JP Abgrall    if (!isIfaceName(intIface) || !isIfaceName(extIface)) {
367fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
368fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
3699ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
3709ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
37187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (int ret = RouteController::disableTethering(intIface, extIface)) {
37287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        ALOGE("failed to remove tethering rule for iif=%s oif=%s", intIface, extIface);
37387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        errno = -ret;
374fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
375210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
3769ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
377fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    setForwardRules(false, intIface, extIface);
378fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (--natCount <= 0) {
3794ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
3804ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        setDefaults();
381fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
382fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
3839ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
384