NatController.cpp revision 5ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13
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
179ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <stdlib.h>
189ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <errno.h>
199ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <sys/socket.h>
209ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <sys/stat.h>
219ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <fcntl.h>
229ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <netinet/in.h>
239ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <arpa/inet.h>
24ff2c0d8c13457e43f0d4bf06d3177271aac104c1Olivier Bailly#include <string.h>
25ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau#include <cutils/properties.h>
269ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
279ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#define LOG_TAG "NatController"
289ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <cutils/log.h>
299ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
309ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include "NatController.h"
31fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "SecondaryTableController.h"
329ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
339e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command);
349ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatstatic char IPTABLES_PATH[] = "/system/bin/iptables";
36fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltstatic char IP_PATH[] = "/system/bin/ip";
379ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
38fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltNatController::NatController(SecondaryTableController *ctrl) {
39fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    secondaryTableCtrl = ctrl;
40fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    setDefaults();
419ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
429ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
439ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() {
449ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
46fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::runCmd(const char *path, const char *cmd) {
4711b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    char *buffer;
4811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    size_t len = strnlen(cmd, 255);
4911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
509ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
5111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    if (len == 255) {
525ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("command too long");
5311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        errno = E2BIG;
5411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        return -1;
559ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
57fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    asprintf(&buffer, "%s %s", path, cmd);
589e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    res = system_nosh(buffer);
5911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    free(buffer);
6011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
619ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
629ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
639ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::setDefaults() {
649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
65fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-P INPUT ACCEPT"))
669ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
67fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-P OUTPUT ACCEPT"))
689ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
69fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-P FORWARD DROP"))
709ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
71fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-F FORWARD"))
729ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
73fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-t nat -F"))
749ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
75fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
76fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    runCmd(IP_PATH, "rule flush");
77063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "-6 rule flush");
78fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    runCmd(IP_PATH, "rule add from all lookup default prio 32767");
79fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    runCmd(IP_PATH, "rule add from all lookup main prio 32766");
80063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "-6 rule add from all lookup default prio 32767");
81063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "-6 rule add from all lookup main prio 32766");
82063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "route flush cache");
83fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
84fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    natCount = 0;
859ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return 0;
869ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
879ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
88fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltbool NatController::checkInterface(const char *iface) {
89fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (strlen(iface) > MAX_IFACE_LENGTH) return false;
909ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return true;
919ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
929ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
93063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwaltconst char *NatController::getVersion(const char *addr) {
94063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    if (strchr(addr, ':') != NULL) {
95063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        return "-6";
96063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    } else {
97063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        return "-4";
98063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    }
99063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt}
100063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
101fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
102fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
103fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::enableNat(const int argc, char **argv) {
1049ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    char cmd[255];
105fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
106fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
107fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int ret = 0;
108fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
109fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
110fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableNumber;
111fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
112fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
1135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid interface specified");
114fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
115fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
116fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
1179ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
118fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
1195ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Missing Argument");
120fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
121fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
122fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
123fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
124fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    tableNumber = secondaryTableCtrl->findTableNumber(extIface);
125fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableNumber != -1) {
126fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        for(i = 0; i < addrCount && ret == 0; i++) {
127063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            snprintf(cmd, sizeof(cmd), "%s rule add from %s table %d", getVersion(argv[5+i]),
128063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                    argv[5+i], tableNumber + BASE_TABLE_NUMBER);
129fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            ret |= runCmd(IP_PATH, cmd);
1305ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            if (ret) ALOGE("IP rule %s got %d", cmd, ret);
131fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
132fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            snprintf(cmd, sizeof(cmd), "route add %s dev %s table %d", argv[5+i], intIface,
133fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                    tableNumber + BASE_TABLE_NUMBER);
134fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            ret |= runCmd(IP_PATH, cmd);
1355ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            if (ret) ALOGE("IP route %s got %d", cmd, ret);
136210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        }
137063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        runCmd(IP_PATH, "route flush cache");
138210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
139210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt
140fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (ret != 0 || setForwardRules(true, intIface, extIface) != 0) {
141fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (tableNumber != -1) {
142fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            for (i = 0; i < addrCount; i++) {
143fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
144fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                        tableNumber + BASE_TABLE_NUMBER);
145fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                runCmd(IP_PATH, cmd);
146fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
147063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                snprintf(cmd, sizeof(cmd), "%s rule del from %s table %d", getVersion(argv[5+i]),
148063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                        argv[5+i], tableNumber + BASE_TABLE_NUMBER);
149fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                runCmd(IP_PATH, cmd);
150fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            }
151063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            runCmd(IP_PATH, "route flush cache");
152fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
1535ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Error setting forward rules");
1549ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        errno = ENODEV;
1559ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
158fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    natCount++;
159fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    // add this if we are the first added nat
160fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (natCount == 1) {
161fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface);
162fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (runCmd(IPTABLES_PATH, cmd)) {
1635ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Error seting postroute rule: %s", cmd);
164fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // unwind what's been done, but don't care about success - what more could we do?
165fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            for (i = 0; i < addrCount; i++) {
166fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
167fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                        tableNumber + BASE_TABLE_NUMBER);
168fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                runCmd(IP_PATH, cmd);
169fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            }
170fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            setDefaults();
171fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            return -1;
172fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
173fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
174fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
175fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
176fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
177fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
178fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::setForwardRules(bool add, const char *intIface, const char * extIface) {
179fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    char cmd[255];
180fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
1819ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    snprintf(cmd, sizeof(cmd),
1821caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt             "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
1831caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt             (add ? "A" : "D"),
1849ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat             extIface, intIface);
185fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
1869ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1879ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1889ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
189ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    snprintf(cmd, sizeof(cmd),
190ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
191ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            (add ? "A" : "D"),
192ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            intIface, extIface);
193fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
194f7bf29c8a37d65e132a4dceb7c5a4200ed5c3d79Robert Greenwalt        // bail on error, but only if adding
195ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        snprintf(cmd, sizeof(cmd),
196ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
197ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                (!add ? "A" : "D"),
198ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                extIface, intIface);
199fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
200ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        return -1;
201ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    }
202ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
2031caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt    snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"),
2041caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt            intIface, extIface);
205fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
206210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        // unwind what's been done, but don't care about success - what more could we do?
207210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        snprintf(cmd, sizeof(cmd),
208ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
209ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                (!add ? "A" : "D"),
210ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                intIface, extIface);
211fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
212ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
213ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        snprintf(cmd, sizeof(cmd),
214210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
215210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 (!add ? "A" : "D"),
216210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 extIface, intIface);
217fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
2189ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
2199ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
220fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
221fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
2229ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
223fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat disable intface extface
224fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
225fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
226fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::disableNat(const int argc, char **argv) {
227fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    char cmd[255];
228fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
229fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
230fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
231fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
232fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableNumber;
233fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
234fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
2355ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid interface specified");
236fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
237fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
2389ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
2399ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
240fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
2415ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Missing Argument");
242fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
243fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
244210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
2459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
246fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    setForwardRules(false, intIface, extIface);
2471caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt
248fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    tableNumber = secondaryTableCtrl->findTableNumber(extIface);
249fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableNumber != -1) {
250fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        for (i = 0; i < addrCount; i++) {
251fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
252fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                    tableNumber + BASE_TABLE_NUMBER);
253fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // if the interface has gone down these will be gone already and give errors
254fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // ignore them.
255fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            runCmd(IP_PATH, cmd);
256063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
257063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            snprintf(cmd, sizeof(cmd), "%s rule del from %s table %d", getVersion(argv[5+i]),
258063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                    argv[5+i], tableNumber + BASE_TABLE_NUMBER);
259063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            runCmd(IP_PATH, cmd);
260fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
261063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
262063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        runCmd(IP_PATH, "route flush cache");
263fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
264fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
265fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (--natCount <= 0) {
266fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        char bootmode[PROPERTY_VALUE_MAX] = {0};
267fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        property_get("ro.bootmode", bootmode, "unknown");
268fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (0 != strcmp("bp-tools", bootmode)) {
269fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
270fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            setDefaults();
271fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
272fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        natCount = 0;
273fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
274fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
2759ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
276