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