1 /**
2 * Copyright (c) 2023-2024 Marcin Niestroj
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 *
10 * Zephyr (top) side of NSOS (Native Simulator Offloaded Sockets).
11 */
12
13 #undef _POSIX_C_SOURCE
14 #define _POSIX_C_SOURCE 200809L
15
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(nsos_sockets);
18
19 #include <soc.h>
20 #include <string.h>
21 #include <zephyr/net/ethernet.h>
22 #include <zephyr/net/net_ip.h>
23 #include <zephyr/net/offloaded_netdev.h>
24 #include <zephyr/net/socket_offload.h>
25 #include <zephyr/posix/fcntl.h>
26 #include <zephyr/sys/fdtable.h>
27 #include <zephyr/sys/dlist.h>
28
29 #include "sockets_internal.h"
30 #include "nsos.h"
31 #include "nsos_errno.h"
32 #include "nsos_fcntl.h"
33 #include "nsos_netdb.h"
34 #include "nsos_socket.h"
35
36 #include "nsi_host_trampolines.h"
37
38 BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE > 0);
39
40 #define NSOS_IRQ_FLAGS (0)
41 #define NSOS_IRQ_PRIORITY (2)
42
43 struct nsos_socket;
44
45 struct nsos_socket_poll {
46 struct nsos_mid_pollfd mid;
47 struct k_poll_signal signal;
48
49 sys_dnode_t node;
50 };
51
52 struct nsos_socket {
53 int fd;
54
55 k_timeout_t recv_timeout;
56 k_timeout_t send_timeout;
57
58 struct nsos_socket_poll poll;
59 };
60
61 static sys_dlist_t nsos_polls = SYS_DLIST_STATIC_INIT(&nsos_polls);
62
socket_family_to_nsos_mid(int family,int * family_mid)63 static int socket_family_to_nsos_mid(int family, int *family_mid)
64 {
65 switch (family) {
66 case AF_UNSPEC:
67 *family_mid = NSOS_MID_AF_UNSPEC;
68 break;
69 case AF_INET:
70 *family_mid = NSOS_MID_AF_INET;
71 break;
72 case AF_INET6:
73 *family_mid = NSOS_MID_AF_INET6;
74 break;
75 case AF_UNIX:
76 *family_mid = NSOS_MID_AF_UNIX;
77 break;
78 case AF_PACKET:
79 *family_mid = NSOS_MID_AF_PACKET;
80 break;
81 default:
82 return -NSOS_MID_EAFNOSUPPORT;
83 }
84
85 return 0;
86 }
87
socket_proto_to_nsos_mid(int proto,int * proto_mid)88 static int socket_proto_to_nsos_mid(int proto, int *proto_mid)
89 {
90 switch (proto) {
91 case IPPROTO_IP:
92 *proto_mid = NSOS_MID_IPPROTO_IP;
93 break;
94 case IPPROTO_ICMP:
95 *proto_mid = NSOS_MID_IPPROTO_ICMP;
96 break;
97 case IPPROTO_IGMP:
98 *proto_mid = NSOS_MID_IPPROTO_IGMP;
99 break;
100 case IPPROTO_IPIP:
101 *proto_mid = NSOS_MID_IPPROTO_IPIP;
102 break;
103 case IPPROTO_TCP:
104 *proto_mid = NSOS_MID_IPPROTO_TCP;
105 break;
106 case IPPROTO_UDP:
107 *proto_mid = NSOS_MID_IPPROTO_UDP;
108 break;
109 case IPPROTO_IPV6:
110 *proto_mid = NSOS_MID_IPPROTO_IPV6;
111 break;
112 case IPPROTO_RAW:
113 *proto_mid = NSOS_MID_IPPROTO_RAW;
114 break;
115 case htons(IPPROTO_ETH_P_ALL):
116 *proto_mid = NSOS_MID_IPPROTO_ETH_P_ALL;
117 break;
118 default:
119 return -NSOS_MID_EPROTONOSUPPORT;
120 }
121
122 return 0;
123 }
124
socket_type_to_nsos_mid(int type,int * type_mid)125 static int socket_type_to_nsos_mid(int type, int *type_mid)
126 {
127 switch (type) {
128 case SOCK_STREAM:
129 *type_mid = NSOS_MID_SOCK_STREAM;
130 break;
131 case SOCK_DGRAM:
132 *type_mid = NSOS_MID_SOCK_DGRAM;
133 break;
134 case SOCK_RAW:
135 *type_mid = NSOS_MID_SOCK_RAW;
136 break;
137 default:
138 return -NSOS_MID_ESOCKTNOSUPPORT;
139 }
140
141 return 0;
142 }
143
socket_flags_to_nsos_mid(int flags)144 static int socket_flags_to_nsos_mid(int flags)
145 {
146 int flags_mid = 0;
147
148 nsos_socket_flag_convert(&flags, ZSOCK_MSG_PEEK,
149 &flags_mid, NSOS_MID_MSG_PEEK);
150 nsos_socket_flag_convert(&flags, ZSOCK_MSG_TRUNC,
151 &flags_mid, NSOS_MID_MSG_TRUNC);
152 nsos_socket_flag_convert(&flags, ZSOCK_MSG_DONTWAIT,
153 &flags_mid, NSOS_MID_MSG_DONTWAIT);
154 nsos_socket_flag_convert(&flags, ZSOCK_MSG_WAITALL,
155 &flags_mid, NSOS_MID_MSG_WAITALL);
156
157 if (flags != 0) {
158 return -NSOS_MID_EINVAL;
159 }
160
161 return flags_mid;
162 }
163
164 static const struct socket_op_vtable nsos_socket_fd_op_vtable;
165
nsos_socket_create(int family,int type,int proto)166 static int nsos_socket_create(int family, int type, int proto)
167 {
168 int fd;
169 struct nsos_socket *sock;
170 int family_mid;
171 int type_mid;
172 int proto_mid;
173 int err;
174
175 err = socket_family_to_nsos_mid(family, &family_mid);
176 if (err) {
177 errno = errno_from_nsos_mid(-err);
178 return -1;
179 }
180
181 err = socket_type_to_nsos_mid(type, &type_mid);
182 if (err) {
183 errno = errno_from_nsos_mid(-err);
184 return -1;
185 }
186
187 err = socket_proto_to_nsos_mid(proto, &proto_mid);
188 if (err) {
189 errno = errno_from_nsos_mid(-err);
190 return -1;
191 }
192
193 fd = zvfs_reserve_fd();
194 if (fd < 0) {
195 return -1;
196 }
197
198 sock = k_malloc(sizeof(*sock));
199 if (!sock) {
200 errno = ENOMEM;
201 goto free_fd;
202 }
203
204 sock->fd = fd;
205 sock->recv_timeout = K_FOREVER;
206 sock->send_timeout = K_FOREVER;
207
208 sock->poll.mid.fd = nsos_adapt_socket(family_mid, type_mid, proto_mid);
209 if (sock->poll.mid.fd < 0) {
210 errno = errno_from_nsos_mid(-sock->poll.mid.fd);
211 goto free_sock;
212 }
213
214 zvfs_finalize_typed_fd(fd, sock, &nsos_socket_fd_op_vtable.fd_vtable, ZVFS_MODE_IFSOCK);
215
216 return fd;
217
218 free_sock:
219 k_free(sock);
220
221 free_fd:
222 zvfs_free_fd(fd);
223
224 return -1;
225 }
226
nsos_adapt_get_zephyr_errno(void)227 static int nsos_adapt_get_zephyr_errno(void)
228 {
229 return errno_from_nsos_mid(nsos_adapt_get_errno());
230 }
231
nsos_read(void * obj,void * buf,size_t sz)232 static ssize_t nsos_read(void *obj, void *buf, size_t sz)
233 {
234 struct nsos_socket *sock = obj;
235 int ret;
236
237 ret = nsi_host_read(sock->poll.mid.fd, buf, sz);
238 if (ret < 0) {
239 errno = nsos_adapt_get_zephyr_errno();
240 }
241
242 return ret;
243 }
244
nsos_write(void * obj,const void * buf,size_t sz)245 static ssize_t nsos_write(void *obj, const void *buf, size_t sz)
246 {
247 struct nsos_socket *sock = obj;
248 int ret;
249
250 ret = nsi_host_write(sock->poll.mid.fd, buf, sz);
251 if (ret < 0) {
252 errno = nsos_adapt_get_zephyr_errno();
253 }
254
255 return ret;
256 }
257
nsos_close(void * obj)258 static int nsos_close(void *obj)
259 {
260 struct nsos_socket *sock = obj;
261 struct nsos_socket_poll *poll;
262 int ret;
263
264 ret = nsi_host_close(sock->poll.mid.fd);
265 if (ret < 0) {
266 errno = nsos_adapt_get_zephyr_errno();
267 }
268
269 SYS_DLIST_FOR_EACH_CONTAINER(&nsos_polls, poll, node) {
270 if (poll == &sock->poll) {
271 poll->mid.revents = ZSOCK_POLLHUP;
272 poll->mid.cb(&poll->mid);
273 }
274 }
275
276 k_free(sock);
277
278 return ret;
279 }
280
pollcb(struct nsos_mid_pollfd * mid)281 static void pollcb(struct nsos_mid_pollfd *mid)
282 {
283 struct nsos_socket_poll *poll = CONTAINER_OF(mid, struct nsos_socket_poll, mid);
284
285 k_poll_signal_raise(&poll->signal, poll->mid.revents);
286 }
287
nsos_poll_prepare(struct nsos_socket * sock,struct zsock_pollfd * pfd,struct k_poll_event ** pev,struct k_poll_event * pev_end,struct nsos_socket_poll * poll)288 static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd,
289 struct k_poll_event **pev, struct k_poll_event *pev_end,
290 struct nsos_socket_poll *poll)
291 {
292 unsigned int signaled;
293 int flags;
294
295 poll->mid.events = pfd->events;
296 poll->mid.revents = 0;
297 poll->mid.cb = pollcb;
298
299 if (*pev == pev_end) {
300 return -ENOMEM;
301 }
302
303 k_poll_signal_init(&poll->signal);
304 k_poll_event_init(*pev, K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &poll->signal);
305
306 sys_dlist_append(&nsos_polls, &poll->node);
307
308 nsos_adapt_poll_add(&poll->mid);
309
310 /* Let other sockets use another k_poll_event */
311 (*pev)++;
312
313 signaled = 0;
314 flags = 0;
315
316 k_poll_signal_check(&poll->signal, &signaled, &flags);
317 if (!signaled) {
318 return 0;
319 }
320
321 /* Events are ready, don't wait */
322 return -EALREADY;
323 }
324
nsos_poll_update(struct nsos_socket * sock,struct zsock_pollfd * pfd,struct k_poll_event ** pev,struct nsos_socket_poll * poll)325 static int nsos_poll_update(struct nsos_socket *sock, struct zsock_pollfd *pfd,
326 struct k_poll_event **pev, struct nsos_socket_poll *poll)
327 {
328 unsigned int signaled;
329 int flags;
330
331 (*pev)++;
332
333 signaled = 0;
334 flags = 0;
335
336 if (!sys_dnode_is_linked(&poll->node)) {
337 nsos_adapt_poll_update(&poll->mid);
338 return 0;
339 }
340
341 nsos_adapt_poll_remove(&poll->mid);
342 sys_dlist_remove(&poll->node);
343
344 k_poll_signal_check(&poll->signal, &signaled, &flags);
345 if (!signaled) {
346 return 0;
347 }
348
349 pfd->revents = flags;
350
351 return 0;
352 }
353
nsos_ioctl(void * obj,unsigned int request,va_list args)354 static int nsos_ioctl(void *obj, unsigned int request, va_list args)
355 {
356 struct nsos_socket *sock = obj;
357
358 switch (request) {
359 case ZFD_IOCTL_POLL_PREPARE: {
360 struct zsock_pollfd *pfd;
361 struct k_poll_event **pev;
362 struct k_poll_event *pev_end;
363
364 pfd = va_arg(args, struct zsock_pollfd *);
365 pev = va_arg(args, struct k_poll_event **);
366 pev_end = va_arg(args, struct k_poll_event *);
367
368 return nsos_poll_prepare(obj, pfd, pev, pev_end, &sock->poll);
369 }
370
371 case ZFD_IOCTL_POLL_UPDATE: {
372 struct zsock_pollfd *pfd;
373 struct k_poll_event **pev;
374
375 pfd = va_arg(args, struct zsock_pollfd *);
376 pev = va_arg(args, struct k_poll_event **);
377
378 return nsos_poll_update(obj, pfd, pev, &sock->poll);
379 }
380
381 case ZFD_IOCTL_POLL_OFFLOAD:
382 return -EOPNOTSUPP;
383
384 case F_GETFL: {
385 int flags;
386
387 flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd);
388
389 return fl_from_nsos_mid(flags);
390 }
391
392 case F_SETFL: {
393 int flags = va_arg(args, int);
394 int ret;
395
396 ret = fl_to_nsos_mid_strict(flags);
397 if (ret < 0) {
398 return -errno_from_nsos_mid(-ret);
399 }
400
401 ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, flags);
402
403 return -errno_from_nsos_mid(-ret);
404 }
405
406 case ZFD_IOCTL_FIONREAD: {
407 int *avail = va_arg(args, int *);
408 int ret;
409
410 ret = nsos_adapt_fionread(sock->poll.mid.fd, avail);
411
412 return -errno_from_nsos_mid(-ret);
413 }
414 }
415
416 return -EINVAL;
417 }
418
sockaddr_to_nsos_mid(const struct sockaddr * addr,socklen_t addrlen,struct nsos_mid_sockaddr ** addr_mid,size_t * addrlen_mid)419 static int sockaddr_to_nsos_mid(const struct sockaddr *addr, socklen_t addrlen,
420 struct nsos_mid_sockaddr **addr_mid, size_t *addrlen_mid)
421 {
422 if (!addr || !addrlen) {
423 *addr_mid = NULL;
424 *addrlen_mid = 0;
425
426 return 0;
427 }
428
429 switch (addr->sa_family) {
430 case AF_INET: {
431 const struct sockaddr_in *addr_in =
432 (const struct sockaddr_in *)addr;
433 struct nsos_mid_sockaddr_in *addr_in_mid =
434 (struct nsos_mid_sockaddr_in *)*addr_mid;
435
436 if (addrlen < sizeof(*addr_in)) {
437 return -NSOS_MID_EINVAL;
438 }
439
440 addr_in_mid->sin_family = NSOS_MID_AF_INET;
441 addr_in_mid->sin_port = addr_in->sin_port;
442 addr_in_mid->sin_addr = addr_in->sin_addr.s_addr;
443
444 *addrlen_mid = sizeof(*addr_in_mid);
445
446 return 0;
447 }
448 case AF_INET6: {
449 const struct sockaddr_in6 *addr_in =
450 (const struct sockaddr_in6 *)addr;
451 struct nsos_mid_sockaddr_in6 *addr_in_mid =
452 (struct nsos_mid_sockaddr_in6 *)*addr_mid;
453
454 if (addrlen < sizeof(*addr_in)) {
455 return -NSOS_MID_EINVAL;
456 }
457
458 addr_in_mid->sin6_family = NSOS_MID_AF_INET6;
459 addr_in_mid->sin6_port = addr_in->sin6_port;
460 memcpy(addr_in_mid->sin6_addr, addr_in->sin6_addr.s6_addr,
461 sizeof(addr_in_mid->sin6_addr));
462 addr_in_mid->sin6_scope_id = addr_in->sin6_scope_id;
463
464 *addrlen_mid = sizeof(*addr_in_mid);
465
466 return 0;
467 }
468 case AF_UNIX: {
469 const struct sockaddr_un *addr_un =
470 (const struct sockaddr_un *)addr;
471 struct nsos_mid_sockaddr_un *addr_un_mid =
472 (struct nsos_mid_sockaddr_un *)*addr_mid;
473
474 if (addrlen < sizeof(*addr_un)) {
475 return -NSOS_MID_EINVAL;
476 }
477
478 addr_un_mid->sun_family = NSOS_MID_AF_UNIX;
479 memcpy(addr_un_mid->sun_path, addr_un->sun_path,
480 sizeof(addr_un_mid->sun_path));
481
482 *addrlen_mid = sizeof(*addr_un_mid);
483
484 return 0;
485 }
486 case AF_PACKET: {
487 const struct sockaddr_ll *addr_ll =
488 (const struct sockaddr_ll *)addr;
489 struct nsos_mid_sockaddr_ll *addr_ll_mid =
490 (struct nsos_mid_sockaddr_ll *)*addr_mid;
491
492 if (addrlen < sizeof(*addr_ll)) {
493 return -NSOS_MID_EINVAL;
494 }
495
496 addr_ll_mid->sll_family = NSOS_MID_AF_UNIX;
497 addr_ll_mid->sll_protocol = addr_ll->sll_protocol;
498 addr_ll_mid->sll_ifindex = addr_ll->sll_ifindex;
499 addr_ll_mid->sll_hatype = addr_ll->sll_hatype;
500 addr_ll_mid->sll_pkttype = addr_ll->sll_pkttype;
501 addr_ll_mid->sll_halen = addr_ll->sll_halen;
502 memcpy(addr_ll_mid->sll_addr, addr_ll->sll_addr,
503 sizeof(addr_ll->sll_addr));
504
505 *addrlen_mid = sizeof(*addr_ll_mid);
506
507 return 0;
508 }
509 }
510
511 return -NSOS_MID_EINVAL;
512 }
513
sockaddr_from_nsos_mid(struct sockaddr * addr,socklen_t * addrlen,const struct nsos_mid_sockaddr * addr_mid,size_t addrlen_mid)514 static int sockaddr_from_nsos_mid(struct sockaddr *addr, socklen_t *addrlen,
515 const struct nsos_mid_sockaddr *addr_mid, size_t addrlen_mid)
516 {
517 if (!addr || !addrlen) {
518 return 0;
519 }
520
521 switch (addr_mid->sa_family) {
522 case NSOS_MID_AF_INET: {
523 const struct nsos_mid_sockaddr_in *addr_in_mid =
524 (const struct nsos_mid_sockaddr_in *)addr_mid;
525 struct sockaddr_in addr_in;
526
527 addr_in.sin_family = AF_INET;
528 addr_in.sin_port = addr_in_mid->sin_port;
529 addr_in.sin_addr.s_addr = addr_in_mid->sin_addr;
530
531 memcpy(addr, &addr_in, MIN(*addrlen, sizeof(addr_in)));
532 *addrlen = sizeof(addr_in);
533
534 return 0;
535 }
536 case NSOS_MID_AF_INET6: {
537 const struct nsos_mid_sockaddr_in6 *addr_in_mid =
538 (const struct nsos_mid_sockaddr_in6 *)addr_mid;
539 struct sockaddr_in6 addr_in;
540
541 addr_in.sin6_family = AF_INET6;
542 addr_in.sin6_port = addr_in_mid->sin6_port;
543 memcpy(addr_in.sin6_addr.s6_addr, addr_in_mid->sin6_addr,
544 sizeof(addr_in.sin6_addr.s6_addr));
545 addr_in.sin6_scope_id = addr_in_mid->sin6_scope_id;
546
547 memcpy(addr, &addr_in, MIN(*addrlen, sizeof(addr_in)));
548 *addrlen = sizeof(addr_in);
549
550 return 0;
551 }
552 }
553
554 return -NSOS_MID_EINVAL;
555 }
556
nsos_wait_for_poll(struct nsos_socket * sock,int events,k_timeout_t timeout)557 static int nsos_wait_for_poll(struct nsos_socket *sock, int events,
558 k_timeout_t timeout)
559 {
560 struct zsock_pollfd pfd = {
561 .fd = sock->fd,
562 .events = events,
563 };
564 struct k_poll_event poll_events[1];
565 struct k_poll_event *pev = poll_events;
566 struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events);
567 struct nsos_socket_poll socket_poll = {};
568 int ret;
569
570 ret = nsos_adapt_dup(sock->poll.mid.fd);
571 if (ret < 0) {
572 goto return_ret;
573 }
574
575 socket_poll.mid.fd = ret;
576
577 ret = nsos_poll_prepare(sock, &pfd, &pev, pev_end, &socket_poll);
578 if (ret == -EALREADY) {
579 ret = 0;
580 goto poll_update;
581 } else if (ret < 0) {
582 goto close_dup;
583 }
584
585 ret = k_poll(poll_events, ARRAY_SIZE(poll_events), timeout);
586 if (ret != 0 && ret != -EAGAIN && ret != -EINTR) {
587 goto poll_update;
588 }
589
590 ret = 0;
591
592 poll_update:
593 pev = poll_events;
594 nsos_poll_update(sock, &pfd, &pev, &socket_poll);
595
596 close_dup:
597 nsi_host_close(socket_poll.mid.fd);
598
599 return_ret:
600 if (ret < 0) {
601 return -errno_to_nsos_mid(-ret);
602 }
603
604 return 0;
605 }
606
nsos_poll_if_blocking(struct nsos_socket * sock,int events,k_timeout_t timeout,int flags)607 static int nsos_poll_if_blocking(struct nsos_socket *sock, int events,
608 k_timeout_t timeout, int flags)
609 {
610 int sock_flags;
611 bool non_blocking;
612
613 if (flags & ZSOCK_MSG_DONTWAIT) {
614 non_blocking = true;
615 } else {
616 sock_flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd);
617 non_blocking = sock_flags & NSOS_MID_O_NONBLOCK;
618 }
619
620 if (!non_blocking) {
621 return nsos_wait_for_poll(sock, events, timeout);
622 }
623
624 return 0;
625 }
626
nsos_bind(void * obj,const struct sockaddr * addr,socklen_t addrlen)627 static int nsos_bind(void *obj, const struct sockaddr *addr, socklen_t addrlen)
628 {
629 struct nsos_socket *sock = obj;
630 struct nsos_mid_sockaddr_storage addr_storage_mid;
631 struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid;
632 size_t addrlen_mid;
633 int ret;
634
635 ret = sockaddr_to_nsos_mid(addr, addrlen, &addr_mid, &addrlen_mid);
636 if (ret < 0) {
637 goto return_ret;
638 }
639
640 ret = nsos_adapt_bind(sock->poll.mid.fd, addr_mid, addrlen_mid);
641
642 return_ret:
643 if (ret < 0) {
644 errno = errno_from_nsos_mid(-ret);
645 return -1;
646 }
647
648 return ret;
649 }
650
nsos_connect_blocking(struct nsos_socket * sock,struct nsos_mid_sockaddr * addr_mid,size_t addrlen_mid,int fcntl_flags)651 static int nsos_connect_blocking(struct nsos_socket *sock,
652 struct nsos_mid_sockaddr *addr_mid,
653 size_t addrlen_mid,
654 int fcntl_flags)
655 {
656 int clear_nonblock_ret;
657 int ret;
658
659 ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, fcntl_flags | NSOS_MID_O_NONBLOCK);
660 if (ret < 0) {
661 return ret;
662 }
663
664 ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid);
665 if (ret == -NSOS_MID_EINPROGRESS) {
666 int so_err;
667 size_t so_err_len = sizeof(so_err);
668
669 ret = nsos_wait_for_poll(sock, ZSOCK_POLLOUT, sock->send_timeout);
670 if (ret < 0) {
671 goto clear_nonblock;
672 }
673
674 ret = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
675 NSOS_MID_SO_ERROR, &so_err, &so_err_len);
676 if (ret < 0) {
677 goto clear_nonblock;
678 }
679
680 ret = so_err;
681 }
682
683 clear_nonblock:
684 clear_nonblock_ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, fcntl_flags);
685 if (clear_nonblock_ret < 0) {
686 LOG_ERR("Failed to clear O_NONBLOCK: %d", clear_nonblock_ret);
687 }
688
689 return ret;
690 }
691
nsos_connect(void * obj,const struct sockaddr * addr,socklen_t addrlen)692 static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrlen)
693 {
694 struct nsos_socket *sock = obj;
695 struct nsos_mid_sockaddr_storage addr_storage_mid;
696 struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid;
697 size_t addrlen_mid;
698 int flags;
699 int ret;
700
701 ret = sockaddr_to_nsos_mid(addr, addrlen, &addr_mid, &addrlen_mid);
702 if (ret < 0) {
703 goto return_ret;
704 }
705
706 flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd);
707
708 if (flags & NSOS_MID_O_NONBLOCK) {
709 ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid);
710 } else {
711 ret = nsos_connect_blocking(sock, addr_mid, addrlen_mid, flags);
712 }
713
714 return_ret:
715 if (ret < 0) {
716 errno = errno_from_nsos_mid(-ret);
717 return -1;
718 }
719
720 return ret;
721 }
722
nsos_listen(void * obj,int backlog)723 static int nsos_listen(void *obj, int backlog)
724 {
725 struct nsos_socket *sock = obj;
726 int ret;
727
728 ret = nsos_adapt_listen(sock->poll.mid.fd, backlog);
729 if (ret < 0) {
730 errno = errno_from_nsos_mid(-ret);
731 return -1;
732 }
733
734 return ret;
735 }
736
nsos_accept(void * obj,struct sockaddr * addr,socklen_t * addrlen)737 static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen)
738 {
739 struct nsos_socket *accept_sock = obj;
740 struct nsos_mid_sockaddr_storage addr_storage_mid;
741 struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid;
742 size_t addrlen_mid = sizeof(addr_storage_mid);
743 int adapt_fd;
744 int zephyr_fd;
745 struct nsos_socket *conn_sock;
746 int ret;
747
748 ret = nsos_poll_if_blocking(accept_sock, ZSOCK_POLLIN,
749 accept_sock->recv_timeout, 0);
750 if (ret < 0) {
751 goto return_ret;
752 }
753
754 ret = nsos_adapt_accept(accept_sock->poll.mid.fd, addr_mid, &addrlen_mid);
755 if (ret < 0) {
756 goto return_ret;
757 }
758
759 adapt_fd = ret;
760
761 ret = sockaddr_from_nsos_mid(addr, addrlen, addr_mid, addrlen_mid);
762 if (ret < 0) {
763 goto close_adapt_fd;
764 }
765
766 zephyr_fd = zvfs_reserve_fd();
767 if (zephyr_fd < 0) {
768 ret = -errno_to_nsos_mid(-zephyr_fd);
769 goto close_adapt_fd;
770 }
771
772 conn_sock = k_malloc(sizeof(*conn_sock));
773 if (!conn_sock) {
774 ret = -NSOS_MID_ENOMEM;
775 goto free_zephyr_fd;
776 }
777
778 conn_sock->fd = zephyr_fd;
779 conn_sock->poll.mid.fd = adapt_fd;
780
781 zvfs_finalize_typed_fd(zephyr_fd, conn_sock, &nsos_socket_fd_op_vtable.fd_vtable,
782 ZVFS_MODE_IFSOCK);
783
784 return zephyr_fd;
785
786 free_zephyr_fd:
787 zvfs_free_fd(zephyr_fd);
788
789 close_adapt_fd:
790 nsi_host_close(adapt_fd);
791
792 return_ret:
793 errno = errno_from_nsos_mid(-ret);
794 return -1;
795 }
796
nsos_sendto(void * obj,const void * buf,size_t len,int flags,const struct sockaddr * addr,socklen_t addrlen)797 static ssize_t nsos_sendto(void *obj, const void *buf, size_t len, int flags,
798 const struct sockaddr *addr, socklen_t addrlen)
799 {
800 struct nsos_socket *sock = obj;
801 struct nsos_mid_sockaddr_storage addr_storage_mid;
802 struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid;
803 size_t addrlen_mid = sizeof(addr_storage_mid);
804 int flags_mid;
805 int ret;
806
807 ret = socket_flags_to_nsos_mid(flags);
808 if (ret < 0) {
809 goto return_ret;
810 }
811
812 flags_mid = ret;
813
814 ret = sockaddr_to_nsos_mid(addr, addrlen, &addr_mid, &addrlen_mid);
815 if (ret < 0) {
816 goto return_ret;
817 }
818
819 ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, sock->send_timeout, flags);
820 if (ret < 0) {
821 goto return_ret;
822 }
823
824 ret = nsos_adapt_sendto(sock->poll.mid.fd, buf, len, flags_mid,
825 addr_mid, addrlen_mid);
826
827 return_ret:
828 if (ret < 0) {
829 errno = errno_from_nsos_mid(-ret);
830 return -1;
831 }
832
833 return ret;
834 }
835
nsos_sendmsg(void * obj,const struct msghdr * msg,int flags)836 static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags)
837 {
838 struct nsos_socket *sock = obj;
839 struct nsos_mid_sockaddr_storage addr_storage_mid;
840 struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid;
841 size_t addrlen_mid = sizeof(addr_storage_mid);
842 struct nsos_mid_msghdr msg_mid;
843 struct nsos_mid_iovec *msg_iov;
844 int flags_mid;
845 int ret;
846
847 ret = socket_flags_to_nsos_mid(flags);
848 if (ret < 0) {
849 goto return_ret;
850 }
851
852 flags_mid = ret;
853
854 ret = sockaddr_to_nsos_mid(msg->msg_name, msg->msg_namelen, &addr_mid, &addrlen_mid);
855 if (ret < 0) {
856 goto return_ret;
857 }
858
859 msg_iov = k_calloc(msg->msg_iovlen, sizeof(*msg_iov));
860 if (!msg_iov) {
861 ret = -NSOS_MID_ENOMEM;
862 goto return_ret;
863 }
864
865 for (size_t i = 0; i < msg->msg_iovlen; i++) {
866 msg_iov[i].iov_base = msg->msg_iov[i].iov_base;
867 msg_iov[i].iov_len = msg->msg_iov[i].iov_len;
868 }
869
870 msg_mid.msg_name = addr_mid;
871 msg_mid.msg_namelen = addrlen_mid;
872 msg_mid.msg_iov = msg_iov;
873 msg_mid.msg_iovlen = msg->msg_iovlen;
874 msg_mid.msg_control = NULL;
875 msg_mid.msg_controllen = 0;
876 msg_mid.msg_flags = 0;
877
878 ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, sock->send_timeout, flags);
879 if (ret < 0) {
880 goto free_msg_iov;
881 }
882
883 ret = nsos_adapt_sendmsg(sock->poll.mid.fd, &msg_mid, flags_mid);
884
885 free_msg_iov:
886 k_free(msg_iov);
887
888 return_ret:
889 if (ret < 0) {
890 errno = errno_from_nsos_mid(-ret);
891 return -1;
892 }
893
894 return ret;
895 }
896
nsos_recvfrom(void * obj,void * buf,size_t len,int flags,struct sockaddr * addr,socklen_t * addrlen)897 static ssize_t nsos_recvfrom(void *obj, void *buf, size_t len, int flags,
898 struct sockaddr *addr, socklen_t *addrlen)
899 {
900 struct nsos_socket *sock = obj;
901 struct nsos_mid_sockaddr_storage addr_storage_mid;
902 struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid;
903 size_t addrlen_mid = sizeof(addr_storage_mid);
904 int flags_mid;
905 int ret;
906
907 ret = socket_flags_to_nsos_mid(flags);
908 if (ret < 0) {
909 goto return_ret;
910 }
911
912 flags_mid = ret;
913
914 ret = nsos_poll_if_blocking(sock, ZSOCK_POLLIN, sock->recv_timeout, flags);
915 if (ret < 0) {
916 goto return_ret;
917 }
918
919 ret = nsos_adapt_recvfrom(sock->poll.mid.fd, buf, len, flags_mid,
920 addr_mid, &addrlen_mid);
921 if (ret < 0) {
922 goto return_ret;
923 }
924
925 sockaddr_from_nsos_mid(addr, addrlen, addr_mid, addrlen_mid);
926
927 return_ret:
928 if (ret < 0) {
929 errno = errno_from_nsos_mid(-ret);
930 return -1;
931 }
932
933 return ret;
934 }
935
nsos_recvmsg(void * obj,struct msghdr * msg,int flags)936 static ssize_t nsos_recvmsg(void *obj, struct msghdr *msg, int flags)
937 {
938 errno = ENOTSUP;
939 return -1;
940 }
941
socket_type_from_nsos_mid(int type_mid,int * type)942 static int socket_type_from_nsos_mid(int type_mid, int *type)
943 {
944 switch (type_mid) {
945 case NSOS_MID_SOCK_STREAM:
946 *type = SOCK_STREAM;
947 break;
948 case NSOS_MID_SOCK_DGRAM:
949 *type = SOCK_DGRAM;
950 break;
951 case NSOS_MID_SOCK_RAW:
952 *type = SOCK_RAW;
953 break;
954 default:
955 return -NSOS_MID_ESOCKTNOSUPPORT;
956 }
957
958 return 0;
959 }
960
socket_proto_from_nsos_mid(int proto_mid,int * proto)961 static int socket_proto_from_nsos_mid(int proto_mid, int *proto)
962 {
963 switch (proto_mid) {
964 case NSOS_MID_IPPROTO_IP:
965 *proto = IPPROTO_IP;
966 break;
967 case NSOS_MID_IPPROTO_ICMP:
968 *proto = IPPROTO_ICMP;
969 break;
970 case NSOS_MID_IPPROTO_IGMP:
971 *proto = IPPROTO_IGMP;
972 break;
973 case NSOS_MID_IPPROTO_IPIP:
974 *proto = IPPROTO_IPIP;
975 break;
976 case NSOS_MID_IPPROTO_TCP:
977 *proto = IPPROTO_TCP;
978 break;
979 case NSOS_MID_IPPROTO_UDP:
980 *proto = IPPROTO_UDP;
981 break;
982 case NSOS_MID_IPPROTO_IPV6:
983 *proto = IPPROTO_IPV6;
984 break;
985 case NSOS_MID_IPPROTO_RAW:
986 *proto = IPPROTO_RAW;
987 break;
988 case NSOS_MID_IPPROTO_ETH_P_ALL:
989 *proto = htons(IPPROTO_ETH_P_ALL);
990 break;
991 default:
992 return -NSOS_MID_EPROTONOSUPPORT;
993 }
994
995 return 0;
996 }
997
socket_family_from_nsos_mid(int family_mid,int * family)998 static int socket_family_from_nsos_mid(int family_mid, int *family)
999 {
1000 switch (family_mid) {
1001 case NSOS_MID_AF_UNSPEC:
1002 *family = AF_UNSPEC;
1003 break;
1004 case NSOS_MID_AF_INET:
1005 *family = AF_INET;
1006 break;
1007 case NSOS_MID_AF_INET6:
1008 *family = AF_INET6;
1009 break;
1010 case NSOS_MID_AF_UNIX:
1011 *family = AF_UNIX;
1012 break;
1013 case NSOS_MID_AF_PACKET:
1014 *family = AF_PACKET;
1015 break;
1016 default:
1017 return -NSOS_MID_EAFNOSUPPORT;
1018 }
1019
1020 return 0;
1021 }
1022
nsos_getsockopt_int(struct nsos_socket * sock,int nsos_mid_level,int nsos_mid_optname,void * optval,socklen_t * optlen)1023 static int nsos_getsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int nsos_mid_optname,
1024 void *optval, socklen_t *optlen)
1025 {
1026 size_t nsos_mid_optlen = sizeof(int);
1027 int err;
1028
1029 if (*optlen != sizeof(int)) {
1030 errno = EINVAL;
1031 return -1;
1032 }
1033
1034 err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1035 NSOS_MID_SO_KEEPALIVE, optval, &nsos_mid_optlen);
1036 if (err) {
1037 errno = errno_from_nsos_mid(-err);
1038 return -1;
1039 }
1040
1041 *optlen = nsos_mid_optlen;
1042
1043 return 0;
1044 }
1045
nsos_getsockopt(void * obj,int level,int optname,void * optval,socklen_t * optlen)1046 static int nsos_getsockopt(void *obj, int level, int optname,
1047 void *optval, socklen_t *optlen)
1048 {
1049 struct nsos_socket *sock = obj;
1050
1051 switch (level) {
1052 case SOL_SOCKET:
1053 switch (optname) {
1054 case SO_ERROR: {
1055 int nsos_mid_err;
1056 int err;
1057
1058 if (*optlen != sizeof(int)) {
1059 errno = EINVAL;
1060 return -1;
1061 }
1062
1063 err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1064 NSOS_MID_SO_ERROR, &nsos_mid_err, NULL);
1065 if (err) {
1066 errno = errno_from_nsos_mid(-err);
1067 return -1;
1068 }
1069
1070 *(int *)optval = errno_from_nsos_mid(nsos_mid_err);
1071
1072 return 0;
1073 }
1074 case SO_TYPE: {
1075 int nsos_mid_type;
1076 int err;
1077
1078 if (*optlen != sizeof(nsos_mid_type)) {
1079 errno = EINVAL;
1080 return -1;
1081 }
1082
1083 err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1084 NSOS_MID_SO_TYPE, &nsos_mid_type, NULL);
1085 if (err) {
1086 errno = errno_from_nsos_mid(-err);
1087 return -1;
1088 }
1089
1090 err = socket_type_from_nsos_mid(nsos_mid_type, optval);
1091 if (err) {
1092 errno = errno_from_nsos_mid(-err);
1093 return -1;
1094 }
1095
1096 return 0;
1097 }
1098 case SO_PROTOCOL: {
1099 int nsos_mid_proto;
1100 int err;
1101
1102 if (*optlen != sizeof(nsos_mid_proto)) {
1103 errno = EINVAL;
1104 return -1;
1105 }
1106
1107 err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1108 NSOS_MID_SO_PROTOCOL, &nsos_mid_proto, NULL);
1109 if (err) {
1110 errno = errno_from_nsos_mid(-err);
1111 return -1;
1112 }
1113
1114 err = socket_proto_from_nsos_mid(nsos_mid_proto, optval);
1115 if (err) {
1116 errno = errno_from_nsos_mid(-err);
1117 return -1;
1118 }
1119
1120 return 0;
1121 }
1122 case SO_DOMAIN: {
1123 int nsos_mid_family;
1124 int err;
1125
1126 if (*optlen != sizeof(nsos_mid_family)) {
1127 errno = EINVAL;
1128 return -1;
1129 }
1130
1131 err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1132 NSOS_MID_SO_DOMAIN, &nsos_mid_family, NULL);
1133 if (err) {
1134 errno = errno_from_nsos_mid(-err);
1135 return -1;
1136 }
1137
1138 err = socket_family_from_nsos_mid(nsos_mid_family, optval);
1139 if (err) {
1140 errno = errno_from_nsos_mid(-err);
1141 return -1;
1142 }
1143
1144 return 0;
1145 }
1146 case SO_RCVBUF:
1147 return nsos_getsockopt_int(sock,
1148 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVBUF,
1149 optval, optlen);
1150 case SO_SNDBUF:
1151 return nsos_getsockopt_int(sock,
1152 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_SNDBUF,
1153 optval, optlen);
1154 case SO_REUSEADDR:
1155 return nsos_getsockopt_int(sock,
1156 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEADDR,
1157 optval, optlen);
1158 case SO_REUSEPORT:
1159 return nsos_getsockopt_int(sock,
1160 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEPORT,
1161 optval, optlen);
1162 case SO_KEEPALIVE:
1163 return nsos_getsockopt_int(sock,
1164 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE,
1165 optval, optlen);
1166 }
1167 break;
1168
1169 case IPPROTO_TCP:
1170 switch (optname) {
1171 case TCP_NODELAY:
1172 return nsos_getsockopt_int(sock,
1173 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_NODELAY,
1174 optval, optlen);
1175 case TCP_KEEPIDLE:
1176 return nsos_getsockopt_int(sock,
1177 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPIDLE,
1178 optval, optlen);
1179 case TCP_KEEPINTVL:
1180 return nsos_getsockopt_int(sock,
1181 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPINTVL,
1182 optval, optlen);
1183 case TCP_KEEPCNT:
1184 return nsos_getsockopt_int(sock,
1185 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT,
1186 optval, optlen);
1187 }
1188 break;
1189
1190 case IPPROTO_IPV6:
1191 switch (optname) {
1192 case IPV6_V6ONLY:
1193 return nsos_getsockopt_int(sock,
1194 NSOS_MID_IPPROTO_IPV6, NSOS_MID_IPV6_V6ONLY,
1195 optval, optlen);
1196 }
1197 break;
1198 }
1199
1200 errno = EOPNOTSUPP;
1201 return -1;
1202 }
1203
nsos_setsockopt_int(struct nsos_socket * sock,int nsos_mid_level,int nsos_mid_optname,const void * optval,socklen_t optlen)1204 static int nsos_setsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int nsos_mid_optname,
1205 const void *optval, socklen_t optlen)
1206 {
1207 int err;
1208
1209 if (optlen != sizeof(int)) {
1210 errno = EINVAL;
1211 return -1;
1212 }
1213
1214 err = nsos_adapt_setsockopt(sock->poll.mid.fd, nsos_mid_level, nsos_mid_optname,
1215 optval, optlen);
1216 if (err) {
1217 errno = errno_from_nsos_mid(-err);
1218 return -1;
1219 }
1220
1221 return 0;
1222 }
1223
nsos_setsockopt(void * obj,int level,int optname,const void * optval,socklen_t optlen)1224 static int nsos_setsockopt(void *obj, int level, int optname,
1225 const void *optval, socklen_t optlen)
1226 {
1227 struct nsos_socket *sock = obj;
1228
1229 switch (level) {
1230 case SOL_SOCKET:
1231 switch (optname) {
1232 case SO_PRIORITY: {
1233 int nsos_mid_priority;
1234 int err;
1235
1236 if (optlen != sizeof(uint8_t)) {
1237 errno = EINVAL;
1238 return -1;
1239 }
1240
1241 nsos_mid_priority = *(uint8_t *)optval;
1242
1243 err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1244 NSOS_MID_SO_PRIORITY, &nsos_mid_priority,
1245 sizeof(nsos_mid_priority));
1246 if (err) {
1247 errno = errno_from_nsos_mid(-err);
1248 return -1;
1249 }
1250
1251 return 0;
1252 }
1253 case SO_RCVTIMEO: {
1254 const struct zsock_timeval *tv = optval;
1255 struct nsos_mid_timeval nsos_mid_tv;
1256 int err;
1257
1258 if (optlen != sizeof(struct zsock_timeval)) {
1259 errno = EINVAL;
1260 return -1;
1261 }
1262
1263 nsos_mid_tv.tv_sec = tv->tv_sec;
1264 nsos_mid_tv.tv_usec = tv->tv_usec;
1265
1266 err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1267 NSOS_MID_SO_RCVTIMEO, &nsos_mid_tv,
1268 sizeof(nsos_mid_tv));
1269 if (err) {
1270 errno = errno_from_nsos_mid(-err);
1271 return -1;
1272 }
1273
1274 if (tv->tv_sec == 0 && tv->tv_usec == 0) {
1275 sock->recv_timeout = K_FOREVER;
1276 } else {
1277 sock->recv_timeout = K_USEC(tv->tv_sec * 1000000LL + tv->tv_usec);
1278 }
1279
1280 return 0;
1281 }
1282 case SO_SNDTIMEO: {
1283 const struct zsock_timeval *tv = optval;
1284 struct nsos_mid_timeval nsos_mid_tv;
1285 int err;
1286
1287 if (optlen != sizeof(struct zsock_timeval)) {
1288 errno = EINVAL;
1289 return -1;
1290 }
1291
1292 nsos_mid_tv.tv_sec = tv->tv_sec;
1293 nsos_mid_tv.tv_usec = tv->tv_usec;
1294
1295 err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET,
1296 NSOS_MID_SO_SNDTIMEO, &nsos_mid_tv,
1297 sizeof(nsos_mid_tv));
1298 if (err) {
1299 errno = errno_from_nsos_mid(-err);
1300 return -1;
1301 }
1302
1303 if (tv->tv_sec == 0 && tv->tv_usec == 0) {
1304 sock->send_timeout = K_FOREVER;
1305 } else {
1306 sock->send_timeout = K_USEC(tv->tv_sec * 1000000LL + tv->tv_usec);
1307 }
1308
1309 return 0;
1310 }
1311 case SO_RCVBUF:
1312 return nsos_setsockopt_int(sock,
1313 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVBUF,
1314 optval, optlen);
1315 case SO_SNDBUF:
1316 return nsos_setsockopt_int(sock,
1317 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_SNDBUF,
1318 optval, optlen);
1319 case SO_REUSEADDR:
1320 return nsos_setsockopt_int(sock,
1321 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEADDR,
1322 optval, optlen);
1323 case SO_REUSEPORT:
1324 return nsos_setsockopt_int(sock,
1325 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEPORT,
1326 optval, optlen);
1327 case SO_LINGER:
1328 return nsos_setsockopt_int(sock,
1329 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_LINGER,
1330 optval, optlen);
1331 case SO_KEEPALIVE:
1332 return nsos_setsockopt_int(sock,
1333 NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE,
1334 optval, optlen);
1335 }
1336 break;
1337
1338 case IPPROTO_TCP:
1339 switch (optname) {
1340 case TCP_NODELAY:
1341 return nsos_setsockopt_int(sock,
1342 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_NODELAY,
1343 optval, optlen);
1344 case TCP_KEEPIDLE:
1345 return nsos_setsockopt_int(sock,
1346 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPIDLE,
1347 optval, optlen);
1348 case TCP_KEEPINTVL:
1349 return nsos_setsockopt_int(sock,
1350 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPINTVL,
1351 optval, optlen);
1352 case TCP_KEEPCNT:
1353 return nsos_setsockopt_int(sock,
1354 NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT,
1355 optval, optlen);
1356 }
1357 break;
1358
1359 case IPPROTO_IPV6:
1360 switch (optname) {
1361 case IPV6_V6ONLY:
1362 return nsos_setsockopt_int(sock,
1363 NSOS_MID_IPPROTO_IPV6, NSOS_MID_IPV6_V6ONLY,
1364 optval, optlen);
1365 }
1366 break;
1367 }
1368
1369 errno = EOPNOTSUPP;
1370 return -1;
1371 }
1372
1373 static const struct socket_op_vtable nsos_socket_fd_op_vtable = {
1374 .fd_vtable = {
1375 .read = nsos_read,
1376 .write = nsos_write,
1377 .close = nsos_close,
1378 .ioctl = nsos_ioctl,
1379 },
1380 .bind = nsos_bind,
1381 .connect = nsos_connect,
1382 .listen = nsos_listen,
1383 .accept = nsos_accept,
1384 .sendto = nsos_sendto,
1385 .sendmsg = nsos_sendmsg,
1386 .recvfrom = nsos_recvfrom,
1387 .recvmsg = nsos_recvmsg,
1388 .getsockopt = nsos_getsockopt,
1389 .setsockopt = nsos_setsockopt,
1390 };
1391
nsos_is_supported(int family,int type,int proto)1392 static bool nsos_is_supported(int family, int type, int proto)
1393 {
1394 int dummy;
1395 int err;
1396
1397 err = socket_family_to_nsos_mid(family, &dummy);
1398 if (err) {
1399 return false;
1400 }
1401
1402 err = socket_type_to_nsos_mid(type, &dummy);
1403 if (err) {
1404 return false;
1405 }
1406
1407 err = socket_proto_to_nsos_mid(proto, &dummy);
1408 if (err) {
1409 return false;
1410 }
1411
1412 return true;
1413 }
1414
1415 NET_SOCKET_OFFLOAD_REGISTER(nsos, CONFIG_NET_SOCKETS_OFFLOAD_PRIORITY, AF_UNSPEC,
1416 nsos_is_supported, nsos_socket_create);
1417
1418 struct zsock_addrinfo_wrap {
1419 struct zsock_addrinfo addrinfo;
1420 struct sockaddr_storage addr_storage;
1421 struct nsos_mid_addrinfo *addrinfo_mid;
1422 };
1423
1424 /*
1425 * (Zephyr)
1426 * zsock_addrinfo_wrap
1427 * -----------------------
1428 * | zsock_addrinfo |
1429 * ----------------------- (trampoline)
1430 * | sockaddr_storage | nsos_addrinfo_wrap
1431 * ----------------------- -----------------------------
1432 * | nsos_mid_addrinfo * | -> | nsos_mid_addrinfo |
1433 * ----------------------- -----------------------------
1434 * | nsos_mid_sockaddr_storage |
1435 * ----------------------------- (Linux host)
1436 * | addrinfo * | -> addrinfo
1437 * -----------------------------
1438 */
1439
addrinfo_from_nsos_mid(struct nsos_mid_addrinfo * nsos_res,struct zsock_addrinfo ** res)1440 static int addrinfo_from_nsos_mid(struct nsos_mid_addrinfo *nsos_res,
1441 struct zsock_addrinfo **res)
1442 {
1443 struct zsock_addrinfo_wrap *res_wraps;
1444 size_t idx_res = 0;
1445 size_t n_res = 0;
1446
1447 for (struct nsos_mid_addrinfo *res_p = nsos_res; res_p; res_p = res_p->ai_next) {
1448 n_res++;
1449 }
1450
1451 if (n_res == 0) {
1452 return 0;
1453 }
1454
1455 res_wraps = k_calloc(n_res, sizeof(*res_wraps));
1456 if (!res_wraps) {
1457 return -ENOMEM;
1458 }
1459
1460 for (struct nsos_mid_addrinfo *res_p = nsos_res; res_p; res_p = res_p->ai_next, idx_res++) {
1461 struct zsock_addrinfo_wrap *wrap = &res_wraps[idx_res];
1462
1463 wrap->addrinfo_mid = res_p;
1464
1465 wrap->addrinfo.ai_flags = res_p->ai_flags;
1466 wrap->addrinfo.ai_family = res_p->ai_family;
1467 wrap->addrinfo.ai_socktype = res_p->ai_socktype;
1468 wrap->addrinfo.ai_protocol = res_p->ai_protocol;
1469
1470 wrap->addrinfo.ai_addr =
1471 (struct sockaddr *)&wrap->addr_storage;
1472 wrap->addrinfo.ai_addrlen = sizeof(wrap->addr_storage);
1473
1474 sockaddr_from_nsos_mid(wrap->addrinfo.ai_addr, &wrap->addrinfo.ai_addrlen,
1475 res_p->ai_addr, res_p->ai_addrlen);
1476
1477 wrap->addrinfo.ai_canonname =
1478 res_p->ai_canonname ? strdup(res_p->ai_canonname) : NULL;
1479 wrap->addrinfo.ai_next = &wrap[1].addrinfo;
1480 }
1481
1482 res_wraps[n_res - 1].addrinfo.ai_next = NULL;
1483
1484 *res = &res_wraps->addrinfo;
1485
1486 return 0;
1487 }
1488
nsos_getaddrinfo(const char * node,const char * service,const struct zsock_addrinfo * hints,struct zsock_addrinfo ** res)1489 static int nsos_getaddrinfo(const char *node, const char *service,
1490 const struct zsock_addrinfo *hints,
1491 struct zsock_addrinfo **res)
1492 {
1493 struct nsos_mid_addrinfo hints_mid;
1494 struct nsos_mid_addrinfo *res_mid;
1495 int system_errno;
1496 int ret;
1497
1498 if (!res) {
1499 return -EINVAL;
1500 }
1501
1502 if (hints) {
1503 hints_mid.ai_flags = hints->ai_flags;
1504 hints_mid.ai_family = hints->ai_family;
1505 hints_mid.ai_socktype = hints->ai_socktype;
1506 hints_mid.ai_protocol = hints->ai_protocol;
1507 }
1508
1509 ret = nsos_adapt_getaddrinfo(node, service,
1510 hints ? &hints_mid : NULL,
1511 &res_mid,
1512 &system_errno);
1513 if (ret < 0) {
1514 if (ret == NSOS_MID_EAI_SYSTEM) {
1515 errno = errno_from_nsos_mid(system_errno);
1516 }
1517
1518 return eai_from_nsos_mid(ret);
1519 }
1520
1521 ret = addrinfo_from_nsos_mid(res_mid, res);
1522 if (ret < 0) {
1523 errno = -ret;
1524 return DNS_EAI_SYSTEM;
1525 }
1526
1527 return ret;
1528 }
1529
nsos_freeaddrinfo(struct zsock_addrinfo * res)1530 static void nsos_freeaddrinfo(struct zsock_addrinfo *res)
1531 {
1532 struct zsock_addrinfo_wrap *wrap =
1533 CONTAINER_OF(res, struct zsock_addrinfo_wrap, addrinfo);
1534
1535 for (struct zsock_addrinfo *res_p = res; res_p; res_p = res_p->ai_next) {
1536 free(res_p->ai_canonname);
1537 }
1538
1539 nsos_adapt_freeaddrinfo(wrap->addrinfo_mid);
1540 k_free(wrap);
1541 }
1542
1543 static const struct socket_dns_offload nsos_dns_ops = {
1544 .getaddrinfo = nsos_getaddrinfo,
1545 .freeaddrinfo = nsos_freeaddrinfo,
1546 };
1547
nsos_isr(const void * obj)1548 static void nsos_isr(const void *obj)
1549 {
1550 struct nsos_socket_poll *poll;
1551
1552 SYS_DLIST_FOR_EACH_CONTAINER(&nsos_polls, poll, node) {
1553 if (poll->mid.revents) {
1554 poll->mid.cb(&poll->mid);
1555 }
1556 }
1557 }
1558
nsos_socket_offload_init(const struct device * arg)1559 static int nsos_socket_offload_init(const struct device *arg)
1560 {
1561 ARG_UNUSED(arg);
1562
1563 IRQ_CONNECT(NSOS_IRQ, NSOS_IRQ_PRIORITY,
1564 nsos_isr, NULL, NSOS_IRQ_FLAGS);
1565 irq_enable(NSOS_IRQ);
1566
1567 return 0;
1568 }
1569
nsos_iface_api_init(struct net_if * iface)1570 static void nsos_iface_api_init(struct net_if *iface)
1571 {
1572 iface->if_dev->socket_offload = nsos_socket_create;
1573
1574 socket_offload_dns_register(&nsos_dns_ops);
1575 }
1576
nsos_iface_enable(const struct net_if * iface,bool enabled)1577 static int nsos_iface_enable(const struct net_if *iface, bool enabled)
1578 {
1579 ARG_UNUSED(iface);
1580 ARG_UNUSED(enabled);
1581 return 0;
1582 }
1583
1584 static struct offloaded_if_api nsos_iface_offload_api = {
1585 .iface_api.init = nsos_iface_api_init,
1586 .enable = nsos_iface_enable,
1587 };
1588
1589 NET_DEVICE_OFFLOAD_INIT(nsos_socket, "nsos_socket",
1590 nsos_socket_offload_init,
1591 NULL,
1592 NULL, NULL,
1593 0, &nsos_iface_offload_api, NET_ETH_MTU);
1594