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