Skip to content

Commit c8798d0

Browse files
rluboskartben
authored andcommitted
net: sockets: packet: Make it possible to receive packets when unbound
In order to be able to receive packets on unbound packet sockets (which should collect packet from all interfaces in such case), it's needed to register receive callback at the socket layer as soon as the socket is created. In additional to that, the default binding for packet sockets need to be revisited. Packet socket should not be bound to the default interface, as this way the socket would only be receiving packets from that particular interface. Instead, leave the interface unspecified in such case. Signed-off-by: Robert Lubos <[email protected]>
1 parent cd0b195 commit c8798d0

File tree

3 files changed

+80
-96
lines changed

3 files changed

+80
-96
lines changed

subsys/net/ip/connection.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -699,13 +699,13 @@ enum net_verdict net_conn_packet_input(struct net_pkt *pkt, uint16_t proto)
699699

700700
/* Apply protocol-specific matching criteria... */
701701

702-
if (!(conn->flags & NET_CONN_LOCAL_ADDR_SET)) {
703-
continue;
704-
}
705-
706-
local = (struct sockaddr_ll *)&conn->local_addr;
707-
if (local->sll_ifindex != net_if_get_by_iface(net_pkt_iface(pkt))) {
708-
continue;
702+
/* Unbound sockets should collect packets from all interfaces. */
703+
if ((conn->flags & NET_CONN_LOCAL_ADDR_SET) != 0U) {
704+
local = (struct sockaddr_ll *)&conn->local_addr;
705+
if (local->sll_ifindex != 0 &&
706+
local->sll_ifindex != net_if_get_by_iface(net_pkt_iface(pkt))) {
707+
continue;
708+
}
709709
}
710710

711711
conn_raw_socket_deliver(pkt, conn, false);
@@ -775,7 +775,7 @@ enum net_verdict net_conn_raw_ip_input(struct net_pkt *pkt,
775775

776776
/* Apply protocol-specific matching criteria... */
777777

778-
if ((conn->flags & NET_CONN_LOCAL_ADDR_SET) &&
778+
if (((conn->flags & NET_CONN_LOCAL_ADDR_SET) != 0U) &&
779779
!conn_addr_cmp(pkt, ip_hdr, &conn->local_addr, false)) {
780780
continue; /* wrong local address */
781781
}

subsys/net/ip/net_context.c

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -770,13 +770,9 @@ static int bind_default(struct net_context *context)
770770
return 0;
771771
}
772772

773-
if (iface == NULL) {
774-
iface = net_if_get_default();
775-
}
776-
777773
ll_addr.sll_family = AF_PACKET;
778774
ll_addr.sll_protocol = htons(ETH_P_ALL);
779-
ll_addr.sll_ifindex = net_if_get_by_iface(iface);
775+
ll_addr.sll_ifindex = (iface == NULL) ? 0 : net_if_get_by_iface(iface);
780776

781777
return net_context_bind(context, (struct sockaddr *)&ll_addr,
782778
sizeof(ll_addr));
@@ -867,11 +863,13 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
867863
/* If we already have connection handler, then it effectively
868864
* means that it's already bound to an interface/port, and we
869865
* don't support rebinding connection to new address/port in
870-
* the code below.
866+
* the code below. Doesn't apply for packet sockets.
871867
* TODO: Support rebinding.
872868
*/
873-
if (context->conn_handler) {
874-
return -EISCONN;
869+
if (addr->sa_family != AF_PACKET) {
870+
if (context->conn_handler != NULL) {
871+
return -EISCONN;
872+
}
875873
}
876874

877875
if (IS_ENABLED(CONFIG_NET_IPV6) && addr->sa_family == AF_INET6) {
@@ -1103,13 +1101,8 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
11031101
}
11041102

11051103
iface = net_if_get_by_index(ll_addr->sll_ifindex);
1106-
if (!iface) {
1107-
NET_ERR("Cannot bind to interface index %d",
1108-
ll_addr->sll_ifindex);
1109-
return -EADDRNOTAVAIL;
1110-
}
11111104

1112-
if (IS_ENABLED(CONFIG_NET_OFFLOAD) &&
1105+
if (IS_ENABLED(CONFIG_NET_OFFLOAD) && iface != NULL &&
11131106
net_if_is_ip_offloaded(iface)) {
11141107
net_context_set_iface(context, iface);
11151108

@@ -1121,20 +1114,22 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
11211114

11221115
k_mutex_lock(&context->lock, K_FOREVER);
11231116

1124-
net_context_set_iface(context, iface);
1125-
11261117
net_sll_ptr(&context->local)->sll_family = AF_PACKET;
11271118
net_sll_ptr(&context->local)->sll_ifindex =
11281119
ll_addr->sll_ifindex;
11291120
net_sll_ptr(&context->local)->sll_protocol =
11301121
ll_addr->sll_protocol;
11311122

1132-
net_if_lock(iface);
1133-
net_sll_ptr(&context->local)->sll_addr =
1134-
net_if_get_link_addr(iface)->addr;
1135-
net_sll_ptr(&context->local)->sll_halen =
1136-
net_if_get_link_addr(iface)->len;
1137-
net_if_unlock(iface);
1123+
if (iface != NULL) {
1124+
net_context_set_iface(context, iface);
1125+
1126+
net_if_lock(iface);
1127+
net_sll_ptr(&context->local)->sll_addr =
1128+
net_if_get_link_addr(iface)->addr;
1129+
net_sll_ptr(&context->local)->sll_halen =
1130+
net_if_get_link_addr(iface)->len;
1131+
net_if_unlock(iface);
1132+
}
11381133

11391134
NET_DBG("Context %p bind to type 0x%04x iface[%d] %p addr %s",
11401135
context, htons(net_context_get_proto(context)),
@@ -3147,9 +3142,11 @@ int net_context_recv(struct net_context *context,
31473142
addr.sll_halen =
31483143
net_sll_ptr(&context->local)->sll_halen;
31493144

3150-
memcpy(addr.sll_addr,
3151-
net_sll_ptr(&context->local)->sll_addr,
3152-
MIN(addr.sll_halen, sizeof(addr.sll_addr)));
3145+
if (net_sll_ptr(&context->local)->sll_addr != NULL) {
3146+
memcpy(addr.sll_addr,
3147+
net_sll_ptr(&context->local)->sll_addr,
3148+
MIN(addr.sll_halen, sizeof(addr.sll_addr)));
3149+
}
31533150

31543151
ret = recv_raw(context, cb, timeout,
31553152
(struct sockaddr *)&addr, user_data);

subsys/net/lib/sockets/sockets_packet.c

Lines changed: 50 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,43 @@ static inline int k_fifo_wait_non_empty(struct k_fifo *fifo,
4040
return k_poll(events, ARRAY_SIZE(events), timeout);
4141
}
4242

43+
static void zpacket_received_cb(struct net_context *ctx,
44+
struct net_pkt *pkt,
45+
union net_ip_header *ip_hdr,
46+
union net_proto_header *proto_hdr,
47+
int status,
48+
void *user_data)
49+
{
50+
NET_DBG("ctx=%p, pkt=%p, st=%d, user_data=%p", ctx, pkt, status,
51+
user_data);
52+
53+
/* if pkt is NULL, EOF */
54+
if (pkt == NULL) {
55+
struct net_pkt *last_pkt = k_fifo_peek_tail(&ctx->recv_q);
56+
57+
if (last_pkt == NULL) {
58+
/* If there're no packets in the queue, recv() may
59+
* be blocked waiting on it to become non-empty,
60+
* so cancel that wait.
61+
*/
62+
sock_set_eof(ctx);
63+
k_fifo_cancel_wait(&ctx->recv_q);
64+
NET_DBG("Marked socket %p as peer-closed", ctx);
65+
} else {
66+
net_pkt_set_eof(last_pkt, true);
67+
NET_DBG("Set EOF flag on pkt %p", ctx);
68+
}
69+
70+
return;
71+
}
72+
73+
/* Normal packet */
74+
net_pkt_set_eof(pkt, false);
75+
76+
k_fifo_put(&ctx->recv_q, pkt);
77+
}
78+
79+
4380
static int zpacket_socket(int family, int type, int proto)
4481
{
4582
struct net_context *ctx;
@@ -73,46 +110,23 @@ static int zpacket_socket(int family, int type, int proto)
73110

74111
/* recv_q and accept_q are in union */
75112
k_fifo_init(&ctx->recv_q);
76-
zvfs_finalize_typed_fd(fd, ctx, (const struct fd_op_vtable *)&packet_sock_fd_op_vtable,
77-
ZVFS_MODE_IFSOCK);
78-
79-
return fd;
80-
}
81-
82-
static void zpacket_received_cb(struct net_context *ctx,
83-
struct net_pkt *pkt,
84-
union net_ip_header *ip_hdr,
85-
union net_proto_header *proto_hdr,
86-
int status,
87-
void *user_data)
88-
{
89-
NET_DBG("ctx=%p, pkt=%p, st=%d, user_data=%p", ctx, pkt, status,
90-
user_data);
91-
92-
/* if pkt is NULL, EOF */
93-
if (!pkt) {
94-
struct net_pkt *last_pkt = k_fifo_peek_tail(&ctx->recv_q);
95113

96-
if (!last_pkt) {
97-
/* If there're no packets in the queue, recv() may
98-
* be blocked waiting on it to become non-empty,
99-
* so cancel that wait.
100-
*/
101-
sock_set_eof(ctx);
102-
k_fifo_cancel_wait(&ctx->recv_q);
103-
NET_DBG("Marked socket %p as peer-closed", ctx);
104-
} else {
105-
net_pkt_set_eof(last_pkt, true);
106-
NET_DBG("Set EOF flag on pkt %p", ctx);
107-
}
108-
109-
return;
114+
/* Register the callback so that the socket is able to receive packets
115+
* as soon as it's created.
116+
*/
117+
ret = net_context_recv(ctx, zpacket_received_cb, K_NO_WAIT,
118+
ctx->user_data);
119+
if (ret < 0) {
120+
net_context_put(ctx);
121+
zvfs_free_fd(fd);
122+
errno = -ret;
123+
return -1;
110124
}
111125

112-
/* Normal packet */
113-
net_pkt_set_eof(pkt, false);
126+
zvfs_finalize_typed_fd(fd, ctx, (const struct fd_op_vtable *)&packet_sock_fd_op_vtable,
127+
ZVFS_MODE_IFSOCK);
114128

115-
k_fifo_put(&ctx->recv_q, pkt);
129+
return fd;
116130
}
117131

118132
static int zpacket_bind_ctx(struct net_context *ctx,
@@ -234,7 +248,6 @@ ssize_t zpacket_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
234248
int flags, const struct sockaddr *dest_addr,
235249
socklen_t addrlen)
236250
{
237-
const struct sockaddr_ll *ll_addr = (const struct sockaddr_ll *)dest_addr;
238251
k_timeout_t timeout = K_FOREVER;
239252
int status;
240253

@@ -249,32 +262,6 @@ ssize_t zpacket_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
249262
net_context_get_option(ctx, NET_OPT_SNDTIMEO, &timeout, NULL);
250263
}
251264

252-
/* If no interface was set on the context yet, use the one provided in
253-
* the destination address for default binding, unless 0 (any interface)
254-
* was set, in that case let the stack choose the default.
255-
*/
256-
if (net_context_get_iface(ctx) == NULL && ll_addr->sll_ifindex != 0) {
257-
struct net_if *iface = net_if_get_by_index(ll_addr->sll_ifindex);
258-
259-
if (iface == NULL) {
260-
errno = EDESTADDRREQ;
261-
return -1;
262-
}
263-
264-
net_context_set_iface(ctx, iface);
265-
}
266-
267-
/* Register the callback before sending in order to receive the response
268-
* from the peer.
269-
*/
270-
271-
status = net_context_recv(ctx, zpacket_received_cb, K_NO_WAIT,
272-
ctx->user_data);
273-
if (status < 0) {
274-
errno = -status;
275-
return -1;
276-
}
277-
278265
status = net_context_sendto(ctx, buf, len, dest_addr, addrlen,
279266
NULL, timeout, ctx->user_data);
280267
if (status < 0) {

0 commit comments

Comments
 (0)