diff --git a/arch/sim/src/sim/posix/sim_hostusrsock.c b/arch/sim/src/sim/posix/sim_hostusrsock.c index 4ba0fb0dafa..52cd495ecad 100644 --- a/arch/sim/src/sim/posix/sim_hostusrsock.c +++ b/arch/sim/src/sim/posix/sim_hostusrsock.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include "sim_internal.h" #include "sim_hostusrsock.h" @@ -92,26 +94,93 @@ static void host_usrsock_set_fd(int fd, fd_set *fds) } } -static void sockaddr_to_native(const struct nuttx_sockaddr *addr, - const nuttx_socklen_t addrlen, - struct sockaddr *naddr, - socklen_t *naddrlen) +static int sockaddr_to_native(const struct nuttx_sockaddr *addr, + nuttx_socklen_t addrlen, + struct sockaddr_storage *naddr, + socklen_t *naddrlen) { - naddr->sa_family = addr->sa_family; - memcpy(naddr->sa_data, addr->sa_data, sizeof(naddr->sa_data)); + if (addr == NULL || naddr == NULL || naddrlen == NULL) + { + return -EINVAL; + } + memset(naddr, 0, sizeof(*naddr)); + + if (addr->sa_family == NUTTX_AF_LOCAL) + { + const struct nuttx_sockaddr_un *un = + (const struct nuttx_sockaddr_un *)addr; + struct sockaddr_un *native = (struct sockaddr_un *)naddr; + size_t pathlen; + + if (addrlen < offsetof(struct nuttx_sockaddr_un, sun_path) + 1) + { + return -EINVAL; + } + + pathlen = strnlen(un->sun_path, sizeof(un->sun_path)); + if (pathlen >= sizeof(native->sun_path)) + { + return -ENAMETOOLONG; + } + + native->sun_family = AF_UNIX; + memcpy(native->sun_path, un->sun_path, pathlen + 1); + *naddrlen = offsetof(struct sockaddr_un, sun_path) + pathlen + 1; + + return 0; + } + + if (addrlen > sizeof(*naddr)) + { + return -ENOSPC; + } + + memcpy(naddr, addr, addrlen); *naddrlen = addrlen; + + return 0; } -static void sockaddr_to_nuttx(const struct sockaddr *naddr, - const socklen_t naddrlen, - struct nuttx_sockaddr *addr, - nuttx_socklen_t *addrlen) +static int sockaddr_to_nuttx(const struct sockaddr_storage *naddr, + socklen_t naddrlen, + struct nuttx_sockaddr *addr, + nuttx_socklen_t *addrlen) { - addr->sa_family = naddr->sa_family; - memcpy(addr->sa_data, naddr->sa_data, sizeof(addr->sa_data)); + if (naddr == NULL || addr == NULL || addrlen == NULL) + { + return -EINVAL; + } + if (naddr->ss_family == AF_UNIX) + { + const struct sockaddr_un *native = (const struct sockaddr_un *)naddr; + struct nuttx_sockaddr_un *un = (struct nuttx_sockaddr_un *)addr; + size_t pathlen; + + if (*addrlen < sizeof(*un)) + { + return -ENOSPC; + } + + memset(un, 0, sizeof(*un)); + pathlen = strnlen(native->sun_path, sizeof(native->sun_path)); + un->sun_family = NUTTX_AF_LOCAL; + memcpy(un->sun_path, native->sun_path, pathlen); + *addrlen = offsetof(struct nuttx_sockaddr_un, sun_path) + pathlen + 1; + + return 0; + } + + if (*addrlen < naddrlen) + { + return -ENOSPC; + } + + memcpy(addr, naddr, naddrlen); *addrlen = naddrlen; + + return 0; } static void sock_nonblock(int socket, int enable) @@ -248,33 +317,68 @@ static int host_usrsock_sockopt(int sockfd, int level, int optname, int host_usrsock_socket(int domain, int type, int protocol) { int opt = 1; + int sockflags = 0; int ret; - if (domain == NUTTX_PF_INET) + switch (domain) { - domain = PF_INET; - } - else - { - return -EINVAL; + case NUTTX_PF_INET: + domain = PF_INET; + break; + +#ifdef CONFIG_NET_IPv6 + case NUTTX_PF_INET6: + domain = PF_INET6; + break; +#endif + + case NUTTX_PF_LOCAL: + domain = PF_UNIX; + break; + + default: + return -EINVAL; } - if (type == NUTTX_SOCK_STREAM) + switch (type & NUTTX_SOCK_TYPE_MASK) { - type = SOCK_STREAM; + case NUTTX_SOCK_STREAM: + sockflags = SOCK_STREAM; + break; + + case NUTTX_SOCK_DGRAM: + sockflags = SOCK_DGRAM; + break; + + case NUTTX_SOCK_RAW: + sockflags = SOCK_RAW; + break; + + case NUTTX_SOCK_SEQPACKET: +#ifdef SOCK_SEQPACKET + sockflags = SOCK_SEQPACKET; + break; +#else + return -EPROTONOSUPPORT; +#endif + + default: + return -EINVAL; } - else if (type == NUTTX_SOCK_DGRAM) + +#ifdef SOCK_CLOEXEC + if ((type & NUTTX_SOCK_CLOEXEC) != 0) { - type = SOCK_DGRAM; + sockflags |= SOCK_CLOEXEC; } - else if (type == NUTTX_SOCK_RAW) +#endif + +#ifdef SOCK_NONBLOCK + if ((type & NUTTX_SOCK_NONBLOCK) != 0) { - type = SOCK_RAW; - } - else - { - return -EINVAL; + sockflags |= SOCK_NONBLOCK; } +#endif if (protocol == NUTTX_IPPROTO_IP) { @@ -297,7 +401,7 @@ int host_usrsock_socket(int domain, int type, int protocol) return -EINVAL; } - ret = socket(domain, type, protocol); + ret = socket(domain, sockflags, protocol); if (ret < 0) { return -errno; @@ -327,17 +431,26 @@ int host_usrsock_connect(int sockfd, const struct nuttx_sockaddr *addr, nuttx_socklen_t addrlen) { - struct sockaddr naddr; + struct sockaddr_storage naddr; socklen_t naddrlen; int ret; - sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); - - sock_nonblock(sockfd, false); - ret = connect(sockfd, &naddr, naddrlen); - sock_nonblock(sockfd, true); + ret = sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); if (ret < 0) { + return ret; + } + + ret = connect(sockfd, (struct sockaddr *)&naddr, naddrlen); + if (ret < 0) + { + if (errno == EINPROGRESS || errno == EALREADY || errno == EWOULDBLOCK) + { + host_usrsock_set_fd(sockfd, &g_active_write_fds); + host_usrsock_set_fd(sockfd, &g_active_read_fds); + return -EINPROGRESS; + } + return -errno; } @@ -351,14 +464,20 @@ ssize_t host_usrsock_sendto(int sockfd, const void *buf, const struct nuttx_sockaddr *dest_addr, nuttx_socklen_t addrlen) { - struct sockaddr naddr; + struct sockaddr_storage naddr; socklen_t naddrlen; int ret; if (dest_addr && addrlen >= sizeof(*dest_addr)) { - sockaddr_to_native(dest_addr, addrlen, &naddr, &naddrlen); - ret = sendto(sockfd, buf, len, flags, &naddr, naddrlen); + ret = sockaddr_to_native(dest_addr, addrlen, &naddr, &naddrlen); + if (ret < 0) + { + return ret; + } + + ret = sendto(sockfd, buf, len, flags, + (struct sockaddr *)&naddr, naddrlen); } else { @@ -384,14 +503,14 @@ ssize_t host_usrsock_recvfrom(int sockfd, void *buf, size_t len, int flags, struct nuttx_sockaddr *src_addr, nuttx_socklen_t *addrlen) { - struct sockaddr naddr; - socklen_t naddrlen; + struct sockaddr_storage naddr; + socklen_t naddrlen = sizeof(naddr); int ret; - if (src_addr && addrlen && *addrlen >= sizeof(*src_addr)) + if (src_addr && addrlen) { - sockaddr_to_native(src_addr, *addrlen, &naddr, &naddrlen); - ret = recvfrom(sockfd, buf, len, flags, &naddr, &naddrlen); + ret = recvfrom(sockfd, buf, len, flags, + (struct sockaddr *)&naddr, &naddrlen); } else { @@ -408,7 +527,7 @@ ssize_t host_usrsock_recvfrom(int sockfd, void *buf, size_t len, int flags, return -errno; } - if (src_addr && addrlen && *addrlen >= sizeof(*src_addr)) + if (src_addr && addrlen) { sockaddr_to_nuttx(&naddr, naddrlen, src_addr, addrlen); } @@ -436,19 +555,19 @@ int host_usrsock_getsockname(int sockfd, struct nuttx_sockaddr *addr, nuttx_socklen_t *addrlen) { - socklen_t naddrlen = sizeof(struct sockaddr); - struct sockaddr naddr; + socklen_t naddrlen = sizeof(struct sockaddr_storage); + struct sockaddr_storage naddr; int ret; - ret = getsockname(sockfd, &naddr, &naddrlen); + ret = getsockname(sockfd, (struct sockaddr *)&naddr, &naddrlen); if (ret < 0) { return -errno; } - if (addr && addrlen && *addrlen >= sizeof(*addr)) + if (addr && addrlen) { - sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); + ret = sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); } return ret; @@ -458,19 +577,19 @@ int host_usrsock_getpeername(int sockfd, struct nuttx_sockaddr *addr, nuttx_socklen_t *addrlen) { - socklen_t naddrlen = sizeof(struct sockaddr); - struct sockaddr naddr; + socklen_t naddrlen = sizeof(struct sockaddr_storage); + struct sockaddr_storage naddr; int ret; - ret = getpeername(sockfd, &naddr, &naddrlen); + ret = getpeername(sockfd, (struct sockaddr *)&naddr, &naddrlen); if (ret < 0) { return -errno; } - if (addr && addrlen && *addrlen >= sizeof(*addr)) + if (addr && addrlen) { - sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); + ret = sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); } return ret; @@ -480,12 +599,17 @@ int host_usrsock_bind(int sockfd, const struct nuttx_sockaddr *addr, nuttx_socklen_t addrlen) { - struct sockaddr naddr; + struct sockaddr_storage naddr; socklen_t naddrlen; + int ret; - sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); + ret = sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); + if (ret < 0) + { + return ret; + } - return bind(sockfd, &naddr, naddrlen) < 0 ? -errno : 0; + return bind(sockfd, (struct sockaddr *)&naddr, naddrlen) < 0 ? -errno : 0; } int host_usrsock_listen(int sockfd, int backlog) @@ -506,17 +630,17 @@ int host_usrsock_listen(int sockfd, int backlog) int host_usrsock_accept(int sockfd, struct nuttx_sockaddr *addr, nuttx_socklen_t *addrlen) { - socklen_t naddrlen = sizeof(socklen_t); - struct sockaddr naddr; + socklen_t naddrlen = sizeof(struct sockaddr_storage); + struct sockaddr_storage naddr; int ret; - ret = accept(sockfd, &naddr, &naddrlen); - if (ret <= 0) + ret = accept(sockfd, (struct sockaddr *)&naddr, &naddrlen); + if (ret < 0) { return -errno; } - if (addr && addrlen && *addrlen >= sizeof(*addr)) + if (addr && addrlen) { sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); } @@ -562,7 +686,7 @@ void host_usrsock_loop(void) int ret; int i; - if (g_active_maxfd <= 0) + if (g_active_maxfd < 0) { return; } diff --git a/arch/sim/src/sim/sim_hostusrsock.h b/arch/sim/src/sim/sim_hostusrsock.h index e5fb2f10d3d..34a2ce243b5 100644 --- a/arch/sim/src/sim/sim_hostusrsock.h +++ b/arch/sim/src/sim/sim_hostusrsock.h @@ -83,6 +83,8 @@ #define NUTTX_PF_PKTRADIO 64 #define NUTTX_PF_RPMSG 65 +#define NUTTX_UNIX_PATH_MAX 108 + #define NUTTX_AF_UNSPEC NUTTX_PF_UNSPEC #define NUTTX_AF_UNIX NUTTX_PF_UNIX #define NUTTX_AF_LOCAL NUTTX_PF_LOCAL @@ -219,6 +221,12 @@ struct nuttx_sockaddr char sa_data[14]; /* 14-bytes data (actually variable length) */ }; +struct nuttx_sockaddr_un +{ + sa_family_t sun_family; /* Address family: AF_LOCAL */ + char sun_path[NUTTX_UNIX_PATH_MAX]; +}; + struct nuttx_linger { int l_onoff; /* Indicates whether linger option is enabled. */ diff --git a/arch/sim/src/sim/sim_usrsock.c b/arch/sim/src/sim/sim_usrsock.c index c8210d03361..ae41fc663b0 100644 --- a/arch/sim/src/sim/sim_usrsock.c +++ b/arch/sim/src/sim/sim_usrsock.c @@ -415,6 +415,7 @@ static const usrsock_handler_t g_usrsock_handler[] = static void sim_usrsock_work(void *arg) { + host_usrsock_loop(); work_queue_next_wq(g_work_queue, &g_usrsock.work, sim_usrsock_work, NULL, SIM_USRSOCK_PERIOD); } diff --git a/net/usrsock/usrsock_sockif.c b/net/usrsock/usrsock_sockif.c index 28079dfd38c..2e796a2b7db 100644 --- a/net/usrsock/usrsock_sockif.c +++ b/net/usrsock/usrsock_sockif.c @@ -103,10 +103,14 @@ static int usrsock_sockif_setup(FAR struct socket *psock) int ret; if (psock->s_domain != PF_INET && psock->s_domain != PF_INET6 && - psock->s_domain != PF_NETLINK) + psock->s_domain != PF_NETLINK +#ifndef CONFIG_NET_LOCAL + && psock->s_domain != PF_LOCAL +#endif + ) { - return -ENOTSUP; /* Only ipv4, ipv6 and netlink support the offload */ - }; + return -ENOTSUP; /* Only supported families can use usrsock offload */ + } /* Let the user socket logic handle the setup... *