xref: /freebsd/tests/sys/netinet/multicast.sh (revision df21a004be237a1dccd03c7b47254625eea62fa9)
1#
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2025 Gleb Smirnoff <glebius@FreeBSD.org>
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26
27. $(atf_get_srcdir)/../common/vnet.subr
28
29# Set up two jails, mjail1 and mjail2, connected with two interface pairs
30multicast_vnet_init()
31{
32
33	vnet_init
34	epair1=$(vnet_mkepair)
35	epair2=$(vnet_mkepair)
36	vnet_mkjail mjail1 ${epair1}a ${epair2}a
37	jexec mjail1 ifconfig ${epair1}a up
38	jexec mjail1 ifconfig ${epair1}a 192.0.2.1/24
39	jexec mjail1 ifconfig ${epair2}a up
40	jexec mjail1 ifconfig ${epair2}a 192.0.3.1/24
41	vnet_mkjail mjail2 ${epair1}b ${epair2}b
42	jexec mjail2 ifconfig ${epair1}b up
43	jexec mjail2 ifconfig ${epair1}b 192.0.2.2/24
44	jexec mjail2 ifconfig ${epair2}b up
45	jexec mjail2 ifconfig ${epair2}b 192.0.3.2/24
46}
47
48multicast_join()
49{
50	jexec mjail2 $(atf_get_srcdir)/multicast-receive \
51	    $1 233.252.0.1 6676 $2 > out & pid=$!
52	while ! jexec mjail2 ifmcstat | grep -q 233\.252\.0\.1; do
53		sleep 0.01
54	done
55}
56
57atf_test_case "IP_ADD_MEMBERSHIP_ip_mreq" "cleanup"
58IP_ADD_MEMBERSHIP_ip_mreq_head()
59{
60	atf_set descr 'IP_ADD_MEMBERSHIP / IP_MULTICAST_IF with ip_mreq'
61	atf_set require.user root
62}
63IP_ADD_MEMBERSHIP_ip_mreq_body()
64{
65	multicast_vnet_init
66
67	# join group on interface with IP address 192.0.2.2
68	multicast_join ip_mreq 192.0.2.2
69	atf_check -s exit:0 -o empty \
70	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
71	    0.0.0.0 6676 233.252.0.1 6676 192.0.2.1 hello
72	atf_check -s exit:0 sh -c "wait $pid; exit $?"
73	atf_check -s exit:0 -o inline:"192.0.2.1:6676 hello\n" cat out
74
75	# join group on interface with IP address 192.0.3.2
76	multicast_join ip_mreq 192.0.3.2
77	atf_check -s exit:0 -o empty \
78	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
79	    0.0.0.0 6676 233.252.0.1 6676 192.0.3.1 hello
80	atf_check -s exit:0 sh -c "wait $pid; exit $?"
81	atf_check -s exit:0 -o inline:"192.0.3.1:6676 hello\n" cat out
82
83	# join group on the first multicast capable interface (epair1a)
84	multicast_join ip_mreq 0.0.0.0
85	atf_check -s exit:0 -o empty \
86	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
87	    0.0.0.0 6676 233.252.0.1 6676 192.0.2.1 hello
88	atf_check -s exit:0 sh -c "wait $pid; exit $?"
89	atf_check -s exit:0 -o inline:"192.0.2.1:6676 hello\n" cat out
90
91	# Set up the receiving jail so that first multicast capable interface
92	# is epair1a and default route points into epair2a.  This will allow us
93	# to exercise both branches of inp_lookup_mcast_ifp().
94	jexec mjail2 route add default 192.0.3.254
95
96	# join group on the interface determined by the route lookup
97	multicast_join ip_mreq 0.0.0.0
98	atf_check -s exit:0 -o empty \
99	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
100	    0.0.0.0 6676 233.252.0.1 6676 192.0.3.1 hello
101	atf_check -s exit:0 sh -c "wait $pid; exit $?"
102	atf_check -s exit:0 -o inline:"192.0.3.1:6676 hello\n" cat out
103}
104IP_ADD_MEMBERSHIP_ip_mreq_cleanup()
105{
106	rm out
107	vnet_cleanup
108}
109
110atf_test_case "IP_ADD_MEMBERSHIP_ip_mreqn" "cleanup"
111IP_ADD_MEMBERSHIP_ip_mreqn_head()
112{
113	atf_set descr 'IP_ADD_MEMBERSHIP / IP_MULTICAST_IF with ip_mreqn'
114	atf_set require.user root
115}
116IP_ADD_MEMBERSHIP_ip_mreqn_body()
117{
118	multicast_vnet_init
119
120	# join group on interface epair2
121	multicast_join ip_mreqn ${epair1}b
122	atf_check -s exit:0 -o empty \
123	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
124	    0.0.0.0 6676 233.252.0.1 6676 ${epair1}a hello
125	atf_check -s exit:0 sh -c "wait $pid; exit $?"
126	atf_check -s exit:0 -o inline:"192.0.2.1:6676 hello\n" cat out
127
128	# join group on interface epair2
129	multicast_join ip_mreqn ${epair2}b
130	atf_check -s exit:0 -o empty \
131	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
132	    0.0.0.0 6676 233.252.0.1 6676 ${epair2}a hello
133	atf_check -s exit:0 sh -c "wait $pid; exit $?"
134	atf_check -s exit:0 -o inline:"192.0.3.1:6676 hello\n" cat out
135
136	# try to join group on the interface determined by the route lookup
137	atf_check -s exit:71 -e inline:"multicast-receive: setsockopt: Can't assign requested address\n" \
138	    jexec mjail2 $(atf_get_srcdir)/multicast-receive \
139	    ip_mreqn 233.252.0.1 6676 0
140	# add route and try again
141	jexec mjail2 route add default 192.0.3.254
142        multicast_join ip_mreqn 0
143	atf_check -s exit:0 -o empty \
144	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
145	    0.0.0.0 6676 233.252.0.1 6676 192.0.3.1 hello
146	atf_check -s exit:0 sh -c "wait $pid; exit $?"
147	atf_check -s exit:0 -o inline:"192.0.3.1:6676 hello\n" cat out
148}
149IP_ADD_MEMBERSHIP_ip_mreqn_cleanup()
150{
151	rm out
152	vnet_cleanup
153}
154
155atf_test_case "MCAST_JOIN_GROUP" "cleanup"
156MCAST_JOIN_GROUP_head()
157{
158	atf_set descr 'MCAST_JOIN_GROUP'
159	atf_set require.user root
160}
161MCAST_JOIN_GROUP_body()
162{
163	multicast_vnet_init
164
165	# join group on interface epair1
166	multicast_join group_req ${epair1}b
167	atf_check -s exit:0 -o empty \
168	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
169	    0.0.0.0 6676 233.252.0.1 6676 ${epair1}a hello
170	atf_check -s exit:0 sh -c "wait $pid; exit $?"
171	atf_check -s exit:0 -o inline:"192.0.2.1:6676 hello\n" cat out
172
173	# join group on interface epair2
174	multicast_join group_req ${epair2}b
175	atf_check -s exit:0 -o empty \
176	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
177	    0.0.0.0 6676 233.252.0.1 6676 ${epair2}a hello
178	atf_check -s exit:0 sh -c "wait $pid; exit $?"
179	atf_check -s exit:0 -o inline:"192.0.3.1:6676 hello\n" cat out
180
181	# try to join group on the interface determined by the route lookup
182	atf_check -s exit:71 -e inline:"multicast-receive: setsockopt: Can't assign requested address\n" \
183	    jexec mjail2 $(atf_get_srcdir)/multicast-receive \
184	    group_req 233.252.0.1 6676 0
185	# add route and try again
186	jexec mjail2 route add default 192.0.3.254
187        multicast_join group_req 0
188	atf_check -s exit:0 -o empty \
189	    jexec mjail1 $(atf_get_srcdir)/multicast-send \
190	    0.0.0.0 6676 233.252.0.1 6676 192.0.3.1 hello
191	atf_check -s exit:0 sh -c "wait $pid; exit $?"
192	atf_check -s exit:0 -o inline:"192.0.3.1:6676 hello\n" cat out
193}
194MCAST_JOIN_GROUP_cleanup()
195{
196	rm out
197	vnet_cleanup
198}
199
200atf_init_test_cases()
201{
202	atf_add_test_case "IP_ADD_MEMBERSHIP_ip_mreq"
203	atf_add_test_case "IP_ADD_MEMBERSHIP_ip_mreqn"
204	atf_add_test_case "MCAST_JOIN_GROUP"
205}
206