From 6c0aef4da036266dba92bfceeb8b3efb3053fb5e Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 10 Apr 2025 16:20:00 +0200 Subject: [PATCH] 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 --- subsys/net/ip/net_context.c | 9 ++++++++- subsys/net/lib/sockets/sockets_packet.c | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/subsys/net/ip/net_context.c b/subsys/net/ip/net_context.c index cbb66bbf790..0890a22764c 100644 --- a/subsys/net/ip/net_context.c +++ b/subsys/net/ip/net_context.c @@ -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) { diff --git a/subsys/net/lib/sockets/sockets_packet.c b/subsys/net/lib/sockets/sockets_packet.c index d167eb5f203..508520c430d 100644 --- a/subsys/net/lib/sockets/sockets_packet.c +++ b/subsys/net/lib/sockets/sockets_packet.c @@ -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. */