NatController.cpp revision ff2c0d8c13457e43f0d4bf06d3177271aac104c1
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <errno.h> 19#include <sys/socket.h> 20#include <sys/stat.h> 21#include <fcntl.h> 22#include <netinet/in.h> 23#include <arpa/inet.h> 24#include <string.h> 25 26#define LOG_TAG "NatController" 27#include <cutils/log.h> 28 29#include "NatController.h" 30 31extern "C" int logwrap(int argc, const char **argv, int background); 32 33static char IPTABLES_PATH[] = "/system/bin/iptables"; 34 35NatController::NatController() { 36 natCount = 0; 37} 38 39NatController::~NatController() { 40} 41 42int NatController::runIptablesCmd(const char *cmd) { 43 char buffer[255]; 44 45 strncpy(buffer, cmd, sizeof(buffer)-1); 46 47 const char *args[16]; 48 char *next = buffer; 49 char *tmp; 50 51 args[0] = IPTABLES_PATH; 52 args[1] = "--verbose"; 53 int i = 2; 54 55 while ((tmp = strsep(&next, " "))) { 56 args[i++] = tmp; 57 if (i == 16) { 58 LOGE("iptables argument overflow"); 59 errno = E2BIG; 60 return -1; 61 } 62 } 63 args[i] = NULL; 64 65 return logwrap(i, args, 0); 66} 67 68int NatController::setDefaults() { 69 70 if (runIptablesCmd("-P INPUT ACCEPT")) 71 return -1; 72 if (runIptablesCmd("-F INPUT")) 73 return -1; 74 if (runIptablesCmd("-P OUTPUT ACCEPT")) 75 return -1; 76 if (runIptablesCmd("-F OUTPUT")) 77 return -1; 78 if (runIptablesCmd("-P FORWARD DROP")) 79 return -1; 80 if (runIptablesCmd("-F FORWARD")) 81 return -1; 82 if (runIptablesCmd("-t nat -F")) 83 return -1; 84 return 0; 85} 86 87bool NatController::interfaceExists(const char *iface) { 88 // XXX: Implement this 89 return true; 90} 91 92int NatController::doNatCommands(const char *intIface, const char *extIface, bool add) { 93 char cmd[255]; 94 95 // handle decrement to 0 case (do reset to defaults) and erroneous dec below 0 96 if (add == false) { 97 if (natCount <= 1) { 98 int ret = setDefaults(); 99 if (ret == 0) { 100 natCount=0; 101 } 102 return ret; 103 } 104 } 105 106 if (!interfaceExists(intIface) || !interfaceExists (extIface)) { 107 LOGE("Invalid interface specified"); 108 errno = ENODEV; 109 return -1; 110 } 111 112 snprintf(cmd, sizeof(cmd), 113 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 114 (add ? "A" : "D"), 115 extIface, intIface); 116 if (runIptablesCmd(cmd)) { 117 return -1; 118 } 119 120 snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"), 121 intIface, extIface); 122 if (runIptablesCmd(cmd)) { 123 // unwind what's been done, but don't care about success - what more could we do? 124 snprintf(cmd, sizeof(cmd), 125 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 126 (!add ? "A" : "D"), 127 extIface, intIface); 128 return -1; 129 } 130 131 // add this if we are the first added nat 132 if (add && natCount == 0) { 133 snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface); 134 if (runIptablesCmd(cmd)) { 135 // unwind what's been done, but don't care about success - what more could we do? 136 setDefaults();; 137 return -1; 138 } 139 } 140 141 if (add) { 142 natCount++; 143 } else { 144 natCount--; 145 } 146 return 0; 147} 148 149int NatController::enableNat(const char *intIface, const char *extIface) { 150 return doNatCommands(intIface, extIface, true); 151} 152 153int NatController::disableNat(const char *intIface, const char *extIface) { 154 return doNatCommands(intIface, extIface, false); 155} 156