Test handling of receiving multiple route information options in RA. Reviewed by: glebius Differential Revision: https://reviews.freebsd.org/D56216
@@ -783,6 +783,72 @@ ndp_slaac_switch_onlink_prefix_cleanup() {
vnet_cleanup
}
+atf_test_case "ndp_routeinfo_option" "cleanup"
+ndp_routeinfo_option_head() {
+ atf_set descr 'Test RFC 4191: Add route based on received RTI in RA'
+ atf_set require.user root
+ atf_set require.progs jq python3 scapy
+}
+
+ndp_routeinfo_option_body() {
+ local epair0 jname prefix lladdr route1 route2
+
+ vnet_init
+
+ jname="v6t-ndp_routeinfo_option"
+ prefix="2001:db8:ffff:1000::"
+ route1="3fff:1000::"
+ route2="3fff:2000::"
+
+ epair0=$(vnet_mkepair)
+
+ vnet_mkjail ${jname} ${epair0}a
+
+ ndp_if_up ${epair0}a ${jname}
+ ndp_if_up ${epair0}b
+ atf_check jexec ${jname} ifconfig ${epair0}a inet6 accept_rtadv
+
+ # Make sure that NAs from us are flagged as coming from a router.
+ atf_check -o ignore sysctl net.inet6.ip6.forwarding=1
+
+ lladdr="$(ndp_if_lladdr ${epair0}b)"
+ # Send an RA with high preference with 3 routes.
+ # The last rti should overwrite the default route rtiltime to 100 seconds
+ # and its preference to medium.
+ atf_check -e ignore python3 $(atf_get_srcdir)/ra.py \
+ --sendif ${epair0}b \
+ --dst $(ndp_if_lladdr ${epair0}a ${jname}) \
+ --src ${lladdr} \
+ --rtrpref 1 --rtrltime 1800 --prefix ${prefix} \
+ --route ${route1} --routelen 32 \
+ --rtipref 1 --rtiltime 1800 \
+ --route ${route2} --routelen 48 \
+ --rtipref 4 --rtiltime 600 \
+ --route :: --routelen 0 \
+ --rtipref 4 --rtiltime 100
+
+ # Wait for a default router to appear.
+ while [ -z "$(jexec ${jname} ndp -r)" ]; do
+ sleep 0.1
+ done
+
+ # Make sure routes from rti option are being installed
+ atf_check -s exit:0 \
+ -o match:"^${route1}/32[[:space:]]+${lladdr}.*1800" \
+ -o match:"^${route2}/48[[:space:]]+${lladdr}.*600" \
+ -o match:"^default[[:space:]]+${lladdr}" \
+ jexec ${jname} netstat -rn6
+
+ # Verify the default route lifetime and its preference is overwrited
+ atf_check -s exit:0 \
+ -o match:"^${lladdr}%${epair0}a if=${epair0}a, flags=, pref=medium, expire=1m.*" \
+ jexec ${jname} ndp -r
+}
+
+ndp_routeinfo_option_cleanup() {
+ vnet_cleanup
+}
+
atf_init_test_cases()
{
@@ -798,4 +864,5 @@ atf_init_test_cases()
atf_add_test_case "ndp_input_validation_hlim"
atf_add_test_case "ndp_input_validation_src_linklocal"
atf_add_test_case "ndp_multirouter_pref"
+ atf_add_test_case "ndp_routeinfo_option"
}
@@ -2,6 +2,7 @@
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2024 Klara, Inc.
+# Copyright (c) 2026 Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
#
import argparse
@@ -41,18 +42,39 @@ def main():
parser.add_argument('--preferredlifetime', nargs=1, required=False,
type=int, default=4294967295,
help='The preferred lifetime of the prefix')
+ parser.add_argument('--route', nargs='*', required=False,
+ action='extend', type=str, default=[],
+ help='The route to be advertised')
+ parser.add_argument('--routelen', nargs='*', required=False,
+ action='extend', type=int, default=[],
+ help='The route length to be advertised')
+ parser.add_argument('--rtipref', nargs='*', required=False,
+ action='extend', type=int, default=[],
+ help='The route info preference advertised')
+ parser.add_argument('--rtiltime', nargs='*', required=False,
+ action='extend', type=int, default=[],
+ help='The route info preference advertised')
args = parser.parse_args()
pkt = sp.Ether() / \
sp.IPv6(src=args.src, dst=args.dst, hlim=args.hoplimit) / \
- sp.ICMPv6ND_RA(chlim=64, prf=args.rtrpref, routerlifetime=args.rtrltime)
+ sp.ICMPv6ND_RA(chlim=64,
+ prf=args.rtrpref,
+ routerlifetime=args.rtrltime)
if (args.prefix):
pkt = pkt / \
- sp.ICMPv6NDOptPrefixInfo(prefix=args.prefix,
- prefixlen=args.prefixlen,
- validlifetime=args.validlifetime,
- preferredlifetime=args.preferredlifetime)
+ sp.ICMPv6NDOptPrefixInfo(prefix=args.prefix,
+ prefixlen=args.prefixlen,
+ validlifetime=args.validlifetime,
+ preferredlifetime=args.preferredlifetime)
+
+ for i in range(0, len(args.route)):
+ pkt = pkt / \
+ sp.ICMPv6NDOptRouteInfo(prefix=args.route[i],
+ plen=args.routelen[i],
+ prf=args.rtipref[i],
+ rtlifetime=args.rtiltime[i])
sp.sendp(pkt, iface=args.sendif[0], verbose=False)
sys.exit(0)