1 /*
2 * Copyright (c) 2019 Intel Corporation
3 * Copyright (c) 2021 Nordic Semiconductor
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stdbool.h>
9 #include <zephyr/posix/fcntl.h>
10
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(net_sock_packet, CONFIG_NET_SOCKETS_LOG_LEVEL);
13
14 #include <zephyr/kernel.h>
15 #include <zephyr/drivers/entropy.h>
16 #include <zephyr/sys/util.h>
17 #include <zephyr/net/net_context.h>
18 #include <zephyr/net/net_pkt.h>
19 #include <zephyr/net/socket.h>
20 #include <zephyr/net/ethernet.h>
21 #include <zephyr/internal/syscall_handler.h>
22 #include <zephyr/sys/fdtable.h>
23
24 #include "../../ip/net_stats.h"
25
26 #include "sockets_internal.h"
27
28 extern const struct socket_op_vtable sock_fd_op_vtable;
29
30 static const struct socket_op_vtable packet_sock_fd_op_vtable;
31
k_fifo_wait_non_empty(struct k_fifo * fifo,k_timeout_t timeout)32 static inline int k_fifo_wait_non_empty(struct k_fifo *fifo,
33 k_timeout_t timeout)
34 {
35 struct k_poll_event events[] = {
36 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
37 K_POLL_MODE_NOTIFY_ONLY, fifo),
38 };
39
40 return k_poll(events, ARRAY_SIZE(events), timeout);
41 }
42
zpacket_received_cb(struct net_context * ctx,struct net_pkt * pkt,union net_ip_header * ip_hdr,union net_proto_header * proto_hdr,int status,void * user_data)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
zpacket_socket(int family,int type,int proto)80 static int zpacket_socket(int family, int type, int proto)
81 {
82 struct net_context *ctx;
83 int fd;
84 int ret;
85
86 fd = zvfs_reserve_fd();
87 if (fd < 0) {
88 return -1;
89 }
90
91 if (proto != 0) {
92 /* For example in Linux, the protocol parameter can be given
93 * as htons(ETH_P_ALL) to receive all the network packets.
94 * So convert the proto field back to host byte order so that
95 * we do not need to change the protocol field handling in
96 * other part of the network stack.
97 */
98 proto = ntohs(proto);
99 }
100
101 ret = net_context_get(family, type, proto, &ctx);
102 if (ret < 0) {
103 zvfs_free_fd(fd);
104 errno = -ret;
105 return -1;
106 }
107
108 /* Initialize user_data, all other calls will preserve it */
109 ctx->user_data = NULL;
110
111 /* recv_q and accept_q are in union */
112 k_fifo_init(&ctx->recv_q);
113
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;
124 }
125
126 zvfs_finalize_typed_fd(fd, ctx, (const struct fd_op_vtable *)&packet_sock_fd_op_vtable,
127 ZVFS_MODE_IFSOCK);
128
129 return fd;
130 }
131
zpacket_bind_ctx(struct net_context * ctx,const struct sockaddr * addr,socklen_t addrlen)132 static int zpacket_bind_ctx(struct net_context *ctx,
133 const struct sockaddr *addr,
134 socklen_t addrlen)
135 {
136 int ret = 0;
137
138 ret = net_context_bind(ctx, addr, addrlen);
139 if (ret < 0) {
140 errno = -ret;
141 return -1;
142 }
143
144 /* For packet socket, we expect to receive packets after call
145 * to bind().
146 */
147 ret = net_context_recv(ctx, zpacket_received_cb, K_NO_WAIT,
148 ctx->user_data);
149 if (ret < 0) {
150 errno = -ret;
151 return -1;
152 }
153
154 return 0;
155 }
156
zpacket_set_eth_pkttype(struct net_if * iface,struct sockaddr_ll * addr,struct net_linkaddr * lladdr)157 static void zpacket_set_eth_pkttype(struct net_if *iface,
158 struct sockaddr_ll *addr,
159 struct net_linkaddr *lladdr)
160 {
161 if (lladdr == NULL || lladdr->len == 0) {
162 return;
163 }
164
165 if (net_eth_is_addr_broadcast((struct net_eth_addr *)lladdr->addr)) {
166 addr->sll_pkttype = PACKET_BROADCAST;
167 } else if (net_eth_is_addr_multicast(
168 (struct net_eth_addr *)lladdr->addr)) {
169 addr->sll_pkttype = PACKET_MULTICAST;
170 } else if (!net_linkaddr_cmp(net_if_get_link_addr(iface), lladdr)) {
171 addr->sll_pkttype = PACKET_HOST;
172 } else {
173 addr->sll_pkttype = PACKET_OTHERHOST;
174 }
175 }
176
zpacket_set_source_addr(struct net_context * ctx,struct net_pkt * pkt,struct sockaddr * src_addr,socklen_t * addrlen)177 static void zpacket_set_source_addr(struct net_context *ctx,
178 struct net_pkt *pkt,
179 struct sockaddr *src_addr,
180 socklen_t *addrlen)
181 {
182 struct sockaddr_ll addr = {0};
183 struct net_if *iface = net_context_get_iface(ctx);
184
185 if (iface == NULL) {
186 return;
187 }
188
189 addr.sll_family = AF_PACKET;
190 addr.sll_ifindex = net_if_get_by_iface(iface);
191
192 if (net_pkt_is_l2_processed(pkt)) {
193 /* L2 has already processed the packet - can copy information
194 * directly from the net_pkt structure
195 */
196 addr.sll_halen = pkt->lladdr_src.len;
197 memcpy(addr.sll_addr, pkt->lladdr_src.addr,
198 MIN(sizeof(addr.sll_addr), pkt->lladdr_src.len));
199
200 addr.sll_protocol = htons(net_pkt_ll_proto_type(pkt));
201
202 if (net_if_get_link_addr(iface)->type == NET_LINK_ETHERNET) {
203 addr.sll_hatype = ARPHRD_ETHER;
204 zpacket_set_eth_pkttype(iface, &addr,
205 net_pkt_lladdr_dst(pkt));
206 }
207 } else if (net_if_get_link_addr(iface)->type == NET_LINK_ETHERNET) {
208 /* Need to extract information from the L2 header. Only
209 * Ethernet L2 supported currently.
210 */
211 struct net_eth_hdr *hdr;
212 struct net_linkaddr dst_addr;
213 struct net_pkt_cursor cur;
214
215 net_pkt_cursor_backup(pkt, &cur);
216 net_pkt_cursor_init(pkt);
217
218 hdr = NET_ETH_HDR(pkt);
219 if (hdr == NULL ||
220 pkt->buffer->len < sizeof(struct net_eth_hdr)) {
221 net_pkt_cursor_restore(pkt, &cur);
222 return;
223 }
224
225 addr.sll_halen = sizeof(struct net_eth_addr);
226 memcpy(addr.sll_addr, hdr->src.addr,
227 sizeof(struct net_eth_addr));
228
229 addr.sll_protocol = hdr->type;
230 addr.sll_hatype = ARPHRD_ETHER;
231
232 (void)net_linkaddr_create(&dst_addr, hdr->dst.addr,
233 sizeof(struct net_eth_addr),
234 NET_LINK_ETHERNET);
235
236 zpacket_set_eth_pkttype(iface, &addr, &dst_addr);
237 net_pkt_cursor_restore(pkt, &cur);
238 }
239
240 /* Copy the result sockaddr_ll structure into provided buffer. If the
241 * buffer is smaller than the structure size, it will be truncated.
242 */
243 memcpy(src_addr, &addr, MIN(sizeof(struct sockaddr_ll), *addrlen));
244 *addrlen = sizeof(struct sockaddr_ll);
245 }
246
zpacket_sendto_ctx(struct net_context * ctx,const void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)247 ssize_t zpacket_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
248 int flags, const struct sockaddr *dest_addr,
249 socklen_t addrlen)
250 {
251 k_timeout_t timeout = K_FOREVER;
252 int status;
253
254 if (!dest_addr) {
255 errno = EDESTADDRREQ;
256 return -1;
257 }
258
259 if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
260 timeout = K_NO_WAIT;
261 } else {
262 net_context_get_option(ctx, NET_OPT_SNDTIMEO, &timeout, NULL);
263 }
264
265 status = net_context_sendto(ctx, buf, len, dest_addr, addrlen,
266 NULL, timeout, ctx->user_data);
267 if (status < 0) {
268 errno = -status;
269 return -1;
270 }
271
272 return status;
273 }
274
zpacket_sendmsg_ctx(struct net_context * ctx,const struct msghdr * msg,int flags)275 ssize_t zpacket_sendmsg_ctx(struct net_context *ctx, const struct msghdr *msg,
276 int flags)
277 {
278 k_timeout_t timeout = K_FOREVER;
279 int status;
280
281 if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
282 timeout = K_NO_WAIT;
283 } else {
284 net_context_get_option(ctx, NET_OPT_SNDTIMEO, &timeout, NULL);
285 }
286
287 status = net_context_sendmsg(ctx, msg, flags, NULL, timeout, NULL);
288 if (status < 0) {
289 errno = -status;
290 return -1;
291 }
292
293 return status;
294 }
295
zpacket_recvfrom_ctx(struct net_context * ctx,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)296 ssize_t zpacket_recvfrom_ctx(struct net_context *ctx, void *buf, size_t max_len,
297 int flags, struct sockaddr *src_addr,
298 socklen_t *addrlen)
299 {
300 size_t recv_len = 0;
301 k_timeout_t timeout = K_FOREVER;
302 struct net_pkt *pkt;
303
304 if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
305 timeout = K_NO_WAIT;
306 } else {
307 net_context_get_option(ctx, NET_OPT_RCVTIMEO, &timeout, NULL);
308 }
309
310 if (flags & ZSOCK_MSG_PEEK) {
311 int res;
312
313 res = k_fifo_wait_non_empty(&ctx->recv_q, timeout);
314 /* EAGAIN when timeout expired, EINTR when cancelled */
315 if (res && res != -EAGAIN && res != -EINTR) {
316 errno = -res;
317 return -1;
318 }
319
320 pkt = k_fifo_peek_head(&ctx->recv_q);
321 } else {
322 pkt = k_fifo_get(&ctx->recv_q, timeout);
323 }
324
325 if (!pkt) {
326 errno = EAGAIN;
327 return -1;
328 }
329
330 /* We do not handle any headers here,
331 * just pass the whole packet to caller.
332 */
333 recv_len = net_pkt_get_len(pkt);
334 if (recv_len > max_len) {
335 recv_len = max_len;
336 }
337
338 if (net_pkt_read(pkt, buf, recv_len)) {
339 errno = ENOBUFS;
340 return -1;
341 }
342
343 if (src_addr && addrlen) {
344 zpacket_set_source_addr(ctx, pkt, src_addr, addrlen);
345 }
346
347 if ((IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS) ||
348 IS_ENABLED(CONFIG_TRACING_NET_CORE)) &&
349 !(flags & ZSOCK_MSG_PEEK)) {
350 net_socket_update_tc_rx_time(pkt, k_cycle_get_32());
351 }
352
353 if (!(flags & ZSOCK_MSG_PEEK)) {
354 net_pkt_unref(pkt);
355 } else {
356 net_pkt_cursor_init(pkt);
357 }
358
359 return recv_len;
360 }
361
zpacket_getsockopt_ctx(struct net_context * ctx,int level,int optname,void * optval,socklen_t * optlen)362 int zpacket_getsockopt_ctx(struct net_context *ctx, int level, int optname,
363 void *optval, socklen_t *optlen)
364 {
365 if (!optval || !optlen) {
366 errno = EINVAL;
367 return -1;
368 }
369
370 return sock_fd_op_vtable.getsockopt(ctx, level, optname,
371 optval, optlen);
372 }
373
zpacket_setsockopt_ctx(struct net_context * ctx,int level,int optname,const void * optval,socklen_t optlen)374 int zpacket_setsockopt_ctx(struct net_context *ctx, int level, int optname,
375 const void *optval, socklen_t optlen)
376 {
377 return sock_fd_op_vtable.setsockopt(ctx, level, optname,
378 optval, optlen);
379 }
380
packet_sock_read_vmeth(void * obj,void * buffer,size_t count)381 static ssize_t packet_sock_read_vmeth(void *obj, void *buffer, size_t count)
382 {
383 return zpacket_recvfrom_ctx(obj, buffer, count, 0, NULL, 0);
384 }
385
packet_sock_write_vmeth(void * obj,const void * buffer,size_t count)386 static ssize_t packet_sock_write_vmeth(void *obj, const void *buffer,
387 size_t count)
388 {
389 return zpacket_sendto_ctx(obj, buffer, count, 0, NULL, 0);
390 }
391
packet_sock_ioctl_vmeth(void * obj,unsigned int request,va_list args)392 static int packet_sock_ioctl_vmeth(void *obj, unsigned int request,
393 va_list args)
394 {
395 return sock_fd_op_vtable.fd_vtable.ioctl(obj, request, args);
396 }
397
398 /*
399 * TODO: A packet socket can be bound to a network device using SO_BINDTODEVICE.
400 */
packet_sock_bind_vmeth(void * obj,const struct sockaddr * addr,socklen_t addrlen)401 static int packet_sock_bind_vmeth(void *obj, const struct sockaddr *addr,
402 socklen_t addrlen)
403 {
404 return zpacket_bind_ctx(obj, addr, addrlen);
405 }
406
407 /* The connect() function is no longer necessary. */
packet_sock_connect_vmeth(void * obj,const struct sockaddr * addr,socklen_t addrlen)408 static int packet_sock_connect_vmeth(void *obj, const struct sockaddr *addr,
409 socklen_t addrlen)
410 {
411 return -EOPNOTSUPP;
412 }
413
414 /*
415 * The listen() and accept() functions are without any functionality,
416 * since the client-Server-Semantic is no longer present.
417 * When we use packet sockets we are sending unconnected packets.
418 */
packet_sock_listen_vmeth(void * obj,int backlog)419 static int packet_sock_listen_vmeth(void *obj, int backlog)
420 {
421 return -EOPNOTSUPP;
422 }
423
packet_sock_accept_vmeth(void * obj,struct sockaddr * addr,socklen_t * addrlen)424 static int packet_sock_accept_vmeth(void *obj, struct sockaddr *addr,
425 socklen_t *addrlen)
426 {
427 return -EOPNOTSUPP;
428 }
429
packet_sock_sendto_vmeth(void * obj,const void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)430 static ssize_t packet_sock_sendto_vmeth(void *obj, const void *buf, size_t len,
431 int flags,
432 const struct sockaddr *dest_addr,
433 socklen_t addrlen)
434 {
435 return zpacket_sendto_ctx(obj, buf, len, flags, dest_addr, addrlen);
436 }
437
packet_sock_sendmsg_vmeth(void * obj,const struct msghdr * msg,int flags)438 static ssize_t packet_sock_sendmsg_vmeth(void *obj, const struct msghdr *msg,
439 int flags)
440 {
441 return zpacket_sendmsg_ctx(obj, msg, flags);
442 }
443
packet_sock_recvfrom_vmeth(void * obj,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)444 static ssize_t packet_sock_recvfrom_vmeth(void *obj, void *buf, size_t max_len,
445 int flags, struct sockaddr *src_addr,
446 socklen_t *addrlen)
447 {
448 return zpacket_recvfrom_ctx(obj, buf, max_len, flags,
449 src_addr, addrlen);
450 }
451
packet_sock_getsockopt_vmeth(void * obj,int level,int optname,void * optval,socklen_t * optlen)452 static int packet_sock_getsockopt_vmeth(void *obj, int level, int optname,
453 void *optval, socklen_t *optlen)
454 {
455 return zpacket_getsockopt_ctx(obj, level, optname, optval, optlen);
456 }
457
packet_sock_setsockopt_vmeth(void * obj,int level,int optname,const void * optval,socklen_t optlen)458 static int packet_sock_setsockopt_vmeth(void *obj, int level, int optname,
459 const void *optval, socklen_t optlen)
460 {
461 return zpacket_setsockopt_ctx(obj, level, optname, optval, optlen);
462 }
463
packet_sock_close2_vmeth(void * obj,int fd)464 static int packet_sock_close2_vmeth(void *obj, int fd)
465 {
466 return zsock_close_ctx(obj, fd);
467 }
468
469 static const struct socket_op_vtable packet_sock_fd_op_vtable = {
470 .fd_vtable = {
471 .read = packet_sock_read_vmeth,
472 .write = packet_sock_write_vmeth,
473 .close2 = packet_sock_close2_vmeth,
474 .ioctl = packet_sock_ioctl_vmeth,
475 },
476 .bind = packet_sock_bind_vmeth,
477 .connect = packet_sock_connect_vmeth,
478 .listen = packet_sock_listen_vmeth,
479 .accept = packet_sock_accept_vmeth,
480 .sendto = packet_sock_sendto_vmeth,
481 .sendmsg = packet_sock_sendmsg_vmeth,
482 .recvfrom = packet_sock_recvfrom_vmeth,
483 .getsockopt = packet_sock_getsockopt_vmeth,
484 .setsockopt = packet_sock_setsockopt_vmeth,
485 };
486
packet_is_supported(int family,int type,int proto)487 static bool packet_is_supported(int family, int type, int proto)
488 {
489 switch (type) {
490 case SOCK_RAW:
491 proto = ntohs(proto);
492 return proto == 0
493 || proto == ETH_P_ALL
494 || proto == ETH_P_ECAT
495 || proto == ETH_P_IEEE802154;
496
497 case SOCK_DGRAM:
498 return true;
499
500 default:
501 return false;
502 }
503 }
504
505 NET_SOCKET_REGISTER(af_packet, NET_SOCKET_DEFAULT_PRIO, AF_PACKET,
506 packet_is_supported, zpacket_socket);
507