oem_iptables_hook.cpp revision c462177bd58e3bf0ac4f618934dae060569e3e0b
1/* 2 * Copyright (C) 2012 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 <stdio.h> 18#include <stdlib.h> 19#include <sys/types.h> 20#include <sys/wait.h> 21#include <errno.h> 22#include <string.h> 23#include <unistd.h> 24 25#define LOG_TAG "OemIptablesHook" 26#include <cutils/log.h> 27#include "NetdConstants.h" 28 29extern "C" int system_nosh(const char *command); 30 31 32static int runIptablesCmd(const char *cmd) { 33 char *buffer; 34 size_t len = strnlen(cmd, 255); 35 int res; 36 37 if (len == 255) { 38 ALOGE("command too long"); 39 return -1; 40 } 41 42 asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd); 43 res = system_nosh(buffer); 44 free(buffer); 45 return res; 46} 47 48static bool oemSetupHooks() { 49 // Order is important! 50 // -N to create the chain (no-op if already exist). 51 // -D to delete any pre-existing jump rule, to prevent dupes (no-op if doesn't exist) 52 // -I to insert our jump rule into the default chain 53 54 runIptablesCmd("-N oem_out"); 55 runIptablesCmd("-D OUTPUT -j oem_out"); 56 if (runIptablesCmd("-I OUTPUT -j oem_out")) 57 return false; 58 59 runIptablesCmd("-N oem_fwd"); 60 runIptablesCmd("-D FORWARD -j oem_fwd"); 61 if (runIptablesCmd("-I FORWARD -j oem_fwd")) 62 return false; 63 64 runIptablesCmd("-t nat -N oem_nat_pre"); 65 runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre"); 66 if (runIptablesCmd("-t nat -I PREROUTING -j oem_nat_pre")) 67 return false; 68 69 return true; 70} 71 72static bool oemCleanupHooks() { 73 // Order is important! 74 // -D to remove ref to the chain 75 // -F to empty the chain 76 // -X to delete the chain 77 78 runIptablesCmd("-D OUTPUT -j oem_out"); 79 runIptablesCmd("-F oem_out"); 80 runIptablesCmd("-X oem_out"); 81 82 runIptablesCmd("-D FORWARD -j oem_fwd"); 83 runIptablesCmd("-F oem_fwd"); 84 runIptablesCmd("-X oem_fwd"); 85 86 runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre"); 87 runIptablesCmd("-t nat -F oem_nat_pre"); 88 runIptablesCmd("-t nat -X oem_nat_pre"); 89 90 return true; 91} 92 93static bool oemInitChains() { 94 int ret = system(OEM_SCRIPT_PATH); 95 if ((-1 == ret) || (0 != WEXITSTATUS(ret))) { 96 ALOGE("%s failed: %s", OEM_SCRIPT_PATH, strerror(errno)); 97 oemCleanupHooks(); 98 return false; 99 } 100 return true; 101} 102 103 104void setupOemIptablesHook() { 105 if (0 == access(OEM_SCRIPT_PATH, R_OK | X_OK)) { 106 // The call to oemCleanupHooks() is superfluous when done on bootup, 107 // but is needed for the case where netd has crashed/stopped and is 108 // restarted. 109 if (oemCleanupHooks() && oemSetupHooks() && oemInitChains()) { 110 ALOGI("OEM iptable hook installed."); 111 } 112 } 113} 114