oem_iptables_hook.cpp revision c462177bd58e3bf0ac4f618934dae060569e3e0b
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>
27c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt#include "NetdConstants.h"
284ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
294ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondoextern "C" int system_nosh(const char *command);
304ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
314ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
324ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic int runIptablesCmd(const char *cmd) {
334ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    char *buffer;
344ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    size_t len = strnlen(cmd, 255);
354ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    int res;
364ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
374ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    if (len == 255) {
387c73e8951d91b5afe9d52f88d7ed3a09d120a725JP Abgrall        ALOGE("command too long");
394ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        return -1;
404ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    }
414ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
424ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    asprintf(&buffer, "%s %s", IPTABLES_PATH, cmd);
434ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    res = system_nosh(buffer);
444ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    free(buffer);
454ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    return res;
464ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo}
474ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
484ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic bool oemSetupHooks() {
494ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // Order is important!
504ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // -N to create the chain (no-op if already exist).
514ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // -D to delete any pre-existing jump rule, to prevent dupes (no-op if doesn't exist)
524ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // -I to insert our jump rule into the default chain
534ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
544ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-N oem_out");
554ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-D OUTPUT -j oem_out");
564ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    if (runIptablesCmd("-I OUTPUT -j oem_out"))
574ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        return false;
584ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
594ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-N oem_fwd");
604ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-D FORWARD -j oem_fwd");
614ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    if (runIptablesCmd("-I FORWARD -j oem_fwd"))
624ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        return false;
634ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
644ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-t nat -N oem_nat_pre");
654ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre");
664ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    if (runIptablesCmd("-t nat -I PREROUTING -j oem_nat_pre"))
674ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        return false;
684ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
694ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    return true;
704ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo}
714ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
724ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic bool oemCleanupHooks() {
734ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // Order is important!
744ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // -D to remove ref to the chain
754ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // -F to empty the chain
764ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    // -X to delete the chain
774ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
784ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-D OUTPUT -j oem_out");
794ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-F oem_out");
804ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-X oem_out");
814ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
824ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-D FORWARD -j oem_fwd");
834ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-F oem_fwd");
844ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-X oem_fwd");
854ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
864ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-t nat -D PREROUTING -j oem_nat_pre");
874ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-t nat -F oem_nat_pre");
884ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    runIptablesCmd("-t nat -X oem_nat_pre");
894ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
904ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    return true;
914ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo}
924ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
934ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondostatic bool oemInitChains() {
944ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    int ret = system(OEM_SCRIPT_PATH);
954ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    if ((-1 == ret) || (0 != WEXITSTATUS(ret))) {
967c73e8951d91b5afe9d52f88d7ed3a09d120a725JP Abgrall        ALOGE("%s failed: %s", OEM_SCRIPT_PATH, strerror(errno));
974ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        oemCleanupHooks();
984ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        return false;
994ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    }
1004ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    return true;
1014ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo}
1024ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
1034ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo
1044ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondovoid setupOemIptablesHook() {
1054ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    if (0 == access(OEM_SCRIPT_PATH, R_OK | X_OK)) {
1064ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        // The call to oemCleanupHooks() is superfluous when done on bootup,
1074ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        // but is needed for the case where netd has crashed/stopped and is
1084ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        // restarted.
1094ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        if (oemCleanupHooks() && oemSetupHooks() && oemInitChains()) {
1107c73e8951d91b5afe9d52f88d7ed3a09d120a725JP Abgrall            ALOGI("OEM iptable hook installed.");
1114ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo        }
1124ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo    }
1134ab468577647d1ee73810b89d2287eaa5546fecbKazuhiro Ondo}
114