NatController.cpp revision 6ccebd085f8df439447ffe6060206a0a5af8d448
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#include <cutils/properties.h> 26 27#define LOG_TAG "NatController" 28#include <cutils/log.h> 29 30#include "NatController.h" 31 32extern "C" int logwrap(int argc, const char **argv, int background); 33 34static char IPTABLES_PATH[] = "/system/bin/iptables"; 35 36NatController::NatController() { 37 natCount = 0; 38} 39 40NatController::~NatController() { 41} 42 43int NatController::runIptablesCmd(const char *cmd) { 44 char buffer[255]; 45 46 strncpy(buffer, cmd, sizeof(buffer)-1); 47 48 const char *args[16]; 49 char *next = buffer; 50 char *tmp; 51 52 args[0] = IPTABLES_PATH; 53 args[1] = "--verbose"; 54 int i = 2; 55 56 while ((tmp = strsep(&next, " "))) { 57 args[i++] = tmp; 58 if (i == 16) { 59 LOGE("iptables argument overflow"); 60 errno = E2BIG; 61 return -1; 62 } 63 } 64 args[i] = NULL; 65 66 return logwrap(i, args, 0); 67} 68 69int NatController::setDefaults() { 70 71 if (runIptablesCmd("-P INPUT ACCEPT")) 72 return -1; 73 if (runIptablesCmd("-P OUTPUT ACCEPT")) 74 return -1; 75 if (runIptablesCmd("-P FORWARD DROP")) 76 return -1; 77 if (runIptablesCmd("-F FORWARD")) 78 return -1; 79 if (runIptablesCmd("-t nat -F")) 80 return -1; 81 return 0; 82} 83 84bool NatController::interfaceExists(const char *iface) { 85 // XXX: Implement this 86 return true; 87} 88 89int NatController::doNatCommands(const char *intIface, const char *extIface, bool add) { 90 char cmd[255]; 91 92 char bootmode[PROPERTY_VALUE_MAX] = {0}; 93 property_get("ro.bootmode", bootmode, "unknown"); 94 if (0 != strcmp("bp-tools", bootmode)) { 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 107 if (!interfaceExists(intIface) || !interfaceExists (extIface)) { 108 LOGE("Invalid interface specified"); 109 errno = ENODEV; 110 return -1; 111 } 112 113 snprintf(cmd, sizeof(cmd), 114 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 115 (add ? "A" : "D"), 116 extIface, intIface); 117 if (runIptablesCmd(cmd)) { 118 return -1; 119 } 120 121 snprintf(cmd, sizeof(cmd), 122 "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP", 123 (add ? "A" : "D"), 124 intIface, extIface); 125 if (runIptablesCmd(cmd)) { 126 snprintf(cmd, sizeof(cmd), 127 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 128 (!add ? "A" : "D"), 129 extIface, intIface); 130 runIptablesCmd(cmd); 131 return -1; 132 } 133 134 snprintf(cmd, sizeof(cmd), "-%s FORWARD -i %s -o %s -j ACCEPT", (add ? "A" : "D"), 135 intIface, extIface); 136 if (runIptablesCmd(cmd)) { 137 // unwind what's been done, but don't care about success - what more could we do? 138 snprintf(cmd, sizeof(cmd), 139 "-%s FORWARD -i %s -o %s -m state --state INVALID -j DROP", 140 (!add ? "A" : "D"), 141 intIface, extIface); 142 runIptablesCmd(cmd); 143 144 snprintf(cmd, sizeof(cmd), 145 "-%s FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 146 (!add ? "A" : "D"), 147 extIface, intIface); 148 runIptablesCmd(cmd); 149 return -1; 150 } 151 152 // add this if we are the first added nat 153 if (add && natCount == 0) { 154 snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface); 155 if (runIptablesCmd(cmd)) { 156 if (0 != strcmp("bp-tools", bootmode)) { 157 // unwind what's been done, but don't care about success - what more could we do? 158 setDefaults();; 159 } 160 return -1; 161 } 162 } 163 164 if (add) { 165 natCount++; 166 } else { 167 natCount--; 168 } 169 return 0; 170} 171 172int NatController::enableNat(const char *intIface, const char *extIface) { 173 return doNatCommands(intIface, extIface, true); 174} 175 176int NatController::disableNat(const char *intIface, const char *extIface) { 177 return doNatCommands(intIface, extIface, false); 178} 179