1225044Sbz#!/bin/sh
2225044Sbz#-
3225044Sbz# Copyright (c) 2010, "Bjoern A. Zeeb" <bz@FreeBSD.org>
4225044Sbz# Copyright (c) 2011, Sandvine Incorporated ULC.
5225044Sbz# All rights reserved.
6225044Sbz#
7225044Sbz# Redistribution and use in source and binary forms, with or without
8225044Sbz# modification, are permitted provided that the following conditions
9225044Sbz# are met:
10225044Sbz# 1. Redistributions of source code must retain the above copyright
11225044Sbz#    notice, this list of conditions and the following disclaimer.
12225044Sbz# 2. Redistributions in binary form must reproduce the above copyright
13225044Sbz#    notice, this list of conditions and the following disclaimer in the
14225044Sbz#    documentation and/or other materials provided with the distribution.
15225044Sbz#
16225044Sbz# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17225044Sbz# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18225044Sbz# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19225044Sbz# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20225044Sbz# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21225044Sbz# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22225044Sbz# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23225044Sbz# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24225044Sbz# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25225044Sbz# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26225044Sbz# SUCH DAMAGE.
27225044Sbz#
28225044Sbz# $FreeBSD: releng/11.0/tools/regression/ipfw/fwd/vimage-fwd.sh 225044 2011-08-20 17:05:11Z bz $
29225044Sbz#
30225044Sbz
31225044Sbz#
32225044Sbz# Test ipfw fwd for IPv4 and IPv6 using VIMAGE, testing that as well.
33225044Sbz# For no test the packet header contents must be changed but always
34225044Sbz# keeping the original destination.
35225044Sbz#
36225044Sbz
37225044Sbzcase `id -u` in
38225044Sbz0)	;;
39225044Sbz*)	echo "ERROR: Must be run as superuser." >&2
40225044Sbz	exit 2
41225044Sbzesac
42225044Sbz
43225044Sbzepair_base()
44225044Sbz{
45225044Sbz	local ep
46225044Sbz	
47225044Sbz	ep=`ifconfig epair create`
48225044Sbz	expr ${ep} : '\(.*\).'
49225044Sbz}
50225044Sbz
51225044Sbzdebug_err()
52225044Sbz{
53225044Sbz	local _p
54225044Sbz	_p="$1"
55225044Sbz
56225044Sbz	case "${DEBUG}" in
57225044Sbz	"")	;;
58225044Sbz	*)
59225044Sbz		echo " ~~ start of debug ~~"
60225044Sbz		echo " ~~ left:"
61225044Sbz		jexec ${ljid} /sbin/ipfw show
62225044Sbz		echo " ~~ middle:"
63225044Sbz		jexec ${mjid} /sbin/ipfw show
64225044Sbz		echo " ~~ right:"
65225044Sbz		jexec ${rjid} /sbin/ipfw show
66225044Sbz		echo " ~~ result file:"
67225044Sbz		cat ${_p}.1
68225044Sbz		echo " ~~ log file:"
69225044Sbz		cat ${_p}
70225044Sbz		echo " ~~ end of debug ~~"
71225044Sbz		;;
72225044Sbz	esac
73225044Sbz}
74225044Sbz
75225044Sbzcheck_cleanup_result_file()
76225044Sbz{
77225044Sbz	local _p
78225044Sbz	_p="$1"
79225044Sbz
80225044Sbz	if test ! -s ${_p}.1; then
81225044Sbz		echo "FAIL (output file empty)."
82225044Sbz		debug_err ${_p}
83225044Sbz	else
84225044Sbz		read line < ${_p}.1
85225044Sbz		# Netcat adds 'X's in udp mode.
86225044Sbz		l="/${line#*/}"
87225044Sbz		if test "${l}" = "${_p}"; then
88225044Sbz			echo "PASS."
89225044Sbz		else
90225044Sbz			echo "FAIL (expected: '${_p}' got '${l}')."
91225044Sbz			debug_err ${_p}
92225044Sbz		fi
93225044Sbz	fi
94225044Sbz
95225044Sbz	rm -f ${_p}.1
96225044Sbz	rm -f ${_p}
97225044Sbz}
98225044Sbz
99225044Sbz# Transparent proxy scenario (local address).
100225044Sbzrun_test_tp()
101225044Sbz{
102225044Sbz	local _descr
103225044Sbz	local _sip _dip _fip _fport _dport _p
104225044Sbz	local _nc_af _nc_p
105225044Sbz	local _lport
106225044Sbz	descr="$1"
107225044Sbz	_sip="$2"
108225044Sbz	_dip="$3"
109225044Sbz	_fip="$4"
110225044Sbz	_fport="$5"
111225044Sbz	_dport="$6"
112225044Sbz	_p="$7"
113225044Sbz	_nc_af="$8"
114225044Sbz
115225044Sbz	_lport=${_dport}
116225044Sbz	case "${_fport}" in
117225044Sbz	"")	_lport="${_dport}" ;;
118225044Sbz	*)	_lport="${_fport#,}" ;;
119225044Sbz	esac
120225044Sbz
121225044Sbz	case "${_p}" in
122225044Sbz	udp)	_nc_p="-u" ;;
123225044Sbz	esac
124225044Sbz
125225044Sbz	OUT=`mktemp -t "ipfwfwd$$-XXXXXX"`
126225044Sbz	echo -n "${descr} (${OUT}).."
127225044Sbz	(
128225044Sbz	jexec ${ljid} /sbin/ipfw -f flush
129225044Sbz	jexec ${ljid} /sbin/ipfw -f zero
130225044Sbz	jexec ${mjid} /sbin/ipfw -f flush
131225044Sbz	jexec ${mjid} /sbin/ipfw -f zero
132225044Sbz	jexec ${rjid} /sbin/ipfw -f flush
133225044Sbz	jexec ${rjid} /sbin/ipfw -f zero
134225044Sbz	jexec ${mjid} /sbin/ipfw add 100 fwd ${_fip}${_fport} ${_p} from ${_sip} to ${_dip}
135225044Sbz
136225044Sbz	jexec ${mjid} /bin/sh -c "nc -w 10 ${_nc_af} -n ${_nc_p} -l ${_fip} ${_lport} > ${OUT}.1 &"
137225044Sbz	jexec ${rjid} /bin/sh -c "echo '${OUT}' | nc -w 1 -v ${_nc_af} -n ${_nc_p} ${_dip} ${_dport}"
138225044Sbz	) > ${OUT} 2>&1
139225044Sbz	check_cleanup_result_file "${OUT}"
140225044Sbz}
141225044Sbz
142225044Sbz# Transparent redirect scenario (non-local address).
143225044Sbzrun_test_nh()
144225044Sbz{
145225044Sbz	local _descr
146225044Sbz	local _sip _dip _fip _fport _dport _p
147225044Sbz	local _nc_af _nc_p
148225044Sbz	local _lport
149225044Sbz	descr="$1"
150225044Sbz	_sip="$2"
151225044Sbz	_dip="$3"
152225044Sbz	_fip="$4"
153225044Sbz	_fport="$5"
154225044Sbz	_dport="$6"
155225044Sbz	_p="$7"
156225044Sbz	_nc_af="$8"
157225044Sbz
158225044Sbz	_lport=${_dport}
159225044Sbz	case "${_fport}" in
160225044Sbz	"")	_lport="${_dport}" ;;
161225044Sbz	*)	_lport="${_fport#,}" ;;
162225044Sbz	esac
163225044Sbz
164225044Sbz	case "${_p}" in
165225044Sbz	udp)	_nc_p="-u" ;;
166225044Sbz	esac
167225044Sbz
168225044Sbz	OUT=`mktemp -t "ipfwfwd$$-XXXXXX"`
169225044Sbz	echo -n "${descr} (${OUT}).."
170225044Sbz	(
171225044Sbz	jexec ${ljid} /sbin/ipfw -f flush
172225044Sbz	jexec ${ljid} /sbin/ipfw -f zero
173225044Sbz	jexec ${mjid} /sbin/ipfw -f flush
174225044Sbz	jexec ${mjid} /sbin/ipfw -f zero
175225044Sbz	jexec ${rjid} /sbin/ipfw -f flush
176225044Sbz	jexec ${rjid} /sbin/ipfw -f zero
177225044Sbz	jexec ${mjid} /sbin/ipfw add 100 fwd ${_fip} ${_p} from ${_sip} to ${_dip}
178225044Sbz
179225044Sbz	jexec ${ljid} /bin/sh -c "nc -w 10 ${_nc_af} -n ${_nc_p} -l ${_dip} ${_lport} > ${OUT}.1 &"
180225044Sbz	jexec ${rjid} /bin/sh -c "echo '${OUT}' | nc -w 1 -v ${_nc_af} -n ${_nc_p} ${_dip} ${_dport}"
181225044Sbz	) > ${OUT} 2>&1
182225044Sbz	check_cleanup_result_file "${OUT}"
183225044Sbz}
184225044Sbz
185225044Sbzecho "==> Setting up test network"
186225044Sbzkldload -q ipfw > /dev/null 2>&1
187225044Sbz
188225044Sbz# Start left (sender) jail.
189225044Sbzljid=`jail -i -c -n lef$$ host.hostname=left.example.net vnet persist`
190225044Sbz
191225044Sbz# Start middle (ipfw) jail.
192225044Sbzmjid=`jail -i -c -n mid$$ host.hostname=center.example.net vnet persist`
193225044Sbz
194225044Sbz# Start right (non-local ip redirects go to here) jail.
195225044Sbzrjid=`jail -i -c -n right$$ host.hostname=right.example.net vnet persist`
196225044Sbz
197225044Sbzecho "left ${ljid}   middle ${mjid}    right ${rjid}"
198225044Sbz
199225044Sbz# Create networking.
200225044Sbz#
201225044Sbz# jail:		left            middle           right
202225044Sbz# ifaces:	lmep:a ---- lmep:b  mrep:a ---- mrep:b
203225044Sbz#
204225044Sbz
205225044Sbzjexec ${mjid} sysctl net.inet.ip.forwarding=1
206225044Sbzjexec ${mjid} sysctl net.inet6.ip6.forwarding=1
207225044Sbzjexec ${mjid} sysctl net.inet6.ip6.accept_rtadv=0
208225044Sbz
209225044Sbzlmep=$(epair_base)
210225044Sbzifconfig ${lmep}a vnet ${ljid}
211225044Sbzifconfig ${lmep}b vnet ${mjid}
212225044Sbz
213225044Sbzjexec ${ljid} ifconfig lo0 inet 127.0.0.1/8
214225044Sbzjexec ${ljid} ifconfig lo0 inet 192.0.2.5/32 alias		# Test 9-10
215225044Sbzjexec ${ljid} ifconfig lo0 inet6 2001:db8:1::1/128 alias	# Test 11-12
216225044Sbzjexec ${ljid} ifconfig ${lmep}a inet  192.0.2.1/30 up
217225044Sbzjexec ${ljid} ifconfig ${lmep}a inet6 2001:db8::1/64 alias
218225044Sbz
219225044Sbzjexec ${ljid} route add default 192.0.2.2
220225044Sbzjexec ${ljid} route add -inet6 default 2001:db8::2
221225044Sbz
222225044Sbzjexec ${mjid} ifconfig lo0 inet 127.0.0.1/8
223225044Sbzjexec ${mjid} ifconfig lo0 inet 192.0.2.255/32 alias		# Test 1-4
224225044Sbzjexec ${mjid} ifconfig lo0 inet6 2001:db8:ffff::1/128 alias	# Test 5-8
225225044Sbzjexec ${mjid} ifconfig ${lmep}b inet  192.0.2.2/30 up
226225044Sbzjexec ${mjid} ifconfig ${lmep}b inet6 2001:db8::2/64 alias
227225044Sbzjexec ${mjid} route add default 192.0.2.1
228225044Sbz
229225044Sbzmrep=$(epair_base)
230225044Sbzifconfig ${mrep}a vnet ${mjid}
231225044Sbzifconfig ${mrep}b vnet ${rjid}
232225044Sbz
233225044Sbzjexec ${mjid} ifconfig ${mrep}a inet  192.0.2.5/30 up
234225044Sbzjexec ${mjid} ifconfig ${mrep}a inet6 2001:db8:1::1/64 alias
235225044Sbz
236225044Sbzjexec ${rjid} ifconfig lo0 inet 127.0.0.1/8
237225044Sbzjexec ${rjid} ifconfig ${mrep}b inet  192.0.2.6/30 up
238225044Sbzjexec ${rjid} ifconfig ${mrep}b inet6 2001:db8:1::2/64 alias
239225044Sbz
240225044Sbzjexec ${rjid} route add default 192.0.2.5
241225044Sbzjexec ${rjid} route add -inet6 default 2001:db8:1::1
242225044Sbz
243225044Sbz# ------------------------------------------------------------------------------
244225044Sbz# Tests
245225044Sbz#
246225044Sbz# The jails are not chrooted to they all share the same base filesystem.
247225044Sbz# This means we can put results into /tmp and just collect them from here.
248225044Sbz#
249225044Sbzecho "==> Running tests"
250225044Sbz
251225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
252225044Sbzi=1
253225044Sbzrun_test_tp "TEST ${i} IPv4 UDP redirect local to other local address, same port" \
254225044Sbz	192.0.2.6 192.0.2.5 192.0.2.255 "" 12345 udp "-4"
255225044Sbz
256225044Sbzi=$((i + 1))
257225044Sbzrun_test_tp "TEST ${i} IPv4 UDP redirect local to other local address, different port" \
258225044Sbz	192.0.2.6 192.0.2.5 192.0.2.255 ",65534" 12345 udp "-4"
259225044Sbz
260225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
261225044Sbzi=$((i + 1))
262225044Sbzrun_test_tp "TEST ${i} IPv4 TCP redirect local to other local address, same port" \
263225044Sbz	192.0.2.6 192.0.2.5 192.0.2.255 "" 12345 tcp "-4"
264225044Sbz
265225044Sbzi=$((i + 1))
266225044Sbzrun_test_tp "TEST ${i} IPv4 TCP redirect local to other local address, different port" \
267225044Sbz	192.0.2.6 192.0.2.5 192.0.2.255 ",65534" 12345 tcp "-4"
268225044Sbz
269225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
270225044Sbzi=$((i + 1))
271225044Sbzrun_test_tp "TEST ${i} IPv4 UDP redirect foreign to local address, same port" \
272225044Sbz	192.0.2.6 192.0.2.1 192.0.2.255 "" 12345 udp "-4"
273225044Sbz
274225044Sbzi=$((i + 1))
275225044Sbzrun_test_tp "TEST ${i} IPv4 UDP redirect foreign to local address, different port" \
276225044Sbz	192.0.2.6 192.0.2.1 192.0.2.255 ",65534" 12345 udp "-4"
277225044Sbz
278225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
279225044Sbzi=$((i + 1))
280225044Sbzrun_test_tp "TEST ${i} IPv4 TCP redirect foreign to local address, same port" \
281225044Sbz	192.0.2.6 192.0.2.1 192.0.2.255 "" 12345 tcp "-4"
282225044Sbz
283225044Sbzi=$((i + 1))
284225044Sbzrun_test_tp "TEST ${i} IPv4 TCP redirect foreign to local address, different port" \
285225044Sbz	192.0.2.6 192.0.2.1 192.0.2.255 ",65534" 12345 tcp "-4"
286225044Sbz
287225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
288225044Sbzi=$((i + 1))
289225044Sbzrun_test_tp "TEST ${i} IPv6 UDP redirect local to other local address, same port" \
290225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 udp "-6"
291225044Sbz
292225044Sbzi=$((i + 1))
293225044Sbzrun_test_tp "TEST ${i} IPv6 UDP redirect local to other local address, different port" \
294225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 udp "-6"
295225044Sbz
296225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
297225044Sbzi=$((i + 1))
298225044Sbzrun_test_tp "TEST ${i} IPv6 TCP redirect local to other local address, same port" \
299225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 tcp "-6"
300225044Sbz
301225044Sbzi=$((i + 1))
302225044Sbzrun_test_tp "TEST ${i} IPv6 TCP redirect local to other local address, different port" \
303225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 tcp "-6"
304225044Sbz
305225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
306225044Sbzi=$((i + 1))
307225044Sbzrun_test_tp "TEST ${i} IPv6 UDP redirect foreign to local address, same port" \
308225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 udp "-6"
309225044Sbz
310225044Sbzi=$((i + 1))
311225044Sbzrun_test_tp "TEST ${i} IPv6 UDP redirect foreign to local address, different port" \
312225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 udp "-6"
313225044Sbz
314225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
315225044Sbzi=$((i + 1))
316225044Sbzrun_test_tp "TEST ${i} IPv6 TCP redirect foreign to local address, same port" \
317225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 tcp "-6"
318225044Sbz
319225044Sbzi=$((i + 1))
320225044Sbzrun_test_tp "TEST ${i} IPv6 TCP redirect foreign to local address, different port" \
321225044Sbz	2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 tcp "-6"
322225044Sbz
323225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
324225044Sbzi=$((i + 1))
325225044Sbzrun_test_nh "TEST ${i} IPv4 UDP redirect to foreign address" \
326225044Sbz	192.0.2.6 192.0.2.5 192.0.2.1 "" 12345 udp "-4"
327225044Sbz
328225044Sbzi=$((i + 1))
329225044Sbzrun_test_nh "TEST ${i} IPv4 TCP redirect to foreign address" \
330225044Sbz	192.0.2.6 192.0.2.5 192.0.2.1 "" 12345 tcp "-4"
331225044Sbz
332225044Sbz#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
333225044Sbzi=$((i + 1))
334225044Sbzrun_test_nh "TEST ${i} IPv6 UDP redirect to foreign address" \
335225044Sbz	2001:db8:1::2 2001:db8:1::1 2001:db8::1 "" 12345 udp "-6"
336225044Sbz
337225044Sbzi=$((i + 1))
338225044Sbzrun_test_nh "TEST ${i} IPv6 TCP redirect to foreign address" \
339225044Sbz	2001:db8:1::2 2001:db8:1::1 2001:db8::1 "" 12345 tcp "-6"
340225044Sbz
341225044Sbz################################################################################
342225044Sbz#
343225044Sbz# Cleanup
344225044Sbz#
345225044Sbzecho "==> Cleaning up in 3 seconds"
346225044Sbz# Let VIMAGE network stacks settle to avoid panics while still "experimental".
347225044Sbzsleep 3
348225044Sbz
349225044Sbzjail -r ${rjid}
350225044Sbzjail -r ${mjid}
351225044Sbzjail -r ${ljid}
352225044Sbz
353225044Sbzfor jid in ${rjid} ${mjid} ${ljid}; do
354225044Sbz	while : ; do
355225044Sbz		x=`jls -as -j ${jid} jid 2>/dev/null`
356225044Sbz		case "${x}" in
357225044Sbz		jid=*)	echo "Waiting for jail ${jid} to stop." >&2
358225044Sbz			sleep 1
359225044Sbz			continue
360225044Sbz			;;
361225044Sbz		esac
362225044Sbz		break
363225044Sbz	done
364225044Sbzdone
365225044Sbz
366225044Sbzifconfig ${lmep}a destroy
367225044Sbzifconfig ${mrep}a destroy
368225044Sbz
369225044Sbz# end
370