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
170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP 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>
239ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <fcntl.h>
249ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <netinet/in.h>
259ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <arpa/inet.h>
26ff2c0d8c13457e43f0d4bf06d3177271aac104c1Olivier Bailly#include <string.h>
27ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau#include <cutils/properties.h>
289ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
299ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#define LOG_TAG "NatController"
309ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <cutils/log.h>
319ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
329ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include "NatController.h"
33fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "SecondaryTableController.h"
34c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt#include "NetdConstants.h"
359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
369e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command);
379ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
388e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* NatController::LOCAL_FORWARD = "natctrl_FORWARD";
398e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeyconst char* NatController::LOCAL_NAT_POSTROUTING = "natctrl_nat_POSTROUTING";
408e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
41fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltNatController::NatController(SecondaryTableController *ctrl) {
42fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    secondaryTableCtrl = ctrl;
439ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
449ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
459ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() {
469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
48fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::runCmd(const char *path, const char *cmd) {
4911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    char *buffer;
5011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    size_t len = strnlen(cmd, 255);
5111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
529ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
5311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    if (len == 255) {
545ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("command too long");
5511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        errno = E2BIG;
5611b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        return -1;
579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
589ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
59fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    asprintf(&buffer, "%s %s", path, cmd);
609e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    res = system_nosh(buffer);
610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    ALOGV("runCmd() buffer='%s' res=%d", buffer, res);
6211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    free(buffer);
6311b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
659ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
660031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint NatController::setupIptablesHooks() {
67458f318280c3b98d84958c63899c949c71612b1aJP Abgrall    setDefaults();
680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
690031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint NatController::setDefaults() {
720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (runCmd(IPTABLES_PATH, "-F natctrl_FORWARD"))
730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return -1;
740031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (runCmd(IPTABLES_PATH, "-t nat -F natctrl_nat_POSTROUTING"))
759ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
76fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
77fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    runCmd(IP_PATH, "rule flush");
78063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "-6 rule flush");
79fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    runCmd(IP_PATH, "rule add from all lookup default prio 32767");
80fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    runCmd(IP_PATH, "rule add from all lookup main prio 32766");
81063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "-6 rule add from all lookup default prio 32767");
82063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "-6 rule add from all lookup main prio 32766");
83063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    runCmd(IP_PATH, "route flush cache");
84fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
85fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    natCount = 0;
864ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
879ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return 0;
889ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
899ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
90fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltbool NatController::checkInterface(const char *iface) {
91d14fd4f83ffeea4ad1cd559a41f775f6814565ccJaime A Lopez-Sollano    if (strlen(iface) > IFNAMSIZ) return false;
929ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return true;
939ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
949ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
95fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
96fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
97fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::enableNat(const int argc, char **argv) {
989ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    char cmd[255];
99fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
100fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
101fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int ret = 0;
102fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
103fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
104fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableNumber;
105fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
106fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
1075ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid interface specified");
108fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
109fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
110fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
1119ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
112fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
1135ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Missing Argument");
114fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
115fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
116fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
117fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
118fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    tableNumber = secondaryTableCtrl->findTableNumber(extIface);
119fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableNumber != -1) {
120c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt        for(i = 0; i < addrCount; i++) {
121c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            ret |= secondaryTableCtrl->modifyFromRule(tableNumber, ADD, argv[5+i]);
122c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
123c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            ret |= secondaryTableCtrl->modifyLocalRoute(tableNumber, ADD, intIface, argv[5+i]);
124210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        }
125063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        runCmd(IP_PATH, "route flush cache");
126210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
127210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt
128fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (ret != 0 || setForwardRules(true, intIface, extIface) != 0) {
129fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (tableNumber != -1) {
130fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            for (i = 0; i < addrCount; i++) {
131c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt                secondaryTableCtrl->modifyLocalRoute(tableNumber, DEL, intIface, argv[5+i]);
132fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
133c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt                secondaryTableCtrl->modifyFromRule(tableNumber, DEL, argv[5+i]);
134fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            }
135063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            runCmd(IP_PATH, "route flush cache");
136fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
1375ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Error setting forward rules");
1389ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        errno = ENODEV;
1399ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1409ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1419ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
1420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /* Always make sure the drop rule is at the end */
1430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-D natctrl_FORWARD -j DROP");
1440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCmd(IPTABLES_PATH, cmd);
1450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-A natctrl_FORWARD -j DROP");
1460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    runCmd(IPTABLES_PATH, cmd);
1470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
1480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
149fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    natCount++;
150fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    // add this if we are the first added nat
151fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (natCount == 1) {
1520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        snprintf(cmd, sizeof(cmd), "-t nat -A natctrl_nat_POSTROUTING -o %s -j MASQUERADE", extIface);
153fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (runCmd(IPTABLES_PATH, cmd)) {
1545ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("Error seting postroute rule: %s", cmd);
155fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // unwind what's been done, but don't care about success - what more could we do?
156fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            for (i = 0; i < addrCount; i++) {
157c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt                secondaryTableCtrl->modifyLocalRoute(tableNumber, DEL, intIface, argv[5+i]);
158c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
159c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt                secondaryTableCtrl->modifyFromRule(tableNumber, DEL, argv[5+i]);
160fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            }
161fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            setDefaults();
162fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            return -1;
163fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
164fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
165fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
166fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
167fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
168fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
169fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::setForwardRules(bool add, const char *intIface, const char * extIface) {
170fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    char cmd[255];
171fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
1729ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    snprintf(cmd, sizeof(cmd),
1730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall             "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
1741caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt             (add ? "A" : "D"),
1759ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat             extIface, intIface);
176fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
1779ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1789ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1799ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
180ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    snprintf(cmd, sizeof(cmd),
1810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            "-%s natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
182ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            (add ? "A" : "D"),
183ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            intIface, extIface);
184fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
185f7bf29c8a37d65e132a4dceb7c5a4200ed5c3d79Robert Greenwalt        // bail on error, but only if adding
186ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        snprintf(cmd, sizeof(cmd),
1870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
188ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                (!add ? "A" : "D"),
189ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                extIface, intIface);
190fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
191ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        return -1;
192ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    }
193ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
1940031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    snprintf(cmd, sizeof(cmd), "-%s natctrl_FORWARD -i %s -o %s -j RETURN", (add ? "A" : "D"),
1951caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt            intIface, extIface);
196fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
197210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        // unwind what's been done, but don't care about success - what more could we do?
198210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        snprintf(cmd, sizeof(cmd),
1990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                "-%s natctrl_FORWARD -i %s -o %s -m state --state INVALID -j DROP",
200ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                (!add ? "A" : "D"),
201ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                intIface, extIface);
202fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
203ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
204ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        snprintf(cmd, sizeof(cmd),
2050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall                 "-%s natctrl_FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j RETURN",
206210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 (!add ? "A" : "D"),
207210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 extIface, intIface);
208fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
2099ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
2109ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
2110031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
212fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
213fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
2149ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
215fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat disable intface extface
216fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
217fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
218fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::disableNat(const int argc, char **argv) {
219fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    char cmd[255];
220fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
221fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
222fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
223fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
224fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableNumber;
225fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
226fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
2275ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Invalid interface specified");
228fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
229fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
2309ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
2319ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
232fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
2335ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("Missing Argument");
234fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
235fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
236210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
2379ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
238fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    setForwardRules(false, intIface, extIface);
2391caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt
240fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    tableNumber = secondaryTableCtrl->findTableNumber(extIface);
241fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableNumber != -1) {
242fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        for (i = 0; i < addrCount; i++) {
243c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            secondaryTableCtrl->modifyLocalRoute(tableNumber, DEL, intIface, argv[5+i]);
244c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt
245c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt            secondaryTableCtrl->modifyFromRule(tableNumber, DEL, argv[5+i]);
246fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
247063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
248063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        runCmd(IP_PATH, "route flush cache");
249fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
250fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
251fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (--natCount <= 0) {
2524ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
2534ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        setDefaults();
254fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
255fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
2569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
257