0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 ret=0
0014
0015 ksft_skip=4
0016
0017 PAUSE_ON_FAIL=no
0018 PAUSE=no
0019
0020 HOST_NS="ns-host"
0021 ROUTER_NS="ns-router"
0022
0023 HOST_INTF="veth-host"
0024 ROUTER_INTF="veth-router"
0025
0026 ROUTER_ADDR="2000:20::1"
0027 HOST_ADDR="2000:20::2"
0028 SUBNET_WIDTH=64
0029 ROUTER_ADDR_WITH_MASK="${ROUTER_ADDR}/${SUBNET_WIDTH}"
0030 HOST_ADDR_WITH_MASK="${HOST_ADDR}/${SUBNET_WIDTH}"
0031
0032 IP_HOST="ip -6 -netns ${HOST_NS}"
0033 IP_HOST_EXEC="ip netns exec ${HOST_NS}"
0034 IP_ROUTER="ip -6 -netns ${ROUTER_NS}"
0035 IP_ROUTER_EXEC="ip netns exec ${ROUTER_NS}"
0036
0037 tcpdump_stdout=
0038 tcpdump_stderr=
0039
0040 log_test()
0041 {
0042 local rc=$1
0043 local expected=$2
0044 local msg="$3"
0045
0046 if [ ${rc} -eq ${expected} ]; then
0047 printf " TEST: %-60s [ OK ]\n" "${msg}"
0048 nsuccess=$((nsuccess+1))
0049 else
0050 ret=1
0051 nfail=$((nfail+1))
0052 printf " TEST: %-60s [FAIL]\n" "${msg}"
0053 if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
0054 echo
0055 echo "hit enter to continue, 'q' to quit"
0056 read a
0057 [ "$a" = "q" ] && exit 1
0058 fi
0059 fi
0060
0061 if [ "${PAUSE}" = "yes" ]; then
0062 echo
0063 echo "hit enter to continue, 'q' to quit"
0064 read a
0065 [ "$a" = "q" ] && exit 1
0066 fi
0067 }
0068
0069 setup()
0070 {
0071 set -e
0072
0073 local drop_unsolicited_na=$1
0074 local accept_untracked_na=$2
0075 local forwarding=$3
0076
0077
0078
0079 ip netns add ${HOST_NS}
0080 ip netns add ${ROUTER_NS}
0081 ${IP_ROUTER} link add ${ROUTER_INTF} type veth \
0082 peer name ${HOST_INTF} netns ${HOST_NS}
0083
0084
0085
0086
0087
0088
0089 ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
0090 ${IP_ROUTER_EXEC} sysctl -qw \
0091 ${ROUTER_CONF}.forwarding=${forwarding}
0092 ${IP_ROUTER_EXEC} sysctl -qw \
0093 ${ROUTER_CONF}.drop_unsolicited_na=${drop_unsolicited_na}
0094 ${IP_ROUTER_EXEC} sysctl -qw \
0095 ${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na}
0096 ${IP_ROUTER_EXEC} sysctl -qw ${ROUTER_CONF}.disable_ipv6=0
0097 ${IP_ROUTER} addr add ${ROUTER_ADDR_WITH_MASK} dev ${ROUTER_INTF}
0098
0099
0100
0101 HOST_CONF=net.ipv6.conf.${HOST_INTF}
0102 ${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.ndisc_notify=1
0103 ${IP_HOST_EXEC} sysctl -qw ${HOST_CONF}.disable_ipv6=0
0104 ${IP_HOST} addr add ${HOST_ADDR_WITH_MASK} dev ${HOST_INTF}
0105
0106 set +e
0107 }
0108
0109 start_tcpdump() {
0110 set -e
0111 tcpdump_stdout=`mktemp`
0112 tcpdump_stderr=`mktemp`
0113 ${IP_ROUTER_EXEC} timeout 15s \
0114 tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
0115 "icmp6 && icmp6[0] == 136 && src ${HOST_ADDR}" \
0116 > ${tcpdump_stdout} 2> /dev/null
0117 set +e
0118 }
0119
0120 cleanup_tcpdump()
0121 {
0122 set -e
0123 [[ ! -z ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
0124 [[ ! -z ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
0125 tcpdump_stdout=
0126 tcpdump_stderr=
0127 set +e
0128 }
0129
0130 cleanup()
0131 {
0132 cleanup_tcpdump
0133 ip netns del ${HOST_NS}
0134 ip netns del ${ROUTER_NS}
0135 }
0136
0137 link_up() {
0138 set -e
0139 ${IP_ROUTER} link set dev ${ROUTER_INTF} up
0140 ${IP_HOST} link set dev ${HOST_INTF} up
0141 set +e
0142 }
0143
0144 verify_ndisc() {
0145 local drop_unsolicited_na=$1
0146 local accept_untracked_na=$2
0147 local forwarding=$3
0148
0149 neigh_show_output=$(${IP_ROUTER} neigh show \
0150 to ${HOST_ADDR} dev ${ROUTER_INTF} nud stale)
0151 if [ ${drop_unsolicited_na} -eq 0 ] && \
0152 [ ${accept_untracked_na} -eq 1 ] && \
0153 [ ${forwarding} -eq 1 ]; then
0154
0155 [[ ${neigh_show_output} ]]
0156 else
0157
0158 [[ -z ${neigh_show_output} ]]
0159 fi
0160 }
0161
0162 test_unsolicited_na_common()
0163 {
0164
0165 setup $1 $2 $3
0166
0167
0168
0169 link_up
0170 start_tcpdump
0171
0172
0173 verify_ndisc $1 $2 $3
0174
0175 }
0176
0177 test_unsolicited_na_combination() {
0178 test_unsolicited_na_common $1 $2 $3
0179 test_msg=("test_unsolicited_na: "
0180 "drop_unsolicited_na=$1 "
0181 "accept_untracked_na=$2 "
0182 "forwarding=$3")
0183 log_test $? 0 "${test_msg[*]}"
0184 cleanup
0185 }
0186
0187 test_unsolicited_na_combinations() {
0188
0189
0190
0191 test_unsolicited_na_combination 0 1 1
0192
0193
0194 test_unsolicited_na_combination 0 0 0
0195 test_unsolicited_na_combination 0 0 1
0196 test_unsolicited_na_combination 0 1 0
0197 test_unsolicited_na_combination 1 0 0
0198 test_unsolicited_na_combination 1 0 1
0199 test_unsolicited_na_combination 1 1 0
0200 test_unsolicited_na_combination 1 1 1
0201 }
0202
0203
0204
0205
0206 usage()
0207 {
0208 cat <<EOF
0209 usage: ${0
0210 -p Pause on fail
0211 -P Pause after each test before cleanup
0212 EOF
0213 }
0214
0215
0216
0217
0218 while getopts :pPh o
0219 do
0220 case $o in
0221 p) PAUSE_ON_FAIL=yes;;
0222 P) PAUSE=yes;;
0223 h) usage; exit 0;;
0224 *) usage; exit 1;;
0225 esac
0226 done
0227
0228
0229 [ "${PAUSE}" = "yes" ] && PAUSE_ON_FAIL=no
0230
0231 if [ "$(id -u)" -ne 0 ];then
0232 echo "SKIP: Need root privileges"
0233 exit $ksft_skip;
0234 fi
0235
0236 if [ ! -x "$(command -v ip)" ]; then
0237 echo "SKIP: Could not run test without ip tool"
0238 exit $ksft_skip
0239 fi
0240
0241 if [ ! -x "$(command -v tcpdump)" ]; then
0242 echo "SKIP: Could not run test without tcpdump tool"
0243 exit $ksft_skip
0244 fi
0245
0246
0247 cleanup &> /dev/null
0248
0249 test_unsolicited_na_combinations
0250
0251 printf "\nTests passed: %3d\n" ${nsuccess}
0252 printf "Tests failed: %3d\n" ${nfail}
0253
0254 exit $ret