1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Check that audit logs generated for nft commands are as expected.
5
6SKIP_RC=4
7RC=0
8
9nft --version >/dev/null 2>&1 || {
10	echo "SKIP: missing nft tool"
11	exit $SKIP_RC
12}
13
14# Run everything in a separate network namespace
15[ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; }
16
17# give other scripts a chance to finish - audit_logread sees all activity
18sleep 1
19
20logfile=$(mktemp)
21rulefile=$(mktemp)
22echo "logging into $logfile"
23./audit_logread >"$logfile" &
24logread_pid=$!
25trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT
26exec 3<"$logfile"
27
28do_test() { # (cmd, log)
29	echo -n "testing for cmd: $1 ... "
30	cat <&3 >/dev/null
31	$1 >/dev/null || exit 1
32	sleep 0.1
33	res=$(diff -a -u <(echo "$2") - <&3)
34	[ $? -eq 0 ] && { echo "OK"; return; }
35	echo "FAIL"
36	grep -v '^\(---\|+++\|@@\)' <<< "$res"
37	((RC--))
38}
39
40nft flush ruleset
41
42# adding tables, chains and rules
43
44for table in t1 t2; do
45	do_test "nft add table $table" \
46	"table=$table family=2 entries=1 op=nft_register_table"
47
48	do_test "nft add chain $table c1" \
49	"table=$table family=2 entries=1 op=nft_register_chain"
50
51	do_test "nft add chain $table c2; add chain $table c3" \
52	"table=$table family=2 entries=2 op=nft_register_chain"
53
54	cmd="add rule $table c1 counter"
55
56	do_test "nft $cmd" \
57	"table=$table family=2 entries=1 op=nft_register_rule"
58
59	do_test "nft $cmd; $cmd" \
60	"table=$table family=2 entries=2 op=nft_register_rule"
61
62	cmd=""
63	sep=""
64	for chain in c2 c3; do
65		for i in {1..3}; do
66			cmd+="$sep add rule $table $chain counter"
67			sep=";"
68		done
69	done
70	do_test "nft $cmd" \
71	"table=$table family=2 entries=6 op=nft_register_rule"
72done
73
74for ((i = 0; i < 500; i++)); do
75	echo "add rule t2 c3 counter accept comment \"rule $i\""
76done >$rulefile
77do_test "nft -f $rulefile" \
78'table=t2 family=2 entries=500 op=nft_register_rule'
79
80# adding sets and elements
81
82settype='type inet_service; counter'
83setelem='{ 22, 80, 443 }'
84setblock="{ $settype; elements = $setelem; }"
85do_test "nft add set t1 s $setblock" \
86"table=t1 family=2 entries=4 op=nft_register_set"
87
88do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \
89"table=t1 family=2 entries=5 op=nft_register_set"
90
91do_test "nft add element t1 s3 $setelem" \
92"table=t1 family=2 entries=3 op=nft_register_setelem"
93
94# adding counters
95
96do_test 'nft add counter t1 c1' \
97'table=t1 family=2 entries=1 op=nft_register_obj'
98
99do_test 'nft add counter t2 c1; add counter t2 c2' \
100'table=t2 family=2 entries=2 op=nft_register_obj'
101
102for ((i = 3; i <= 500; i++)); do
103	echo "add counter t2 c$i"
104done >$rulefile
105do_test "nft -f $rulefile" \
106'table=t2 family=2 entries=498 op=nft_register_obj'
107
108# adding/updating quotas
109
110do_test 'nft add quota t1 q1 { 10 bytes }' \
111'table=t1 family=2 entries=1 op=nft_register_obj'
112
113do_test 'nft add quota t2 q1 { 10 bytes }; add quota t2 q2 { 10 bytes }' \
114'table=t2 family=2 entries=2 op=nft_register_obj'
115
116for ((i = 3; i <= 500; i++)); do
117	echo "add quota t2 q$i { 10 bytes }"
118done >$rulefile
119do_test "nft -f $rulefile" \
120'table=t2 family=2 entries=498 op=nft_register_obj'
121
122# changing the quota value triggers obj update path
123do_test 'nft add quota t1 q1 { 20 bytes }' \
124'table=t1 family=2 entries=1 op=nft_register_obj'
125
126# resetting rules
127
128do_test 'nft reset rules t1 c2' \
129'table=t1 family=2 entries=3 op=nft_reset_rule'
130
131do_test 'nft reset rules table t1' \
132'table=t1 family=2 entries=3 op=nft_reset_rule
133table=t1 family=2 entries=3 op=nft_reset_rule
134table=t1 family=2 entries=3 op=nft_reset_rule'
135
136do_test 'nft reset rules t2 c3' \
137'table=t2 family=2 entries=189 op=nft_reset_rule
138table=t2 family=2 entries=188 op=nft_reset_rule
139table=t2 family=2 entries=126 op=nft_reset_rule'
140
141do_test 'nft reset rules t2' \
142'table=t2 family=2 entries=3 op=nft_reset_rule
143table=t2 family=2 entries=3 op=nft_reset_rule
144table=t2 family=2 entries=186 op=nft_reset_rule
145table=t2 family=2 entries=188 op=nft_reset_rule
146table=t2 family=2 entries=129 op=nft_reset_rule'
147
148do_test 'nft reset rules' \
149'table=t1 family=2 entries=3 op=nft_reset_rule
150table=t1 family=2 entries=3 op=nft_reset_rule
151table=t1 family=2 entries=3 op=nft_reset_rule
152table=t2 family=2 entries=3 op=nft_reset_rule
153table=t2 family=2 entries=3 op=nft_reset_rule
154table=t2 family=2 entries=180 op=nft_reset_rule
155table=t2 family=2 entries=188 op=nft_reset_rule
156table=t2 family=2 entries=135 op=nft_reset_rule'
157
158# resetting sets and elements
159
160elem=(22 ,80 ,443)
161relem=""
162for i in {1..3}; do
163	relem+="${elem[((i - 1))]}"
164	do_test "nft reset element t1 s { $relem }" \
165	"table=t1 family=2 entries=$i op=nft_reset_setelem"
166done
167
168do_test 'nft reset set t1 s' \
169'table=t1 family=2 entries=3 op=nft_reset_setelem'
170
171# resetting counters
172
173do_test 'nft reset counter t1 c1' \
174'table=t1 family=2 entries=1 op=nft_reset_obj'
175
176do_test 'nft reset counters t1' \
177'table=t1 family=2 entries=1 op=nft_reset_obj'
178
179do_test 'nft reset counters t2' \
180'table=t2 family=2 entries=342 op=nft_reset_obj
181table=t2 family=2 entries=158 op=nft_reset_obj'
182
183do_test 'nft reset counters' \
184'table=t1 family=2 entries=1 op=nft_reset_obj
185table=t2 family=2 entries=341 op=nft_reset_obj
186table=t2 family=2 entries=159 op=nft_reset_obj'
187
188# resetting quotas
189
190do_test 'nft reset quota t1 q1' \
191'table=t1 family=2 entries=1 op=nft_reset_obj'
192
193do_test 'nft reset quotas t1' \
194'table=t1 family=2 entries=1 op=nft_reset_obj'
195
196do_test 'nft reset quotas t2' \
197'table=t2 family=2 entries=315 op=nft_reset_obj
198table=t2 family=2 entries=185 op=nft_reset_obj'
199
200do_test 'nft reset quotas' \
201'table=t1 family=2 entries=1 op=nft_reset_obj
202table=t2 family=2 entries=314 op=nft_reset_obj
203table=t2 family=2 entries=186 op=nft_reset_obj'
204
205# deleting rules
206
207readarray -t handles < <(nft -a list chain t1 c1 | \
208			 sed -n 's/.*counter.* handle \(.*\)$/\1/p')
209
210do_test "nft delete rule t1 c1 handle ${handles[0]}" \
211'table=t1 family=2 entries=1 op=nft_unregister_rule'
212
213cmd='delete rule t1 c1 handle'
214do_test "nft $cmd ${handles[1]}; $cmd ${handles[2]}" \
215'table=t1 family=2 entries=2 op=nft_unregister_rule'
216
217do_test 'nft flush chain t1 c2' \
218'table=t1 family=2 entries=3 op=nft_unregister_rule'
219
220do_test 'nft flush table t2' \
221'table=t2 family=2 entries=509 op=nft_unregister_rule'
222
223# deleting chains
224
225do_test 'nft delete chain t2 c2' \
226'table=t2 family=2 entries=1 op=nft_unregister_chain'
227
228# deleting sets and elements
229
230do_test 'nft delete element t1 s { 22 }' \
231'table=t1 family=2 entries=1 op=nft_unregister_setelem'
232
233do_test 'nft delete element t1 s { 80, 443 }' \
234'table=t1 family=2 entries=2 op=nft_unregister_setelem'
235
236do_test 'nft flush set t1 s2' \
237'table=t1 family=2 entries=3 op=nft_unregister_setelem'
238
239do_test 'nft delete set t1 s2' \
240'table=t1 family=2 entries=1 op=nft_unregister_set'
241
242do_test 'nft delete set t1 s3' \
243'table=t1 family=2 entries=1 op=nft_unregister_set'
244
245exit $RC
246