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