1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ksft_skip=4
5
6NS=ns
7IP6=2001:db8:1::1/64
8TGT6=2001:db8:1::2
9TMPF=$(mktemp --suffix ".pcap")
10
11cleanup()
12{
13    rm -f $TMPF
14    ip netns del $NS
15}
16
17trap cleanup EXIT
18
19NSEXE="ip netns exec $NS"
20
21tcpdump -h | grep immediate-mode >> /dev/null
22if [ $? -ne 0 ]; then
23    echo "SKIP - tcpdump with --immediate-mode option required"
24    exit $ksft_skip
25fi
26
27# Namespaces
28ip netns add $NS
29
30$NSEXE sysctl -w net.ipv4.ping_group_range='0 2147483647' > /dev/null
31
32# Connectivity
33ip -netns $NS link add type dummy
34ip -netns $NS link set dev dummy0 up
35ip -netns $NS addr add $IP6 dev dummy0
36
37# Test
38BAD=0
39TOTAL=0
40
41check_result() {
42    ((TOTAL++))
43    if [ $1 -ne $2 ]; then
44	echo "  Case $3 returned $1, expected $2"
45	((BAD++))
46    fi
47}
48
49# IPV6_DONTFRAG
50for ovr in setsock cmsg both diff; do
51    for df in 0 1; do
52	for p in u i r; do
53	    [ $p == "u" ] && prot=UDP
54	    [ $p == "i" ] && prot=ICMP
55	    [ $p == "r" ] && prot=RAW
56
57	    [ $ovr == "setsock" ] && m="-F $df"
58	    [ $ovr == "cmsg" ]    && m="-f $df"
59	    [ $ovr == "both" ]    && m="-F $df -f $df"
60	    [ $ovr == "diff" ]    && m="-F $((1 - df)) -f $df"
61
62	    $NSEXE ./cmsg_sender -s -S 2000 -6 -p $p $m $TGT6 1234
63	    check_result $? $df "DONTFRAG $prot $ovr"
64	done
65    done
66done
67
68# IPV6_TCLASS
69TOS=0x10
70TOS2=0x20
71
72ip -6 -netns $NS rule add tos $TOS lookup 300
73ip -6 -netns $NS route add table 300 prohibit any
74
75for ovr in setsock cmsg both diff; do
76    for p in u i r; do
77	[ $p == "u" ] && prot=UDP
78	[ $p == "i" ] && prot=ICMP
79	[ $p == "r" ] && prot=RAW
80
81	[ $ovr == "setsock" ] && m="-C"
82	[ $ovr == "cmsg" ]    && m="-c"
83	[ $ovr == "both" ]    && m="-C $((TOS2)) -c"
84	[ $ovr == "diff" ]    && m="-C $((TOS )) -c"
85
86	$NSEXE nohup tcpdump --immediate-mode -p -ni dummy0 -w $TMPF -c 4 2> /dev/null &
87	BG=$!
88	sleep 0.05
89
90	$NSEXE ./cmsg_sender -6 -p $p $m $((TOS2)) $TGT6 1234
91	check_result $? 0 "TCLASS $prot $ovr - pass"
92
93	while [ -d /proc/$BG ]; do
94	    $NSEXE ./cmsg_sender -6 -p u $TGT6 1234
95	done
96
97	tcpdump -r $TMPF -v 2>&1 | grep "class $TOS2" >> /dev/null
98	check_result $? 0 "TCLASS $prot $ovr - packet data"
99	rm $TMPF
100
101	[ $ovr == "both" ]    && m="-C $((TOS )) -c"
102	[ $ovr == "diff" ]    && m="-C $((TOS2)) -c"
103
104	$NSEXE ./cmsg_sender -6 -p $p $m $((TOS)) -s $TGT6 1234
105	check_result $? 1 "TCLASS $prot $ovr - rejection"
106    done
107done
108
109# IPV6_HOPLIMIT
110LIM=4
111
112for ovr in setsock cmsg both diff; do
113    for p in u i r; do
114	[ $p == "u" ] && prot=UDP
115	[ $p == "i" ] && prot=ICMP
116	[ $p == "r" ] && prot=RAW
117
118	[ $ovr == "setsock" ] && m="-L"
119	[ $ovr == "cmsg" ]    && m="-l"
120	[ $ovr == "both" ]    && m="-L $LIM -l"
121	[ $ovr == "diff" ]    && m="-L $((LIM + 1)) -l"
122
123	$NSEXE nohup tcpdump --immediate-mode -p -ni dummy0 -w $TMPF -c 4 2> /dev/null &
124	BG=$!
125	sleep 0.05
126
127	$NSEXE ./cmsg_sender -6 -p $p $m $LIM $TGT6 1234
128	check_result $? 0 "HOPLIMIT $prot $ovr - pass"
129
130	while [ -d /proc/$BG ]; do
131	    $NSEXE ./cmsg_sender -6 -p u $TGT6 1234
132	done
133
134	tcpdump -r $TMPF -v 2>&1 | grep "hlim $LIM[^0-9]" >> /dev/null
135	check_result $? 0 "HOPLIMIT $prot $ovr - packet data"
136	rm $TMPF
137    done
138done
139
140# IPV6 exthdr
141for p in u i r; do
142    # Very basic "does it crash" test
143    for h in h d r; do
144	$NSEXE ./cmsg_sender -p $p -6 -H $h $TGT6 1234
145	check_result $? 0 "ExtHdr $prot $ovr - pass"
146    done
147done
148
149# Summary
150if [ $BAD -ne 0 ]; then
151    echo "FAIL - $BAD/$TOTAL cases failed"
152    exit 1
153else
154    echo "OK"
155    exit 0
156fi
157