NatController.cpp revision 6e4d5db1b11f808bb4bdcc8dd45a7158c6c88515
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>
184309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville#include <sys/wait.h>
199ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <errno.h>
209ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <sys/socket.h>
219ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <sys/stat.h>
229ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <fcntl.h>
239ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <netinet/in.h>
249ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <arpa/inet.h>
259ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
269ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#define LOG_TAG "NatController"
279ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <cutils/log.h>
289ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
299ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include "NatController.h"
309ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
319ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatextern "C" int logwrap(int argc, const char **argv, int background);
329ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
339ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatstatic char IPTABLES_PATH[] = "/system/bin/iptables";
344309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Savillestatic char OEM_SCRIPT_PATH[] = "/system/bin/oem-iptables-init.sh";
359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
364309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink SavilleNatController::NatController() : mOemChainsExist(false) {
371caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt    natCount = 0;
384309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
394309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    setDefaults();
404309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
414309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (0 == access(OEM_SCRIPT_PATH, R_OK | X_OK)) {
424309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        // The call to oemCleanupHooks() is superfluous when done on bootup,
434309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        // but is needed for the case where netd has crashed/stopped and is
444309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        // restarted.
454309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        if (!oemCleanupHooks() && !oemSetupHooks() && !oemInitChains()) {
464309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            mOemChainsExist = true;
474309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        }
484309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    }
499ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
509ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
519ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() {
529ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
539ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
549ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::runIptablesCmd(const char *cmd) {
559ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    char buffer[255];
569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    strncpy(buffer, cmd, sizeof(buffer)-1);
589ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
599ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    const char *args[16];
609ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    char *next = buffer;
619ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    char *tmp;
629ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
639ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    args[0] = IPTABLES_PATH;
649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    args[1] = "--verbose";
659ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    int i = 2;
669ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
679ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    while ((tmp = strsep(&next, " "))) {
689ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        args[i++] = tmp;
699ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        if (i == 16) {
709ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat            LOGE("iptables argument overflow");
719ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat            errno = E2BIG;
729ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat            return -1;
739ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        }
749ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
759ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    args[i] = NULL;
769ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
779ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return logwrap(i, args, 0);
789ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
799ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
809ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::setDefaults() {
819ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
829ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (runIptablesCmd("-P INPUT ACCEPT"))
839ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
849ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (runIptablesCmd("-P OUTPUT ACCEPT"))
859ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
869ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (runIptablesCmd("-P FORWARD DROP"))
879ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
889ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (runIptablesCmd("-F FORWARD"))
899ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
904309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
914309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (runIptablesCmd("-t nat -F PREROUTING"))
924309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        return -1;
934309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (runIptablesCmd("-t nat -F OUTPUT"))
949ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
954309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (runIptablesCmd("-t nat -F POSTROUTING"))
964309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        return -1;
974309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
984309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    return 0;
994309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville}
1004309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1014309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Savilleint NatController::oemSetupHooks() {
1024309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // Order is important!
1034309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // -N to create the chain (no-op if already exist).
1044309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // -D to delete any pre-existing jump rule, to prevent dupes (no-op if doesn't exist)
1054309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // -I to insert our jump rule into the default chain
1064309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1074309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-N oem_out");
1084309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-D OUTPUT -j oem_out");
1094309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (runIptablesCmd("-I OUTPUT -j oem_out"))
1104309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        return -1;
1114309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1124309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-N oem_fwd");
1134309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-D FORWARD -j oem_fwd");
1144309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (runIptablesCmd("-I FORWARD -j oem_fwd"))
1154309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        return -1;
1164309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1174309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-t nat -N oem_nat_pre");
1184309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre");
1194309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (runIptablesCmd("-t nat -I PREROUTING -j oem_nat_pre"))
1204309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        return -1;
1214309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1224309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    return 0;
1234309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville}
1244309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1254309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Savilleint NatController::oemCleanupHooks() {
1264309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // Order is important!
1274309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // -D to remove ref to the chain
1284309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // -F to empty the chain
1294309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // -X to delete the chain
1304309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1314309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-D OUTPUT -j oem_out");
1324309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-F oem_out");
1334309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-X oem_out");
1344309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1354309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-D FORWARD -j oem_fwd");
1364309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-F oem_fwd");
1374309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-X oem_fwd");
1384309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1394309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre");
1404309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-t nat -F oem_nat_pre");
1414309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    runIptablesCmd("-t nat -X oem_nat_pre");
1424309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1434309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    return 0;
1444309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville}
1454309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville
1464309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville// This method should only be called when netd starts up.  The OEM chains are
1474309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville// intended to be static, so there's no need to flush and recreate them every
1484309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville// time setDefaults() is called.
1494309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Savilleint NatController::oemInitChains() {
1504309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    int ret = system(OEM_SCRIPT_PATH);
1514309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if ((-1 == ret) || (0 != WEXITSTATUS(ret))) {
1524309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        LOGE("%s failed: %s", OEM_SCRIPT_PATH, strerror(errno));
1534309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        return -1;
1544309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    }
1559ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return 0;
1569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
1579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
1589ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatbool NatController::interfaceExists(const char *iface) {
159b5ff9b277f256df84caf3d798ccc83b4740a1d31Paul Eastham    // XXX: Implement this
1609ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return true;
1619ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
1629ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
1631caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwaltint NatController::doNatCommands(const char *intIface, const char *extIface, bool add) {
1649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    char cmd[255];
1659ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
1664309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0
1674309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville    if (add == false) {
1684309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville        if (natCount <= 1) {
1694309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            int ret = setDefaults();
1704309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            if (ret == 0) {
1714309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville                natCount=0;
172210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt            }
1734309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            if (mOemChainsExist)
1744309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville                oemSetupHooks();
1754309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            return ret;
176210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        }
177210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
178210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt
1799ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (!interfaceExists(intIface) || !interfaceExists (extIface)) {
1809ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        LOGE("Invalid interface specified");
1819ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        errno = ENODEV;
1829ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1839ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1849ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
1859ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    snprintf(cmd, sizeof(cmd),
1861caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt             "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT",
1871caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt             (add ? "A" : "D"),
1889ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat             extIface, intIface);
1899ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (runIptablesCmd(cmd)) {
1909ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
1919ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
1929ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
193ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    snprintf(cmd, sizeof(cmd),
194ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP",
195ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            (add ? "A" : "D"),
196ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt            intIface, extIface);
197ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt    if (runIptablesCmd(cmd)) {
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);
2026e4d5db1b11f808bb4bdcc8dd45a7158c6c88515Robert Greenwalt        runIptablesCmd(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);
2089ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (runIptablesCmd(cmd)) {
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);
214ddb9f6eb8d8c35f46c1e3da68f375b85903e85c9Robert Greenwalt        runIptablesCmd(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);
2206e4d5db1b11f808bb4bdcc8dd45a7158c6c88515Robert Greenwalt        runIptablesCmd(cmd);
2219ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat        return -1;
2229ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
2239ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
224210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    // add this if we are the first added nat
2251caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt    if (add && natCount == 0) {
2261caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt        snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface);
2271caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt        if (runIptablesCmd(cmd)) {
2284309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            // unwind what's been done, but don't care about success - what more could we do?
2294309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            setDefaults();;
2304309f87d5baa54a2741f35e0cb09959c55ff1ab6Wink Saville            oemSetupHooks();
2311caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt            return -1;
2321caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt        }
2339ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    }
2349ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
235210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    if (add) {
236210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        natCount++;
237210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    } else {
238210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt        natCount--;
239210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    }
2409ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    return 0;
2419ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
2429ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat
2431caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwaltint NatController::enableNat(const char *intIface, const char *extIface) {
2441caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt    return doNatCommands(intIface, extIface, true);
2451caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt}
2461caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt
2479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::disableNat(const char *intIface, const char *extIface) {
248210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt    return doNatCommands(intIface, extIface, false);
2499ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat}
250