[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT/LWIP PATCH 1/4] sockets.c: Register implementation against posix-socket
From: Alexander Jung <alexander.jung@xxxxxxxxx> This patch registers LwIP's socket implementatin against the internal Unikraft posix-socket microlibrary and exposes AF_INET and AF_INET6 implementations. Signed-off-by: Alexander Jung <alexander.jung@xxxxxxxxx> --- Config.uk | 4 +- sockets.c | 1252 ++++++++++++++++++++--------------------------------- 2 files changed, 477 insertions(+), 779 deletions(-) diff --git a/Config.uk b/Config.uk index debf0c7..64bab89 100644 --- a/Config.uk +++ b/Config.uk @@ -157,8 +157,8 @@ config LWIP_DNS_TABLE_SIZE endif config LWIP_SOCKET - bool "Socket API" - select LIBVFSCORE + bool "Provide POSIX socket API" + select LIBPOSIX_SOCKET depends on LWIP_THREADS && (LWIP_UDP || LWIP_TCP) default y diff --git a/sockets.c b/sockets.c index 8fde21a..da1f70d 100644 --- a/sockets.c +++ b/sockets.c @@ -1,8 +1,9 @@ /* SPDX-License-Identifier: BSD-3-Clause */ /* * Authors: Sharan Santhanam <sharan.santhanam@xxxxxxxxx> + * Alexander Jung <alexander.jung@xxxxxxxxx> * - * Copyright (c) 2019, NEC Laboratories Europe GmbH, NEC Corporation. + * Copyright (c) 2020, NEC Laboratories Europe GmbH, NEC Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,873 +30,570 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. - * - * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. */ -/* network stub calls */ #include <uk/config.h> -#include <sys/time.h> -#if CONFIG_LWIP_SOCKET_PPOLL -#include <signal.h> -#endif -#include <vfscore/dentry.h> -#include <vfscore/file.h> -#include <vfscore/fs.h> -#include <vfscore/mount.h> -#include <vfscore/vnode.h> -#include <uk/alloc.h> -#include <uk/essentials.h> -#include <uk/errptr.h> -#include <stdio.h> -#include <errno.h> +#include <uk/assert.h> +#include <sys/socket.h> +#include <uk/socket.h> #include <lwip/sockets.h> +#include <uk/print.h> -#define SOCK_NET_SET_ERRNO(errcode) \ - (errno = -(errcode)) - -static int sock_net_close(struct vnode *s_vnode, - struct vfscore_file *vfscore_file); -static int sock_net_write(struct vnode *s_vnode, - struct uio *buf, int ioflag __unused); -static int sock_net_read(struct vnode *s_vnode, - struct vfscore_file *vfscore_file __unused, - struct uio *buf, int ioflag __unused); -static int sock_net_ioctl(struct vnode *s_vnode, - struct vfscore_file *vfscore_file __unused, - unsigned long request, - void *buf); - -#define sock_net_getattr ((vnop_getattr_t) vfscore_vop_einval) -#define sock_net_inactive ((vnop_inactive_t) vfscore_vop_nullop) - -static struct vnops sock_net_vnops = { - .vop_close = sock_net_close, - .vop_write = sock_net_write, - .vop_read = sock_net_read, - .vop_ioctl = sock_net_ioctl, - .vop_getattr = sock_net_getattr, - .vop_inactive = sock_net_inactive -}; - -#define sock_net_vget ((vfsop_vget_t) vfscore_vop_nullop) - -static struct vfsops sock_net_vfsops = { - .vfs_vget = sock_net_vget, - .vfs_vnops = &sock_net_vnops -}; - - -static uint64_t s_inode = 0; -/* - * Bogus mount point used by all sockets - */ -static struct mount s_mount = { - .m_op = &sock_net_vfsops +struct lwip_socket { + int lwip_fd; }; -struct sock_net_file { - struct vfscore_file *vfscore_file; - int sock_fd; -}; - -static inline struct sock_net_file *sock_net_file_get(int fd) -{ - struct sock_net_file *file = NULL; - struct vfscore_file *fos; - - fos = vfscore_get_file(fd); - if (!fos) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed with invalid descriptor\n")); - file = ERR2PTR(-EINVAL); - goto EXIT; - } - if (fos->f_dentry->d_vnode->v_type != VSOCK) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("file descriptor is not a socket\n")); - file = ERR2PTR(-EBADF); - goto EXIT; - } - file = fos->f_data; -EXIT: - return file; -} - -static int sock_fd_alloc(int sock_fd) +int +lwip_lib_socket_init(struct posix_socket_driver *d) { - int ret = 0; - int vfs_fd; - struct sock_net_file *file = NULL; - struct vfscore_file *vfs_file = NULL; - struct dentry *s_dentry; - struct vnode *s_vnode; - - /* Reserve file descriptor number */ - vfs_fd = vfscore_alloc_fd(); - if (vfs_fd < 0) { - ret = -ENFILE; - LWIP_DEBUGF(SOCKETS_DEBUG, - ("Failed to allocate file descriptor number\n")); - goto ERR_EXIT; - } - - /* Allocate file, dentry, and vnode */ - file = uk_calloc(uk_alloc_get_default(), 1, sizeof(*file)); - if (!file) { - ret = -ENOMEM; - LWIP_DEBUGF(SOCKETS_DEBUG, - ("Failed to allocate socket file: Out of memory\n")); - goto ERR_MALLOC_FILE; - } - vfs_file = uk_calloc(uk_alloc_get_default(), 1, sizeof(*vfs_file)); - if (!vfs_file) { - ret = -ENOMEM; - LWIP_DEBUGF(SOCKETS_DEBUG, - ("Failed to allocate socket vfs_file: Out of memory\n")); - goto ERR_MALLOC_VFS_FILE; - } - - ret = vfscore_vget(&s_mount, s_inode++, &s_vnode); - UK_ASSERT(ret == 0); /* we should not find it in cache */ - - if (!s_vnode) { - ret = -ENOMEM; - LWIP_DEBUGF(SOCKETS_DEBUG, - ("Failed to allocate socket vnode: Out of memory\n")); - goto ERR_ALLOC_VNODE; - } - - uk_mutex_unlock(&s_vnode->v_lock); - - /* - * it doesn't matter that all the dentries have the - * same path since we never lookup for them - */ - s_dentry = dentry_alloc(NULL, s_vnode, "/"); - - if (!s_dentry) { - ret = -ENOMEM; - LWIP_DEBUGF(SOCKETS_DEBUG, - ("Failed to allocate socket dentry: Out of memory\n")); - goto ERR_ALLOC_DENTRY; - } - - /* Put things together, and fill out necessary fields */ - vfs_file->fd = vfs_fd; - vfs_file->f_flags = UK_FWRITE | UK_FREAD; - vfs_file->f_count = 1; - vfs_file->f_data = file; - vfs_file->f_dentry = s_dentry; - vfs_file->f_vfs_flags = UK_VFSCORE_NOPOS; - - s_vnode->v_data = file; - s_vnode->v_type = VSOCK; - - file->vfscore_file = vfs_file; - file->sock_fd = sock_fd; - LWIP_DEBUGF(SOCKETS_DEBUG, ("Allocated socket %d (%x)\n", - file->vfscore_file->fd, - file->sock_fd)); - - /* Storing the information within the vfs structure */ - ret = vfscore_install_fd(vfs_fd, file->vfscore_file); - if (ret) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("Failed to install socket fd\n")); - goto ERR_VFS_INSTALL; - } - - /* Only the dentry should hold a reference; release ours */ - vrele(s_vnode); - - /* Return file descriptor of our socket */ - return vfs_fd; - -ERR_VFS_INSTALL: - drele(s_dentry); -ERR_ALLOC_DENTRY: - vrele(s_vnode); -ERR_ALLOC_VNODE: - uk_free(uk_alloc_get_default(), vfs_file); -ERR_MALLOC_VFS_FILE: - uk_free(uk_alloc_get_default(), file); -ERR_MALLOC_FILE: - vfscore_put_fd(vfs_fd); -ERR_EXIT: - UK_ASSERT(ret < 0); - return ret; + return 0; } -static int sock_net_close(struct vnode *s_vnode, - struct vfscore_file *vfscore_file) +static void * +lwip_glue_create(struct posix_socket_driver *d, + int family, int type, int protocol) { - int ret; - struct sock_net_file *file = NULL; - - file = s_vnode->v_data; - LWIP_DEBUGF(SOCKETS_DEBUG, ("%s fd:%d lwip_fd:%d\n", - __func__, - file->vfscore_file->fd, - file->sock_fd)); - - UK_ASSERT(vfscore_file->f_dentry->d_vnode == s_vnode); - UK_ASSERT(s_vnode->v_refcnt == 1); - - /* Close and release the lwip socket */ - ret = lwip_close(file->sock_fd); - - /* - * Free socket file - * The rest of the resources will be freed by vfs - * - * TODO: vfs ignores close errors right now, so free our file - */ - uk_free(uk_alloc_get_default(), file); - - /* - * lwip sets errno and returns -1 in case of error, but - * vfs expects us to return a positive errno - */ - if (ret < 0) - return errno; - - return ret; -} + void *ret = NULL; + struct lwip_socket *lwip_sock; + + /* Use our socket data store to hold onto LwIP's file descriptor. */ + lwip_sock = uk_calloc(d->allocator, 1, sizeof(struct lwip_socket)); + if (!lwip_sock) { + ret = NULL; + SOCKET_LIB_ERR(d, -1, "could not allocate socket: out of memory"); + goto EXIT; + } + + /* Create an LwIP socket */ + lwip_sock->lwip_fd = lwip_socket(family, type, protocol); + if (lwip_sock->lwip_fd < 0) { + ret = NULL; + goto LWIP_SOCKET_CLEANUP; + } + + /* Return the whole LwIP socket struct for the driver */ + ret = lwip_sock; -static int sock_net_write(struct vnode *s_vnode, - struct uio *buf, int ioflag __unused) -{ - int ret = 0; - struct sock_net_file *file = NULL; - - file = s_vnode->v_data; - LWIP_DEBUGF(SOCKETS_DEBUG, ("%s fd:%d lwip_fd:%d\n", - __func__, - file->vfscore_file->fd, - file->sock_fd)); - ret = lwip_writev(file->sock_fd, buf->uio_iov, buf->uio_iovcnt); - /* - * lwip sets errno and returns -1 in case of error, but - * vfs expects us to return a positive errno - */ - if (ret < 0) - return errno; - - buf->uio_resid -= ret; - return 0; -} +EXIT: + return ret; -static int sock_net_read(struct vnode *s_vnode, - struct vfscore_file *vfscore_file __unused, - struct uio *buf, int ioflag __unused) -{ - int ret = 0; - struct sock_net_file *file = NULL; - - file = s_vnode->v_data; - LWIP_DEBUGF(SOCKETS_DEBUG, ("%s fd:%d lwip_fd:%d\n", - __func__, - file->vfscore_file->fd, - file->sock_fd)); - ret = lwip_readv(file->sock_fd, buf->uio_iov, buf->uio_iovcnt); - /* - * lwip sets errno and returns -1 in case of error, but - * vfs expects us to return a positive errno - */ - if (ret < 0) - return errno; - - buf->uio_resid -= ret; - return 0; +LWIP_SOCKET_CLEANUP: + uk_free(d->allocator, lwip_sock); + goto EXIT; } -static int sock_net_ioctl(struct vnode *s_vnode, - struct vfscore_file *vfscore_file __unused, - unsigned long request, - void *buf) +static void * +lwip_glue_accept(struct posix_socket_driver *d, + void *sock, struct sockaddr *restrict addr, + socklen_t *restrict addr_len) { - struct sock_net_file *file = NULL; - - file = s_vnode->v_data; - LWIP_DEBUGF(SOCKETS_DEBUG, ("%s fd:%d lwip_fd:%d\n", - __func__, - file->vfscore_file->fd, - file->sock_fd)); - return lwip_ioctl(file->sock_fd, request, buf); -} + void *ret = NULL; + struct lwip_socket *lwip_sock; + struct lwip_socket *new_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = NULL; + SOCKET_LIB_ERR(d, -1, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Use our socket data store to hold onto LwIP's file descriptor. */ + new_sock = uk_calloc(d->allocator, 1, sizeof(struct lwip_socket)); + if (!new_sock) { + ret = NULL; + SOCKET_LIB_ERR(d, -1, "could not allocate socket: out of memory"); + goto EXIT; + } + + /* Create an LwIP socket */ + new_sock->lwip_fd = lwip_accept(lwip_sock->lwip_fd, addr, addr_len); + if (new_sock->lwip_fd < 0) { + ret = NULL; + goto LWIP_SOCKET_CLEANUP; + } + + /* Return the whole LwIP socket struct for the driver */ + ret = new_sock; -int socket(int domain, int type, int protocol) -{ - int ret = 0; - int vfs_fd = 0xff; - int sock_fd = 0; - - /* Create lwip_socket */ - sock_fd = lwip_socket(domain, type, protocol); - if (sock_fd < 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("failed to create socket %d\n", - errno)); - ret = -1; - goto EXIT; - } - - /* Allocate the file descriptor */ - vfs_fd = sock_fd_alloc(sock_fd); - if (vfs_fd < 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to allocate descriptor %d\n", - errno)); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(vfs_fd); - goto LWIP_SOCKET_CLEANUP; - } - - /* Returning the file descriptor to the user */ - ret = vfs_fd; EXIT: - return ret; + return ret; + LWIP_SOCKET_CLEANUP: - /* Cleanup the lwip socket */ - lwip_close(sock_fd); - goto EXIT; + uk_free(d->allocator, new_sock); + goto EXIT; } -int accept(int s, struct sockaddr *addr, socklen_t *addrlen) +static int +lwip_glue_bind(struct posix_socket_driver *d, + void *sock, const struct sockaddr *addr, socklen_t addr_len) { - int ret = 0; - struct sock_net_file *file; - int sock_fd, vfs_fd; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to accept incoming connection\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - - /* Accept an incoming connection */ - sock_fd = lwip_accept(file->sock_fd, addr, addrlen); - if (sock_fd < 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to accept incoming connection\n")); - ret = -1; - goto EXIT_FDROP; - } - - /* Allocate the file descriptor for the accepted connection */ - vfs_fd = sock_fd_alloc(sock_fd); - if (vfs_fd < 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to allocate descriptor for accepted connection\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(vfs_fd); - goto LWIP_SOCKET_CLEANUP; - } - ret = vfs_fd; -EXIT_FDROP: - vfscore_put_file(file->vfscore_file); /* release refcount */ -EXIT: - return ret; + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Bind an LwIP socket */ + ret = lwip_bind(lwip_sock->lwip_fd, addr, addr_len); + if (ret < 0) + ret = -1; -LWIP_SOCKET_CLEANUP: - lwip_close(sock_fd); - goto EXIT_FDROP; +EXIT: + return ret; } -int bind(int s, const struct sockaddr *name, socklen_t namelen) +static int +lwip_glue_shutdown(struct posix_socket_driver *d, + void *sock, int how) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - /* Bind an incoming connection */ - ret = lwip_bind(file->sock_fd, name, namelen); - if (ret < 0) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to bind with socket\n")); - ret = -1; - goto EXIT_FDROP; - } -EXIT_FDROP: - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Bind an LwIP socket */ + ret = lwip_shutdown(lwip_sock->lwip_fd, how); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int poll(struct pollfd fds[], nfds_t nfds, int timeout) +static int +lwip_glue_getpeername(struct posix_socket_driver *d, + void *sock, struct sockaddr *restrict addr, + socklen_t *restrict addr_len) { - int ret; - unsigned int i; - struct sock_net_file *file; - struct pollfd lwip_fds[nfds]; - - for (i = 0; i < nfds; i++) { - if (fds[i].fd < 0) - lwip_fds[i].fd = fds[i].fd; - else { - file = sock_net_file_get(fds[i].fd); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - lwip_fds[i].fd = file->sock_fd; - lwip_fds[i].events = fds[i].events; - vfscore_put_file(file->vfscore_file); /* release refcount */ - } - } - - ret = lwip_poll(lwip_fds, nfds, timeout); - if (ret < 0) - goto EXIT; - - for (i = 0; i < nfds; i++) { - if (fds[i].fd < 0) - fds[i].revents = 0; - else - fds[i].revents = lwip_fds[i].revents; - } + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Get the peer name using LwIP */ + ret = lwip_getpeername(lwip_sock->lwip_fd, addr, addr_len); + if (ret < 0) + ret = -1; EXIT: - return ret; + return ret; } -#if CONFIG_LWIP_SOCKET_PPOLL -#if CONFIG_LIBPTHREAD_EMBEDDED -#define __sigmask pthread_sigmask -#else -#define __sigmask sigprocmask -#endif -int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, - const sigset_t *sigmask) +static int +lwip_glue_getsockname(struct posix_socket_driver *d, + void *sock, struct sockaddr *restrict addr, + socklen_t *restrict addr_len) { - sigset_t origmask; - int timeout, rc, _rc; - - if (!fds) { - errno = EFAULT; - rc = -1; - goto out; - } - - timeout = (tmo_p == NULL) ? -1 : - (tmo_p->tv_sec * 1000 + tmo_p->tv_nsec / 1000000); - rc = __sigmask(SIG_SETMASK, sigmask, &origmask); - if (rc) - goto out; - rc = poll(fds, nfds, timeout); - _rc = __sigmask(SIG_SETMASK, &origmask, NULL); - if (rc == 0 && _rc != 0) - rc = _rc; -out: - return rc; + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Get the socket name using LwIP */ + ret = lwip_getsockname(lwip_sock->lwip_fd, addr, addr_len); + if (ret < 0) + ret = -1; + +EXIT: + return ret; } -#endif /* CONFIG_LWIP_SOCKET_PPOLL */ -int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - struct timeval *timeout) +static int +lwip_glue_getsockopt(struct posix_socket_driver *d, + void *sock, int level, int optname, void *restrict optval, + socklen_t *restrict optlen) { - uint64_t nsecs; - fd_set rd, wr, xc; - int i, ret, maxfd; - struct sock_net_file *file; - - if (nfds == 0 && timeout != NULL) { - nsecs = timeout->tv_sec * 1000000000; - nsecs += timeout->tv_usec * 1000; - uk_sched_thread_sleep(nsecs); - return 0; - } - - /* translate the public (vfscore) fds into lwIP socket fds */ - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_ZERO(&xc); - maxfd = 0; - for (i = 0; i < nfds; i++) { - if (readfds && FD_ISSET(i, readfds)) { - file = sock_net_file_get(i); - if (PTRISERR(file)) { -#if CONFIG_LWIP_SOCKET_SELECT_GENERIC_FDS - /* We allow other fd types, but we don't support them */ - if (PTR2ERR(file) == -EBADF) { - FD_CLR(i, readfds); - continue; - } -#else - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; -#endif - } - if (maxfd < file->sock_fd) - maxfd = file->sock_fd; - FD_SET(file->sock_fd, &rd); - vfscore_put_file(file->vfscore_file); /* release refcount */ - } - if (writefds && FD_ISSET(i, writefds)) { - file = sock_net_file_get(i); - if (PTRISERR(file)) { -#if CONFIG_LWIP_SOCKET_SELECT_GENERIC_FDS - /* We allow other fd types, but we don't support them */ - if (PTR2ERR(file) == -EBADF) { - FD_CLR(i, writefds); - continue; - } -#else - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; -#endif - } - if (maxfd < file->sock_fd) - maxfd = file->sock_fd; - FD_SET(file->sock_fd, &wr); - vfscore_put_file(file->vfscore_file); /* release refcount */ - } - if (exceptfds && FD_ISSET(i, exceptfds)) { - file = sock_net_file_get(i); - if (PTRISERR(file)) { -#if CONFIG_LWIP_SOCKET_SELECT_GENERIC_FDS - /* We allow other fd types, but we don't support them */ - if (PTR2ERR(file) == -EBADF) { - FD_CLR(i, exceptfds); - continue; - } -#else - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; -#endif - } - if (maxfd < file->sock_fd) - maxfd = file->sock_fd; - FD_SET(file->sock_fd, &xc); - vfscore_put_file(file->vfscore_file); /* release refcount */ - } - } - - ret = lwip_select(maxfd+1, &rd, &wr, &xc, timeout); - if (ret < 0) - goto EXIT; - - /* translate back from lwIP socket fds to public (vfscore) fds. - * But there's no way to go from lwIP to vfscore, so iterate over - * everything again. Check which ones were set originally, and if - * they aren't also set in lwip_select()'s return, clear them. - */ - for (i = 0; i < nfds; i++) { - if (readfds && FD_ISSET(i, readfds)) { - /* This lookup can't fail, or it would already have - * failed during the translation above. - */ - file = sock_net_file_get(i); - if (!FD_ISSET(file->sock_fd, &rd)) - FD_CLR(i, readfds); - vfscore_put_file(file->vfscore_file); /* release refcount */ - } - if (writefds && FD_ISSET(i, writefds)) { - /* This lookup can't fail, or it would already have - * failed during the translation above. - */ - file = sock_net_file_get(i); - if (!FD_ISSET(file->sock_fd, &wr)) - FD_CLR(i, writefds); - vfscore_put_file(file->vfscore_file); /* release refcount */ - } - if (exceptfds && FD_ISSET(i, exceptfds)) { - /* This lookup can't fail, or it would already have - * failed during the translation above. - */ - file = sock_net_file_get(i); - if (!FD_ISSET(file->sock_fd, &xc)) - FD_CLR(i, exceptfds); - vfscore_put_file(file->vfscore_file); /* release refcount */ - } - } + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Get the socket options using LwIP */ + ret = lwip_getsockopt(lwip_sock->lwip_fd, level, optname, optval, optlen); + if (ret < 0) + ret = -1; EXIT: - return ret; + return ret; } -int shutdown(int s, int how) +static int +lwip_glue_setsockopt(struct posix_socket_driver *d, + void *sock, int level, int optname, const void *optval, + socklen_t optlen) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - /* Setting the errno */ - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - /* Shutdown of the descriptor */ - ret = lwip_shutdown(file->sock_fd, how); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Set the socket options using LwIP */ + ret = lwip_setsockopt(lwip_sock->lwip_fd, level, optname, optval, optlen); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int getpeername(int s, struct sockaddr *name, socklen_t *namelen) +static int +lwip_glue_connect(struct posix_socket_driver *d, + void *sock, const struct sockaddr *addr, + socklen_t addr_len) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("failed to identify socket\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_getpeername(file->sock_fd, name, namelen); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Connect to a socket using LwIP */ + ret = lwip_connect(lwip_sock->lwip_fd, addr, addr_len); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int getsockname(int s, struct sockaddr *name, socklen_t *namelen) +static int +lwip_glue_listen(struct posix_socket_driver *d, + void *sock, int backlog) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("failed to identify socket\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_getsockname(file->sock_fd, name, namelen); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Listen usiing LwIP socket */ + ret = lwip_listen(lwip_sock->lwip_fd, backlog); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +static ssize_t +lwip_glue_recv(struct posix_socket_driver *d, + void *sock, void *buf, size_t len, int flags) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_getsockopt(file->sock_fd, level, optname, optval, optlen); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Receive data to a buffer from a socket using LwIP */ + ret = lwip_recv(lwip_sock->lwip_fd, buf, len, flags); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; + return 0; } -int setsockopt(int s, int level, int optname, const void *optval, - socklen_t optlen) +static ssize_t +lwip_glue_recvfrom(struct posix_socket_driver *d, + void *sock, void *restrict buf, size_t len, int flags, + struct sockaddr *from, socklen_t *restrict fromlen) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_setsockopt(file->sock_fd, level, optname, optval, optlen); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Recieve data to a buffer from a socket using LwIP */ + ret = lwip_recvfrom(lwip_sock->lwip_fd, buf, len, flags, from, fromlen); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int connect(int s, const struct sockaddr *name, socklen_t namelen) +static ssize_t +lwip_glue_recvmsg(struct posix_socket_driver *d, + void *sock, struct msghdr *msg, int flags) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_connect(file->sock_fd, name, namelen); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Receive a structured message from a socket using LwIP */ + ret = lwip_recvmsg(lwip_sock->lwip_fd, msg, flags); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int listen(int s, int backlog) +static ssize_t +lwip_glue_send(struct posix_socket_driver *d, + void *sock, const void *buf, size_t len, int flags) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_listen(file->sock_fd, backlog); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Send data from a buffer to a socket using LwIP */ + ret = lwip_send(lwip_sock->lwip_fd, buf, len, flags); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int recv(int s, void *mem, size_t len, int flags) +static ssize_t +lwip_glue_sendmsg(struct posix_socket_driver *d, + void *sock, const struct msghdr *msg, int flags) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_recv(file->sock_fd, mem, len, flags); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Send a structured message over a socket using LwIP */ + ret = lwip_sendmsg(lwip_sock->lwip_fd, msg, flags); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) +static ssize_t +lwip_glue_sendto(struct posix_socket_driver *d, + void *sock, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_recvfrom(file->sock_fd, mem, len, flags, from, fromlen); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Send to an address over a socket using LwIP */ + ret = lwip_sendto(lwip_sock->lwip_fd, buf, len, flags, dest_addr, addrlen); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int recvmsg(int s, struct msghdr *msg, int flags) +static int +lwip_glue_read(struct posix_socket_driver *d, + void *sock, void *buf, size_t count) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_recvmsg(file->sock_fd, msg, flags); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Listen usiing LwIP socket */ + ret = lwip_readv(lwip_sock->lwip_fd, buf, count); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int send(int s, const void *dataptr, size_t size, int flags) +static int +lwip_glue_write(struct posix_socket_driver *d, + void *sock, const void *buf, size_t count) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_send(file->sock_fd, dataptr, size, flags); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Write to an incomming connection using LwIP */ + ret = lwip_writev(lwip_sock->lwip_fd, buf, count); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int sendmsg(int s, const struct msghdr *message, int flags) +static int +lwip_glue_close(struct posix_socket_driver *d, + void *sock) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_sendmsg(file->sock_fd, message, flags); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Close an incoming connection using LwIP */ + ret = lwip_close(lwip_sock->lwip_fd); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int sendto(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) +static int +lwip_glue_ioctl(struct posix_socket_driver *d, + void *sock, int request, void *argp) { - int ret = 0; - struct sock_net_file *file = NULL; - - file = sock_net_file_get(s); - if (PTRISERR(file)) { - LWIP_DEBUGF(SOCKETS_DEBUG, - ("failed to identify socket descriptor\n")); - ret = -1; - SOCK_NET_SET_ERRNO(PTR2ERR(file)); - goto EXIT; - } - ret = lwip_sendto(file->sock_fd, dataptr, size, flags, to, tolen); - vfscore_put_file(file->vfscore_file); /* release refcount */ + int ret = 0; + struct lwip_socket *lwip_sock; + + /* Transform the socket descriptor to the lwip_socket pointer. */ + lwip_sock = (struct lwip_socket *)sock; + if (lwip_sock->lwip_fd < 0) { + ret = -1; + SOCKET_LIB_ERR(d, ret, "failed to identify socket descriptor"); + goto EXIT; + } + + /* Close an incoming connection using LwIP */ + ret = lwip_ioctl(lwip_sock->lwip_fd, request, argp); + if (ret < 0) + ret = -1; + EXIT: - return ret; + return ret; } -int socketpair(int domain, int type, int protocol, int sv[2]) -{ - errno = ENOTSUP; - return -1; -} +static struct posix_socket_ops lwip_socket_ops = { + /* The initialization function on socket registration. */ + .init = lwip_lib_socket_init, + /* POSIX interfaces */ + .create = lwip_glue_create, + .accept = lwip_glue_accept, + .bind = lwip_glue_bind, + .shutdown = lwip_glue_shutdown, + .getpeername = lwip_glue_getpeername, + .getsockname = lwip_glue_getsockname, + .getsockopt = lwip_glue_getsockopt, + .setsockopt = lwip_glue_setsockopt, + .connect = lwip_glue_connect, + .listen = lwip_glue_listen, + .recv = lwip_glue_recv, + .recvfrom = lwip_glue_recvfrom, + .recvmsg = lwip_glue_recvmsg, + .send = lwip_glue_send, + .sendmsg = lwip_glue_sendmsg, + .sendto = lwip_glue_sendto, + /* vfscore ops */ + .read = lwip_glue_read, + .write = lwip_glue_write, + .close = lwip_glue_close, + .ioctl = lwip_glue_ioctl, +}; + +POSIX_SOCKET_FAMILY_REGISTER(AF_INET, &lwip_socket_ops, NULL); + +#ifdef CONFIG_LWIP_IPV6 +POSIX_SOCKET_FAMILY_REGISTER(AF_INET6, &lwip_socket_ops, NULL); +#endif /* CONFIG_LWIP_IPV6 */ \ No newline at end of file -- 2.20.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |