oem_iptables_hook.cpp revision 7c73e8951d91b5afe9d52f88d7ed3a09d120a725
14ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo/* 24ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * Copyright (C) 2012 The Android Open Source Project 34ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * 44ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * Licensed under the Apache License, Version 2.0 (the "License"); 54ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * you may not use this file except in compliance with the License. 64ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * You may obtain a copy of the License at 74ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * 84ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * http://www.apache.org/licenses/LICENSE-2.0 94ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * 104ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * Unless required by applicable law or agreed to in writing, software 114ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * distributed under the License is distributed on an "AS IS" BASIS, 124ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * See the License for the specific language governing permissions and 144ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo * limitations under the License. 154ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo */ 164ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 174ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <stdio.h> 184ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <stdlib.h> 194ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <sys/types.h> 204ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <sys/wait.h> 214ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <errno.h> 224ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <string.h> 234ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <unistd.h> 244ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 254ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#define LOG_TAG "OemIptablesHook" 264ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo#include <cutils/log.h> 274ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 284ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondoextern "C" int system_nosh(const char *command); 294ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 304ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic char IPTABLES_PATH[] = "/system/bin/iptables"; 314ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic char OEM_SCRIPT_PATH[] = "/system/bin/oem-iptables-init.sh"; 324ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 334ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic int runIptablesCmd(const char *cmd) { 344ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo char *buffer; 354ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo size_t len = strnlen(cmd, 255); 364ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo int res; 374ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 384ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo if (len == 255) { 397c73e8951d91b5afe9d52f88d7ed3a09d120a725JP Abgrall ALOGE("command too long"); 404ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return -1; 414ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo } 424ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 434ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd); 444ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo res = system_nosh(buffer); 454ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo free(buffer); 464ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return res; 474ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo} 484ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 494ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic bool oemSetupHooks() { 504ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // Order is important! 514ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // -N to create the chain (no-op if already exist). 524ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // -D to delete any pre-existing jump rule, to prevent dupes (no-op if doesn't exist) 534ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // -I to insert our jump rule into the default chain 544ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 554ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-N oem_out"); 564ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-D OUTPUT -j oem_out"); 574ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo if (runIptablesCmd("-I OUTPUT -j oem_out")) 584ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return false; 594ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 604ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-N oem_fwd"); 614ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-D FORWARD -j oem_fwd"); 624ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo if (runIptablesCmd("-I FORWARD -j oem_fwd")) 634ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return false; 644ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 654ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-t nat -N oem_nat_pre"); 664ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre"); 674ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo if (runIptablesCmd("-t nat -I PREROUTING -j oem_nat_pre")) 684ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return false; 694ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 704ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return true; 714ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo} 724ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 734ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic bool oemCleanupHooks() { 744ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // Order is important! 754ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // -D to remove ref to the chain 764ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // -F to empty the chain 774ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // -X to delete the chain 784ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 794ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-D OUTPUT -j oem_out"); 804ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-F oem_out"); 814ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-X oem_out"); 824ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 834ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-D FORWARD -j oem_fwd"); 844ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-F oem_fwd"); 854ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-X oem_fwd"); 864ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 874ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre"); 884ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-t nat -F oem_nat_pre"); 894ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo runIptablesCmd("-t nat -X oem_nat_pre"); 904ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 914ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return true; 924ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo} 934ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 944ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic bool oemInitChains() { 954ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo int ret = system(OEM_SCRIPT_PATH); 964ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo if ((-1 == ret) || (0 != WEXITSTATUS(ret))) { 977c73e8951d91b5afe9d52f88d7ed3a09d120a725JP Abgrall ALOGE("%s failed: %s", OEM_SCRIPT_PATH, strerror(errno)); 984ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo oemCleanupHooks(); 994ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return false; 1004ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo } 1014ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo return true; 1024ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo} 1034ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 1044ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo 1054ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondovoid setupOemIptablesHook() { 1064ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo if (0 == access(OEM_SCRIPT_PATH, R_OK | X_OK)) { 1074ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // The call to oemCleanupHooks() is superfluous when done on bootup, 1084ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // but is needed for the case where netd has crashed/stopped and is 1094ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo // restarted. 1104ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo if (oemCleanupHooks() && oemSetupHooks() && oemInitChains()) { 1117c73e8951d91b5afe9d52f88d7ed3a09d120a725JP Abgrall ALOGI("OEM iptable hook installed."); 1124ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo } 1134ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo } 1144ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo} 115