1#	$OpenBSD: Makefile,v 1.30 2024/03/12 21:31:29 bluhm Exp $
2
3# The following ports must be installed:
4#
5# scapy               powerful interactive packet manipulation in python
6
7.if ! exists(/usr/local/bin/scapy)
8.BEGIN:
9	@true
10regress:
11	@echo Install scapy package to run this regress.
12	@echo SKIPPED
13.endif
14
15# This test needs a manual setup of two machines
16# Set up machines: LOCAL REMOTE
17# LOCAL is the machine where this makefile is running.
18# REMOTE is running OpenBSD with or without pf to test fragment reassemly
19# Enable echo udp6 in inetd.conf on REMOTE to test UDP fragments.
20# REMOTE_SSH is used to login and enable or disable pf automatically.
21
22# Configure addresses on the machines.
23# Adapt interface and addresse variables to your local setup.
24
25LOCAL_IF ?=	em1
26LOCAL_MAC ?=	00:1b:21:0e:6e:8e
27REMOTE_MAC ?=	00:04:23:b0:68:8e
28
29LOCAL_ADDR6 ?=	fdd7:e83e:66bc:81::21
30REMOTE_ADDR6 ?=	fdd7:e83e:66bc:81::22
31
32REMOTE_SSH ?=
33
34.if empty (LOCAL_IF) || empty (LOCAL_MAC) || empty (REMOTE_MAC) || \
35    empty (LOCAL_ADDR6) || empty (REMOTE_ADDR6) || empty (REMOTE_SSH)
36.BEGIN:
37	@true
38regress:
39	@echo This tests needs a remote machine to operate on.
40	@echo LOCAL_IF LOCAL_MAC REMOTE_MAC LOCAL_ADDR6 REMOTE_ADDR6 REMOTE_SSH
41	@echo Fill out these variables for additional tests.
42	@echo SKIPPED
43.endif
44
45.MAIN: all
46
47.if make (regress) || make (all)
48.BEGIN:
49	${SUDO} true
50	ssh -t ${REMOTE_SSH} ${SUDO} true
51	rm -f stamp-stack stamp-pf
52	@echo
53.endif
54
55# Create python include file containing the addresses.
56addr.py: Makefile
57	rm -f $@ $@.tmp
58	echo 'LOCAL_IF = "${LOCAL_IF}"' >>$@.tmp
59	echo 'LOCAL_MAC = "${LOCAL_MAC}"' >>$@.tmp
60	echo 'REMOTE_MAC = "${REMOTE_MAC}"' >>$@.tmp
61.for var in LOCAL_ADDR REMOTE_ADDR
62	echo '${var}6 = "${${var}6}"' >>$@.tmp
63.endfor
64	mv $@.tmp $@
65
66# Set variables so that make runs with and without obj directory.
67# Only do that if necessary to keep visible output short.
68.if ${.CURDIR} == ${.OBJDIR}
69PYTHON =	python3 -u ./
70.else
71PYTHON =	PYTHONPATH=${.OBJDIR} python3 -u ${.CURDIR}/
72.endif
73
74stamp-stack:
75	rm -f stamp-stack stamp-pf
76	-ssh ${REMOTE_SSH} ${SUDO} pfctl -d
77	ssh ${REMOTE_SSH} ${SUDO} pfctl -a regress -Fr
78	date >$@
79
80stamp-pf: addr.py pf.conf
81	rm -f stamp-stack stamp-pf
82	cat addr.py ${.CURDIR}/pf.conf | pfctl -n -f -
83	cat addr.py ${.CURDIR}/pf.conf | \
84	    ssh ${REMOTE_SSH} ${SUDO} pfctl -a regress -f -
85	-ssh ${REMOTE_SSH} ${SUDO} pfctl -e
86	date >$@
87
88FRAG6_SCRIPTS !!=	cd ${.CURDIR} && ls -1 frag6*.py
89
90run-stack-frag6_queuelimit.py:
91	# stack does not limit the amount of fragments during reassembly
92	@echo DISABLED
93
94run-pf-frag6_oversize.py run-pf-frag6_unfragsize.py:
95	# pf does not send icmp parameter problem, so test does not work
96	@echo DISABLED
97
98run-stack-frag6_doubleatomic.py: addr.py stamp-stack
99	# IPv6 stack accepts double atomic fragement, this is not a big issue
100	set +e; ${SUDO} ${PYTHON}frag6_doubleatomic.py; [[ $$? == 1 ]]
101
102.for sp in stack pf
103
104# Ping all addresses.  This ensures that the ip addresses are configured
105# and all routing table are set up to allow bidirectional packet flow.
106${sp}: run-${sp}-ping6
107REGRESS_TARGETS +=	run-${sp}-ping6
108run-${sp}-ping6: stamp-${sp}
109.for ip in LOCAL_ADDR REMOTE_ADDR
110	@echo Check ping6 ${ip}6:
111	ping6 -n -c 1 ${${ip}6}
112.endfor
113
114# Ping all addresses again but with 5000 bytes payload.  These large
115# packets get fragmented by LOCAL and must be handled by REMOTE.
116${sp}: run-${sp}-fragping6
117REGRESS_TARGETS +=	run-${sp}-fragping6
118run-${sp}-fragping6: stamp-${sp}
119.for ip in LOCAL_ADDR REMOTE_ADDR
120	@echo Check ping6 ${ip}6:
121	ping6 -n -c 1 -s 5000 -m ${${ip}6}
122.endfor
123
124.for s in ${FRAG6_SCRIPTS}
125${sp}: run-${sp}-${s}
126REGRESS_TARGETS +=	run-${sp}-${s}
127run-${sp}-${s}: addr.py stamp-${sp}
128	${SUDO} ${PYTHON}${s}
129.endfor
130
131.endfor
132
133# After running the tests, turn on pf on remote machine.
134# This is the expected default configuration.
135REGRESS_CLEANUP +=	cleanup-pf
136cleanup-pf:
137	rm -f stamp-stack stamp-pf
138	ssh ${REMOTE_SSH} ${SUDO} pfctl -a regress -Fa
139	-ssh ${REMOTE_SSH} ${SUDO} pfctl -e || true
140
141CLEANFILES +=		addr.py *.pyc *.log stamp-*
142
143.PHONY: check-setup check-setup-local check-setup-remote
144
145# Check wether the address, route and remote setup is correct
146check-setup: check-setup-local check-setup-remote
147
148check-setup-local:
149	@echo '\n======== $@ ========'
150	ping6 -n -c 1 ${LOCAL_ADDR6}  # LOCAL_ADDR6
151	route -n get -inet6 ${LOCAL_ADDR6} |\
152	    grep -q 'flags: .*LOCAL'  # LOCAL_ADDR6
153	ping6 -n -c 1 ${REMOTE_ADDR6}  # REMOTE_ADDR6
154	route -n get -inet6 ${REMOTE_ADDR6} |\
155	    grep -q 'interface: ${LOCAL_IF}$$'  # REMOTE_ADDR6 LOCAL_IF
156	ndp -n ${REMOTE_ADDR6} |\
157	    grep -q ' ${REMOTE_MAC} '  # REMOTE_ADDR6 REMOTE_MAC
158
159check-setup-remote:
160	@echo '\n======== $@ ========'
161	ssh ${REMOTE_SSH} ping6 -n -c 1 ${REMOTE_ADDR6}  # REMOTE_ADDR6
162	ssh ${REMOTE_SSH} route -n get -inet6 ${REMOTE_ADDR6} |\
163	    grep -q 'flags: .*LOCAL'  # REMOTE_ADDR6
164	ssh ${REMOTE_SSH} ping6 -n -c 1 ${LOCAL_ADDR6}  # LOCAL_ADDR6
165	ssh ${REMOTE_SSH} ndp -n ${LOCAL_ADDR6} |\
166	    grep -q ' ${LOCAL_MAC} '  # LOCAL_ADDR6 LOCAL_MAC
167	ssh ${REMOTE_SSH} route -n get -inet6 ${FAKE_NET_ADDR6} |\
168	    grep -q 'gateway: ${LOCAL_ADDR6}'  # FAKE_NET_ADDR6 LOCAL_ADDR6
169	ssh ${REMOTE_SSH} netstat -na -f inet6 -p udp | fgrep ' *.7 '
170
171.include <bsd.regress.mk>
172