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