Skip to content

Commit 2866694

Browse files
committed
dhcp: T9085: drop stale defaults when option 3 disappears
Cleanup ran only when new_routers was non-empty, so a RENEW that clears option 3 (or the no-default-route enter hook blanking it) left the old FRR default in place. Run the old-vs-new gateway drop before that return. Verify del/add against /usr/sbin/ip rather than the wrapper exit status: vtysh no-route fails when the route is already gone.
1 parent ddcb818 commit 2866694

1 file changed

Lines changed: 30 additions & 11 deletions

File tree

src/etc/dhcp/dhclient-exit-hooks.d/02-vyos-dhcp-renew-default-route

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
# and append ${VRF_OPTION} so VRF leases see the same table the add uses.
1515
#
1616
# If option 3 changes across a same-IP RENEW, drop defaults via gateways
17-
# that disappeared from $new_routers. Otherwise FRR keeps the old nexthop
18-
# and the kernel shows ECMP over old+new. Compare $old_routers vs
19-
# $new_routers (same pattern as 98-vyos-static-routes-dhclient-hook).
17+
# that disappeared from $new_routers (including option 3 going away entirely).
18+
# Otherwise FRR keeps the old nexthop and the kernel shows ECMP over old+new.
19+
# Compare $old_routers vs $new_routers (same pattern as
20+
# 98-vyos-static-routes-dhclient-hook). The no-default-route enter hook blanks
21+
# new_routers; removing a leftover option-3 default is the right outcome there
22+
# too, so cleanup runs before the empty-new_routers return.
2023
#
2124
# Adds still use the enter-hook ip() wrapper so FRR gets tag/distance
22-
# IF_METRIC. Honor no-default-route (enter hook blanks new_routers) and
23-
# skip when classless static routes are present (stock ignores option 3).
25+
# IF_METRIC. Skip when classless static routes are present (stock ignores
26+
# option 3). Wrapper exit status is not a gate: vtysh "no ip route" fails
27+
# when the route is already gone. Verify the kernel table with /usr/sbin/ip.
2428

2529
RUN="yes"
2630

@@ -38,13 +42,15 @@ if [ -n "$new_rfc3442_classless_static_routes" ]; then
3842
return 0 2>/dev/null || exit 0
3943
fi
4044

41-
if [ -z "$new_routers" ]; then
42-
return 0 2>/dev/null || exit 0
43-
fi
45+
# Kernel/FRR-installed default present? Real ip(8) only — never the wrapper.
46+
_default_via_present() {
47+
/usr/sbin/ip -4 route show default via "$1" dev "${interface}" ${VRF_OPTION} 2>/dev/null | grep -q .
48+
}
4449

4550
if_metric="${IF_METRIC:-210}"
4651

47-
# Drop defaults via gateways the server no longer announces.
52+
# Drop defaults via gateways the server no longer announces, including when
53+
# option 3 disappeared (empty new_routers) or no-default-route blanked it.
4854
if [ -n "$old_routers" ] && [ "$old_routers" != "$new_routers" ]; then
4955
for router in $old_routers; do
5056
skip=
@@ -61,12 +67,20 @@ if [ -n "$old_routers" ] && [ "$old_routers" != "$new_routers" ]; then
6167
"RENEW/REBIND: removing stale default via ${router} dev ${interface}"
6268
# Wrapper: FRR-aware del (staticd + kernel).
6369
ip -4 route del default via "${router}" dev "${interface}" >/dev/null 2>&1
70+
if _default_via_present "${router}"; then
71+
logmsg warn \
72+
"RENEW/REBIND: stale default still present via ${router} dev ${interface}"
73+
fi
6474
done
6575
fi
6676

77+
# Honor no-default-route / missing option 3: nothing to install.
78+
if [ -z "$new_routers" ]; then
79+
return 0 2>/dev/null || exit 0
80+
fi
81+
6782
for router in $new_routers; do
68-
# Read-only check: real ip(8), not the enter-hook wrapper.
69-
if /usr/sbin/ip -4 route show default via "${router}" dev "${interface}" ${VRF_OPTION} 2>/dev/null | grep -q .; then
83+
if _default_via_present "${router}"; then
7084
if_metric=$((if_metric + 1))
7185
continue
7286
fi
@@ -78,5 +92,10 @@ for router in $new_routers; do
7892
ip -4 route add default via "${router}" dev "${interface}" \
7993
metric "${if_metric}" >/dev/null 2>&1
8094

95+
if ! _default_via_present "${router}"; then
96+
logmsg warn \
97+
"RENEW/REBIND: default still missing via ${router} dev ${interface} after add"
98+
fi
99+
81100
if_metric=$((if_metric + 1))
82101
done

0 commit comments

Comments
 (0)