net: sockets: packet: Ensure correct interface is used

Make sure that when sendto is being used without the socket being bound
before, a correct interface is used for transmission. As
zpacket_sendto_ctx() calls net_context_recv() to register receive
callback before sending, a default binding was used by the context
layer, which would bind the socket to the default interface. This could
lead to unexpected results, i.e. packet being sent on a default
interface, even though a different one was specified.

Make also sure that there is no ambiguity in the interface selection -
the application should be explicitly clear what interface it wants to
use when it comes to packet sockets. It's better to return an error if
no valid interface was specified.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2025-04-10 16:20:00 +02:00 committed by Benjamin Cabé
commit 6c0aef4da0
2 changed files with 24 additions and 1 deletions

View file

@ -764,14 +764,19 @@ static int bind_default(struct net_context *context)
if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) && family == AF_PACKET) {
struct sockaddr_ll ll_addr;
struct net_if *iface = net_context_get_iface(context);
if (net_sll_ptr(&context->local)->sll_addr) {
return 0;
}
if (iface == NULL) {
iface = net_if_get_default();
}
ll_addr.sll_family = AF_PACKET;
ll_addr.sll_protocol = htons(ETH_P_ALL);
ll_addr.sll_ifindex = net_if_get_by_iface(net_if_get_default());
ll_addr.sll_ifindex = net_if_get_by_iface(iface);
return net_context_bind(context, (struct sockaddr *)&ll_addr,
sizeof(ll_addr));
@ -2487,6 +2492,8 @@ static int context_sendto(struct net_context *context,
ll_addr->sll_ifindex);
return -EDESTADDRREQ;
}
net_context_set_iface(context, iface);
}
if (net_context_get_type(context) == SOCK_DGRAM) {

View file

@ -234,6 +234,7 @@ ssize_t zpacket_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
int flags, const struct sockaddr *dest_addr,
socklen_t addrlen)
{
const struct sockaddr_ll *ll_addr = (const struct sockaddr_ll *)dest_addr;
k_timeout_t timeout = K_FOREVER;
int status;
@ -248,6 +249,21 @@ ssize_t zpacket_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
net_context_get_option(ctx, NET_OPT_SNDTIMEO, &timeout, NULL);
}
/* If no interface was set on the context yet, use the one provided in
* the destination address for default binding, unless 0 (any interface)
* was set, in that case let the stack choose the default.
*/
if (net_context_get_iface(ctx) == NULL && ll_addr->sll_ifindex != 0) {
struct net_if *iface = net_if_get_by_index(ll_addr->sll_ifindex);
if (iface == NULL) {
errno = EDESTADDRREQ;
return -1;
}
net_context_set_iface(ctx, iface);
}
/* Register the callback before sending in order to receive the response
* from the peer.
*/