Fix the regression introduced in 9e30ecf23b1b whereby IPv4 broadcast packets were having their ethernet destination field mangled. The problem was first observed with WOL magic packets but affects all UDP IPv4 broadcast packets.
The regression can be observed by sending an IPv4 WOL packet using the wakeonlan program to any ethernet address:
wakeonlan 46:3b:ad:61:e0:5d
and capturing the packet with tcpdump:
tcpdump -i eth0 -w /tmp/bad.cap dst port 9
The ethernet destination MUST be ff:ff:ff:ff:ff:ff for broadcast, but is mangled in affected kernels.
Revert the change made in 9e30ecf23b1b and ensure the MTU value for broadcast routes is retained by calling ip_dst_init_metrics() directly, avoiding the need to enter the main code block in rt_set_nexthop().
Simplify the code path taken for broadcast packets back to the original before the regression, adding only the call to ip_dst_init_metrics().
The broadcast_pmtu.sh selftest provided with the original patch still passes with this patch applied.
Cc: stable@vger.kernel.org Fixes: 9e30ecf23b1b ("net: ipv4: fix incorrect MTU in broadcast routes") Link: https://lore.kernel.org/regressions/20250822165231.4353-4-bacs@librecast.net Signed-off-by: Brett A C Sheffield bacs@librecast.net --- net/ipv4/route.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f639a2ae881a..ab4d72a59c7b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2588,6 +2588,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, do_cache = true; if (type == RTN_BROADCAST) { flags |= RTCF_BROADCAST | RTCF_LOCAL; + fi = NULL; } else if (type == RTN_MULTICAST) { flags |= RTCF_MULTICAST | RTCF_LOCAL; if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, @@ -2657,8 +2658,12 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->dst.output = ip_mc_output; RT_CACHE_STAT_INC(out_slow_mc); } + if (type == RTN_BROADCAST && res->fi) { + /* ensure MTU value for broadcast routes is retained */ + ip_dst_init_metrics(&rth->dst, res->fi->fib_metrics); + } #ifdef CONFIG_IP_MROUTE - if (type == RTN_MULTICAST) { + else if (type == RTN_MULTICAST) { if (IN_DEV_MFORWARD(in_dev) && !ipv4_is_local_multicast(fl4->daddr)) { rth->dst.input = ip_mr_input;