summaryrefslogtreecommitdiffstats
path: root/net/miniupnpd/test.sh
blob: 8b977e198557356bd0c8e39f28309cfb952212cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/bin/sh
# Functional tests for the miniupnpd IGD/NAT-PMP daemon variants. The package
# version is checked by the build framework, so it is not tested here.

bin=/usr/sbin/miniupnpd

# Binary, runtime linking and the OpenWrt integration files common to both
# firewall variants. "miniupnpd -h" exits non-zero but must print the usage
# banner, which also proves every shared-library dep resolves at runtime.
common_checks() {
	[ -x "$bin" ] || { echo "FAIL: $bin missing or not executable"; exit 1; }
	"$bin" -h 2>&1 | grep -q "^Usage:" \
		|| { echo "FAIL: 'miniupnpd -h' printed no usage banner"; exit 1; }
	[ -x /etc/init.d/miniupnpd ] || { echo "FAIL: init script missing"; exit 1; }
	grep -q "USE_PROCD=1" /etc/init.d/miniupnpd \
		|| { echo "FAIL: init script is not a procd service"; exit 1; }
	grep -q "config upnpd" /etc/config/upnpd \
		|| { echo "FAIL: /etc/config/upnpd is not valid UCI"; exit 1; }
	[ -f /etc/hotplug.d/iface/50-miniupnpd ] \
		|| { echo "FAIL: iface hotplug script missing"; exit 1; }
}

# The config-file parser runs before any firewall or socket setup, so it can be
# exercised inside the CI container. A bogus option must be rejected non-zero
# and a minimal valid config must be accepted without a parse error.
config_checks() {
	good="/tmp/miniupnpd-good.$$.conf"
	bad="/tmp/miniupnpd-bad.$$.conf"
	log="/tmp/miniupnpd.$$.log"
	cat > "$good" <<-EOF
		ext_ifname=lo
		listening_ip=127.0.0.1
		port=5000
		enable_natpmp=yes
		enable_upnp=yes
		notify_interval=60
		uuid=00000000-0000-0000-0000-000000000000
	EOF
	echo "not_a_real_option=1" > "$bad"

	if "$bin" -f "$bad" -d > "$log" 2>&1; then
		echo "FAIL: invalid config option was accepted"
		rm -f "$good" "$bad" "$log"; exit 1
	fi
	grep -qiE "invalid option|Error reading configuration" "$log" \
		|| { echo "FAIL: no parse error reported for bad config"
		     rm -f "$good" "$bad" "$log"; exit 1; }

	# A valid config: launch briefly and confirm the parser accepted it. The
	# daemon may later stop at firewall/socket setup in the container; that is
	# past the parser and irrelevant to this check.
	"$bin" -f "$good" -d > "$log" 2>&1 &
	mpid=$!
	sleep 2
	kill "$mpid" 2>/dev/null
	wait "$mpid" 2>/dev/null
	if grep -qiE "invalid option|Error reading configuration" "$log"; then
		echo "FAIL: valid config was rejected by the parser"
		rm -f "$good" "$bad" "$log"; exit 1
	fi
	rm -f "$good" "$bad" "$log"
}

case "$1" in
miniupnpd-iptables)
	# iptables variant ships the fw3 shell include. Its uci-defaults seeder
	# is not checked here: the postinst sources /etc/uci-defaults/* and
	# deletes each script that succeeds, so it is gone by now.
	common_checks
	[ -f /usr/share/miniupnpd/firewall.include ] || { echo "FAIL: firewall.include missing"; exit 1; }
	sh -n /usr/share/miniupnpd/firewall.include \
		|| { echo "FAIL: firewall.include has a shell syntax error"; exit 1; }
	config_checks
	echo "miniupnpd-iptables: all functional tests passed"
	;;
miniupnpd-nftables)
	# nftables variant ships the nft rule fragments consumed by fw4.
	common_checks
	for f in table-post/20-miniupnpd.nft \
		chain-post/dstnat/20-miniupnpd.nft \
		chain-post/forward/20-miniupnpd.nft \
		chain-post/srcnat/20-miniupnpd.nft; do
		[ -s "/usr/share/nftables.d/$f" ] \
			|| { echo "FAIL: nft fragment $f missing or empty"; exit 1; }
	done
	config_checks
	echo "miniupnpd-nftables: all functional tests passed"
	;;
*)
	echo "Untested package: $1" >&2
	exit 1
	;;
esac