1#	$OpenBSD: Makefile,v 1.16 2023/05/24 11:52:30 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)
8regress:
9	@echo Install scapy package to run this regress.
10	@echo SKIPPED
11.endif
12
13# This test needs a manual setup of two machines
14# Set up machines: LOCAL REMOTE
15# LOCAL is the machine where this makefile is running.
16# REMOTE is running OpenBSD with echo and chargen server to test PMTU
17# FAKE is an non existing machine in a non existing network.
18# REMOTE_SSH is the hostname to log in on the REMOTE machine.
19
20# Configure Addresses on the machines.
21# Adapt interface and addresse variables to your local setup.
22#
23LOCAL_IF ?=
24LOCAL_MAC ?=
25REMOTE_MAC ?=
26REMOTE_SSH ?=
27
28LOCAL_ADDR ?=
29REMOTE_ADDR ?=
30FAKE_NET ?=
31FAKE_NET_ADDR ?=
32
33LOCAL_ADDR6 ?=
34REMOTE_ADDR6 ?=
35FAKE_NET6 ?=
36FAKE_NET_ADDR6 ?=
37
38.if empty (LOCAL_IF) || empty (REMOTE_SSH) || \
39    empty (LOCAL_MAC) || empty (REMOTE_MAC) || \
40    empty (LOCAL_ADDR) || empty (LOCAL_ADDR6) || \
41    empty (REMOTE_ADDR) || empty (REMOTE_ADDR6) || \
42    empty (FAKE_NET) || empty (FAKE_NET6) || \
43    empty (FAKE_NET_ADDR) || empty (FAKE_NET_ADDR6)
44regress:
45	@echo This tests needs a remote machine to operate on
46	@echo LOCAL_IF REMOTE_SSH LOCAL_MAC REMOTE_MAC LOCAL_ADDR LOCAL_ADDR6
47	@echo REMOTE_ADDR REMOTE_ADDR6 FAKE_NET FAKE_NET6 FAKE_NET_ADDR
48	@echo FAKE_NET_ADDR6
49	@echo are empty.  Fill out these variables for additional tests.
50	@echo SKIPPED
51
52.elif make (regress) || make (all)
53.BEGIN: addr.py
54	${SUDO} true
55	ssh -t ${REMOTE_SSH} ${SUDO} true
56	@echo
57.endif
58
59# Create python include file containing the addresses.
60addr.py: Makefile
61	rm -f $@ $@.tmp
62	echo 'LOCAL_IF = "${LOCAL_IF}"' >>$@.tmp
63	echo 'LOCAL_MAC = "${LOCAL_MAC}"' >>$@.tmp
64	echo 'REMOTE_MAC = "${REMOTE_MAC}"' >>$@.tmp
65.for var in LOCAL REMOTE FAKE_NET
66	echo '${var}_ADDR = "${${var}_ADDR}"' >>$@.tmp
67	echo '${var}_ADDR6 = "${${var}_ADDR6}"' >>$@.tmp
68.endfor
69	echo 'FAKE_NET = "${FAKE_NET}"' >>$@.tmp
70	echo 'FAKE_NET6 = "${FAKE_NET6}"' >>$@.tmp
71	mv $@.tmp $@
72
73REGRESS_SETUP_ONCE +=	pfctl
74stamp-pfctl: addr.py pf.conf
75pfctl:
76	# default "block return; pass" interferes with test, use "block; pass"
77	cat addr.py ${.CURDIR}/pf.conf | /sbin/pfctl -n -f -
78	cat addr.py ${.CURDIR}/pf.conf | ${SUDO} /sbin/pfctl -a regress -f -
79	cat addr.py ${.CURDIR}/pf.conf | \
80	    ssh ${REMOTE_SSH} ${SUDO} pfctl -a regress -f -
81
82# Set variables so that make runs with and without obj directory.
83# Only do that if necessary to keep visible output short.
84.if ${.CURDIR} == ${.OBJDIR}
85PYTHON =	python3 -u ./
86.else
87PYTHON =	PYTHONPATH=${.OBJDIR} python3 -u ${.CURDIR}/
88.endif
89
90# Clear local and remote path mtu routes, set fake net route
91REGRESS_CLEANUP +=	reset-route
92reset-route:
93	${SUDO} route -n delete -inet -host ${REMOTE_ADDR} || true
94	ssh ${REMOTE_SSH} ${SUDO} route -n delete -inet -host ${FAKE_NET_ADDR} || true
95REGRESS_CLEANUP +=	reset-route6
96reset-route6:
97	${SUDO} route -n delete -inet6 -host ${REMOTE_ADDR6} || true
98	ssh ${REMOTE_SSH} ${SUDO} route -n delete -inet6 -host ${FAKE_NET_ADDR6} || true
99
100# Clear host routes and ping all addresses.  This ensures that
101# the IP addresses are configured and all routing table are set up
102# to allow bidirectional packet flow.
103REGRESS_TARGETS +=	run-ping
104run-ping: reset-route
105.for ip in LOCAL_ADDR REMOTE_ADDR
106	@echo Check ping ${ip}
107	ping -n -c 1 ${${ip}}
108.endfor
109REGRESS_TARGETS +=	run-ping6
110run-ping6: reset-route6
111.for ip in LOCAL_ADDR REMOTE_ADDR
112	@echo Check ping6 ${ip}6
113	ping6 -n -c 1 ${${ip}6}
114.endfor
115
116REGRESS_TARGETS +=	run-pmtu
117run-pmtu: addr.py reset-route
118	@echo Send ICMP fragmentation needed after fake TCP connect
119	${SUDO} ${PYTHON}tcp_connect.py
120REGRESS_TARGETS +=	run-pmtu6
121run-pmtu6: addr.py reset-route6
122	@echo Send ICMP6 packet too big after fake TCP connect
123	${SUDO} ${PYTHON}tcp_connect6.py
124
125REGRESS_TARGETS +=	run-udp6
126run-udp6: addr.py reset-route6
127	@echo Send ICMP6 packet too big after UDP echo
128	${SUDO} ${PYTHON}udp_echo6.py
129
130REGRESS_TARGETS +=	run-gateway6
131run-gateway6: run-udp6
132	@echo Remove gateway route of a dynamic PMTU route
133	ssh ${REMOTE_SSH} ${SUDO} route -n delete -inet6 -host ${LOCAL_ADDR6}
134	ssh ${REMOTE_SSH} route -n get -inet6 -host ${FAKE_NET_ADDR6}\
135	    >pmtu.route
136	cat pmtu.route
137	grep -q 'gateway: ${LOCAL_ADDR6}' pmtu.route
138	grep -q 'flags: <UP,GATEWAY,HOST,DYNAMIC,DONE>' pmtu.route
139	${SUDO} ${PYTHON}udp_echo6.py
140
141REGRESS_TARGETS +=	run-tcpfrag6
142run-tcpfrag6: addr.py reset-route6
143	@echo Send ICMP6 and try to trigger a short TCP segment
144	${SUDO} ${PYTHON}tcp_atomicfrag6.py
145REGRESS_TARGETS +=	run-udpfrag6
146run-udpfrag6: addr.py reset-route6
147	@echo Send ICMP6 and try to trigger an atomic UDP IPv6 fragment
148	${SUDO} ${PYTHON}udp_atomicfrag6.py
149
150CLEANFILES +=		addr.py *.pyc *.log *.route
151
152.PHONY: check-setup check-setup-local check-setup-remote
153
154# Check wether the address, route and remote setup is correct
155check-setup: check-setup-local check-setup-remote
156
157check-setup-local:
158	@echo '\n======== $@ ========'
159	ping -n -c 1 ${LOCAL_ADDR}  # LOCAL_ADDR
160	route -n get -inet ${LOCAL_ADDR} | grep -q 'flags: .*LOCAL'  # LOCAL_ADDR
161	arp -na | grep -q '^${LOCAL_ADDR} * ${LOCAL_MAC} * ${LOCAL_IF} permanent'  # LOCAL_ADDR LOCAL_MAC LOCAL_IF
162	ping -n -c 1 ${REMOTE_ADDR}  # REMOTE_ADDR
163	route -n get -inet ${REMOTE_ADDR} | fgrep -q 'interface: ${LOCAL_IF}'  # REMOTE_ADDR LOCAL_IF
164	! ping -n -c 1 -w 1 ${FAKE_NET_ADDR}  # FAKE_NET_ADDR
165	route -n get -inet ${FAKE_NET_ADDR} | grep -q 'flags: .*BLACKHOLE'  # FAKE_NET_ADDR
166	route -n get -inet -net ${FAKE_NET} | grep -q 'flags: .*BLACKHOLE'  # FAKE_NET
167	ping6 -n -c 1 ${LOCAL_ADDR6}  # LOCAL_ADDR6
168	route -n get -inet6 ${LOCAL_ADDR6} | grep -q 'flags: .*LOCAL'  # LOCAL_ADDR6
169	ndp -na | grep -q '^${LOCAL_ADDR6} * ${LOCAL_MAC} * ${LOCAL_IF} permanent'  # LOCAL_ADDR6 LOCAL_MAC LOCAL_IF
170	ping6 -n -c 1 ${REMOTE_ADDR6}  # REMOTE_ADDR6
171	route -n get -inet6 ${REMOTE_ADDR6} | fgrep -q 'interface: ${LOCAL_IF}'  # REMOTE_ADDR6 LOCAL_IF
172	! ping -n -c 1 -w 1 ${FAKE_NET_ADDR6}  # FAKE_NET_ADDR6
173	route -n get -inet6 ${FAKE_NET_ADDR6} | grep -q 'flags: .*BLACKHOLE'  # FAKE_NET_ADDR6
174	route -n get -inet6 -net ${FAKE_NET6} | grep -q 'flags: .*BLACKHOLE'  # FAKE_NET6
175	${SUDO} pfctl -sr | grep '^anchor "regress" all$$'
176	${SUDO} pfctl -si | grep '^Status: Enabled '
177
178check-setup-remote:
179	@echo '\n======== $@ ========'
180	ssh ${REMOTE_SSH} ping -n -c 1 ${REMOTE_ADDR}  # REMOTE_ADDR
181	ssh ${REMOTE_SSH} route -n get -inet ${REMOTE_ADDR} | grep -q 'flags: .*LOCAL'  # REMOTE_ADDR
182	ssh ${REMOTE_SSH} arp -na | grep -q '^${REMOTE_ADDR} * ${REMOTE_MAC} * .* permanent'  # REMOTE_ADDR REMOTE_MAC
183	ssh ${REMOTE_SSH} ping -n -c 1 ${LOCAL_ADDR}  # LOCAL_ADDR
184.for ip in FAKE_NET FAKE_NET_ADDR
185	ssh ${REMOTE_SSH} route -n get -inet ${${ip}} | fgrep -q 'gateway: ${LOCAL_ADDR}'  # ${ip} LOCAL_ADDR
186.endfor
187	ssh ${REMOTE_SSH} ping6 -n -c 1 ${REMOTE_ADDR6}  # REMOTE_ADDR6
188	ssh ${REMOTE_SSH} route -n get -inet6 ${REMOTE_ADDR6} | grep -q 'flags: .*LOCAL'  # REMOTE_ADDR6
189	ssh ${REMOTE_SSH} ndp -na | grep -q '^${REMOTE_ADDR6} * ${REMOTE_MAC} * .* permanent'  # REMOTE_ADDR6 REMOTE_MAC
190	ssh ${REMOTE_SSH} ping6 -n -c 1 ${LOCAL_ADDR6}  # LOCAL_ADDR6
191.for ip in FAKE_NET6 FAKE_NET_ADDR6
192	ssh ${REMOTE_SSH} route -n get -inet6 ${${ip}} | fgrep -q 'gateway: ${LOCAL_ADDR6}'  # ${ip} LOCAL_ADDR6
193.endfor
194.for af in inet inet6
195	ssh ${REMOTE_SSH} netstat -na -f ${af} -p tcp | fgrep ' *.19 '
196.endfor
197	ssh ${REMOTE_SSH} netstat -na -f inet6 -p udp | fgrep ' *.7 '
198	ssh ${REMOTE_SSH} ${SUDO} pfctl -sr | grep '^anchor "regress" all$$'
199	ssh ${REMOTE_SSH} ${SUDO} pfctl -si | grep '^Status: Enabled '
200
201.include <bsd.regress.mk>
202