xref: /openbsd/regress/sys/net/pf_forward/Makefile (revision 09467b48)
1#	$OpenBSD: Makefile,v 1.31 2020/02/02 21:01:53 bluhm Exp $
2
3# Copyright (c) 2012-2020 Alexander Bluhm <bluhm@openbsd.org>
4#
5# Permission to use, copy, modify, and distribute this software for any
6# purpose with or without fee is hereby granted, provided that the above
7# copyright notice and this permission notice appear in all copies.
8#
9# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17# The following ports must be installed:
18#
19# scapy               powerful interactive packet manipulation in python
20
21.if ! exists(/usr/local/bin/scapy)
22regress:
23	@echo Install scapy package to run this regress.
24	@echo SKIPPED
25.endif
26
27# This test needs a manual setup of four machines
28# The setup is the same as for regress/sys/net/pf_fragment
29# Set up machines: SRC PF RT ECO
30# SRC is the machine where this makefile is running.
31# PF is running OpenBSD forwarding through pf, it is the test target.
32# RT is a router forwarding packets, maximum MTU is 1300.
33# ECO is reflecting the ping and UDP and TCP echo packets.
34# RDR does not exist, PF redirects the traffic to ECO.
35# AF does not exist, PF translates address family and sends to ECO.
36# RTT addresses exist on ECO, PF has no route and must use route-to RT
37# RPT addresses exist on SRC, PF has no route and must use reply-to SRC
38#
39# +---+   1   +--+   2   +--+   3   +---+ 4
40# |SRC| ----> |PF| ----> |RT| ----> |ECO| 7
41# +---+ 8     +--+       +--+       +---+ 9
42#     out    in  out    in  out    in   out
43#
44# 5 +---+ 6   7 +--+    8 +---+ 9   10 +---+ 11
45#   |RDR|       |AF|      |RTT|        |RPT|
46#   +---+       +--+      +---+        +---+
47#  in   out    in        in          out
48
49# Configure Addresses on the machines, there must be routes for the
50# networks.  Adapt interface and addresse variables to your local
51# setup.  To control the remote machine you need a hostname for
52# ssh to log in.
53# You must have an anchor "regress" for the divert rules in the pf.conf
54# of the PF machine.  The kernel of the PF machine gets testet.
55#
56# Run make check-setup to see if you got the setup correct.
57
58SRC_IF ?=	tap0
59SRC_MAC ?=	fe:e1:ba:d1:0a:dc
60PF_IFIN ?=	vio0
61PF_IFOUT ?=	vio1
62PF_MAC ?=	52:54:00:12:34:50
63PF_SSH ?=
64RT_SSH ?=
65ECO_SSH ?=
66
67SRC_OUT ?=	10.188.210.10
68PF_IN ?=	10.188.210.50
69PF_OUT ?=	10.188.211.50
70RT_IN ?=	10.188.211.51
71RT_OUT ?=	10.188.212.51
72ECO_IN ?=	10.188.212.52
73ECO_OUT ?=	10.188.213.52
74RDR_IN ?=	10.188.214.188
75RDR_OUT ?=	10.188.215.188
76AF_IN ?=	10.188.216.82		# /24 must be dec(ECO_IN6/120)
77RTT_IN ?=	10.188.217.52
78RTT_OUT ?=	10.188.218.52
79RPT_IN ?=	10.188.220.10
80RPT_OUT ?=	10.188.221.10
81
82SRC_OUT6 ?=	fdd7:e83e:66bc:210:fce1:baff:fed1:561f
83PF_IN6 ?=	fdd7:e83e:66bc:210:5054:ff:fe12:3450
84PF_OUT6 ?=	fdd7:e83e:66bc:211:5054:ff:fe12:3450
85RT_IN6 ?=	fdd7:e83e:66bc:211:5054:ff:fe12:3451
86RT_OUT6 ?=	fdd7:e83e:66bc:212:5054:ff:fe12:3451
87ECO_IN6 ?=	fdd7:e83e:66bc:212:5054:ff:fe12:3452
88ECO_OUT6 ?=	fdd7:e83e:66bc:213:5054:ff:fe12:3452
89RDR_IN6 ?=	fdd7:e83e:66bc:214::188
90RDR_OUT6 ?=	fdd7:e83e:66bc:215::188
91AF_IN6 ?=	fdd7:e83e:66bc:216::34	# /120 must be hex(ECO_IN/24)
92RTT_IN6 ?=	fdd7:e83e:66bc:217:5054:ff:fe12:3452
93RTT_OUT6 ?=	fdd7:e83e:66bc:218:5054:ff:fe12:3452
94RPT_IN6 ?=	fdd7:e83e:66bc:1220:fce1:baff:fed1:561f
95RPT_OUT6 ?=	fdd7:e83e:66bc:1221:fce1:baff:fed1:561f
96
97.if empty (PF_SSH) || empty (RT_SSH) || empty (ECO_SSH)
98regress:
99	@echo this tests needs three remote machines to operate on
100	@echo PF_SSH RT_SSH ECO_SSH are empty
101	@echo fill out these variables for additional tests, then
102	@echo check wether your test machines are set up properly
103	@echo SKIPPED
104.endif
105
106.MAIN: all
107
108.if ! empty (PF_SSH)
109.if make (regress) || make (all)
110.BEGIN:
111	@echo
112	${SUDO} true
113	ssh -t ${PF_SSH} ${SUDO} true
114	rm -f stamp-pfctl
115.endif
116.endif
117
118# Create python include file containing the addresses.
119addr.py: Makefile
120	rm -f $@ $@.tmp
121	echo 'SRC_IF="${SRC_IF}"' >>$@.tmp
122	echo 'SRC_MAC="${SRC_MAC}"' >>$@.tmp
123	echo 'PF_IFIN="${PF_IFIN}"' >>$@.tmp
124	echo 'PF_IFOUT="${PF_IFOUT}"' >>$@.tmp
125	echo 'PF_MAC="${PF_MAC}"' >>$@.tmp
126.for var in SRC_OUT PF_IN PF_OUT RT_IN RT_OUT ECO_IN ECO_OUT RDR_IN RDR_OUT\
127    AF_IN RTT_IN RTT_OUT RPT_IN RPT_OUT
128	echo '${var}="${${var}}"' >>$@.tmp
129	echo '${var}6="${${var}6}"' >>$@.tmp
130.endfor
131	mv $@.tmp $@
132
133# Load the pf rules into the kernel of the PF machine.
134# XXX pfctl does not replace variables after @.
135stamp-pfctl: addr.py pf.conf
136	cat addr.py ${.CURDIR}/pf.conf | /sbin/pfctl -n -f -
137	cat addr.py ${.CURDIR}/pf.conf | \
138	    sed 's/@$$PF_IFIN /@${PF_IFIN} /;s/@$$PF_IFOUT /@${PF_IFOUT} /' | \
139	    ssh ${PF_SSH} ${SUDO} pfctl -a regress -f -
140	@date >$@
141
142# Set variables so that make runs with and without obj directory.
143# Only do that if necessary to keep visible output short.
144.if ${.CURDIR} == ${.OBJDIR}
145PYTHON =	python2.7 -u ./
146.else
147PYTHON =	PYTHONPATH=${.OBJDIR} python2.7 -u ${.CURDIR}/
148.endif
149
150.for inet in inet inet6
151
152run-ping-mtu-1400-${inet}-RPT_OUT:
153	@echo '\n======== $@ ========'
154	# RPT_OUT with locally generated ICMP time exceeded cannot work.
155	# The generated packet will not match the out rule with reply-to
156	# so it will be rejected by the route.
157	@echo DISABLED
158
159.for proto in icmp udp
160run-traceroute-${proto}-${inet}-RPT_OUT:
161	@echo '\n======== $@ ========'
162	# RPT_OUT traceroute cannot work.  The ICMP time exceeded packet
163	# generated by IP forward will not match the out rule with reply-to
164	# so it will be rejected by the route.
165	@echo DISABLED
166.endfor # proto
167
168# Ping all addresses.  This ensures that the IP addresses are configured
169# and all routing table are set up to allow bidirectional packet flow.
170# Note that RDR does not exist physically.  So this traffic is rewritten
171# by PF and handled by ECO.
172
173.for ip in SRC_OUT PF_IN PF_OUT RT_IN RT_OUT ECO_IN ECO_OUT RDR_IN RDR_OUT\
174    AF_IN RTT_IN RTT_OUT RPT_IN RPT_OUT
175REGRESS_TARGETS +=	run-ping-${inet}-${ip}
176run-ping-${inet}-${ip}: stamp-pfctl
177	@echo '\n======== $@ ========'
178	@echo Check ping ${ip}${inet:S/inet//}:
179.if "RPT_IN" == ${ip} || "RPT_OUT" == ${ip}
180	ping${inet:S/inet//} -n -c 1 -I ${${ip}${inet:S/inet//}}\
181	    ${ECO_IN${inet:S/inet//}}
182.else
183	ping${inet:S/inet//} -n -c 1 ${${ip}${inet:S/inet//}}
184.endif
185.endfor # ip
186
187.for ip in ECO_IN ECO_OUT RDR_IN RDR_OUT AF_IN RTT_IN RTT_OUT RPT_IN RPT_OUT
188
189# Send a large IPv4/ICMP-Echo-Request packet with enabled DF bit and
190# parse response packet to determine MTU of the packet filter.  The
191# outgoing MTU of PF has to be 1400 octets.  Packet size is 1500.
192# Check that the IP length of the original packet and the ICMP
193# quoted packet are the same.
194
195REGRESS_TARGETS +=	run-ping-mtu-1400-${inet}-${ip}
196run-ping-mtu-1400-${inet}-${ip}: stamp-pfctl
197	@echo '\n======== $@ ========'
198	@echo Check path MTU to ${ip}${inet:S/inet//} is 1400
199.if "RPT_IN" == ${ip} || "RPT_OUT" == ${ip}
200	${SUDO} ${PYTHON}ping${inet:S/inet//}_mtu.py ${${ip}${inet:S/inet//}}\
201	    ${ECO_IN${inet:S/inet//}} 1500 1400
202.elif "AF_IN" == ${ip}
203.if "inet" == ${inet}
204	${SUDO} ${PYTHON}ping_mtu.py ${SRC_OUT} ${${ip}} 1500 1380
205.else
206	${SUDO} ${PYTHON}ping6_mtu.py ${SRC_OUT6} ${${ip}6} 1500 1420
207.endif
208.else
209	${SUDO} ${PYTHON}ping${inet:S/inet//}_mtu.py ${SRC_OUT${inet:S/inet//}}\
210	    ${${ip}${inet:S/inet//}} 1500 1400
211.endif
212
213# Send a large IPv4/ICMP-Echo-Request packet with enabled DF bit and
214# parse response packet to determine MTU of the router.  The MTU has
215# to be 1300 octets.  The MTU has to be defined at out interface of
216# the router RT before.  Packet size is 1400 to pass PF MTU.
217# Check that the IP length of the original packet and the ICMP
218# quoted packet are the same.
219
220REGRESS_TARGETS +=	run-ping-mtu-1300-${inet}-${ip}
221run-ping-mtu-1300-${inet}-${ip}: stamp-pfctl
222	@echo '\n======== $@ ========'
223	@echo Check path MTU from ${ip}${inet:S/inet//} is 1300
224.if "RPT_IN" == ${ip} || "RPT_OUT" == ${ip}
225	${SUDO} ${PYTHON}ping${inet:S/inet//}_mtu.py ${${ip}${inet:S/inet//}}\
226	    ${ECO_IN${inet:S/inet//}} 1400 1300
227.elif "AF_IN" == ${ip}
228.if "inet" == ${inet}
229	${SUDO} ${PYTHON}ping_mtu.py ${SRC_OUT} ${${ip}} 1380 1280
230.else
231	${SUDO} ${PYTHON}ping6_mtu.py ${SRC_OUT6} ${${ip}6} 1420 1320
232.endif
233.else
234	${SUDO} ${PYTHON}ping${inet:S/inet//}_mtu.py ${SRC_OUT${inet:S/inet//}}\
235	    ${${ip}${inet:S/inet//}} 1400 1300
236.endif
237
238# Send one UDP echo port 7 packet to all destination addresses with netcat.
239# The response must arrive in 1 second.
240
241REGRESS_TARGETS +=	run-udp-${inet}-${ip}
242run-udp-${inet}-${ip}: stamp-pfctl
243	@echo '\n======== $@ ========'
244	@echo Check UDP ${ip${inet:S/inet//}}:
245.if "RPT_IN" == ${ip} || "RPT_OUT" == ${ip}
246	echo $$$$ | nc -n -u -W 1 -w 3 -s ${${ip}${inet:S/inet//}}\
247	    ${ECO_IN${inet:S/inet//}} 7 | grep $$$$
248.else
249	echo $$$$ | nc -n -u -W 1 -w 3 ${${ip}${inet:S/inet//}} 7 | grep $$$$
250.endif
251
252# Send a data stream to TCP echo port 7 to all destination addresses
253# with netcat.  Use enough data to make sure PMTU discovery works.
254# Count the reflected bytes and compare with the transmitted ones.
255# Delete host route before test to trigger PMTU discovery.
256
257REGRESS_TARGETS +=	run-tcp-${inet}-${ip}
258run-tcp-${inet}-${ip}: stamp-pfctl
259	@echo '\n======== $@ ========'
260	@echo Check tcp ${ip}${inet:S/inet//}:
261	${SUDO} route -n delete -host -inet ${${ip}${inet:S/inet//}} || true
262.if "RPT_IN" == ${ip} || "RPT_OUT" == ${ip}
263	openssl rand 200000 | nc -n -N -w 10 -s ${${ip}${inet:S/inet//}}\
264	    ${ECO_IN${inet:S/inet//}} 7 | wc -c | grep '200000$$'
265.else
266	openssl rand 200000 | nc -n -N -w 10 ${${ip}${inet:S/inet//}} 7 |\
267	    wc -c | grep '200000$$'
268.endif
269
270.endfor # ip
271
272# Run traceroute with ICMP and UDP to all destination addresses.
273# Expect three hops in output and that every probe has a response.
274
275TRACEROUTE_CHECK =	awk \
276    'BEGIN{ x=0 } \
277    { print $$0 } \
278    { n=$$1 } \
279    /\*/{ x++ } \
280    END{ if (n!=3) { print "hopcount is not 3: "n; exit 1 } } \
281    END{ if (x!=0) { print "unanswered probes: "x; exit 1 } }'
282
283.for ip in ECO_IN ECO_OUT RDR_IN RDR_OUT AF_IN RTT_IN RTT_OUT RPT_IN RPT_OUT
284.for proto in icmp udp
285REGRESS_TARGETS +=	run-traceroute-${proto}-${inet}-${ip}
286run-traceroute-${proto}-${inet}-${ip}: stamp-pfctl
287	@echo '\n======== $@ ========'
288	@echo Check traceroute ${proto} ${ip${inet:S/inet//}}:
289.if "RPT_IN" == ${ip} || "RPT_OUT" == ${ip}
290	traceroute${inet:S/inet//} ${proto:S/icmp/-I/:S/udp//}\
291	    -s ${${ip}${inet:S/inet//}} ${ECO_IN${inet:S/inet//}} |\
292	    ${TRACEROUTE_CHECK}
293.else
294	traceroute${inet:S/inet//} ${proto:S/icmp/-I/:S/udp//}\
295	    ${${ip}${inet:S/inet//}} | ${TRACEROUTE_CHECK}
296.endif
297.endfor # proto
298.endfor # ip
299
300.endfor # inet
301
302CLEANFILES +=		addr.py *.pyc *.log stamp-*
303
304.PHONY: check-setup
305
306# Check wether the address, route and remote setup is correct
307check-setup: check-setup-src check-setup-pf check-setup-rt check-setup-eco
308
309check-setup-src:
310	@echo '\n======== $@ ========'
311.for ip in SRC_OUT RPT_IN RPT_OUT
312	ping -n -c 1 ${${ip}}  # ${ip}
313	/sbin/route -n get -inet ${${ip}} | grep -q 'flags: .*LOCAL'  # ${ip}
314.endfor
315	ping -n -c 1 ${PF_IN}  # PF_IN
316	/sbin/route -n get -inet ${PF_IN} | fgrep -q 'interface: ${SRC_IF}' \
317	    # PF_IN SRC_IF
318.for ip in PF_OUT RT_IN RT_OUT ECO_IN ECO_OUT RDR_IN RDR_OUT AF_IN\
319    RTT_IN RTT_OUT
320	/sbin/route -n get -inet ${${ip}} | fgrep -q 'gateway: ${PF_IN}' \
321	    # ${ip} PF_IN
322.endfor
323.for ip in SRC_OUT RPT_IN RPT_OUT
324	ping6 -n -c 1 ${${ip}6}  # ${ip}6
325	/sbin/route -n get -inet6 ${${ip}6} | grep -q 'flags: .*LOCAL'  # ${ip}6
326.endfor
327	ping6 -n -c 1 ${PF_IN6}  # PF_IN6
328	/sbin/route -n get -inet6 ${PF_IN6} | fgrep -q 'interface: ${SRC_IF}' \
329	    # PF_IN6 SRC_IF
330.for ip in PF_OUT RT_IN RT_OUT ECO_IN ECO_OUT RDR_IN RDR_OUT AF_IN\
331    RTT_IN RTT_OUT
332	/sbin/route -n get -inet6 ${${ip}6} | fgrep -q 'gateway: ${PF_IN6}' \
333	    # ${ip}6 PF_IN6
334.endfor
335	/sbin/sysctl net.inet.ip.forwarding | fgrep =1
336	/sbin/sysctl net.inet6.ip6.forwarding | fgrep =1
337
338check-setup-pf:
339	@echo '\n======== $@ ========'
340	ssh ${PF_SSH} ping -n -c 1 ${PF_IN}  # PF_IN
341	ssh ${PF_SSH} route -n get -inet ${PF_IN} | grep -q 'flags: .*LOCAL' \
342	    # PF_IN
343	ssh ${PF_SSH} ping -n -c 1 ${SRC_OUT}  # SRC_OUT
344	ssh ${PF_SSH} ping -n -c 1 ${PF_OUT}  # PF_OUT
345	ssh ${PF_SSH} route -n get -inet ${PF_OUT} | grep -q 'flags: .*LOCAL' \
346	    # PF_OUT
347	ssh ${PF_SSH} ping -n -c 1 ${RT_IN}  # RT_IN
348.for ip in RT_OUT ECO_IN ECO_OUT
349	ssh ${PF_SSH} route -n get -inet ${${ip}} |\
350	    fgrep -q 'gateway: ${RT_IN}'  # ${ip} RT_IN
351.endfor
352.for ip in RTT_IN RTT_OUT RPT_IN RPT_OUT
353	ssh ${PF_SSH} route -n get -inet ${${ip}} | grep -q 'flags: .*REJECT' \
354	    # ${ip} reject
355.endfor
356	ssh ${PF_SSH} ping6 -n -c 1 ${PF_IN6}  # PF_IN6
357	ssh ${PF_SSH} route -n get -inet6 ${PF_IN6} | grep -q 'flags: .*LOCAL' \
358	    # PF_IN6
359	ssh ${PF_SSH} ping6 -n -c 1 ${SRC_OUT6}  # SRC_OUT6
360	ssh ${PF_SSH} ping6 -n -c 1 ${PF_OUT6}  # PF_OUT6
361	ssh ${PF_SSH} route -n get -inet6 ${PF_OUT6} |\
362	    grep -q 'flags: .*LOCAL'  # PF_OUT6
363	ssh ${PF_SSH} ping6 -n -c 1 ${RT_IN6}  # RT_IN6
364.for ip in RT_OUT ECO_IN ECO_OUT
365	ssh ${PF_SSH} route -n get -inet6 ${${ip}6} |\
366	    fgrep -q 'gateway: ${RT_IN6}'  # ${ip}6 RT_IN6
367.endfor
368.for ip in RTT_IN RTT_OUT RPT_IN RPT_OUT
369	ssh ${PF_SSH} route -n get -inet6 ${${ip}6} |\
370	    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	ssh ${PF_SSH} ifconfig ${PF_IFOUT} | fgrep 'mtu 1400'
377
378check-setup-rt:
379	@echo '\n======== $@ ========'
380	ssh ${RT_SSH} ping -n -c 1 ${RT_IN}  # RT_IN
381	ssh ${RT_SSH} route -n get -inet ${RT_IN} | grep -q 'flags: .*LOCAL' \
382	    # RT_IN
383	ssh ${RT_SSH} ping -n -c 1 ${PF_OUT}  # PF_OUT
384.for ip in PF_IN SRC_OUT RPT_IN RPT_OUT
385	ssh ${RT_SSH} route -n get -inet ${${ip}} |\
386	    fgrep -q 'gateway: ${PF_OUT}'  # ${ip} PF_OUT
387.endfor
388	ssh ${RT_SSH} ping -n -c 1 ${RT_OUT}  # RT_OUT
389	ssh ${RT_SSH} route -n get -inet ${RT_OUT} | grep -q 'flags: .*LOCAL' \
390	    # RT_OUT
391	ssh ${RT_SSH} ping -n -c 1 ${ECO_IN}  # ECO_IN
392.for ip in ECO_OUT RTT_IN RTT_OUT
393	ssh ${RT_SSH} route -n get -inet ${${ip}} |\
394	    fgrep -q 'gateway: ${ECO_IN}'  # ${ip} ECO_IN
395.endfor
396	ssh ${RT_SSH} ping6 -n -c 1 ${RT_IN6}  # RT_IN6
397	ssh ${RT_SSH} route -n get -inet6 ${RT_IN6} | grep -q 'flags: .*LOCAL' \
398	    # RT_IN6
399	ssh ${RT_SSH} ping6 -n -c 1 ${PF_OUT6}  # PF_OUT6
400.for ip in PF_IN SRC_OUT RPT_IN RPT_OUT
401	ssh ${RT_SSH} route -n get -inet6 ${${ip}6} |\
402	    fgrep -q 'gateway: ${PF_OUT6}'  # ${ip}6 PF_OUT6
403.endfor
404	ssh ${RT_SSH} ping6 -n -c 1 ${RT_OUT6}  # RT_OUT6
405	ssh ${RT_SSH} route -n get -inet6 ${RT_OUT6} |\
406	    grep -q 'flags: .*LOCAL'  # RT_OUT6
407	ssh ${RT_SSH} ping6 -n -c 1 ${ECO_IN6}  # ECO_IN6
408.for ip in ECO_OUT RTT_IN RTT_OUT
409	ssh ${RT_SSH} route -n get -inet6 ${${ip}6} |\
410	    fgrep -q 'gateway: ${ECO_IN6}'  # ${ip}6 ECO_IN6
411.endfor
412	ssh ${RT_SSH} sysctl net.inet.ip.forwarding | fgrep =1
413	ssh ${RT_SSH} sysctl net.inet6.ip6.forwarding | fgrep =1
414	ssh ${RT_SSH} ifconfig | fgrep 'mtu 1300'
415
416check-setup-eco:
417	@echo '\n======== $@ ========'
418.for ip in ECO_IN ECO_OUT RTT_IN RTT_OUT
419	ssh ${ECO_SSH} ping -n -c 1 ${${ip}}  # ${ip}
420	ssh ${ECO_SSH} route -n get -inet ${${ip}} | grep -q 'flags: .*LOCAL' \
421	    # ${ip}
422.endfor
423	ssh ${ECO_SSH} ping -n -c 1 ${RT_OUT}  # RT_OUT
424.for ip in RT_IN PF_OUT PF_IN SRC_OUT RPT_IN RPT_OUT
425	ssh ${ECO_SSH} route -n get -inet ${${ip}} |\
426	    fgrep -q 'gateway: ${RT_OUT}'  # ${ip} RT_OUT
427.endfor
428.for ip in ECO_IN ECO_OUT RTT_IN RTT_OUT
429	ssh ${ECO_SSH} ping6 -n -c 1 ${${ip}6}  # ${ip}6
430	ssh ${ECO_SSH} route -n get -inet6 ${${ip}6} |\
431	    grep -q 'flags: .*LOCAL'  # ${ip}6
432.endfor
433	ssh ${ECO_SSH} ping6 -n -c 1 ${RT_OUT6}  # RT_OUT6
434.for ip in RT_IN PF_OUT PF_IN SRC_OUT RPT_IN RPT_OUT
435	ssh ${ECO_SSH} route -n get -inet6 ${${ip}6} |\
436	    fgrep -q 'gateway: ${RT_OUT6}'  # ${ip}6 RT_OUT6
437.endfor
438.for inet in inet inet6
439.for proto in udp tcp
440	ssh ${ECO_SSH} netstat -na -f ${inet} -p ${proto} | fgrep ' *.7 '
441.endfor
442.endfor
443.for ip in ECO_IN ECO_OUT RTT_IN RTT_OUT
444	ssh ${ECO_SSH} netstat -nav -f inet -p udp | fgrep ' ${${ip}}.7 '
445	ssh ${ECO_SSH} netstat -nav -f inet6 -p udp | fgrep ' ${${ip}6}.7 '
446	ssh ${ECO_SSH} sysctl net.inet.ip.forwarding | fgrep =1
447	ssh ${ECO_SSH} sysctl net.inet6.ip6.forwarding | fgrep =1
448.endfor
449
450.include <bsd.regress.mk>
451