xref: /openbsd/regress/sys/net/pf_divert/Makefile (revision 31432b1d)
1#	$OpenBSD: Makefile,v 1.22 2019/07/12 19:31:29 bluhm Exp $
2
3# The following ports must be installed for the regression tests:
4# p5-IO-Socket-INET6	object interface for AF_INET and AF_INET6 domain sockets
5# p5-Socket6		Perl defines relating to AF_INET6 sockets
6#
7# Check wether all required perl packages are installed.  If some
8# are missing print a warning and skip the tests, but do not fail.
9
10PERL_REQUIRE !=	perl -Mstrict -Mwarnings -e ' \
11    eval { require IO::Socket::INET6 } or print $@; \
12    eval { require Socket6 } or print $@; \
13'
14.if ! empty(PERL_REQUIRE)
15regress:
16	@echo "${PERL_REQUIRE}"
17	@echo install these perl packages for additional tests
18	@echo SKIPPED
19.endif
20
21# Fill out these variables as you have to test divert with the pf
22# kernel running on a remote machine.  You have to specify a local
23# and remote ip address for the test connections.  The fake ip address
24# will be routed via the remote address to test divert with non-existing
25# addresses.  To control the remote machine you need a hostname for
26# ssh to log in.  All the test files must be in the same directory
27# local and remote.
28# You must have an anchor "regress" for the divert rules in the pf.conf
29# of the remote machine.  The kernel of the remote machine gets testet.
30#
31# Run make check-setup to see if you got the setup correct.
32
33LOCAL_ADDR ?=
34REMOTE_ADDR ?=
35FAKE_ADDR ?=
36LOCAL_ADDR6 ?=
37REMOTE_ADDR6 ?=
38FAKE_ADDR6 ?=
39REMOTE_SSH ?=
40
41.if empty (LOCAL_ADDR) || empty (REMOTE_ADDR) || empty (FAKE_ADDR) || \
42    empty (LOCAL_ADDR6) || empty (REMOTE_ADDR6) || empty (FAKE_ADDR6) || \
43    empty (REMOTE_SSH)
44regress:
45	@echo This tests needs a remote machine to operate on.
46	@echo LOCAL_ADDR REMOTE_ADDR FAKE_ADDR LOCAL_ADDR6
47	@echo REMOTE_ADDR6 FAKE_ADDR6 REMOTE_SSH are empty.
48	@echo Fill out these variables for additional tests.
49	@echo SKIPPED
50.endif
51
52# Automatically generate regress targets from test cases in directory.
53
54PERLS =			Client.pm Packet.pm Proc.pm Remote.pm Server.pm \
55			funcs.pl remote.pl
56ARGS !=			cd ${.CURDIR} && ls args-*.pl
57TARGETS ?=		\
58	inet-args-tcp-to inet6-args-tcp-to \
59	inet-args-tcp-reply inet6-args-tcp-reply \
60	inet-args-udp-to inet6-args-udp-to \
61	inet-args-udp-reply inet6-args-udp-reply \
62	inet-args-udp-reply-to inet6-args-udp-reply-to \
63	inet-args-rip-to inet6-args-rip-to \
64	inet-args-rip-reply inet6-args-rip-reply \
65	inet-args-rip-reply-to inet6-args-rip-reply-to \
66	inet-args-icmp-to inet6-args-icmp-to \
67	inet-args-icmp-reply-to inet6-args-icmp-reply-to \
68	inet-args-icmp-reply-reuse inet6-args-icmp-reply-reuse \
69	inet-reuse-tcp-to-to inet6-reuse-tcp-to-to \
70	inet-reuse-tcp-to-reply inet6-reuse-tcp-to-reply \
71	inet-reuse-tcp-reply-to inet6-reuse-tcp-reply-to \
72	inet-reuse-tcp-reply-reply inet6-reuse-tcp-reply-reply \
73	inet-reuse-udp-to-to inet6-reuse-udp-to-to \
74	inet-reuse-udp-to-reply inet6-reuse-udp-to-reply \
75	inet-reuse-udp-to-reply-to inet6-reuse-udp-to-reply-to \
76	inet-reuse-udp-reply-to inet6-reuse-udp-reply-to \
77	inet-reuse-udp-reply-reply inet6-reuse-udp-reply-reply \
78	inet-reuse-udp-reply-reply-to inet6-reuse-udp-reply-reply-to \
79	inet-reuse-udp-reply-to-to inet6-reuse-udp-reply-to-to \
80	inet-reuse-udp-reply-to-reply inet6-reuse-udp-reply-to-reply \
81	inet-reuse-udp-reply-to-reply-to inet6-reuse-udp-reply-to-reply-to \
82	inet-reuse-rip-to-to inet6-reuse-rip-to-to \
83	inet-reuse-rip-to-reply inet6-reuse-rip-to-reply \
84	inet-reuse-rip-to-reply-to inet6-reuse-rip-to-reply-to \
85	inet-reuse-rip-reply-to inet6-reuse-rip-reply-to \
86	inet-reuse-rip-reply-reply inet6-reuse-rip-reply-reply \
87	inet-reuse-rip-reply-reply-to inet6-reuse-rip-reply-reply-to \
88	inet-reuse-rip-reply-to-to inet6-reuse-rip-reply-to-to \
89	inet-reuse-rip-reply-to-reply inet6-reuse-rip-reply-to-reply \
90	inet-reuse-rip-reply-to-reply-to inet6-reuse-rip-reply-to-reply-to \
91	inet-args-udp-packet-in inet6-args-udp-packet-in \
92	inet-args-udp-packet-out inet6-args-udp-packet-out
93REGRESS_TARGETS =	${TARGETS:S/^/run-/}
94CLEANFILES +=		*.log *.port *.ktrace ktrace.out stamp-*
95
96.MAIN: all
97
98.if ! empty (REMOTE_SSH)
99.if make (regress) || make (all)
100.BEGIN:
101	@echo
102	${SUDO} true
103	ssh -t ${REMOTE_SSH} ${SUDO} true
104.if ! empty (FAKE_ADDR) && ! empty (REMOTE_ADDR)
105	-${SUDO} route -n delete -inet -host ${FAKE_ADDR} 2>/dev/null
106	${SUDO} route -n add -inet -host ${FAKE_ADDR} ${REMOTE_ADDR}
107.endif
108.if ! empty (FAKE_ADDR6) && ! empty (REMOTE_ADDR6)
109	-${SUDO} route -n delete -inet6 -host ${FAKE_ADDR6} 2>/dev/null
110	${SUDO} route -n add -inet6 -host ${FAKE_ADDR6} ${REMOTE_ADDR6}
111.endif
112.endif
113.endif
114
115# Set variables so that make runs with and without obj directory.
116# Only do that if necessary to keep visible output short.
117
118.if ${.CURDIR} == ${.OBJDIR}
119PERLINC =	-I.
120PERLPATH =
121.else
122PERLINC =	-I${.CURDIR}
123PERLPATH =	${.CURDIR}/
124.endif
125
126# The arg tests take a perl hash with arguments controlling the test
127# parameters.  The remote.pl test has local client or server and the
128# diverted process is running on the remote machine reachable with
129# ssh.
130
131.for  inet addr  in  inet ADDR  inet6 ADDR6
132
133run-${inet}-reuse-rip-to-reply-to:
134	@echo '\n======== $@ ========'
135	@echo 'rip to before reply is broken, it does not remove the state.'
136	@echo DISABLED
137
138.for a in ${ARGS}
139run-${inet}-${a:R}: ${a}
140	@echo '\n======== $@ ========'
141.if ${@:M*-packet-*}
142	time ${SUDO} SUDO=${SUDO} KTRACE=${KTRACE} \
143	    perl ${PERLINC} ${PERLPATH}remote.pl -f ${inet} \
144	    ${LOCAL_${addr}} ${REMOTE_${addr}} ${REMOTE_SSH} \
145	    ${PERLPATH}${a}
146.else
147	time ${SUDO} SUDO=${SUDO} KTRACE=${KTRACE} \
148	    perl ${PERLINC} ${PERLPATH}remote.pl -f ${inet} \
149	    ${LOCAL_${addr}} ${FAKE_${addr}} ${REMOTE_SSH} \
150	    ${PERLPATH}${a}
151.endif
152.endfor
153
154STATE_EXIST_tcp_to =		!
155STATE_EXIST_udp_to =
156STATE_EXIST_rip_to =
157STATE_EXIST_tcp_reply =		!
158STATE_EXIST_udp_reply =		!
159STATE_EXIST_rip_reply =		!
160STATE_EXIST_tcp_reply-to =	!
161STATE_EXIST_udp_reply-to =	!
162STATE_EXIST_rip_reply-to =	!
163
164.for proto in tcp udp rip
165
166.for  first second  in  to to  to reply  to reply-to  reply to  reply reply  reply reply-to  reply-to to  reply-to reply  reply-to reply-to
167
168run-${inet}-reuse-${proto}-${first}-${second}:
169	@echo '\n======== $@ ========'
170	# create state with ${first} divert rule
171	time ${SUDO} SUDO=${SUDO} KTRACE=${KTRACE} \
172	    perl ${PERLINC} ${PERLPATH}remote.pl -f ${inet} \
173	    ${LOCAL_${addr}} ${FAKE_${addr}} ${REMOTE_SSH} \
174	    ${PERLPATH}args-${proto}-${first}.pl
175	sed -n '/^connect peer:/s/.* //p' client.log >client.port
176	sed -n '/^connect sock:/s/.* //p' client.log >server.port
177.if "tcp" == ${proto}
178	# drop client tcp socket still in time wait to allow reuse
179.if "reply" == ${first} || "reply-to" == ${first}
180	${SUDO} tcpdrop \
181	    ${LOCAL_${addr}} `cat client.port` \
182	    ${FAKE_${addr}} `cat server.port`
183	# to avoid SYN retransmit, kill local tcp state that will be reused
184.if "inet" == ${inet}
185	${SUDO} pfctl -k key -k '${proto} ${LOCAL_${addr}}:'`cat client.port`' <- ${FAKE_${addr}}:'`cat server.port`''
186.elif "inet6" == ${inet}
187	${SUDO} pfctl -k key -k '${proto} ${LOCAL_${addr}}['`cat client.port`'] <- ${FAKE_${addr}}['`cat server.port`']'
188.endif
189.else # "to" == ${first}
190	# to avoid SYN retransmit, kill local tcp state that will be reused
191.if "inet" == ${inet}
192	${SUDO} pfctl -k key -k '${proto} ${LOCAL_${addr}}:'`cat server.port`' -> ${FAKE_${addr}}:'`cat client.port`''
193.elif "inet6" == ${inet}
194	${SUDO} pfctl -k key -k '${proto} ${LOCAL_${addr}}['`cat server.port`'] -> ${FAKE_${addr}}['`cat client.port`']'
195.endif
196	# tcp socket is in time wait so state must still exist
197	ssh ${REMOTE_SSH} ${SUDO} pfctl -ss | \
198	    egrep 'all ${proto} ${FAKE_${addr}}:?\[?'`cat client.port`'\]? .. ${LOCAL_${addr}}:?\[?'`cat server.port`'\]? '
199	ssh ${REMOTE_SSH} ${SUDO} tcpdrop \
200	    ${FAKE_${addr}} `cat client.port` \
201	    ${LOCAL_${addr}} `cat server.port`
202	# divert-to state disappeared when the tcp socket was dropped
203	ssh ${REMOTE_SSH} ${SUDO} pfctl -ss | ! \
204	    egrep 'all ${proto} ${FAKE_${addr}}:?\[?'`cat client.port`'\]? .. ${LOCAL_${addr}}:?\[?'`cat server.port`'\]? '
205.endif
206.endif
207.if "to" == ${first}
208.if "tcp" == ${proto}
209	# divert-to state has disappeared as tcp socket is always connected
210.else
211	# divert-to state still exists as the socket is unconnected
212.endif
213.else
214	# divert-reply state has disappeared when the connected socket closed
215.endif
216	ssh ${REMOTE_SSH} ${SUDO} pfctl -ss | ${STATE_EXIST_${proto}_${first}} \
217	    egrep ' (tcp|udp|254) ${FAKE_${addr}}[][0-9:]* .. ${LOCAL_${addr}}[][0-9:]* '
218	# create state again with ${second} divert rule
219	time ${SUDO} SUDO=${SUDO} KTRACE=${KTRACE} \
220	    perl ${PERLINC} ${PERLPATH}remote.pl ${inet} \
221	    ${LOCAL_${addr}} ${FAKE_${addr}} ${REMOTE_SSH} \
222	    `cat client.port` `cat server.port` \
223	    ${PERLPATH}args-${proto}-${second}.pl
224.if "tcp" == ${proto}
225.if "reply" == ${second} || "reply-to" == ${second}
226	# drop client tcp socket still in time wait to clean up
227	${SUDO} tcpdrop \
228	    ${LOCAL_${addr}} `cat server.port` \
229	    ${FAKE_${addr}} `cat client.port`
230.else # "to" == ${second}
231	# dropping the server tcp socket in time wait must remove the state
232	ssh ${REMOTE_SSH} ${SUDO} pfctl -ss | \
233	    egrep 'all ${proto} ${FAKE_${addr}}:?\[?'`cat server.port`'\]? .. ${LOCAL_${addr}}:?\[?'`cat client.port`'\]? '
234	ssh ${REMOTE_SSH} ${SUDO} tcpdrop \
235	    ${FAKE_${addr}} `cat server.port` \
236	    ${LOCAL_${addr}} `cat client.port`
237	ssh ${REMOTE_SSH} ${SUDO} pfctl -ss | ! \
238	    egrep 'all ${proto} ${FAKE_${addr}}:?\[?'`cat server.port`'\]? .. ${LOCAL_${addr}}:?\[?'`cat client.port`'\]? '
239.endif
240.endif
241	# states must disappear after connected socket has been closed
242	ssh ${REMOTE_SSH} ${SUDO} pfctl -ss | ${STATE_EXIST_${proto}_${second}} \
243	    egrep ' (tcp|udp|254) ${FAKE_${addr}}[][0-9:]* .. ${LOCAL_${addr}}[][0-9:]* '
244
245.endfor
246.endfor
247.endfor
248
249.PHONY: syntax check-setup
250
251# make perl syntax check for all args files
252syntax: stamp-syntax
253
254stamp-syntax: ${PERLS} ${ARGS}
255.for p in ${PERLS}
256	@perl -c ${PERLINC} ${PERLPATH}$p
257.endfor
258.for a in ${ARGS}
259	@perl -c ${PERLPATH}$a
260.endfor
261	@date >$@
262
263# Check wether the address, route and remote setup is correct
264check-setup:
265	@echo '\n======== $@ ========'
266	ping -n -c 1 ${LOCAL_ADDR}
267	ping -n -c 1 ${REMOTE_ADDR}
268	ping6 -n -c 1 ${LOCAL_ADDR6}
269	ping6 -n -c 1 ${REMOTE_ADDR6}
270	route -n get -inet ${FAKE_ADDR} | grep 'if address: ${LOCAL_ADDR}$$'
271	route -n get -inet ${FAKE_ADDR} | grep 'gateway: ${REMOTE_ADDR}$$'
272	route -n get -inet6 ${FAKE_ADDR6} | grep 'if address: ${LOCAL_ADDR6}$$'
273	route -n get -inet6 ${FAKE_ADDR6} | grep 'gateway: ${REMOTE_ADDR6}$$'
274	ssh ${REMOTE_SSH} ${SUDO} pfctl -sr | grep '^anchor "regress" all$$'
275	ssh ${REMOTE_SSH} ${SUDO} pfctl -si | grep '^Status: Enabled '
276	ssh ${REMOTE_SSH} perl -MIO::Socket::INET6 -MSocket6 -e 1
277
278.include <bsd.regress.mk>
279