From owner-svn-src-head@freebsd.org Wed Aug 5 08:18:07 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id F3FB89B4AC3; Wed, 5 Aug 2015 08:18:06 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D809493C; Wed, 5 Aug 2015 08:18:06 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t758I6gH001147; Wed, 5 Aug 2015 08:18:06 GMT (envelope-from ed@FreeBSD.org) Received: (from ed@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t758I628001144; Wed, 5 Aug 2015 08:18:06 GMT (envelope-from ed@FreeBSD.org) Message-Id: <201508050818.t758I628001144@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ed set sender to ed@FreeBSD.org using -f From: Ed Schouten Date: Wed, 5 Aug 2015 08:18:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r286312 - head/sys/compat/cloudabi X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Aug 2015 08:18:07 -0000 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 +#include +#include +#include +#include +#include #include +#include #include #include #include #include +#include + +#include + #include #include +#include + +/* 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 + #include 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 *);