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