xref: /openbsd/regress/sys/net/pf_fragment/Makefile (revision 264ca280)
1#	$OpenBSD: Makefile,v 1.19 2016/05/28 19:54:26 sthen Exp $
2
3# The following ports must be installed:
4#
5# python-2.7          interpreted object-oriented programming language
6# py-libdnet          python interface to libdnet
7# scapy               powerful interactive packet manipulation in python
8
9# Check whether all required python packages are installed.  If some
10# are missing print a warning and skip the tests, but do not fail.
11PYTHON_IMPORT != python2.7 -c 'from scapy.all import *' 2>&1 || true
12.if ! empty(PYTHON_IMPORT)
13regress:
14	@echo '${PYTHON_IMPORT}'
15	@echo install python and the scapy module for additional tests
16.endif
17
18# This test needs a manual setup of four machines
19# The setup is the same as for regress/sys/net/pf_forward
20# Set up machines: SRC PF RT ECO
21# SRC is the machine where this makefile is running.
22# PF is running OpenBSD forwarding through pf, it is the test target.
23# RT is a router forwarding packets, maximum MTU is 1300.
24# ECO is reflecting the ping and UDP echo packets.
25# RDR does not exist, PF redirects the traffic to ECO.
26# RTT addresses exist on ECO, PF has no route and must use route-to RT
27#
28# +---+   0   +--+   1   +--+   2   +---+ 7   4 +---+   7 +---+
29# |SRC| ----> |PF| ----> |RT| ----> |ECO|       |RDR|     |RTT|
30# +---+       +--+       +--+       +---+       +---+     +---+
31#     out    in  out    in  out    in   rtt    in        in
32
33# Configure Addresses on the machines, there must be routes for the
34# networks.  Adapt interface and address variables to your local
35# setup.  To control the remote machine you need a hostname for
36# ssh to log in.
37# You must have an anchor "regress" for the divert rules in the pf.conf
38# of the PF machine.  The kernel of the PF machine gets tested.
39#
40# Run make check-setup to see if you got the setup correct.
41
42SRC_IF ?=	tap0
43SRC_MAC ?=	fe:e1:ba:d1:0a:dc
44PF_IFIN ?=	vio0
45PF_IFOUT ?=	vio1
46PF_MAC ?=	52:54:00:12:34:50
47PF_SSH ?=
48RT_SSH ?=
49ECO_SSH ?=
50
51SRC_OUT ?=	10.188.210.10
52PF_IN ?=	10.188.210.50
53PF_OUT ?=	10.188.211.50
54RT_IN ?=	10.188.211.51
55RT_OUT ?=	10.188.212.51
56ECO_IN ?=	10.188.212.52
57RDR_IN ?=	10.188.214.188
58RTT_IN ?=	10.188.217.52
59
60SRC_OUT6 ?=	fdd7:e83e:66bc:210:fce1:baff:fed1:561f
61PF_IN6 ?=	fdd7:e83e:66bc:210:5054:ff:fe12:3450
62PF_OUT6 ?=	fdd7:e83e:66bc:211:5054:ff:fe12:3450
63RT_IN6 ?=	fdd7:e83e:66bc:211:5054:ff:fe12:3451
64RT_OUT6 ?=	fdd7:e83e:66bc:212:5054:ff:fe12:3451
65ECO_IN6 ?=	fdd7:e83e:66bc:212:5054:ff:fe12:3452
66RDR_IN6 ?=	fdd7:e83e:66bc:214::188
67RTT_IN6 ?=	fdd7:e83e:66bc:217:5054:ff:fe12:3452
68
69.if empty (PF_SSH) || empty (RT_SSH) || empty (ECO_SSH)
70regress:
71	@echo this test needs three remote machines to operate on
72	@echo PF_SSH RT_SSH ECO_SSH are empty
73	@echo fill out these variables for additional tests, then
74	@echo check whether your test machines are set up properly
75.endif
76
77.MAIN: all
78
79.if ! empty (PF_SSH)
80.if make (regress) || make (all)
81.BEGIN: pf.conf addr.py
82	@echo
83	${SUDO} true
84	ssh -t ${PF_SSH} ${SUDO} true
85	rm -f stamp-pfctl
86.endif
87.endif
88
89depend: addr.py
90
91# Create python include file containing the addresses.
92addr.py: Makefile
93	rm -f $@ $@.tmp
94	echo 'SRC_IF="${SRC_IF}"' >>$@.tmp
95	echo 'SRC_MAC="${SRC_MAC}"' >>$@.tmp
96	echo 'PF_IFIN="${PF_IFIN}"' >>$@.tmp
97	echo 'PF_IFOUT="${PF_IFOUT}"' >>$@.tmp
98	echo 'PF_MAC="${PF_MAC}"' >>$@.tmp
99.for var in SRC_OUT PF_IN PF_OUT RT_IN RT_OUT ECO_IN RDR_IN RTT_IN
100	echo '${var}="${${var}}"' >>$@.tmp
101	echo '${var}6="${${var}6}"' >>$@.tmp
102.endfor
103	mv $@.tmp $@
104
105# load the pf rules into the kernel of the PF machine
106# XXX pfctl does not replace variables after @
107stamp-pfctl: addr.py pf.conf
108	cat addr.py ${.CURDIR}/pf.conf | pfctl -n -f -
109	cat addr.py ${.CURDIR}/pf.conf | \
110	    sed 's/@$$PF_IFIN /@${PF_IFIN} /;s/@$$PF_IFOUT /@${PF_IFOUT} /' | \
111	    ssh ${PF_SSH} ${SUDO} pfctl -a regress -f -
112	@date >$@
113
114# Set variables so that make runs with and without obj directory.
115# Only do that if necessary to keep visible output short.
116.if ${.CURDIR} == ${.OBJDIR}
117PYTHON =	python2.7 ./
118.else
119PYTHON =	PYTHONPATH=${.OBJDIR} python2.7 ${.CURDIR}/
120.endif
121
122# Ping all addresses.  This ensures that the IP addresses are configured
123# and all routing table are set up to allow bidirectional packet flow.
124# Note that RDR does not exist physically.  So this traffic is rewritten
125# by PF and handled by ECO.
126TARGETS +=	ping  ping6
127
128run-regress-ping: stamp-pfctl
129	@echo '\n======== $@ ========'
130.for ip in SRC_OUT PF_IN PF_OUT RT_IN RT_OUT ECO_IN RDR_IN RTT_IN
131	@echo Check ping ${ip}:
132	ping -n -c 1 ${${ip}}
133.endfor
134
135run-regress-ping6: stamp-pfctl
136	@echo '\n======== $@ ========'
137.for ip in SRC_OUT PF_IN PF_OUT RT_IN RT_OUT ECO_IN RDR_IN RTT_IN
138	@echo Check ping ${ip}6:
139	ping6 -n -c 1 ${${ip}6}
140.endfor
141
142# Ping all addresses again but with 5000 bytes payload.  These large
143# packets get fragmented by SRC and must be handled by PF.
144# Send 1 packet in advance for Path-MTU discovery.
145TARGETS +=	fragping  fragping6
146
147run-regress-fragping: stamp-pfctl
148	@echo '\n======== $@ ========'
149.for ip in PF_IN PF_OUT RT_IN RT_OUT ECO_IN RDR_IN RTT_IN
150	@echo Check ping ${ip}:
151	ping -n -c 1 -s 5000 ${${ip}}
152.endfor
153
154run-regress-fragping6: stamp-pfctl
155	@echo '\n======== $@ ========'
156.for ip in PF_IN PF_OUT RT_IN RT_OUT
157	@echo Check ping ${ip}6:
158	${SUDO} route -n delete -host -inet6 ${${ip}6} || true
159	ping6 -n -c 1 -s 1452 -m ${${ip}6} & sleep 1; kill $$! || true
160	ping6 -n -c 1 -s 5000 -m ${${ip}6}
161.endfor
162.for ip in ECO_IN RDR_IN RTT_IN
163	@echo Check ping ${ip}6:
164	${SUDO} route -n delete -host -inet6 ${${ip}6} || true
165	ping6 -n -c 1 -s 1352 -m ${${ip}6} & sleep 1; kill $$! || true
166	ping6 -n -c 1 -s 5000 -m ${${ip}6}
167.endfor
168
169# Send a large IPv4/ICMP-Echo-Request packet with enabled DF bit and
170# parse response packet to determine MTU of the router.  The MTU has
171# to be 1300 octets.  The MTU has to be defined at out interface of
172# the router RT before.
173TARGETS +=	ping-mtu ping6-mtu
174
175run-regress-ping-mtu: addr.py stamp-pfctl
176	@echo '\n======== $@ ========'
177.for ip in ECO_IN RDR_IN RTT_IN
178	@echo Check path MTU to ${ip}
179	${SUDO} ${PYTHON}ping_mtu_1300.py ${${ip}}
180.endfor
181
182run-regress-ping6-mtu: addr.py stamp-pfctl
183	@echo '\n======== $@ ========'
184.for ip in ECO_IN RDR_IN RTT_IN
185	@echo Check path MTU to ${ip}6
186	${SUDO} ${PYTHON}ping6_mtu_1300.py ${${ip}6}
187.endfor
188
189# Send packet too big to get to destination.
190# Check that checksum of the quoted original packet in ICMP is correct.
191
192# Currently these test fail as pf does not fix the checksum of
193# NATed packets inside of ICMP packets.
194# XXX TARGETS +=	ping-cksum ping6-cksum udp-cksum udp6-cksum
195
196run-regress-ping-cksum: addr.py stamp-pfctl
197	@echo '\n======== $@ ========'
198.for ip in ECO_IN RDR_IN RTT_IN
199	@echo Check ICMP chksum in fragmentation needed to ${ip}
200	${SUDO} ${PYTHON}ping_cksum.py ${${ip}}
201.endfor
202
203run-regress-ping6-cksum: addr.py stamp-pfctl
204	@echo '\n======== $@ ========'
205.for ip in ECO_IN RDR_IN RTT_IN
206	@echo Check ICMP6 chksum in packet too big to ${ip}6
207	${SUDO} ${PYTHON}ping6_cksum.py ${${ip}6}
208.endfor
209
210run-regress-udp-cksum: addr.py stamp-pfctl
211	@echo '\n======== $@ ========'
212.for ip in ECO_IN RDR_IN RTT_IN
213	@echo Check UDP chksum in packet too big to ${ip}
214	${SUDO} ${PYTHON}udp_cksum.py ${${ip}}
215.endfor
216
217run-regress-udp6-cksum: addr.py stamp-pfctl
218	@echo '\n======== $@ ========'
219.for ip in ECO_IN RDR_IN RTT_IN
220	@echo Check UDP6 chksum in packet too big to ${ip}6
221	${SUDO} ${PYTHON}udp6_cksum.py ${${ip}6}
222.endfor
223
224# Send handcrafted fragmented packets with overlaps
225TARGETS +=	frag frag6
226
227run-regress-frag: addr.py stamp-pfctl
228	@echo '\n======== $@ ========'
229.for ip in ECO_IN RDR_IN RTT_IN
230	@echo Check ping reassembly ${ip}
231	${SUDO} ${PYTHON}frag.py ${${ip}}
232.endfor
233
234run-regress-frag6: addr.py stamp-pfctl
235	@echo '\n======== $@ ========'
236.for ip in ECO_IN RDR_IN RTT_IN
237	@echo Check ping6 reassembly ${ip}6
238	${SUDO} ${PYTHON}frag6.py ${${ip}6}
239.endfor
240
241TARGETS +=	frag6-ext
242
243run-regress-frag6-ext: addr.py stamp-pfctl
244	@echo '\n======== $@ ========'
245.for ip in ECO_IN RDR_IN RTT_IN
246	@echo Check ping6 extension header reassembly ${ip}6
247	${SUDO} ${PYTHON}frag6_ext.py ${${ip}6}
248.endfor
249
250TARGETS +=	frag-cutnew frag6-cutnew
251
252run-regress-frag-cutnew: addr.py stamp-pfctl
253	@echo '\n======== $@ ========'
254.for ip in ECO_IN RDR_IN RTT_IN
255	@echo Check ping head overlap reassembly ${ip}
256	${SUDO} ${PYTHON}frag_cutnew.py ${${ip}}
257.endfor
258
259run-regress-frag6-cutnew: addr.py stamp-pfctl
260	@echo '\n======== $@ ========'
261.for ip in ECO_IN RDR_IN RTT_IN
262	@echo Check ping6 head overlap reassembly ${ip}6
263	${SUDO} ${PYTHON}frag6_cutnew.py ${${ip}6}
264.endfor
265
266TARGETS +=	frag-cutold frag6-cutold
267
268run-regress-frag-cutold: addr.py stamp-pfctl
269	@echo '\n======== $@ ========'
270.for ip in ECO_IN RDR_IN RTT_IN
271	@echo Check ping tail overlap reassembly ${ip}
272	${SUDO} ${PYTHON}frag_cutold.py ${${ip}}
273.endfor
274
275run-regress-frag6-cutold: addr.py stamp-pfctl
276	@echo '\n======== $@ ========'
277.for ip in ECO_IN RDR_IN RTT_IN
278	@echo Check ping6 tail overlap reassembly ${ip}6
279	${SUDO} ${PYTHON}frag6_cutold.py ${${ip}6}
280.endfor
281
282TARGETS +=	frag-dropold frag6-dropold
283
284run-regress-frag-dropold: addr.py stamp-pfctl
285	@echo '\n======== $@ ========'
286.for ip in ECO_IN RDR_IN RTT_IN
287	@echo Check ping total overlapping reassembly ${ip}
288	${SUDO} ${PYTHON}frag_dropold.py ${${ip}}
289.endfor
290
291run-regress-frag6-dropold: addr.py stamp-pfctl
292	@echo '\n======== $@ ========'
293.for ip in ECO_IN RDR_IN RTT_IN
294	@echo Check ping6 total overlapping reassembly ${ip}6
295	${SUDO} ${PYTHON}frag6_dropold.py ${${ip}6}
296.endfor
297
298TARGETS +=	frag-dropnew frag6-dropnew
299
300run-regress-frag-dropnew: addr.py stamp-pfctl
301	@echo '\n======== $@ ========'
302.for ip in ECO_IN RDR_IN RTT_IN
303	@echo Check ping total overlaped reassembly ${ip}
304	${SUDO} ${PYTHON}frag_dropnew.py ${${ip}}
305.endfor
306
307run-regress-frag6-dropnew: addr.py stamp-pfctl
308	@echo '\n======== $@ ========'
309.for ip in ECO_IN RDR_IN RTT_IN
310	@echo Check ping6 total overlaped reassembly ${ip}6
311	${SUDO} ${PYTHON}frag6_dropnew.py ${${ip}6}
312.endfor
313
314REGRESS_TARGETS =	${TARGETS:S/^/run-regress-/}
315
316CLEANFILES +=		addr.py *.pyc *.log stamp-*
317
318.PHONY: check-setup
319
320# Check whether the address, route and remote setup are correct
321check-setup:
322	@echo '\n======== $@ SRC ========'
323.for ip in SRC_OUT
324	ping -n -c 1 ${${ip}}  # ${ip}
325	route -n get -inet ${${ip}} | grep -q 'flags: .*LOCAL'  # ${ip}
326.endfor
327	ping -n -c 1 ${PF_IN}  # PF_IN
328	route -n get -inet ${PF_IN} | fgrep -q 'interface: ${SRC_IF}'  # PF_IN SRC_IF
329.for ip in PF_OUT RT_IN RT_OUT ECO_IN RDR_IN RTT_IN
330	route -n get -inet ${${ip}} | fgrep -q 'gateway: ${PF_IN}'  # ${ip} PF_IN
331.endfor
332.for ip in SRC_OUT
333	ping6 -n -c 1 ${${ip}6}  # ${ip}6
334	route -n get -inet6 ${${ip}6} | grep -q 'flags: .*LOCAL'  # ${ip}6
335.endfor
336	ping6 -n -c 1 ${PF_IN6}  # PF_IN6
337	route -n get -inet6 ${PF_IN6} | fgrep -q 'interface: ${SRC_IF}'  # PF_IN6 SRC_IF
338.for ip in PF_OUT RT_IN RT_OUT ECO_IN RDR_IN RTT_IN
339	route -n get -inet6 ${${ip}6} | fgrep -q 'gateway: ${PF_IN6}'  # ${ip}6 PF_IN6
340.endfor
341	@echo '\n======== $@ PF ========'
342	ssh ${PF_SSH} ping -n -c 1 ${PF_IN}  # PF_IN
343	ssh ${PF_SSH} route -n get -inet ${PF_IN} | grep -q 'flags: .*LOCAL'  # PF_IN
344	ssh ${PF_SSH} ping -n -c 1 ${SRC_OUT}  # SRC_OUT
345	ssh ${PF_SSH} ping -n -c 1 ${PF_OUT}  # PF_OUT
346	ssh ${PF_SSH} route -n get -inet ${PF_OUT} | grep -q 'flags: .*LOCAL'  # PF_OUT
347	ssh ${PF_SSH} ping -n -c 1 ${RT_IN}  # RT_IN
348.for ip in RT_OUT ECO_IN
349	ssh ${PF_SSH} route -n get -inet ${${ip}} | fgrep -q 'gateway: ${RT_IN}'  # ${ip} RT_IN
350.endfor
351.for ip in RTT_IN
352	ssh ${PF_SSH} route -n get -inet ${${ip}} | grep -q 'flags: .*REJECT'  # ${ip} reject
353.endfor
354	ssh ${PF_SSH} ping6 -n -c 1 ${PF_IN6}  # PF_IN6
355	ssh ${PF_SSH} route -n get -inet6 ${PF_IN6} | grep -q 'flags: .*LOCAL'  # PF_IN6
356	ssh ${PF_SSH} ping6 -n -c 1 ${SRC_OUT6}  # SRC_OUT6
357	ssh ${PF_SSH} ping6 -n -c 1 ${PF_OUT6}  # PF_OUT6
358	ssh ${PF_SSH} route -n get -inet6 ${PF_OUT6} | grep -q 'flags: .*LOCAL'  # PF_OUT6
359	ssh ${PF_SSH} ping6 -n -c 1 ${RT_IN6}  # RT_IN6
360.for ip in RT_OUT ECO_IN
361	ssh ${PF_SSH} route -n get -inet6 ${${ip}6} | fgrep -q 'gateway: ${RT_IN6}'  # ${ip}6 RT_IN6
362.endfor
363.for ip in RTT_IN
364	ssh ${PF_SSH} route -n get -inet6 ${${ip}6} | grep -q 'flags: .*REJECT'  # ${ip}6 reject
365.endfor
366	ssh ${PF_SSH} ${SUDO} pfctl -sr | grep '^anchor "regress" all$$'
367	ssh ${PF_SSH} ${SUDO} pfctl -si | grep '^Status: Enabled '
368	ssh ${PF_SSH} sysctl net.inet.ip.forwarding | fgrep =1
369	ssh ${PF_SSH} sysctl net.inet6.ip6.forwarding | fgrep =1
370	@echo '\n======== $@ RT ========'
371	ssh ${RT_SSH} ping -n -c 1 ${RT_IN}  # RT_IN
372	ssh ${RT_SSH} route -n get -inet ${RT_IN} | grep -q 'flags: .*LOCAL'  # RT_IN
373	ssh ${RT_SSH} ping -n -c 1 ${PF_OUT}  # PF_OUT
374.for ip in PF_IN SRC_OUT
375	ssh ${RT_SSH} route -n get -inet ${${ip}} | fgrep -q 'gateway: ${PF_OUT}'  # ${ip} PF_OUT
376.endfor
377	ssh ${RT_SSH} ping -n -c 1 ${RT_OUT}  # RT_OUT
378	ssh ${RT_SSH} route -n get -inet ${RT_OUT} | grep -q 'flags: .*LOCAL'  # RT_OUT
379	ssh ${RT_SSH} ping -n -c 1 ${ECO_IN}  # ECO_IN
380.for ip in RTT_IN
381	ssh ${RT_SSH} route -n get -inet ${${ip}} | fgrep -q 'gateway: ${ECO_IN}'  # ${ip} ECO_IN
382.endfor
383	ssh ${RT_SSH} ping6 -n -c 1 ${RT_IN6}  # RT_IN6
384	ssh ${RT_SSH} route -n get -inet6 ${RT_IN6} | grep -q 'flags: .*LOCAL'  # RT_IN6
385	ssh ${RT_SSH} ping6 -n -c 1 ${PF_OUT6}  # PF_OUT6
386.for ip in PF_IN SRC_OUT
387	ssh ${RT_SSH} route -n get -inet6 ${${ip}6} | fgrep -q 'gateway: ${PF_OUT6}'  # ${ip}6 PF_OUT6
388.endfor
389	ssh ${RT_SSH} ping6 -n -c 1 ${RT_OUT6}  # RT_OUT6
390	ssh ${RT_SSH} route -n get -inet6 ${RT_OUT6} | grep -q 'flags: .*LOCAL'  # RT_OUT6
391	ssh ${RT_SSH} ping6 -n -c 1 ${ECO_IN6}  # ECO_IN6
392.for ip in RTT_IN
393	ssh ${RT_SSH} route -n get -inet6 ${${ip}6} | fgrep -q 'gateway: ${ECO_IN6}'  # ${ip}6 ECO_IN6
394.endfor
395	ssh ${RT_SSH} sysctl net.inet.ip.forwarding | fgrep =1
396	ssh ${RT_SSH} sysctl net.inet6.ip6.forwarding | fgrep =1
397	ssh ${RT_SSH} ifconfig | fgrep 'mtu 1300'
398	@echo '\n======== $@ ECO ========'
399.for ip in ECO_IN RTT_IN
400	ssh ${ECO_SSH} ping -n -c 1 ${${ip}}  # ${ip}
401	ssh ${ECO_SSH} route -n get -inet ${${ip}} | grep -q 'flags: .*LOCAL'  # ${ip}
402.endfor
403	ssh ${ECO_SSH} ping -n -c 1 ${RT_OUT}  # RT_OUT
404.for ip in RT_IN PF_OUT PF_IN SRC_OUT
405	ssh ${ECO_SSH} route -n get -inet ${${ip}} | fgrep -q 'gateway: ${RT_OUT}'  # ${ip} RT_OUT
406.endfor
407.for ip in ECO_IN RTT_IN
408	ssh ${ECO_SSH} ping6 -n -c 1 ${${ip}6}  # ${ip}6
409	ssh ${ECO_SSH} route -n get -inet6 ${${ip}6} | grep -q 'flags: .*LOCAL'  # ${ip}6
410.endfor
411	ssh ${ECO_SSH} ping6 -n -c 1 ${RT_OUT6}  # RT_OUT6
412.for ip in RT_IN PF_OUT PF_IN SRC_OUT
413	ssh ${ECO_SSH} route -n get -inet6 ${${ip}6} | fgrep -q 'gateway: ${RT_OUT6}'  # ${ip}6 RT_OUT6
414.endfor
415
416.include <bsd.regress.mk>
417