#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

# This test is for the accept_unsolicited_na feature to
# enable RFC9131 behaviour. The following is the test-matrix.
# drop   accept  fwding                   behaviour
# ----   ------  ------  ----------------------------------------------
#    1        X       X  Drop NA packet and don't pass up the stack
#    0        0       X  Pass NA packet up the stack, don't update NC
#    0        1       0  Pass NA packet up the stack, don't update NC
#    0        1       1  Pass NA packet up the stack, and add a STALE
#                           NC entry

ret=0
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4

PAUSE_ON_FAIL=no
PAUSE=no

HOST_NS="ns-host"
ROUTER_NS="ns-router"

HOST_INTF="veth-host"
ROUTER_INTF="veth-router"

ROUTER_ADDR="2000:20::1"
HOST_ADDR="2000:20::2"
SUBNET_WIDTH=64
ROUTER_ADDR_WITH_MASK="${ROUTER_ADDR}/${SUBNET_WIDTH}"
HOST_ADDR_WITH_MASK="${HOST_ADDR}/${SUBNET_WIDTH}"

IP_HOST="ip -6 -netns ${HOST_NS}"
IP_HOST_EXEC="ip netns exec ${HOST_NS}"
IP_ROUTER="ip -6 -netns ${ROUTER_NS}"
IP_ROUTER_EXEC="ip netns exec ${ROUTER_NS}"

tcpdump_stdout=
tcpdump_stderr=

log_test()
{
	local rc=$1
	local expected=$2
	local msg="$3"

	if [ ${rc} -eq ${expected} ]; then
		printf "    TEST: %-60s  [ OK ]\n" "${msg}"
		nsuccess=$((nsuccess+1))
	else
		ret=1
		nfail=$((nfail+1))
		printf "    TEST: %-60s  [FAIL]\n" "${msg}"
		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
		echo
			echo "hit enter to continue, 'q' to quit"
			read a
			[ "$a" = "q" ] && exit 1
		fi
	fi

	if [ "${PAUSE}" = "yes" ]; then
		echo
		echo "hit enter to continue, 'q' to quit"
		read a
		[ "$a" = "q" ] && exit 1
	fi
}

setup()
{
	set -e

	local drop_unsolicited_na=$1
	local accept_unsolicited_na=$2
	local forwarding=$3

	# Setup two namespaces and a veth tunnel across them.
	# On end of the tunnel is a router and the other end is a host.
	ip netns add ${HOST_NS}
	ip netns add ${ROUTER_NS}
	${IP_ROUTER} link add ${ROUTER_INTF} type veth \
                peer name ${HOST_INTF} netns ${HOST_NS}

	# Enable IPv6 on both router and host, and configure static addresses.
	# The router here is the DUT
	# Setup router configuration as specified by the arguments.
	# forwarding=0 case is to check that a non-router
	# doesn't add neighbour entries.
        ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
	${IP_ROUTER_EXEC} sysctl -qw \
                ${ROUTER_CONF}.forwarding=${forwarding}
	${IP_ROUTER_EXEC} sysctl -qw \
                ${ROUTER_CONF}.drop_unsolicited_na=${drop_unsolicited_na}
	${IP_ROUTER_EXEC} sysctl -qw \
                ${ROUTER_CONF}.accept_unsolicited_na=${accept_unsolicited_na}
	${IP_ROUTER_EXEC} sysctl -qw ${ROUTER_CONF}.disable_ipv6=0
	${IP_ROUTER} addr add ${ROUTER_ADDR_WITH_MASK} dev ${ROUTER_INTF}

	# Turn on ndisc_notify on host interface so that
	# the host sends unsolicited NAs.
	HOST_CONF=net.ipv6.conf.${HOST_INTF}
	${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.ndisc_notify=1
	${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.disable_ipv6=0
	${IP_HOST} addr add ${HOST_ADDR_WITH_MASK} dev ${HOST_INTF}

	set +e
}

start_tcpdump() {
	set -e
	tcpdump_stdout=`mktemp`
	tcpdump_stderr=`mktemp`
	${IP_ROUTER_EXEC} timeout 15s \
                tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
                "icmp6 && icmp6[0] == 136 && src ${HOST_ADDR}" \
                > ${tcpdump_stdout} 2> /dev/null
	set +e
}

cleanup_tcpdump()
{
	set -e
	[[ ! -z  ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
	[[ ! -z  ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
	tcpdump_stdout=
	tcpdump_stderr=
	set +e
}

cleanup()
{
	cleanup_tcpdump
	ip netns del ${HOST_NS}
	ip netns del ${ROUTER_NS}
}

link_up() {
	set -e
	${IP_ROUTER} link set dev ${ROUTER_INTF} up
	${IP_HOST} link set dev ${HOST_INTF} up
	set +e
}

verify_ndisc() {
	local drop_unsolicited_na=$1
	local accept_unsolicited_na=$2
	local forwarding=$3

	neigh_show_output=$(${IP_ROUTER} neigh show \
                to ${HOST_ADDR} dev ${ROUTER_INTF} nud stale)
	if [ ${drop_unsolicited_na} -eq 0 ] && \
			[ ${accept_unsolicited_na} -eq 1 ] && \
			[ ${forwarding} -eq 1 ]; then
		# Neighbour entry expected to be present for 011 case
		[[ ${neigh_show_output} ]]
	else
		# Neighbour entry expected to be absent for all other cases
		[[ -z ${neigh_show_output} ]]
	fi
}

test_unsolicited_na_common()
{
	# Setup the test bed, but keep links down
	setup $1 $2 $3

	# Bring the link up, wait for the NA,
	# and add a delay to ensure neighbour processing is done.
	link_up
	start_tcpdump

	# Verify the neighbour table
	verify_ndisc $1 $2 $3

}

test_unsolicited_na_combination() {
	test_unsolicited_na_common $1 $2 $3
	test_msg=("test_unsolicited_na: "
		"drop_unsolicited_na=$1 "
		"accept_unsolicited_na=$2 "
		"forwarding=$3")
	log_test $? 0 "${test_msg[*]}"
	cleanup
}

test_unsolicited_na_combinations() {
	# Args: drop_unsolicited_na accept_unsolicited_na forwarding

	# Expect entry
	test_unsolicited_na_combination 0 1 1

	# Expect no entry
	test_unsolicited_na_combination 0 0 0
	test_unsolicited_na_combination 0 0 1
	test_unsolicited_na_combination 0 1 0
	test_unsolicited_na_combination 1 0 0
	test_unsolicited_na_combination 1 0 1
	test_unsolicited_na_combination 1 1 0
	test_unsolicited_na_combination 1 1 1
}

###############################################################################
# usage

usage()
{
	cat <<EOF
usage: ${0##*/} OPTS
        -p          Pause on fail
        -P          Pause after each test before cleanup
EOF
}

###############################################################################
# main

while getopts :pPh o
do
	case $o in
		p) PAUSE_ON_FAIL=yes;;
		P) PAUSE=yes;;
		h) usage; exit 0;;
		*) usage; exit 1;;
	esac
done

# make sure we don't pause twice
[ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no

if [ "$(id -u)" -ne 0 ];then
	echo "SKIP: Need root privileges"
	exit $ksft_skip;
fi

if [ ! -x "$(command -v ip)" ]; then
	echo "SKIP: Could not run test without ip tool"
	exit $ksft_skip
fi

if [ ! -x "$(command -v tcpdump)" ]; then
	echo "SKIP: Could not run test without tcpdump tool"
	exit $ksft_skip
fi

# start clean
cleanup &> /dev/null

test_unsolicited_na_combinations

printf "\nTests passed: %3d\n" ${nsuccess}
printf "Tests failed: %3d\n"   ${nfail}

exit $ret
