freebsd-skq/tools/regression/ipfw/fwd/vimage-fwd.sh
bz eccbdd061b Add support for IPv6 to ipfw fwd:
Distinguish IPv4 and IPv6 addresses and optional port numbers in
user space to set the option for the correct protocol family.
Add support in the kernel for carrying the new IPv6 destination
address and port.
Add support to TCP and UDP for IPv6 and fix UDP IPv4 to not change
the address in the IP header.
Add support for IPv6 forwarding to a non-local destination.
Add a regession test uitilizing VIMAGE to check all 20 possible
combinations I could think of.

Obtained from:	David Dolson at Sandvine Incorporated
		(original version for ipfw fwd IPv6 support)
Sponsored by:	Sandvine Incorporated
PR:		bin/117214
MFC after:	4 weeks
Approved by:	re (kib)
2011-08-20 17:05:11 +00:00

370 lines
11 KiB
Bash
Executable File

#!/bin/sh
#-
# Copyright (c) 2010, "Bjoern A. Zeeb" <bz@FreeBSD.org>
# Copyright (c) 2011, Sandvine Incorporated ULC.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
#
# Test ipfw fwd for IPv4 and IPv6 using VIMAGE, testing that as well.
# For no test the packet header contents must be changed but always
# keeping the original destination.
#
case `id -u` in
0) ;;
*) echo "ERROR: Must be run as superuser." >&2
exit 2
esac
epair_base()
{
local ep
ep=`ifconfig epair create`
expr ${ep} : '\(.*\).'
}
debug_err()
{
local _p
_p="$1"
case "${DEBUG}" in
"") ;;
*)
echo " ~~ start of debug ~~"
echo " ~~ left:"
jexec ${ljid} /sbin/ipfw show
echo " ~~ middle:"
jexec ${mjid} /sbin/ipfw show
echo " ~~ right:"
jexec ${rjid} /sbin/ipfw show
echo " ~~ result file:"
cat ${_p}.1
echo " ~~ log file:"
cat ${_p}
echo " ~~ end of debug ~~"
;;
esac
}
check_cleanup_result_file()
{
local _p
_p="$1"
if test ! -s ${_p}.1; then
echo "FAIL (output file empty)."
debug_err ${_p}
else
read line < ${_p}.1
# Netcat adds 'X's in udp mode.
l="/${line#*/}"
if test "${l}" = "${_p}"; then
echo "PASS."
else
echo "FAIL (expected: '${_p}' got '${l}')."
debug_err ${_p}
fi
fi
rm -f ${_p}.1
rm -f ${_p}
}
# Transparent proxy scenario (local address).
run_test_tp()
{
local _descr
local _sip _dip _fip _fport _dport _p
local _nc_af _nc_p
local _lport
descr="$1"
_sip="$2"
_dip="$3"
_fip="$4"
_fport="$5"
_dport="$6"
_p="$7"
_nc_af="$8"
_lport=${_dport}
case "${_fport}" in
"") _lport="${_dport}" ;;
*) _lport="${_fport#,}" ;;
esac
case "${_p}" in
udp) _nc_p="-u" ;;
esac
OUT=`mktemp -t "ipfwfwd$$-XXXXXX"`
echo -n "${descr} (${OUT}).."
(
jexec ${ljid} /sbin/ipfw -f flush
jexec ${ljid} /sbin/ipfw -f zero
jexec ${mjid} /sbin/ipfw -f flush
jexec ${mjid} /sbin/ipfw -f zero
jexec ${rjid} /sbin/ipfw -f flush
jexec ${rjid} /sbin/ipfw -f zero
jexec ${mjid} /sbin/ipfw add 100 fwd ${_fip}${_fport} ${_p} from ${_sip} to ${_dip}
jexec ${mjid} /bin/sh -c "nc -w 10 ${_nc_af} -n ${_nc_p} -l ${_fip} ${_lport} > ${OUT}.1 &"
jexec ${rjid} /bin/sh -c "echo '${OUT}' | nc -w 1 -v ${_nc_af} -n ${_nc_p} ${_dip} ${_dport}"
) > ${OUT} 2>&1
check_cleanup_result_file "${OUT}"
}
# Transparent redirect scenario (non-local address).
run_test_nh()
{
local _descr
local _sip _dip _fip _fport _dport _p
local _nc_af _nc_p
local _lport
descr="$1"
_sip="$2"
_dip="$3"
_fip="$4"
_fport="$5"
_dport="$6"
_p="$7"
_nc_af="$8"
_lport=${_dport}
case "${_fport}" in
"") _lport="${_dport}" ;;
*) _lport="${_fport#,}" ;;
esac
case "${_p}" in
udp) _nc_p="-u" ;;
esac
OUT=`mktemp -t "ipfwfwd$$-XXXXXX"`
echo -n "${descr} (${OUT}).."
(
jexec ${ljid} /sbin/ipfw -f flush
jexec ${ljid} /sbin/ipfw -f zero
jexec ${mjid} /sbin/ipfw -f flush
jexec ${mjid} /sbin/ipfw -f zero
jexec ${rjid} /sbin/ipfw -f flush
jexec ${rjid} /sbin/ipfw -f zero
jexec ${mjid} /sbin/ipfw add 100 fwd ${_fip} ${_p} from ${_sip} to ${_dip}
jexec ${ljid} /bin/sh -c "nc -w 10 ${_nc_af} -n ${_nc_p} -l ${_dip} ${_lport} > ${OUT}.1 &"
jexec ${rjid} /bin/sh -c "echo '${OUT}' | nc -w 1 -v ${_nc_af} -n ${_nc_p} ${_dip} ${_dport}"
) > ${OUT} 2>&1
check_cleanup_result_file "${OUT}"
}
echo "==> Setting up test network"
kldload -q ipfw > /dev/null 2>&1
# Start left (sender) jail.
ljid=`jail -i -c -n lef$$ host.hostname=left.example.net vnet persist`
# Start middle (ipfw) jail.
mjid=`jail -i -c -n mid$$ host.hostname=center.example.net vnet persist`
# Start right (non-local ip redirects go to here) jail.
rjid=`jail -i -c -n right$$ host.hostname=right.example.net vnet persist`
echo "left ${ljid} middle ${mjid} right ${rjid}"
# Create networking.
#
# jail: left middle right
# ifaces: lmep:a ---- lmep:b mrep:a ---- mrep:b
#
jexec ${mjid} sysctl net.inet.ip.forwarding=1
jexec ${mjid} sysctl net.inet6.ip6.forwarding=1
jexec ${mjid} sysctl net.inet6.ip6.accept_rtadv=0
lmep=$(epair_base)
ifconfig ${lmep}a vnet ${ljid}
ifconfig ${lmep}b vnet ${mjid}
jexec ${ljid} ifconfig lo0 inet 127.0.0.1/8
jexec ${ljid} ifconfig lo0 inet 192.0.2.5/32 alias # Test 9-10
jexec ${ljid} ifconfig lo0 inet6 2001:db8:1::1/128 alias # Test 11-12
jexec ${ljid} ifconfig ${lmep}a inet 192.0.2.1/30 up
jexec ${ljid} ifconfig ${lmep}a inet6 2001:db8::1/64 alias
jexec ${ljid} route add default 192.0.2.2
jexec ${ljid} route add -inet6 default 2001:db8::2
jexec ${mjid} ifconfig lo0 inet 127.0.0.1/8
jexec ${mjid} ifconfig lo0 inet 192.0.2.255/32 alias # Test 1-4
jexec ${mjid} ifconfig lo0 inet6 2001:db8:ffff::1/128 alias # Test 5-8
jexec ${mjid} ifconfig ${lmep}b inet 192.0.2.2/30 up
jexec ${mjid} ifconfig ${lmep}b inet6 2001:db8::2/64 alias
jexec ${mjid} route add default 192.0.2.1
mrep=$(epair_base)
ifconfig ${mrep}a vnet ${mjid}
ifconfig ${mrep}b vnet ${rjid}
jexec ${mjid} ifconfig ${mrep}a inet 192.0.2.5/30 up
jexec ${mjid} ifconfig ${mrep}a inet6 2001:db8:1::1/64 alias
jexec ${rjid} ifconfig lo0 inet 127.0.0.1/8
jexec ${rjid} ifconfig ${mrep}b inet 192.0.2.6/30 up
jexec ${rjid} ifconfig ${mrep}b inet6 2001:db8:1::2/64 alias
jexec ${rjid} route add default 192.0.2.5
jexec ${rjid} route add -inet6 default 2001:db8:1::1
# ------------------------------------------------------------------------------
# Tests
#
# The jails are not chrooted to they all share the same base filesystem.
# This means we can put results into /tmp and just collect them from here.
#
echo "==> Running tests"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=1
run_test_tp "TEST ${i} IPv4 UDP redirect local to other local address, same port" \
192.0.2.6 192.0.2.5 192.0.2.255 "" 12345 udp "-4"
i=$((i + 1))
run_test_tp "TEST ${i} IPv4 UDP redirect local to other local address, different port" \
192.0.2.6 192.0.2.5 192.0.2.255 ",65534" 12345 udp "-4"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_tp "TEST ${i} IPv4 TCP redirect local to other local address, same port" \
192.0.2.6 192.0.2.5 192.0.2.255 "" 12345 tcp "-4"
i=$((i + 1))
run_test_tp "TEST ${i} IPv4 TCP redirect local to other local address, different port" \
192.0.2.6 192.0.2.5 192.0.2.255 ",65534" 12345 tcp "-4"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_tp "TEST ${i} IPv4 UDP redirect foreign to local address, same port" \
192.0.2.6 192.0.2.1 192.0.2.255 "" 12345 udp "-4"
i=$((i + 1))
run_test_tp "TEST ${i} IPv4 UDP redirect foreign to local address, different port" \
192.0.2.6 192.0.2.1 192.0.2.255 ",65534" 12345 udp "-4"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_tp "TEST ${i} IPv4 TCP redirect foreign to local address, same port" \
192.0.2.6 192.0.2.1 192.0.2.255 "" 12345 tcp "-4"
i=$((i + 1))
run_test_tp "TEST ${i} IPv4 TCP redirect foreign to local address, different port" \
192.0.2.6 192.0.2.1 192.0.2.255 ",65534" 12345 tcp "-4"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 UDP redirect local to other local address, same port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 udp "-6"
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 UDP redirect local to other local address, different port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 udp "-6"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 TCP redirect local to other local address, same port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 tcp "-6"
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 TCP redirect local to other local address, different port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 tcp "-6"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 UDP redirect foreign to local address, same port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 udp "-6"
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 UDP redirect foreign to local address, different port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 udp "-6"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 TCP redirect foreign to local address, same port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 "" 12345 tcp "-6"
i=$((i + 1))
run_test_tp "TEST ${i} IPv6 TCP redirect foreign to local address, different port" \
2001:db8:1::2 2001:db8::1 2001:db8:ffff::1 ",65534" 12345 tcp "-6"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_nh "TEST ${i} IPv4 UDP redirect to foreign address" \
192.0.2.6 192.0.2.5 192.0.2.1 "" 12345 udp "-4"
i=$((i + 1))
run_test_nh "TEST ${i} IPv4 TCP redirect to foreign address" \
192.0.2.6 192.0.2.5 192.0.2.1 "" 12345 tcp "-4"
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
i=$((i + 1))
run_test_nh "TEST ${i} IPv6 UDP redirect to foreign address" \
2001:db8:1::2 2001:db8:1::1 2001:db8::1 "" 12345 udp "-6"
i=$((i + 1))
run_test_nh "TEST ${i} IPv6 TCP redirect to foreign address" \
2001:db8:1::2 2001:db8:1::1 2001:db8::1 "" 12345 tcp "-6"
################################################################################
#
# Cleanup
#
echo "==> Cleaning up in 3 seconds"
# Let VIMAGE network stacks settle to avoid panics while still "experimental".
sleep 3
jail -r ${rjid}
jail -r ${mjid}
jail -r ${ljid}
for jid in ${rjid} ${mjid} ${ljid}; do
while : ; do
x=`jls -as -j ${jid} jid 2>/dev/null`
case "${x}" in
jid=*) echo "Waiting for jail ${jid} to stop." >&2
sleep 1
continue
;;
esac
break
done
done
ifconfig ${lmep}a destroy
ifconfig ${mrep}a destroy
# end