NatController.cpp revision 4ab468577647d1ee73810b89d2287eaa5546fecb
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"
324ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include "oem_iptables_hook.h"
339ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
349e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command);
359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
369ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatstatic char IPTABLES_PATH[] = "/system/bin/iptables";
37fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltstatic char IP_PATH[] = "/system/bin/ip";
389ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
39fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltNatController::NatController(SecondaryTableController *ctrl) {
40fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    secondaryTableCtrl = ctrl;
41fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    setDefaults();
429ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
439ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
449ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() {
459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
47fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::runCmd(const char *path, const char *cmd) {
4811b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    char *buffer;
4911b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    size_t len = strnlen(cmd, 255);
5011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    int res;
519ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
5211b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    if (len == 255) {
53fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        LOGE("command too long");
5411b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        errno = E2BIG;
5511b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall        return -1;
569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
58fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    asprintf(&buffer, "%s %s", path, cmd);
599e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    res = system_nosh(buffer);
6011b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    free(buffer);
6111b4e9b26fe7b878992162afb39f5a8acfd143edJP Abgrall    return res;
629ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
639ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::setDefaults() {
659ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
66fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-P INPUT ACCEPT"))
679ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
68fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-P OUTPUT ACCEPT"))
699ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
70fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-P FORWARD DROP"))
719ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
72fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-F FORWARD"))
739ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
74fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, "-t nat -F"))
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
874ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    setupOemIptablesHook();
889ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return 0;
899ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
909ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
91fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltbool NatController::checkInterface(const char *iface) {
92fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (strlen(iface) > MAX_IFACE_LENGTH) return false;
939ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return true;
949ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
959ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
96063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwaltconst char *NatController::getVersion(const char *addr) {
97063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    if (strchr(addr, ':') != NULL) {
98063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        return "-6";
99063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    } else {
100063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        return "-4";
101063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt    }
102063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt}
103063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
104fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
105fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
106fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::enableNat(const int argc, char **argv) {
1079ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    char cmd[255];
108fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
109fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
110fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int ret = 0;
111fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
112fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
113fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableNumber;
114fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
115fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
116fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        LOGE("Invalid interface specified");
117fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
118fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
119fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
1209ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
121fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
122fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        LOGE("Missing Argument");
123fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
124fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
125fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
126fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
127fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    tableNumber = secondaryTableCtrl->findTableNumber(extIface);
128fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableNumber != -1) {
129fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        for(i = 0; i < addrCount && ret == 0; i++) {
130063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            snprintf(cmd, sizeof(cmd), "%s rule add from %s table %d", getVersion(argv[5+i]),
131063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                    argv[5+i], tableNumber + BASE_TABLE_NUMBER);
132fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            ret |= runCmd(IP_PATH, cmd);
133fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            if (ret) LOGE("IP rule %s got %d", cmd, ret);
134fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
135fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            snprintf(cmd, sizeof(cmd), "route add %s dev %s table %d", argv[5+i], intIface,
136fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                    tableNumber + BASE_TABLE_NUMBER);
137fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            ret |= runCmd(IP_PATH, cmd);
138fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            if (ret) LOGE("IP route %s got %d", cmd, ret);
139210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        }
140063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        runCmd(IP_PATH, "route flush cache");
141210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
142210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt
143fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (ret != 0 || setForwardRules(true, intIface, extIface) != 0) {
144fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (tableNumber != -1) {
145fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            for (i = 0; i < addrCount; i++) {
146fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
147fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                        tableNumber + BASE_TABLE_NUMBER);
148fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                runCmd(IP_PATH, cmd);
149fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
150063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                snprintf(cmd, sizeof(cmd), "%s rule del from %s table %d", getVersion(argv[5+i]),
151063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                        argv[5+i], tableNumber + BASE_TABLE_NUMBER);
152fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                runCmd(IP_PATH, cmd);
153fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            }
154063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            runCmd(IP_PATH, "route flush cache");
155fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
156fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        LOGE("Error setting forward rules");
1579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        errno = ENODEV;
1589ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1599ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1609ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
161fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    natCount++;
162fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    // add this if we are the first added nat
163fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (natCount == 1) {
164fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface);
165fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        if (runCmd(IPTABLES_PATH, cmd)) {
166fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            LOGE("Error seting postroute rule: %s", cmd);
167fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // unwind what's been done, but don't care about success - what more could we do?
168fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            for (i = 0; i < addrCount; i++) {
169fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
170fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                        tableNumber + BASE_TABLE_NUMBER);
171fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                runCmd(IP_PATH, cmd);
172fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            }
173fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            setDefaults();
174fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            return -1;
175fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
176fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
177fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
178fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
179fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
180fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
181fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::setForwardRules(bool add, const char *intIface, const char * extIface) {
182fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    char cmd[255];
183fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
1849ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    snprintf(cmd, sizeof(cmd),
1851caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt             "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
1861caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt             (add ? "A" : "D"),
1879ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat             extIface, intIface);
188fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
1899ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1909ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1919ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
192ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    snprintf(cmd, sizeof(cmd),
193ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
194ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            (add ? "A" : "D"),
195ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            intIface, extIface);
196fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
197f7bf29c8a37d65e132a4dceb7c5a4200ed5c3d79Robert Greenwalt        // bail on error, but only if adding
198ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        snprintf(cmd, sizeof(cmd),
199ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
200ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                (!add ? "A" : "D"),
201ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                extIface, intIface);
202fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
203ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        return -1;
204ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    }
205ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
2061caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt    snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"),
2071caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt            intIface, extIface);
208fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (runCmd(IPTABLES_PATH, cmd) && add) {
209210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        // unwind what's been done, but don't care about success - what more could we do?
210210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        snprintf(cmd, sizeof(cmd),
211ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
212ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                (!add ? "A" : "D"),
213ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt                intIface, extIface);
214fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
215ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt
216ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        snprintf(cmd, sizeof(cmd),
217210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
218210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 (!add ? "A" : "D"),
219210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt                 extIface, intIface);
220fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        runCmd(IPTABLES_PATH, cmd);
2219ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
2229ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
223fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
224fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt}
2259ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
226fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat disable intface extface
227fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt//  0    1       2       3       4            5
228fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt// nat enable intface extface addrcnt nated-ipaddr/prelength
229fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint NatController::disableNat(const int argc, char **argv) {
230fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    char cmd[255];
231fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int i;
232fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int addrCount = atoi(argv[4]);
233fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *intIface = argv[2];
234fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    const char *extIface = argv[3];
235fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    int tableNumber;
236fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
237fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (!checkInterface(intIface) || !checkInterface(extIface)) {
238fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        LOGE("Invalid interface specified");
239fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = ENODEV;
240fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
2419ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
2429ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
243fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5 + addrCount) {
244fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        LOGE("Missing Argument");
245fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        errno = EINVAL;
246fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        return -1;
247210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
2489ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
249fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    setForwardRules(false, intIface, extIface);
2501caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt
251fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    tableNumber = secondaryTableCtrl->findTableNumber(extIface);
252fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (tableNumber != -1) {
253fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        for (i = 0; i < addrCount; i++) {
254fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            snprintf(cmd, sizeof(cmd), "route del %s dev %s table %d", argv[5+i], intIface,
255fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt                    tableNumber + BASE_TABLE_NUMBER);
256fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // if the interface has gone down these will be gone already and give errors
257fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            // ignore them.
258fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt            runCmd(IP_PATH, cmd);
259063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
260063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            snprintf(cmd, sizeof(cmd), "%s rule del from %s table %d", getVersion(argv[5+i]),
261063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt                    argv[5+i], tableNumber + BASE_TABLE_NUMBER);
262063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt            runCmd(IP_PATH, cmd);
263fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        }
264063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt
265063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt        runCmd(IP_PATH, "route flush cache");
266fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
267fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt
268fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (--natCount <= 0) {
2694ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
2704ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        setDefaults();
271fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    }
272fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    return 0;
2739ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
274