NatController.cpp revision ac208608c9e10ef199fdd11c38a31675ee9290c0
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" 319ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 329ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatextern "C" int logwrap(int argc, const char **argv, int background); 339ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 349ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatstatic char IPTABLES_PATH[] = "/system/bin/iptables"; 359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 369ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::NatController() { 371caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt natCount = 0; 389ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 399ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 409ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController::~NatController() { 419ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 429ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 439ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::runIptablesCmd(const char *cmd) { 449ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char buffer[255]; 459ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat strncpy(buffer, cmd, sizeof(buffer)-1); 479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 489ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat const char *args[16]; 499ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char *next = buffer; 509ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char *tmp; 519ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 529ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[0] = IPTABLES_PATH; 539ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[1] = "--verbose"; 549ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat int i = 2; 559ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 569ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat while ((tmp = strsep(&next, " "))) { 579ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[i++] = tmp; 589ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (i == 16) { 599ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat LOGE("iptables argument overflow"); 609ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat errno = E2BIG; 619ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 629ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 639ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 649ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat args[i] = NULL; 659ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 669ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return logwrap(i, args, 0); 679ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 689ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 699ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::setDefaults() { 709ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 719ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-P INPUT ACCEPT")) 729ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 739ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-F INPUT")) 749ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 759ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-P OUTPUT ACCEPT")) 769ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 779ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-F OUTPUT")) 789ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 799ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-P FORWARD DROP")) 809ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 819ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-F FORWARD")) 829ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 839ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd("-t nat -F")) 849ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 859ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return 0; 869ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 879ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 889ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatbool NatController::interfaceExists(const char *iface) { 89b5ff9b277f256df84caf3d798ccc83b4740a1d31Paul Eastham // XXX: Implement this 909ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return true; 919ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 929ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 931caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwaltint NatController::doNatCommands(const char *intIface, const char *extIface, bool add) { 949ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat char cmd[255]; 959ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 96ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau char bootmode[PROPERTY_VALUE_MAX] = {0}; 97ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau property_get("ro.bootmode", bootmode, "unknown"); 98ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau if (0 != strcmp("bp-tools", bootmode)) { 99ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0 100ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau if (add == false) { 101ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau if (natCount <= 1) { 102ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau int ret = setDefaults(); 103ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau if (ret == 0) { 104ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau natCount=0; 105ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau } 106ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau return ret; 107210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt } 108210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt } 109210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt } 110210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt 1119ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (!interfaceExists(intIface) || !interfaceExists (extIface)) { 1129ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat LOGE("Invalid interface specified"); 1139ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat errno = ENODEV; 1149ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 1159ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 1169ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1179ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat snprintf(cmd, sizeof(cmd), 1181caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 1191caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt (add ? "A" : "D"), 1209ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat extIface, intIface); 1219ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd(cmd)) { 1229ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 1239ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 1249ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1251caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"), 1261caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt intIface, extIface); 1279ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat if (runIptablesCmd(cmd)) { 128210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt // unwind what's been done, but don't care about success - what more could we do? 129210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt snprintf(cmd, sizeof(cmd), 130210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 131210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt (!add ? "A" : "D"), 132210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt extIface, intIface); 1339ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return -1; 1349ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 1359ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 136210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt // add this if we are the first added nat 1371caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt if (add && natCount == 0) { 1381caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface); 1391caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt if (runIptablesCmd(cmd)) { 140ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau if (0 != strcmp("bp-tools", bootmode)) { 141ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau // unwind what's been done, but don't care about success - what more could we do? 142ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau setDefaults();; 143ac208608c9e10ef199fdd11c38a31675ee9290c0John Michelau } 1441caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return -1; 1451caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt } 1469ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat } 1479ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 148210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt if (add) { 149210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt natCount++; 150210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt } else { 151210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt natCount--; 152210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt } 1539ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat return 0; 1549ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 1559ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat 1561caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwaltint NatController::enableNat(const char *intIface, const char *extIface) { 1571caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt return doNatCommands(intIface, extIface, true); 1581caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt} 1591caafe66a6b927fa5d8eb4c59ec9eb48b0b1b075Robert Greenwalt 1609ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehatint NatController::disableNat(const char *intIface, const char *extIface) { 161210b97745e14830cdb1f29ee1109e6e516f4e6f6Robert Greenwalt return doNatCommands(intIface, extIface, false); 1629ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat} 163