NatController.cpp revision 1caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075
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> 249ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 259ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#define LOG_TAG "NatController" 269ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include <cutils/log.h> 279ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 289ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat#include "NatController.h" 299ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 309ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatextern "C" int logwrap(int argc, const char **argv, int background); 319ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 329ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatstatic char IPTABLES_PATH[] = "/system/bin/iptables"; 339ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 349ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::NatController() { 351caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt natCount = 0; 369ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 379ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 389ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() { 399ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 409ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 419ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::runIptablesCmd(const char *cmd) { 429ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char buffer[255]; 439ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 449ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat strncpy(buffer, cmd, sizeof(buffer)-1); 459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat const char *args[16]; 479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char *next = buffer; 489ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char *tmp; 499ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 509ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[0] = IPTABLES_PATH; 519ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[1] = "--verbose"; 529ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat int i = 2; 539ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 549ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat while ((tmp = strsep(&next, " "))) { 559ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[i++] = tmp; 569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (i == 16) { 579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat LOGE("iptables argument overflow"); 589ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat errno = E2BIG; 599ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 609ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 619ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 629ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[i] = NULL; 639ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return logwrap(i, args, 0); 659ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 669ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 679ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::setDefaults() { 689ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 699ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-P INPUT ACCEPT")) 709ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 719ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-F INPUT")) 729ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 739ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-P OUTPUT ACCEPT")) 749ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 759ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-F OUTPUT")) 769ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 779ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-P FORWARD DROP")) 789ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 799ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-F FORWARD")) 809ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 819ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-t nat -F")) 829ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 839ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return 0; 849ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 859ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 869ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatbool NatController::interfaceExists(const char *iface) { 879ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat // XXX: STOPSHIP - Implement this 889ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return true; 899ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 909ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 911caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwaltint NatController::doNatCommands(const char *intIface, const char *extIface, bool add) { 929ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char cmd[255]; 939ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 949ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (!interfaceExists(intIface) || !interfaceExists (extIface)) { 959ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat LOGE("Invalid interface specified"); 969ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat errno = ENODEV; 979ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 989ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 999ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1009ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat snprintf(cmd, sizeof(cmd), 1011caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 1021caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt (add ? "A" : "D"), 1039ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat extIface, intIface); 1049ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd(cmd)) { 1059ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 1069ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 1079ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1081caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"), 1091caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt intIface, extIface); 1109ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd(cmd)) { 1119ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 1129ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 1139ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1141caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt if (add && natCount == 0) { 1151caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface); 1161caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt if (runIptablesCmd(cmd)) { 1171caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return -1; 1181caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } 1191caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } else if (!add) { 1201caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt snprintf(cmd, sizeof(cmd), "-t nat -D POSTROUTING -o %s -j MASQUERADE", extIface); 1211caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt if (runIptablesCmd(cmd)) { 1221caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return -1; 1231caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } 1249ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 1259ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1269ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return 0; 1279ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 1289ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1291caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwaltint NatController::enableNat(const char *intIface, const char *extIface) { 1301caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt natCount++; 1311caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return doNatCommands(intIface, extIface, true); 1321caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt natCount++; 1331caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt} 1341caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt 1359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::disableNat(const char *intIface, const char *extIface) { 1361caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt if (natCount > 0) { 1371caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt if (natCount == 1) { 1381caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return setDefaults(); 1391caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } else { 1401caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return doNatCommands(intIface, extIface, false); 1411caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } 1421caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt natCount--; 1431caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } else { 1441caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt LOGE("Trying to disableNat with none enabled!"); 1451caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return setDefaults(); 1461caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } 1479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 148