#!/bin/sh
#
# Testsuite for the IPv6 installation
#
# (P) & (C) 2001 by Peter Bieringer <pb@bieringer.de>
#
# Version: 2001-11-25
#
# Because of the complexity of "network-functions-ipv6" I've started to create
#  an testsuite (work-in-progress)
# 
# ChangeLog:
#  20010315 :initial
#  20010317 :add tests for all tunnel modes, IPv6 address test and libary version test
#  20010317b:add duplicate tunnel test
#  20010317c:test maximum numbers of creatable sit devices
#  20010511 :change status of 'forwarding_ipv6'
#  20011125 :Adapt function names after renaming in libary
#
# Test status of libary functions
#  ipv6_add_addr_on_device          : indirect
#  ipv6_del_addr_on_device          : indirect
#  ipv6_cleanup_device              : missing
#
#  ipv6_enable_autotunnel           : indirect
#  ipv6_disable_autotunnel          : indirect
#
#  ipv6_add_nbma_tunnel             : direct
#  ipv6_del_nbma_tunnel             : direct
#  ipv6_cleanup_nbma_tunnels_to_dest: missing
#
#  ipv6_add_tunnel_device           : direct
#  ipv6_del_tunnel_device           : direct
#
#  ipv6_add_6to4_tunnel             : direct
#  ipv6_del_6to4_tunnel             : direct
#
#  ipv6_add_route                   : indirect (ipv6_add_nbma_tunnel)
#  ipv6_del_routei                  : indirect (ipv6_del_nbma_tunnel)
#  ipv6_cleanup_routes              : missing
#
#  forwarding_ipv6:           no more (not in use anymore)
#
#  ipv6_test_addr_exists_on_device  : indirect
#  ipv6_test_ipv4_addr_valid        : indirect
#  ipv6_test_ipv4_addr_global_usable: indirect
#  ipv6_test_ipv6_addr_valid        : indirect
#  ipv6_test                        : indirect
#  test_interface_status:     indirect (some)
#
#  getversion_ipv6_functions: direct



## Get version of testsuite
print_separator() {
	echo "--------------------------------"
}
	

## Get version of testsuite
testsuite_get_testsuite_version() {
	TESTSUITEVERSION="`cat $0 | grep "^# Version:" | awk '{ print $3 }' | sed 's/-//g'`"
	echo "INFO: Version of testsuite is: '$TESTSUITEVERSION'"
}

## Test main network configuration file "/etc/sysconfig/network"
testsuite_etc_sysconfig_network() {
	# Get values
	. /etc/sysconfig/network

	echo "ACTION: Test IPv6 related content of '/etc/sysconfig/network'"
	status="good"
	if [ -z "$NETWORKING_IPV6" ]; then
		echo "ERROR: NETWORKING_IPV6 is empty or doesn't exist"
		status="bad"
	else
		echo "INFO: NETWORKING_IPV6 contains '$NETWORKING_IPV6'"
		if [ "$NETWORKING_IPV6" = "yes" ]; then
			echo "GOOD: NETWORKING_IPV6 contains 'yes' and is therefore enabled"
		else
			echo "ERROR: NETWORKING_IPV6 contains not 'yes' and is therefore disabled"
			status="bad"
		fi
	fi

	if [ -z "$IPV6_TUNNELMODE" ]; then
		echo "INFO: IPV6_TUNNELMODE is empty or doesn't exist, take default one"
	else
		echo "IPV6_TUNNELMODE contains '$IPV6_TUNNELMODE'"
		if [ "$IPV6_TUNNELMODE" = "IP" ]; then
			echo "GOOD: IPV6_TUNNELMODE contains 'IP' and therefore \"ip tunnel\" is used to create tunnels"
		elif [ "$IPV6_TUNNELMODE" = "NBMA" ]; then
			echo "GOOD: IPV6_TUNNELMODE contains 'NBMA' and therefore \"route\" is used to create tunnels"
		else
			echo "ERROR: IPV6_TUNNELMODE contains neither 'IP' nor 'NBMA', IPv6 tunneling is not working"
			status="bad"
		fi
	fi

	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}


## Test IPv6 function libary file "/etc/sysconfig/network-scripts/network-functions-ipv6"
testsuite_etc_sysconfig_network_scripts_network_functions_ipv6() {
	echo "ACTION: Run basic tests at '/etc/sysconfig/network-scripts/network-functions-ipv6'"

	# Source libary
	. /etc/sysconfig/network-scripts/network-functions-ipv6

	status="good"

	# Get version
	result="`getversion_ipv6_functions 2>/dev/null`"
	if [ $? -ne 0  ]; then
		echo "ERROR: The used file '/etc/sysconfig/network-scripts/network-functions-ipv6' is outdated, because it doesn't support the function 'getversion_ipv6_functions', please update it"
		status="bad"
	else
		echo "INFO: Version of '/etc/sysconfig/network-scripts/network-functions-ipv6' is '$result'"
	fi

	if [ $result -lt 20011124  ]; then
		echo "ERROR: The used file '/etc/sysconfig/network-scripts/network-functions-ipv6' is outdated for that test script, please update it"
		status="bad"
	fi

	# Display startup test results
	echo "INFO: Use tool 'ipv6calc': '$EXISTS_ipv6calc'"
	echo "INFO: Use tool 'ipcalc'  : '$EXISTS_ipcalc'"

	# Run IPv6 test
	if ipv6_test; then
		echo "GOOD: The IPv6 basic tests were ok"
	else
		echo "ERROR: The IPv6 basic tests were not ok"
		status="bad"
	fi

	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}


## Test IPv6 address valid
testsuite_ipv6_valid() {
	local status="good"
	echo "TEST: Test now the 'IPv6 address valid test'"

	echo "ACTION: 'ipv6_test_ipv6_addr_valid 3ffe::1/16'" # valid
	if ! ipv6_test_ipv6_addr_valid 3ffe::1/16; then
		echo "ERROR: test fails"
		local status="bad"
	else
		echo "GOOD: result is ok"
	fi
		
	echo "ACTION: 'ipv6_test_ipv6_addr_valid 3ffe::1'" 
	if ! ipv6_test_ipv6_addr_valid 3ffe::1; then
		echo "ERROR: test fails"
		local status="bad"
	else
	        echo "GOOD: result is ok"
	fi

	echo "ACTION: 'ipv6_test_ipv6_addr_valid ::1.2.3.4/48'" # valid
	if ! ipv6_test_ipv6_addr_valid ::1.2.3.4/48; then
		echo "ERROR: test fails"
		local status="bad"
    else
        echo "GOOD: result is ok"
	fi

	if  [ "$EXISTS_ipv6calc" = "yes" ]; then
		echo "ACTION: 'ipv6_test_ipv6_addr_valid 1.2.3.4::1.2.3.4/1'" # invalid
		if ipv6_test_ipv6_addr_valid 1.2.3.4::1.2.3.4/1; then
			echo "ERROR: test fails"
			local status="bad"
    	else
        	echo "GOOD: result is ok"
		fi
	fi

	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}


## Test the working tunnel setup using "ip" (tool of "iproute" package)
testsuite_ip_tunnel() {
	local status="good"

	echo "TEST: Test now the tunneling setup using 'ip'"

	# Create a tunnel device
	echo "ACTION: 'ipv6_add_tunnel_dev tuntest 1.2.3.4 fec0::1/64'"
	ipv6_add_tunnel_device tuntest 1.2.3.4 fec0::1/64
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is up
	ipv6_test_device_status tuntest
	local retval=$?
	
	if [ $retval -eq 0 ]; then
		echo "GOOD: Tunnel interface 'tuntest' creation works, device is up"
	else
		echo "ERROR: Tunnel interface 'tuntest' wasn't created"
		status="bad"
	fi

	# Delete tunnel device
	echo "ACTION: 'ipv6_del_tunnel_dev tuntest'"
	ipv6_del_tunnel_device tuntest
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is down and deleted
	ipv6_test_device_status tuntest
	local retval=$?
	if [ $retval -eq 0 ]; then
		echo "ERROR: Tunnel interface 'tuntest' is still up"
		local status="bad"
	elif [ $retval -eq 1 ]; then 
		echo "ERROR: Tunnel interface 'tuntest' still exists"
		local status="bad"
	elif [ $retval -eq 2 ]; then
		echo "GOOD: Tunnel interface 'tuntest' does no longer exists"
	else
		echo "ERROR: Unexpected return code from 'test_interface_status tuntest'"
	fi

	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}


## Test the working tunnel setup using "ip" (tool of "iproute" package)
testsuite_ip_tunnel_dup() {
	echo "TEST: Test now duplicate tunneling setup using 'ip'"

	# Create first tunnel device
	echo "ACTION: 'ipv6_add_tunnel_device tunt1 1.2.3.4'"
	ipv6_add_tunnel_device tunt1 1.2.3.4 
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is up
	ipv6_test_device_status tunt1
	local retval=$?
	
	if [ $retval -eq 0 ]; then
		echo "GOOD: Tunnel interface 'tunt1' creation works, device is up"
	else
		echo "ERROR: Tunnel interface 'tunt1' wasn't created"
		status="bad"
	fi

	# Create second tunnel device
	echo "ACTION: 'ipv6_add_tunnel_device tunt2 1.2.3.4'"
	ipv6_add_tunnel_device tunt2 1.2.3.4 
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -eq 2 ]; then
		echo "GOOD: Return code '2', fatal error was detected"
	else
		local status="bad"
	fi

	# Test whether device is up
	ipv6_test_device_status tunt2
	local retval=$?
	
	if [ $retval -eq 0 ]; then
		echo "ERROR: Tunnel interface 'tunt2' creation works, device is up"
		status="bad"
	else
		echo "GOOD: Tunnel interface 'tunt2' wasn't created"
	fi

	# Delete tunnel device
	echo "ACTION: 'ipv6_del_tunnel_device tunt2'"
	ipv6_del_tunnel_device tunt2
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is down and deleted
	ipv6_test_device_status tunt2
	local retval=$?
	if [ $retval -eq 0 ]; then
		echo "ERROR: Tunnel interface 'tunt2' is still up"
		local status="bad"
	elif [ $retval -eq 1 ]; then 
		echo "ERROR: Tunnel interface 'tunt2' still exists"
		local status="bad"
	elif [ $retval -eq 2 ]; then
		echo "GOOD: Tunnel interface 'tunt2' does no longer exists"
	else
		echo "ERROR: Unexpected return code from 'test_interface_status tunt2'"
	fi

	# Delete tunnel device
	echo "ACTION: 'ipv6_del_tunnel_device tunt1'"
	ipv6_del_tunnel_device tunt1
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is down and deleted
	ipv6_test_device_status tunt1
	local retval=$?
	if [ $retval -eq 0 ]; then
		echo "ERROR: Tunnel interface 'tunt1' is still up"
		local status="bad"
	elif [ $retval -eq 1 ]; then 
		echo "ERROR: Tunnel interface 'tunt1' still exists"
		local status="bad"
	elif [ $retval -eq 2 ]; then
		echo "GOOD: Tunnel interface 'tunt1' does no longer exists"
	else
		echo "ERROR: Unexpected return code from 'test_interface_status tunt1'"
	fi
	
	
	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}


## Test the working tunnel setup using "ip" for maximum number
testsuite_ip_tunnel_maximum() {
	echo "TEST: Test maximum creatable tunneling sitX (X=1..255) devices using 'ip'"

	echo "ACTION: Try to create 255 sit devices"
	count=1
	while [ $count -le 255 ]; do
		devname="sit$count"
		echo -n "$count "
		ip tunnel add $devname mode sit remote 1.2.3.$count
		ifconfig $devname up
		local retval=$?
		if [ $retval -ne 0 ]; then
			local status="bad"
			break
		fi

		count=$[ $count + 1 ]
	done
	echo
	count=$[ $count - 1 ]
	echo "Maximum number of created sit devices: '$count'"

	# Shut down all devices now
	echo "ACTION: Delete them now again"
	while [ $count -gt 0 ]; do
		devname="sit$count"
		echo -n "$count "
		ifconfig $devname down
		ip tunnel del $devname
		local retval=$?
		if [ $retval -ne 0 ]; then
			local status="bad"
			break
		fi
		count=$[ $count - 1 ]
	done
	echo
		
	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}
## Test the working tunnel setup using NBMA-style
testsuite_nbma_tunnel() {
	local status="good"

	echo "TEST: Test now the tunneling setup using NBMA-style"

	# Create a tunnel device
	echo "ACTION: 'ipv6_add_nbma_tunnel tuntest 1.2.3.4 3ffe::/16'"
	ipv6_add_nbma_tunnel tuntest 1.2.3.4 3ffe::/16
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is up
	ipv6_test_device_status sit0
	local retval=$?
	
	if [ $retval -eq 0 ]; then
		echo "GOOD: Tunnel interface 'sit0' enabling works, device is up"
	else
		echo "ERROR: Tunnel interface 'sit0' couldn't be enabled"
		status="bad"
	fi

	# Delete tunnel device
	echo "ACTION: 'ifdown_ipv6_tunnel tuntest 1.2.3.4 3ffe::/16'"
	ipv6_del_nbma_tunnel tuntest 1.2.3.4 3ffe::/16
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is down and deleted
	ipv6_test_device_status sit0
	local retval=$?
	if [ $retval -eq 0 ]; then
		echo "ERROR: Tunnel interface 'sit0' is still up"
		local status="bad"
	elif [ $retval -eq 1 ]; then 
		echo "GOOD: Tunnel interface 'sit0' is down"
	elif [ $retval -eq 2 ]; then
		echo "ERROR: Tunnel interface 'sit0' no longer exits, very strange"
	else
		echo "ERROR: Unexpected return code from 'test_interface_status'"
	fi
	
		
	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}


## Test the working 6to4-tunnel setup
testsuite_6to4_tunnel() {
	local status="good"

	echo "TEST: Test now the 6to4-tunneling setup"

	# Create a tunnel device
	echo "ACTION: 'ipv6_add_6to4_tunnel tuntest 1.2.3.4'"
	ipv6_add_6to4_tunnel tuntest 1.2.3.4
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is up
	ipv6_test_device_status sit0
	local retval=$?
	
	if [ $retval -eq 0 ]; then
		echo "GOOD: Tunnel interface 'sit0' enabling works, device is up"
	else
		echo "ERROR: Tunnel interface 'sit0' couldn't be enabled"
		status="bad"
	fi

	# Delete tunnel device
	echo "ACTION: 'ipv6_del_6to4_tunnel tuntest 1.2.3.4'"
	ipv6_del_6to4_tunnel tuntest 1.2.3.4
	local retval=$?
	echo "INFO: Return code is: '$retval'"
	if [ $retval -ne 0 ]; then
		echo "ERROR: Return code not '0'"
		local status="bad"
	fi

	# Test whether device is down and deleted
	ipv6_test_device_status sit0
	local retval=$?
	if [ $retval -eq 0 ]; then
		echo "INFO: Tunnel interface 'sit0' is still up"

		# Delete all 6to4 tunnels device
		echo "ACTION: 'ifdown_ipv6to4_all tuntest'"
		ipv6_cleanup_6to4_tunnels tuntest
		local retval=$?
		echo "INFO: Return code is: '$retval'"
		if [ $retval -ne 0 ]; then
			echo "ERROR: Return code not '0'"
			local status="bad"
		fi

		if [ $retval -eq 0 ]; then
			echo "ERROR: Tunnel interface 'sit0' is still up"
		elif [ $retval -eq 1 ]; then 
			echo "GOOD: Tunnel interface 'sit0' is down"
		elif [ $retval -eq 2 ]; then
			echo "ERROR: Tunnel interface 'sit0' no longer exits, very strange"
		else
			echo "ERROR: Unexpected return code from 'test_interface_status'"
		fi
	elif [ $retval -eq 1 ]; then 
		echo "GOOD: Tunnel interface 'sit0' is down"
	elif [ $retval -eq 2 ]; then
		echo "ERROR: Tunnel interface 'sit0' no longer exits, very strange"
	else
		echo "ERROR: Unexpected return code from 'test_interface_status'"
	fi
	
		
	if [ "$status" = "bad" ]; then
		return 1
	else
		return 0
	fi
}

### Run tests
print_separator
testsuite_get_testsuite_version
print_separator
testsuite_etc_sysconfig_network || exit 1
print_separator
testsuite_etc_sysconfig_network_scripts_network_functions_ipv6 || exit 1
print_separator
testsuite_ipv6_valid || exit 1
print_separator
testsuite_ip_tunnel || exit 1
print_separator
testsuite_ip_tunnel_dup || exit 1
print_separator
testsuite_ip_tunnel_maximum || exit1
print_separator
testsuite_nbma_tunnel || exit 1
print_separator
testsuite_6to4_tunnel || exit 1
print_separator

echo "All tests were done successfully - good luck for the real life IPv6 setup!"
