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