NatController.cpp revision 9ff78fb7da7158f5bd7c86d89a842691820259cf
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (C) 2008 The Android Open Source Project 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Licensed under the Apache License, Version 2.0 (the "License"); 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * you may not use this file except in compliance with the License. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * You may obtain a copy of the License at 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * http://www.apache.org/licenses/LICENSE-2.0 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Unless required by applicable law or agreed to in writing, software 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * distributed under the License is distributed on an "AS IS" BASIS, 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See the License for the specific language governing permissions and 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * limitations under the License. 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <stdlib.h> 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <errno.h> 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/socket.h> 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/stat.h> 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h> 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netinet/in.h> 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <arpa/inet.h> 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define LOG_TAG "NatController" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <cutils/log.h> 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "NatController.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtextern "C" int logwrap(int argc, const char **argv, int background); 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char IPTABLES_PATH[] = "/system/bin/iptables"; 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtNatController::NatController() { 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry ShmidtNatController::~NatController() { 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint NatController::runIptablesCmd(const char *cmd) { 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buffer[255]; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strncpy(buffer, cmd, sizeof(buffer)-1); 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *args[16]; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *next = buffer; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *tmp; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt args[0] = IPTABLES_PATH; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt args[1] = "--verbose"; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i = 2; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while ((tmp = strsep(&next, " "))) { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt args[i++] = tmp; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i == 16) { 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGE("iptables argument overflow"); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt errno = E2BIG; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt args[i] = NULL; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return logwrap(i, args, 0); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint NatController::setDefaults() { 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd("-P INPUT ACCEPT")) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd("-F INPUT")) 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd("-P OUTPUT ACCEPT")) 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd("-F OUTPUT")) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd("-P FORWARD DROP")) 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd("-F FORWARD")) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd("-t nat -F")) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtbool NatController::interfaceExists(const char *iface) { 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt // XXX: STOPSHIP - Implement this 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return true; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// TODO: Make this work for multiple masqueraded networks 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint NatController::enableNat(const char *intIface, const char *extIface) { 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char cmd[255]; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!interfaceExists(intIface) || !interfaceExists (extIface)) { 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt LOGE("Invalid interface specified"); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt errno = ENODEV; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt snprintf(cmd, sizeof(cmd), 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "-A FORWARD -i %s -o %s -m state --state ESTABLISHED,RELATED -j ACCEPT", 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt extIface, intIface); 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd(cmd)) { 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt snprintf(cmd, sizeof(cmd), "-A FORWARD -i %s -o %s -j ACCEPT", intIface, extIface); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd(cmd)) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt snprintf(cmd, sizeof(cmd), "-t nat -A POSTROUTING -o %s -j MASQUERADE", extIface); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (runIptablesCmd(cmd)) { 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt// TODO: Make this work for multiple masqueraded networks 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint NatController::disableNat(const char *intIface, const char *extIface) { 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return setDefaults(); 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt