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