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