From cd4712a2f01f00a219a29fbe03c401f583381118 Mon Sep 17 00:00:00 2001 From: Felipe Moura Date: Sun, 16 Aug 2026 17:28:55 -0300 Subject: [PATCH] net/arp: do not resolve an address to another interface's MAC On a cache miss arp_find() returns the MAC of any interface holding the address, ignoring the egress device. Two interfaces on one subnet then leave the peer unreachable until the entry is relearned. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Felipe Moura --- net/arp/arp_table.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/net/arp/arp_table.c b/net/arp/arp_table.c index a1728989e77..3e2938b7993 100644 --- a/net/arp/arp_table.c +++ b/net/arp/arp_table.c @@ -81,8 +81,9 @@ struct arp_table_info_s { - in_addr_t ai_ipaddr; /* IP address for lookup */ - FAR uint8_t *ai_ethaddr; /* Location to return the MAC address */ + in_addr_t ai_ipaddr; /* IP address for lookup */ + FAR uint8_t *ai_ethaddr; /* Location to return the MAC address */ + FAR struct net_driver_s *ai_dev; /* The device the frame will be sent on */ }; /**************************************************************************** @@ -117,6 +118,16 @@ static int arp_match(FAR struct net_driver_s *dev, FAR void *arg) { FAR struct arp_table_info_s *info = arg; + /* Only the egress device may answer for its own address. Otherwise a + * frame sent on one interface takes the MAC of another that happens to + * hold the address, which breaks setups sharing a subnet. + */ + + if (info->ai_dev != NULL && dev != info->ai_dev) + { + return 0; + } + /* Make sure that this is an Ethernet device (or an IEEE 802.11 device * which is also Ethernet) */ @@ -529,6 +540,7 @@ int arp_find(in_addr_t ipaddr, FAR uint8_t *ethaddr, info.ai_ipaddr = ipaddr; info.ai_ethaddr = ethaddr; + info.ai_dev = dev; if (netdev_foreach(arp_match, &info) != 0) {