Date: Wed, 5 Aug 2015 08:18:06 +0000 (UTC) From: Ed Schouten <ed@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r286312 - head/sys/compat/cloudabi Message-ID: <201508050818.t758I628001144@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ed Date: Wed Aug 5 08:18:05 2015 New Revision: 286312 URL: https://svnweb.freebsd.org/changeset/base/286312 Log: Add the remaining pointer size independent CloudABI socket system calls. CloudABI uses a structure called cloudabi_sockstat_t. Think of it as 'struct stat' for sockets. It is used by functions such as getsockname(), getpeername(), some of the getsockopt() values, etc. This change implements the sock_stat_get() system call that returns a copy of this structure. The accept() system call should also return a full copy of this structure eventually, but for now we're only interested in the peer address. Add a TODO() to make sure this is patched up later on. Differential Revision: https://reviews.freebsd.org/D3218 Modified: head/sys/compat/cloudabi/cloudabi_sock.c head/sys/compat/cloudabi/cloudabi_util.h Modified: head/sys/compat/cloudabi/cloudabi_sock.c ============================================================================== --- head/sys/compat/cloudabi/cloudabi_sock.c Wed Aug 5 08:17:10 2015 (r286311) +++ head/sys/compat/cloudabi/cloudabi_sock.c Wed Aug 5 08:18:05 2015 (r286312) @@ -27,14 +27,62 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> +#include <sys/capsicum.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/protosw.h> #include <sys/socket.h> +#include <sys/socketvar.h> #include <sys/syscallsubr.h> #include <sys/sysproto.h> #include <sys/systm.h> #include <sys/un.h> +#include <net/vnet.h> + +#include <netinet/in.h> + #include <compat/cloudabi/cloudabi_proto.h> #include <compat/cloudabi/cloudabi_syscalldefs.h> +#include <compat/cloudabi/cloudabi_util.h> + +/* Converts FreeBSD's struct sockaddr to CloudABI's cloudabi_sockaddr_t. */ +void +cloudabi_convert_sockaddr(const struct sockaddr *sa, socklen_t sal, + cloudabi_sockaddr_t *rsa) +{ + const struct sockaddr_in *sin; + const struct sockaddr_in6 *sin6; + + /* Zero-sized socket address. */ + if (sal < offsetof(struct sockaddr, sa_family) + sizeof(sa->sa_family)) + return; + + switch (sa->sa_family) { + case AF_INET: + if (sal < sizeof(struct sockaddr_in)) + return; + sin = (const struct sockaddr_in *)sa; + rsa->sa_family = CLOUDABI_AF_INET; + memcpy(&rsa->sa_inet.addr, &sin->sin_addr, + sizeof(rsa->sa_inet.addr)); + rsa->sa_inet.port = ntohs(sin->sin_port); + return; + case AF_INET6: + if (sal < sizeof(struct sockaddr_in6)) + return; + sin6 = (const struct sockaddr_in6 *)sa; + rsa->sa_family = CLOUDABI_AF_INET6; + memcpy(&rsa->sa_inet6.addr, &sin6->sin6_addr, + sizeof(rsa->sa_inet6.addr)); + rsa->sa_inet6.port = ntohs(sin6->sin6_port); + return; + case AF_UNIX: + rsa->sa_family = CLOUDABI_AF_UNIX; + return; + } +} /* Copies a pathname into a UNIX socket address structure. */ static int @@ -62,9 +110,27 @@ int cloudabi_sys_sock_accept(struct thread *td, struct cloudabi_sys_sock_accept_args *uap) { + struct sockaddr *sa; + cloudabi_sockstat_t ss = {}; + socklen_t sal; + int error; - /* Not implemented. */ - return (ENOSYS); + if (uap->buf == NULL) { + /* Only return the new file descriptor number. */ + return (kern_accept(td, uap->s, NULL, NULL, NULL)); + } else { + /* Also return properties of the new socket descriptor. */ + sal = MAX(sizeof(struct sockaddr_in), + sizeof(struct sockaddr_in6)); + error = kern_accept(td, uap->s, (void *)&sa, &sal, NULL); + if (error != 0) + return (error); + + /* TODO(ed): Fill the other members of cloudabi_sockstat_t. */ + cloudabi_convert_sockaddr(sa, sal, &ss.ss_peername); + free(sa, M_SONAME); + return (copyout(&ss, uap->buf, sizeof(ss))); + } } int @@ -134,7 +200,51 @@ int cloudabi_sys_sock_stat_get(struct thread *td, struct cloudabi_sys_sock_stat_get_args *uap) { + cloudabi_sockstat_t ss = {}; + cap_rights_t rights; + struct file *fp; + struct sockaddr *sa; + struct socket *so; + int error; + + error = getsock_cap(td, uap->fd, cap_rights_init(&rights, + CAP_GETSOCKOPT | CAP_GETPEERNAME | CAP_GETSOCKNAME), &fp, NULL); + if (error != 0) + return (error); + so = fp->f_data; + + CURVNET_SET(so->so_vnet); + + /* Set ss_sockname. */ + error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); + if (error == 0) { + cloudabi_convert_sockaddr(sa, sa->sa_len, &ss.ss_sockname); + free(sa, M_SONAME); + } + + /* Set ss_peername. */ + if ((so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) != 0) { + error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa); + if (error == 0) { + cloudabi_convert_sockaddr(sa, sa->sa_len, + &ss.ss_peername); + free(sa, M_SONAME); + } + } + + CURVNET_RESTORE(); + + /* Set ss_error. */ + SOCK_LOCK(so); + ss.ss_error = so->so_error; + if ((uap->flags & CLOUDABI_SOCKSTAT_CLEAR_ERROR) != 0) + so->so_error = 0; + SOCK_UNLOCK(so); + + /* Set ss_state. */ + if ((so->so_options & SO_ACCEPTCONN) != 0) + ss.ss_state |= CLOUDABI_SOCKSTAT_ACCEPTCONN; - /* Not implemented. */ - return (ENOSYS); + fdrop(fp, td); + return (copyout(&ss, uap->buf, sizeof(ss))); } Modified: head/sys/compat/cloudabi/cloudabi_util.h ============================================================================== --- head/sys/compat/cloudabi/cloudabi_util.h Wed Aug 5 08:17:10 2015 (r286311) +++ head/sys/compat/cloudabi/cloudabi_util.h Wed Aug 5 08:18:05 2015 (r286312) @@ -28,6 +28,8 @@ #ifndef _CLOUDABI_UTIL_H_ #define _CLOUDABI_UTIL_H_ +#include <sys/socket.h> + #include <compat/cloudabi/cloudabi_syscalldefs.h> struct file; @@ -41,6 +43,10 @@ int cloudabi_clock_time_get(struct threa /* Converts a FreeBSD errno to a CloudABI errno. */ cloudabi_errno_t cloudabi_convert_errno(int); +/* Converts FreeBSD's struct sockaddr to CloudABI's cloudabi_sockaddr_t. */ +void cloudabi_convert_sockaddr(const struct sockaddr *, socklen_t, + cloudabi_sockaddr_t *); + /* Converts a file descriptor to a CloudABI file descriptor type. */ cloudabi_filetype_t cloudabi_convert_filetype(const struct file *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508050818.t758I628001144>