Skip to content

net: Choose IP corresponding to the same network#102036

Merged
henrikbrixandersen merged 1 commit intozephyrproject-rtos:mainfrom
anhuba:arp_request_has_wrong_src_ip
Jan 13, 2026
Merged

net: Choose IP corresponding to the same network#102036
henrikbrixandersen merged 1 commit intozephyrproject-rtos:mainfrom
anhuba:arp_request_has_wrong_src_ip

Conversation

@anhuba
Copy link
Copy Markdown
Contributor

@anhuba anhuba commented Jan 9, 2026

If we have more than one IP on an interface we should choose the IP corresponding to the same network as the target IP. Otherwise we might not get ARP replies from some devices.

Copy link
Copy Markdown
Contributor

@rlubos rlubos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use net: arp: For the commit title prefix, it's an ARP-specifc change.

Comment thread subsys/net/l2/ethernet/arp.c Outdated
Comment thread subsys/net/l2/ethernet/arp.c Outdated
Comment thread subsys/net/l2/ethernet/arp.c Outdated
Comment on lines +246 to +258
addr, ipv4->unicast[i].ipv4.address.in_addr.s4_addr))) {
addr, ipv4->unicast[i].ipv4.address.in_addr.s4_addr)) &&
(!netaddr ||
is_same_net(netaddr->s_addr,
ipv4->unicast[i].ipv4.address.in_addr.s_addr,
ipv4->unicast[i].netmask.s_addr))) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if I read this correctly we'll now have a change in behavior in case there's no subnet match with any of the addresses on the interface. I.e. so far we'd choose any valid address as the source for the ARP request, but now we'd send unspec address as a source on subnet mismatch.

I'm generally fine with the proposed change to prefer addresses on the same subnet, but as I said it should be a preference, not a hard requirement. What if we rewrite the function a bit (which hopefully will improve the clarity as well):

static inline struct net_in_addr *if_get_addr(struct net_if *iface,
					      const uint8_t *own_addr,
					      const struct net_in_addr *dst_addr)
{
	struct net_if_ipv4 *ipv4 = iface->config.ip.ipv4;
	struct net_in_addr *best_match = NULL;

	if (!ipv4) {
		return NULL;
	}

	ARRAY_FOR_EACH(ipv4->unicast, i) {
		if (ipv4->unicast[i].ipv4.is_used &&
		    ipv4->unicast[i].ipv4.address.family == NET_AF_INET &&
		    ipv4->unicast[i].ipv4.addr_state == NET_ADDR_PREFERRED) {
			if (own_addr != NULL) {
				/* Specific address requested as own address. */
				if (!net_ipv4_addr_cmp_raw(
						own_addr,
						ipv4->unicast[i].ipv4.address.in_addr.s4_addr)) {
					/* No match, try next. */
					continue;
				}

				/* Got exact match. */
				best_match = &ipv4->unicast[i].ipv4.address.in_addr;
				break;
			}

			/* Prefer address on the same subnet as destination. */
			if (dst_addr != NULL &&
			    is_same_subnet(dst_addr->s_addr,
				           ipv4->unicast[i].ipv4.address.in_addr.s_addr,
				           ipv4->unicast[i].netmask.s_addr)) {
				/* Got address on the same subnet. */
				best_match = &ipv4->unicast[i].ipv4.address.in_addr;
				break;
			}

			/* Fallback to any valid address on hte interface. */
			if (best_match == NULL) {
				best_match = &ipv4->unicast[i].ipv4.address.in_addr;
			}
		}
	}

	return best_match;
}

(please note I haven't tested this)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually get ARP requests from the upper layer for IP addresses not configured on our interface?
If we do, would that not be a bug in the upper layer?

If we fill in the wrong sender IP in the ARP request, we might get an ARP reply from most devices (as most implementations seem to ignore the sender IP) as before the fix, but we still won't get ARP replies for devices which ignore our request due to the wrong sender IP.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upper layer doesn't really care if the address is on the local network or not, it's the ARP layer that makes decision whether to try to resolve address directly, or try to use GW address instead:
https://github.com/zephyrproject-rtos/zephyr/blob/76dd50833fabb56a8de65f01629f205de6c4f155/subsys/net/l2/ethernet/arp.c#L382C22-L401

So in general, yes, we should only be resolving addresses in local network, however there is for example this corner case with LL IPv4 address, if we only have link-local address configured on the interface we still try to resolve the target address as best effort appraoch. And if we force subnet matching, it'd no longer work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I have rewritten to take the IP of the matching subnet, if available and use the same IP as before as a fall back.

Comment thread subsys/net/l2/ethernet/arp.c Outdated
@anhuba anhuba force-pushed the arp_request_has_wrong_src_ip branch from cf7bdc2 to 9d7b11b Compare January 12, 2026 10:21
@zephyrbot zephyrbot requested a review from rlubos January 12, 2026 10:23
@mathieuchopstm mathieuchopstm removed their request for review January 12, 2026 10:27
@anhuba anhuba force-pushed the arp_request_has_wrong_src_ip branch from 9d7b11b to 9fbbfbe Compare January 12, 2026 12:36
rlubos
rlubos previously approved these changes Jan 12, 2026
Comment thread subsys/net/l2/ethernet/arp.c Outdated
Comment thread subsys/net/l2/ethernet/arp.c Outdated
Comment thread subsys/net/l2/ethernet/arp.c Outdated
If we have more than one IP on an interface we should choose the IP
corresponding to the same network as the target IP.

Signed-off-by: Andreas Huber <andreas.huber@sautergroup.com>
@zephyrbot zephyrbot requested review from jukkar and rlubos January 12, 2026 15:27
@sonarqubecloud
Copy link
Copy Markdown

@henrikbrixandersen henrikbrixandersen merged commit bb9616c into zephyrproject-rtos:main Jan 13, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants