NatController.cpp revision 56afacf838d24cf8e54d2cf0d8ab9182ab704125
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"
35a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak#include "NetworkController.h"
36fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "SecondaryTableController.h"
37c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt#include "NetdConstants.h"
389ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
398e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
408e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
41baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallconst char* NatController::LOCAL_TETHER_COUNTERS_CHAIN = "natctrl_tether_counters";
428e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
43a0efaece8c05370f201efe099a537ceb014c6fdfSzymon JakubczakNatController::NatController(SecondaryTableController *table_ctrl, NetworkController* net_ctrl) :
44a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak        mSecondaryTableCtrl(table_ctrl), mNetCtrl(net_ctrl) {
459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
479ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() {
489ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
499ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
504ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrallstruct CommandsAndArgs {
514ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    /* The array size doesn't really matter as the compiler will barf if too many initializers are specified. */
524ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    const char *cmd[32];
534ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    bool checkRes;
544ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall};
554ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall
56001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchandint NatController::runCmd(int argc, const char **argv) {
5711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
589ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
59001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
60baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
61baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#if !LOG_NDEBUG
62baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    std::string full_cmd = argv[0];
63baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    argc--; argv++;
64baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /*
65baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * HACK: Sometimes runCmd() is called with a ridcously large value (32)
66baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * and it works because the argv[] contains a NULL after the last
67baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * true argv. So here we use the NULL argv[] to terminate when the argc
68baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * is horribly wrong, and argc for the normal cases.
69baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     */
70baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    for (; argc && argv[0]; argc--, argv++) {
71baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        full_cmd += " ";
72baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        full_cmd += argv[0];
73baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
74baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    ALOGV("runCmd(%s) res=%d", full_cmd.c_str(), res);
75baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall#endif
7611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
779ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
789ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint NatController::setupIptablesHooks() {
80baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    int res;
81baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    res = setDefaults();
82baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (res < 0) {
83baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return res;
84baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
85baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
86baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    struct CommandsAndArgs defaultCommands[] = {
87baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        /*
88baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * Chain for tethering counters.
89baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         * This chain is reached via --goto, and then RETURNS.
90baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall         */
91baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-F", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
92baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-X", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
93baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-N", LOCAL_TETHER_COUNTERS_CHAIN,}, 1},
94baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    };
95baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE(defaultCommands); cmdNum++) {
96baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        if (runCmd(ARRAY_SIZE(defaultCommands[cmdNum].cmd), defaultCommands[cmdNum].cmd) &&
97baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            defaultCommands[cmdNum].checkRes) {
98baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                return -1;
99baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        }
100baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
101f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    ifacePairList.clear();
102baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
1030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
1040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint NatController::setDefaults() {
107baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /*
108baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     * The following only works because:
109baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     *  - the defaultsCommands[].cmd array is padded with NULL, and
110baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     *  - the 1st argc of runCmd() will just be the max for the CommandsAndArgs[].cmd, and
111baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     *  - internally it will be memcopied to an array and terminated with a NULL.
112baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall     */
1134ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    struct CommandsAndArgs defaultCommands[] = {
114baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-F", LOCAL_FORWARD,}, 1},
115baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-A", LOCAL_FORWARD, "-j", "DROP"}, 1},
116baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        {{IPTABLES_PATH, "-t", "nat", "-F", LOCAL_NAT_POSTROUTING}, 1},
1174ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        {{IP_PATH, "rule", "flush"}, 0},
1184ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        {{IP_PATH, "-6", "rule", "flush"}, 0},
1194ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        {{IP_PATH, "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
1204ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        {{IP_PATH, "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
1214ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
1224ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
1234ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        {{IP_PATH, "route", "flush", "cache"}, 0},
124001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
1254ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE(defaultCommands); cmdNum++) {
1264ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        if (runCmd(ARRAY_SIZE(defaultCommands[cmdNum].cmd), defaultCommands[cmdNum].cmd) &&
1274ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall            defaultCommands[cmdNum].checkRes) {
1284ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall                return -1;
1294ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        }
1304ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    }
131fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
132fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    natCount = 0;
1334ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
1349ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return 0;
1359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
1369ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
137fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltbool NatController::checkInterface(const char *iface) {
138d14fd4f83ffeea4ad1cd559a41f775f6814565ccJaime A Lopez-Sollano    if (strlen(iface) > IFNAMSIZ) return false;
1399ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return true;
1409ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
1419ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
1424ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrallint NatController::routesOp(bool add, const char *intIface, const char *extIface, char **argv, int addrCount) {
143a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    unsigned netId = mNetCtrl->getNetworkId(extIface);
1444ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    int ret = 0;
1454ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall
146a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    for (int i = 0; i < addrCount; i++) {
147a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak        if (add) {
148a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            ret |= mSecondaryTableCtrl->modifyFromRule(netId, ADD, argv[5+i]);
149a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            ret |= mSecondaryTableCtrl->modifyLocalRoute(netId, ADD, intIface, argv[5+i]);
150a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak        } else {
151a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            ret |= mSecondaryTableCtrl->modifyLocalRoute(netId, DEL, intIface, argv[5+i]);
152a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            ret |= mSecondaryTableCtrl->modifyFromRule(netId, DEL, argv[5+i]);
1534ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        }
1544ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    }
155a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    const char *cmd[] = {
156a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            IP_PATH,
157a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            "route",
158a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            "flush",
159a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak            "cache"
160a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    };
161a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    runCmd(ARRAY_SIZE(cmd), cmd);
1624ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    return ret;
1634ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall}
1644ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall
165fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
166fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
167fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::enableNat(const int argc, char **argv) {
168fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
169fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
170fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
171fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
172baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    ALOGV("enableNat(intIface=<%s>, extIface=<%s>)",intIface, extIface);
173baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
174fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
1755ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid interface specified");
176fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
177fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
178fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
1799ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
180baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /* Bug: b/9565268. "enableNat wlan0 wlan0". For now we fail until java-land is fixed */
181baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (!strcmp(intIface, extIface)) {
182baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        ALOGE("Duplicate interface specified: %s %s", intIface, extIface);
183baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        errno = EINVAL;
184baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return -1;
185baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
186baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
187fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
1885ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Missing Argument");
189fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
190fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
191fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
192659692a56cca02822a43b792baba2632d39eb739JP Abgrall    if (routesOp(true, intIface, extIface, argv, addrCount)) {
193659692a56cca02822a43b792baba2632d39eb739JP Abgrall        ALOGE("Error setting route rules");
1944ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall        routesOp(false, intIface, extIface, argv, addrCount);
1959ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        errno = ENODEV;
1969ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1979ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1989ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
199fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    // add this if we are the first added nat
200659692a56cca02822a43b792baba2632d39eb739JP Abgrall    if (natCount == 0) {
201001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        const char *cmd[] = {
202001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                IPTABLES_PATH,
203001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-t",
204001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "nat",
205001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-A",
206baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                LOCAL_NAT_POSTROUTING,
207001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-o",
208001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                extIface,
209001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "-j",
210001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand                "MASQUERADE"
211001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        };
212001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        if (runCmd(ARRAY_SIZE(cmd), cmd)) {
213001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            ALOGE("Error seting postroute rule: iface=%s", extIface);
214fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // unwind what's been done, but don't care about success - what more could we do?
2154ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall            routesOp(false, intIface, extIface, argv, addrCount);
216fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            setDefaults();
217fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            return -1;
218fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
219fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
220fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
221659692a56cca02822a43b792baba2632d39eb739JP Abgrall
222659692a56cca02822a43b792baba2632d39eb739JP Abgrall    if (setForwardRules(true, intIface, extIface) != 0) {
223659692a56cca02822a43b792baba2632d39eb739JP Abgrall        ALOGE("Error setting forward rules");
224659692a56cca02822a43b792baba2632d39eb739JP Abgrall        routesOp(false, intIface, extIface, argv, addrCount);
225659692a56cca02822a43b792baba2632d39eb739JP Abgrall        if (natCount == 0) {
226659692a56cca02822a43b792baba2632d39eb739JP Abgrall            setDefaults();
227659692a56cca02822a43b792baba2632d39eb739JP Abgrall        }
228659692a56cca02822a43b792baba2632d39eb739JP Abgrall        errno = ENODEV;
229659692a56cca02822a43b792baba2632d39eb739JP Abgrall        return -1;
230659692a56cca02822a43b792baba2632d39eb739JP Abgrall    }
231659692a56cca02822a43b792baba2632d39eb739JP Abgrall
232659692a56cca02822a43b792baba2632d39eb739JP Abgrall    /* Always make sure the drop rule is at the end */
233659692a56cca02822a43b792baba2632d39eb739JP Abgrall    const char *cmd1[] = {
234659692a56cca02822a43b792baba2632d39eb739JP Abgrall            IPTABLES_PATH,
235659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-D",
236baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
237659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-j",
238659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "DROP"
239659692a56cca02822a43b792baba2632d39eb739JP Abgrall    };
240659692a56cca02822a43b792baba2632d39eb739JP Abgrall    runCmd(ARRAY_SIZE(cmd1), cmd1);
241659692a56cca02822a43b792baba2632d39eb739JP Abgrall    const char *cmd2[] = {
242659692a56cca02822a43b792baba2632d39eb739JP Abgrall            IPTABLES_PATH,
243659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-A",
244baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
245659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "-j",
246659692a56cca02822a43b792baba2632d39eb739JP Abgrall            "DROP"
247659692a56cca02822a43b792baba2632d39eb739JP Abgrall    };
248659692a56cca02822a43b792baba2632d39eb739JP Abgrall    runCmd(ARRAY_SIZE(cmd2), cmd2);
249659692a56cca02822a43b792baba2632d39eb739JP Abgrall
250659692a56cca02822a43b792baba2632d39eb739JP Abgrall    natCount++;
251fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
252fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
253fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
254f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrallbool NatController::checkTetherCountingRuleExist(const char *pair_name) {
255f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    std::list<std::string>::iterator it;
256f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
257f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    for (it = ifacePairList.begin(); it != ifacePairList.end(); it++) {
258f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        if (*it == pair_name) {
259f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            /* We already have this counter */
260f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            return true;
261f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        }
262f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    }
263f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    return false;
264f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall}
265f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
266baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallint NatController::setTetherCountingRules(bool add, const char *intIface, const char *extIface) {
267baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
268baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    /* We only ever add tethering quota rules so that they stick. */
269baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (!add) {
270baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return 0;
271baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
27256afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran    char *pair_name;
273f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    asprintf(&pair_name, "%s_%s", intIface, extIface);
274f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
275f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    if (checkTetherCountingRuleExist(pair_name)) {
276f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
277baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return 0;
278baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
279baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    const char *cmd2b[] = {
280baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            IPTABLES_PATH,
281baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-A",
282baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN,
283baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-i",
284baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            intIface,
285baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-o",
286baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            extIface,
287baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-j",
288baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall          "RETURN"
289baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    };
290baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
291baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (runCmd(ARRAY_SIZE(cmd2b), cmd2b) && add) {
292f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
293baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return -1;
294baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
295f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    ifacePairList.push_front(pair_name);
296f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    free(pair_name);
297f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall
298f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    asprintf(&pair_name, "%s_%s", extIface, intIface);
299f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    if (checkTetherCountingRuleExist(pair_name)) {
300f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
301baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return 0;
302baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
303baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
304baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    const char *cmd3b[] = {
305baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            IPTABLES_PATH,
306baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-A",
307baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN,
308baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-i",
309baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            extIface,
310baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-o",
311baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            intIface,
312baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-j",
313baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "RETURN"
314baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    };
315baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
316baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (runCmd(ARRAY_SIZE(cmd3b), cmd3b) && add) {
317baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        // unwind what's been done, but don't care about success - what more could we do?
318f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        free(pair_name);
319baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        return -1;
320baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
321f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    ifacePairList.push_front(pair_name);
322f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall    free(pair_name);
323baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    return 0;
324baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall}
325baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
326baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrallint NatController::setForwardRules(bool add, const char *intIface, const char *extIface) {
327001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd1[] = {
328001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IPTABLES_PATH,
329001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            add ? "-A" : "-D",
330baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
331001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-i",
332001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            extIface,
333001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-o",
334001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            intIface,
335001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-m",
336001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "state",
337001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "--state",
338001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "ESTABLISHED,RELATED",
339baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-g",
340baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN
341001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
342001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    int rc = 0;
343001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
344001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (runCmd(ARRAY_SIZE(cmd1), cmd1) && add) {
3459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
3469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
3479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
348001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd2[] = {
349001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IPTABLES_PATH,
350001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            add ? "-A" : "-D",
351baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
352001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-i",
353001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            intIface,
354001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-o",
355001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            extIface,
356001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-m",
357001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "state",
358001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "--state",
359001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "INVALID",
360001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-j",
361001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "DROP"
362001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
363001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
364001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    const char *cmd3[] = {
365001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            IPTABLES_PATH,
366001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            add ? "-A" : "-D",
367baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_FORWARD,
368001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-i",
369001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            intIface,
370001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            "-o",
371001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand            extIface,
372baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            "-g",
373baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            LOCAL_TETHER_COUNTERS_CHAIN
374001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    };
375001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
376001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (runCmd(ARRAY_SIZE(cmd2), cmd2) && add) {
377f7bf29c8a37d65e132a4dceb7c5a4200ed5c3d79Robert Greenwalt        // bail on error, but only if adding
378001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        rc = -1;
379001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        goto err_invalid_drop;
380ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    }
381ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
382001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    if (runCmd(ARRAY_SIZE(cmd3), cmd3) && add) {
383210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        // unwind what's been done, but don't care about success - what more could we do?
384001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        rc = -1;
385001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand        goto err_return;
3869ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
3870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
388baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    if (setTetherCountingRules(add, intIface, extIface) && add) {
389baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        rc = -1;
390baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        goto err_return;
391baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall    }
392baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall
393fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
394001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand
395001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchanderr_return:
396001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    cmd2[1] = "-D";
397001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    runCmd(ARRAY_SIZE(cmd2), cmd2);
398001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchanderr_invalid_drop:
399001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    cmd1[1] = "-D";
400001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    runCmd(ARRAY_SIZE(cmd1), cmd1);
401001f0a436e9fe0353dccd98ee34b91095d9ed1a1Rom Lemarchand    return rc;
402fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
4039ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
404fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat disable intface extface
405fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
406fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
407fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::disableNat(const int argc, char **argv) {
408fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
409fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
410fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
411fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
412fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
4135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid interface specified");
414fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
415fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
4169ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
4179ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
418fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
4195ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Missing Argument");
420fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
421fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
422210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
4239ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
424fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    setForwardRules(false, intIface, extIface);
4254ae80dea9cbf1fe1b33037aeb5feb04daeba8ee0JP Abgrall    routesOp(false, intIface, extIface, argv, addrCount);
426fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (--natCount <= 0) {
4274ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
4284ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        setDefaults();
429fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
430fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
4319ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
432