138 lines
4.8 KiB
Bash
138 lines
4.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -eo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
TACHYON_LIB="$ROOT_DIR/tachyon/files/usr/lib"
|
|
NFT_RUNTIME="$ROOT_DIR/tachyon/files/usr/lib/nft/apply.uc"
|
|
WORK_DIR="$(mktemp -d)"
|
|
NFT_LOG="$WORK_DIR/nft.log"
|
|
LOGGER_LOG="$WORK_DIR/logger.log"
|
|
export NFT_LOG LOGGER_LOG
|
|
|
|
cleanup() {
|
|
rm -rf "$WORK_DIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
fail() {
|
|
printf 'FAIL: %s\n' "$1" >&2
|
|
printf 'nft log:\n' >&2
|
|
cat "$NFT_LOG" >&2 2>/dev/null || true
|
|
exit 1
|
|
}
|
|
|
|
assert_contains() {
|
|
local file="$1"
|
|
local expected="$2"
|
|
local label="$3"
|
|
|
|
grep -Fq "$expected" "$file" || fail "$label: expected '$expected'"
|
|
}
|
|
|
|
mkdir -p "$WORK_DIR/bin"
|
|
|
|
cat >"$WORK_DIR/bin/nft" <<'NFT'
|
|
#!/usr/bin/env bash
|
|
set -eo pipefail
|
|
{
|
|
printf 'nft'
|
|
for arg in "$@"; do
|
|
printf '\t%s' "$arg"
|
|
done
|
|
printf '\n'
|
|
} >> "${NFT_LOG:?}"
|
|
|
|
if [ "$#" -ge 5 ] && [ "$1" = "flush" ] && [ "$2" = "chain" ]; then
|
|
if [ ! -f "$WORK_DIR/chain_exists" ]; then
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ "$#" -ge 5 ] && [ "$1" = "add" ] && [ "$2" = "chain" ]; then
|
|
touch "$WORK_DIR/chain_exists"
|
|
fi
|
|
|
|
if [ "$#" -ge 5 ] && [ "$1" = "delete" ] && [ "$2" = "chain" ]; then
|
|
rm -f "$WORK_DIR/chain_exists"
|
|
fi
|
|
NFT
|
|
chmod 0755 "$WORK_DIR/bin/nft"
|
|
|
|
cat >"$WORK_DIR/bin/logger" <<'LOGGER'
|
|
#!/usr/bin/env bash
|
|
set -eo pipefail
|
|
printf 'logger\t%s\n' "$*" >> "${LOGGER_LOG:?}"
|
|
LOGGER
|
|
chmod 0755 "$WORK_DIR/bin/logger"
|
|
|
|
export PATH="$WORK_DIR/bin:$PATH"
|
|
|
|
nft_ucode() {
|
|
ucode -S -L "$TACHYON_LIB" "$NFT_RUNTIME" "$@"
|
|
}
|
|
|
|
# Test 1: Direct enable call
|
|
: > "$NFT_LOG"
|
|
rm -f "$WORK_DIR/chain_exists"
|
|
nft_ucode nft-enable-router-output-intercept TachyonTable localv4 0x00100000 1
|
|
assert_contains "$NFT_LOG" $'nft\tadd\tchain\tinet\tTachyonTable\toutput_redirect\t{ type nat hook output priority -100; policy accept; }' "enable: creates chain output_redirect"
|
|
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tct\tstatus\tdnat\treturn' "enable: ct status dnat return"
|
|
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tip\tdaddr\t@localv4\treturn' "enable: localv4 bypass"
|
|
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\ttcp\tdport\t53\treturn' "enable: port 53 bypass"
|
|
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tudp\tdport\t123\treturn' "enable: exclude_ntp bypass"
|
|
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tmeta\tmark\t0x00100000\treturn' "enable: outbound_mark bypass"
|
|
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tmeta\tl4proto\ttcp\tcounter\tredirect\tto\t:1604' "enable: tcp redirect to 1604"
|
|
|
|
# Test 2: Direct disable call
|
|
: > "$NFT_LOG"
|
|
nft_ucode nft-disable-router-output-intercept TachyonTable
|
|
assert_contains "$NFT_LOG" $'nft\tdelete\tchain\tinet\tTachyonTable\toutput_redirect' "disable: deletes chain output_redirect"
|
|
|
|
# Test 3: Sync from UCI - when enabled
|
|
STATE_ENABLED="$WORK_DIR/enabled.state"
|
|
cat >"$STATE_ENABLED" <<'STATE'
|
|
tachyon.settings=settings
|
|
tachyon.settings.route_router_traffic=1
|
|
tachyon.settings.route_router_traffic_section=proxy_sec
|
|
tachyon.settings.exclude_ntp=1
|
|
tachyon.proxy_sec=section
|
|
tachyon.proxy_sec.enabled=1
|
|
tachyon.proxy_sec.routing_mode=proxy
|
|
tachyon.proxy_sec.mark=354
|
|
tachyon.proxy_sec.tproxy_port=10080
|
|
STATE
|
|
|
|
: > "$NFT_LOG"
|
|
rm -f "$WORK_DIR/chain_exists"
|
|
TACHYON_UCI_STATE_FILE="$STATE_ENABLED" nft_ucode nft-sync-router-output-intercept TachyonTable localv4 0x00100000
|
|
assert_contains "$NFT_LOG" $'nft\tadd\tchain\tinet\tTachyonTable\toutput_redirect\t{ type nat hook output priority -100; policy accept; }' "sync(enabled): creates chain"
|
|
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tmeta\tl4proto\ttcp\tcounter\tredirect\tto\t:1604' "sync(enabled): redirects to port"
|
|
|
|
# Test 4: Sync from UCI - when disabled
|
|
STATE_DISABLED="$WORK_DIR/disabled.state"
|
|
cat >"$STATE_DISABLED" <<'STATE'
|
|
tachyon.settings=settings
|
|
tachyon.settings.route_router_traffic=0
|
|
tachyon.settings.route_router_traffic_section=proxy_sec
|
|
tachyon.proxy_sec=section
|
|
tachyon.proxy_sec.enabled=1
|
|
tachyon.proxy_sec.routing_mode=proxy
|
|
tachyon.proxy_sec.mark=354
|
|
STATE
|
|
|
|
: > "$NFT_LOG"
|
|
TACHYON_UCI_STATE_FILE="$STATE_DISABLED" nft_ucode nft-sync-router-output-intercept TachyonTable localv4 0x00100000
|
|
assert_contains "$NFT_LOG" $'nft\tdelete\tchain\tinet\tTachyonTable\toutput_redirect' "sync(disabled): deletes chain"
|
|
|
|
# Test 5: Verify UCI setting loads route_router_traffic
|
|
CHECK_SETTINGS=$(TACHYON_UCI_STATE_FILE="$STATE_DISABLED" ucode -S -L "$TACHYON_LIB" -e '
|
|
let uci = require("core.uci");
|
|
let val = uci.get("tachyon.settings.route_router_traffic");
|
|
print("val=" + val);
|
|
')
|
|
if [ "$CHECK_SETTINGS" != "val=0" ]; then
|
|
fail "UCI route_router_traffic expected val=0, got '$CHECK_SETTINGS'"
|
|
fi
|
|
|
|
printf 'ALL TESTS PASSED for route_router_traffic\n'
|