Skip to content

Commit a3e0c02

Browse files
committed
fix nft file directory create
1 parent 64d18e1 commit a3e0c02

3 files changed

Lines changed: 86 additions & 2 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk
33

44
PKG_NAME:=https-dns-proxy
55
PKG_VERSION:=2026.03.18
6-
PKG_RELEASE:=1
6+
PKG_RELEASE:=2
77

88
PKG_SOURCE_PROTO:=git
99
PKG_SOURCE_URL:=https://github.com/aarond10/https_dns_proxy/

files/etc/init.d/https-dns-proxy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ notrack_nft() {
156156
)"
157157
existing_content="$(cat "$NOTRACK_NFT_FILE" 2>/dev/null)"
158158
if [ "$new_content" != "$existing_content" ]; then
159+
mkdir -p "${NOTRACK_NFT_FILE%/*}"
159160
echo "$new_content" > "$NOTRACK_NFT_FILE"
160161
fi
161162
[ -s "$NOTRACK_NFT_FILE" ] && nft -c -f "$NOTRACK_NFT_FILE"

tests/run_tests.sh

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,18 +180,36 @@ logger() { :; }
180180
# Override ubus to return nothing (init script defines its own wrapper)
181181
__UBUS_BIN="true"
182182

183+
# Mock `nft`: track invocations and return success by default. Tests can
184+
# override __nft_rc to simulate failure.
185+
__nft_calls_file="$TESTDIR/nft_calls"
186+
__nft_rc=0
187+
: > "$__nft_calls_file"
188+
nft() {
189+
printf '%s\n' "$*" >> "$__nft_calls_file"
190+
return "$__nft_rc"
191+
}
192+
183193
# ── Source the init script (skip the shebang line) ──────────────────
194+
#
195+
# Patch the readonly NOTRACK_NFT_FILE path so tests can write under
196+
# $TESTDIR instead of /usr/share/nftables.d/ruleset-post/.
184197

185198
INIT_SCRIPT="./files/etc/init.d/https-dns-proxy"
186199
if [ ! -f "$INIT_SCRIPT" ]; then
187200
echo "ERROR: Cannot find $INIT_SCRIPT. Run from the https-dns-proxy package root."
188201
exit 1
189202
fi
190203

204+
PATCHED_INIT="$TESTDIR/https-dns-proxy.patched"
205+
NOTRACK_TEST_FILE="$TESTDIR/usr/share/nftables.d/ruleset-post/20-https-dns-proxy-notrack.nft"
206+
sed "s|^readonly NOTRACK_NFT_FILE=.*|readonly NOTRACK_NFT_FILE='$NOTRACK_TEST_FILE'|" \
207+
"$INIT_SCRIPT" > "$PATCHED_INIT"
208+
191209
# Source all functions. The #!/bin/sh /etc/rc.common line is harmless
192210
# when we've already defined the framework stubs above.
193211
# shellcheck disable=SC1090
194-
. "$INIT_SCRIPT"
212+
. "$PATCHED_INIT"
195213

196214
###############################################################################
197215
# TEST CATEGORIES #
@@ -611,6 +629,71 @@ load_package_config
611629
assert_eq "load_package_config: canary disabled → canaryDomains empty" "" "$canaryDomains"
612630
assert_eq "load_package_config: force_dns=0 → unset" "" "$force_dns"
613631

632+
printf "\n##\n## 10: notrack_nft (regression: missing nftables.d/ruleset-post dir)\n##\n\n"
633+
634+
# Reset state — ensure parent dir does NOT exist (this is the apk-install
635+
# bug: post-install runs `start` before fw4 has created the directory).
636+
rm -rf "$TESTDIR/usr/share"
637+
__nft_rc=0
638+
: > "$__nft_calls_file"
639+
640+
assert_eq "notrack_nft: NOTRACK_NFT_FILE patched to test path" "$NOTRACK_TEST_FILE" "$NOTRACK_NFT_FILE"
641+
642+
# Pre-condition: parent dir genuinely missing
643+
[ ! -d "$(dirname "$NOTRACK_TEST_FILE")" ]
644+
assert_rc "notrack_nft: parent dir absent before update" 0 $?
645+
646+
# THE REGRESSION: previously this failed with
647+
# "can't create .../20-https-dns-proxy-notrack.nft: nonexistent directory"
648+
notrack_nft update "53 5053"
649+
assert_rc "notrack_nft update creates parent dir on first call" 0 $?
650+
651+
[ -f "$NOTRACK_TEST_FILE" ]
652+
assert_rc "notrack_nft update wrote nft snippet file" 0 $?
653+
654+
[ -d "$(dirname "$NOTRACK_TEST_FILE")" ]
655+
assert_rc "notrack_nft update created parent dir" 0 $?
656+
657+
# Content should reference the table, hook, and ports we passed
658+
grep -q "table inet https_dns_proxy_notrack" "$NOTRACK_TEST_FILE"
659+
assert_rc "notrack_nft snippet declares the wrapper table" 0 $?
660+
661+
grep -q "type filter hook output priority raw" "$NOTRACK_TEST_FILE"
662+
assert_rc "notrack_nft snippet declares raw output hook" 0 $?
663+
664+
grep -q "53 5053" "$NOTRACK_TEST_FILE"
665+
assert_rc "notrack_nft snippet contains supplied ports" 0 $?
666+
667+
# Syntax check should have been invoked
668+
grep -q -- "-c -f $NOTRACK_TEST_FILE" "$__nft_calls_file"
669+
assert_rc "notrack_nft update invokes 'nft -c -f' on the snippet" 0 $?
670+
671+
# ── Idempotence: same content → no extra write churn ──
672+
# We can't easily detect a no-op write, but we can confirm the function
673+
# still succeeds when the file already exists with matching content.
674+
notrack_nft update "53 5053"
675+
assert_rc "notrack_nft update idempotent on identical content" 0 $?
676+
677+
# ── Empty port_set → routes to remove ──
678+
notrack_nft update ""
679+
[ ! -f "$NOTRACK_TEST_FILE" ]
680+
assert_rc "notrack_nft update '' removes the snippet file" 0 $?
681+
682+
# ── Explicit remove ──
683+
mkdir -p "$(dirname "$NOTRACK_TEST_FILE")"
684+
echo "stale" > "$NOTRACK_TEST_FILE"
685+
: > "$__nft_calls_file"
686+
notrack_nft remove
687+
[ ! -f "$NOTRACK_TEST_FILE" ]
688+
assert_rc "notrack_nft remove deletes the snippet file" 0 $?
689+
690+
grep -q "delete table inet https_dns_proxy_notrack" "$__nft_calls_file"
691+
assert_rc "notrack_nft remove invokes 'nft delete table'" 0 $?
692+
693+
# ── remove is a no-op when file already absent ──
694+
notrack_nft remove
695+
assert_rc "notrack_nft remove succeeds when file already absent" 0 $?
696+
614697
###############################################################################
615698
# SHELL SCRIPT SYNTAX #
616699
###############################################################################

0 commit comments

Comments
 (0)