[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[UNIKRAFT PATCH 1/3] lib/posix-socket: Introduce abstraction for communication sockets



From: Alexander Jung <alexander.jung@xxxxxxxxx>

This initial commit introduces a microlibrary to manage multiple
implementations of POSIX compliant sockets.  By exposing global
prototypes as an abstraction, the microlibrary can interchange
between AF socket families.  For example, an implementation
for AF_INET can register against this microlibrary in order to
communicate over the IP/TCP stack.

Signed-off-by: Alexander Jung <alexander.jung@xxxxxxxxx>
---
 lib/posix-socket/Config.uk                  |   18 +
 lib/posix-socket/Makefile.uk                |   10 +
 lib/posix-socket/driver.c                   |  154 +++
 lib/posix-socket/exportsyms.uk              |   26 +
 lib/posix-socket/extra.ld                   |    9 +
 lib/posix-socket/include/uk/socket.h        |   45 +
 lib/posix-socket/include/uk/socket_driver.h | 1018 +++++++++++++++++++
 lib/posix-socket/include/uk/socket_vnops.h  |   97 ++
 lib/posix-socket/socket.c                   |  722 +++++++++++++
 lib/posix-socket/socket_vnops.c             |  323 ++++++
 10 files changed, 2422 insertions(+)
 create mode 100644 lib/posix-socket/Config.uk
 create mode 100644 lib/posix-socket/Makefile.uk
 create mode 100644 lib/posix-socket/driver.c
 create mode 100644 lib/posix-socket/exportsyms.uk
 create mode 100644 lib/posix-socket/extra.ld
 create mode 100644 lib/posix-socket/include/uk/socket.h
 create mode 100644 lib/posix-socket/include/uk/socket_driver.h
 create mode 100644 lib/posix-socket/include/uk/socket_vnops.h
 create mode 100644 lib/posix-socket/socket.c
 create mode 100644 lib/posix-socket/socket_vnops.c

diff --git a/lib/posix-socket/Config.uk b/lib/posix-socket/Config.uk
new file mode 100644
index 0000000..bf99f17
--- /dev/null
+++ b/lib/posix-socket/Config.uk
@@ -0,0 +1,18 @@
+menuconfig LIBPOSIX_SOCKET
+       bool "posix-socket: Abstraction for communication sockets"
+       default n
+       select LIBUKDEBUG
+       select LIBUKALLOC
+  select LIBFDTABLE
+       help
+               This microlibrary allows other microlibraries to register a 
socket family 
+               number, such as AF_INET, for their socket implementation and 
provides the 
+               POSIX socket API unikernel-wide and acts appropriately on a 
given file 
+               descriptor.  
+               
+               The API includes prototypes for socket(), accept(), bind(), 
shutdown(), 
+               connect(), listen(), send(), sendmsg(), sendto(), recv(), 
recvfrom(), 
+               recvmsg(), getpeername(), getsockname(), getsockopt() and 
setsockopt().
+
+if LIBPOSIX_SOCKET
+endif
diff --git a/lib/posix-socket/Makefile.uk b/lib/posix-socket/Makefile.uk
new file mode 100644
index 0000000..a9beee0
--- /dev/null
+++ b/lib/posix-socket/Makefile.uk
@@ -0,0 +1,10 @@
+$(eval $(call addlib_s,libposix_socket,$(CONFIG_LIBPOSIX_SOCKET)))
+
+LIBPOSIX_SOCKET_COMMON_INCLUDES-y += -I$(LIBPOSIX_SOCKET_BASE)/include
+
+CINCLUDES-$(CONFIG_LIBPOSIX_SOCKET) += $(LIBPOSIX_SOCKET_COMMON_INCLUDES-y)
+CXXINCLUDES-$(CONFIG_LIBPOSIX_SOCKET) += $(LIBPOSIX_SOCKET_COMMON_INCLUDES-y)
+
+LIBPOSIX_SOCKET_SRCS-$(CONFIG_LIBPOSIX_SOCKET) += 
$(LIBPOSIX_SOCKET_BASE)/driver.c
+LIBPOSIX_SOCKET_SRCS-$(CONFIG_LIBPOSIX_SOCKET) += 
$(LIBPOSIX_SOCKET_BASE)/socket_vnops.c
+LIBPOSIX_SOCKET_SRCS-$(CONFIG_LIBPOSIX_SOCKET) += 
$(LIBPOSIX_SOCKET_BASE)/socket.c
diff --git a/lib/posix-socket/driver.c b/lib/posix-socket/driver.c
new file mode 100644
index 0000000..ad01241
--- /dev/null
+++ b/lib/posix-socket/driver.c
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Alexander Jung <alexander.jung@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR SOCKETINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * 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.
+ */
+
+#include <inttypes.h>
+#include <uk/alloc.h>
+#include <uk/assert.h>
+#include <uk/print.h>
+#include <uk/list.h>
+#include <uk/socket_driver.h>
+#include <sys/types.h>
+
+/**
+ * List of socket family drivers
+ */
+UK_TAILQ_HEAD(posix_socket_driver_list, struct posix_socket_driver);
+struct posix_socket_driver_list posix_socket_families =
+          UK_TAILQ_HEAD_INITIALIZER(posix_socket_families);
+static uint16_t uk_posix_socket_family_count;
+
+unsigned int
+posix_socket_family_count(void)
+{
+  return uk_posix_socket_family_count;
+}
+
+void _posix_socket_family_register(struct posix_socket_driver *d,
+          int fam,
+          struct posix_socket_ops *ops,
+          struct uk_alloc *alloc)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(ops);
+
+  if (unlikely(fam == 0)) {
+    uk_pr_crit("Cannot register unspecified socket family: %p\n", ops);
+    return;
+  }
+
+  uk_pr_debug("Registering socket handler: library: %s, family: %d: %p...\n", 
d->libname, fam, ops);
+
+  struct posix_socket_driver *e;
+  UK_TAILQ_FOREACH(e, &posix_socket_families, _list) {
+    if (e->af_family == fam) {
+      uk_pr_warn("Socket family (%d) already registerd to library %s!", fam, 
e->libname);
+      return;
+    }
+  }
+
+  new_posix_socket_family(d, fam, alloc, ops);
+  UK_TAILQ_INSERT_TAIL(&posix_socket_families, d, _list);
+  uk_posix_socket_family_count++;
+}
+
+void
+_posix_socket_family_unregister(struct posix_socket_driver *d)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(uk_posix_socket_family_count > 0);
+
+  uk_pr_debug("Unregistering socket handler: %d\n", d->af_family);
+
+       UK_TAILQ_REMOVE(&posix_socket_families, d, _list);
+  uk_posix_socket_family_count--;
+}
+
+static int
+posix_socket_family_init(struct posix_socket_driver *d)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops);
+
+  uk_pr_debug("Initializing socket handler: %d\n", d->af_family);
+
+  /* Assign the default allocator if not specified */
+  if (d->allocator == NULL) {
+    d->allocator = uk_alloc_get_default();
+    uk_pr_debug("Using default memory allocator for socket family: %d: %p\n", 
d->af_family, d->allocator);
+  }
+
+  if (!d->ops->init)
+    return 0;
+
+  return d->ops->init(d);
+}
+
+/* Returns the number of successfully initialized device sockets */
+static int
+posix_socket_family_lib_init(void)
+{
+  uk_pr_info("Initializing socket handlers...\n");
+  
+       struct posix_socket_driver *d;
+  unsigned int ret = 0;
+ 
+  if (posix_socket_family_count() == 0)
+    return 0;
+
+  UK_TAILQ_FOREACH(d, &posix_socket_families, _list) {
+    if (posix_socket_family_init(d) >= 0)
+      ++ret;
+  }
+
+  return ret;
+}
+
+struct posix_socket_driver *
+posix_socket_driver_get(int af_family)
+{
+  struct posix_socket_driver *d;
+
+  UK_TAILQ_FOREACH(d, &posix_socket_families, _list) {
+    if (d->af_family == af_family)
+      return d;
+  }
+
+  return NULL;
+}
+
+struct posix_socket_driver *
+posix_socket_get_family(int sock)
+{
+  return NULL;
+}
+
+uk_initcall_class_prio(posix_socket_family_lib_init, 
POSIX_SOCKET_FAMILY_INIT_CLASS, POSIX_SOCKET_FAMILY_INIT_PRIO);
diff --git a/lib/posix-socket/exportsyms.uk b/lib/posix-socket/exportsyms.uk
new file mode 100644
index 0000000..f2e2f37
--- /dev/null
+++ b/lib/posix-socket/exportsyms.uk
@@ -0,0 +1,26 @@
+posix_socket
+posix_socket_get_family
+posix_socket_family_count
+_posix_socket_family_register
+_posix_socket_family_unregister
+socket_alloc_fd
+
+# Full socket API
+socket
+accept
+bind
+shutdown
+getpeername
+getsockname
+getnameinfo
+getsockopt
+setsockopt
+connect
+listen
+recv
+recvfrom
+recvmsg
+send
+sendmsg
+sendto
+socketpair
diff --git a/lib/posix-socket/extra.ld b/lib/posix-socket/extra.ld
new file mode 100644
index 0000000..78346f1
--- /dev/null
+++ b/lib/posix-socket/extra.ld
@@ -0,0 +1,9 @@
+SECTIONS
+{
+       .posix_socket_driver_list : {
+               PROVIDE(posix_socket_driver_list_start = .);
+               KEEP (*(.posix_socket_driver_list))
+    PROVIDE(posix_socket_driver_list_end = .);
+       }
+}
+INSERT AFTER .text;
diff --git a/lib/posix-socket/include/uk/socket.h 
b/lib/posix-socket/include/uk/socket.h
new file mode 100644
index 0000000..9cd420a
--- /dev/null
+++ b/lib/posix-socket/include/uk/socket.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Alexander Jung <alexander.jung@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, NEC Corporation.
+ *                     All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * 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.
+ */
+#ifndef __UK_SOCKET__
+#define __UK_SOCKET__
+
+#include <uk/socket_driver.h>
+#include <uk/socket_vnops.h>
+
+#define SOCKET_LIB_ERR(d, errno, msg) \
+  uk_pr_err("%s_err: %d: %s", d->libname, errno, msg)
+
+#define SOCKET_ERR(errno, msg) \
+  uk_pr_err("%d: %s", errno, msg)
+
+#endif /* __UK_SOCKET__ */
diff --git a/lib/posix-socket/include/uk/socket_driver.h 
b/lib/posix-socket/include/uk/socket_driver.h
new file mode 100644
index 0000000..2a9226f
--- /dev/null
+++ b/lib/posix-socket/include/uk/socket_driver.h
@@ -0,0 +1,1018 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Alexander Jung <alexander.jung@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, NEC Corporation.
+ *                     All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * 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.
+ */
+
+#ifndef __UK_SOCKET_DRIVER_H__
+#define __UK_SOCKET_DRIVER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <uk/list.h>
+#include <uk/assert.h>
+#include <uk/init.h>
+#include <uk/list.h>
+#include <uk/ctors.h>
+#include <uk/alloc.h>
+#include <uk/essentials.h>
+#include <errno.h>
+#include <sys/socket.h>
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define __NEED_socklen_t
+#include <bits/alltypes.h>
+#endif
+
+#define POSIX_SOCKET_FAMILY_INIT_CLASS UK_INIT_CLASS_EARLY
+#define POSIX_SOCKET_FAMILY_INIT_PRIO 0
+#define POSIX_SOCKET_FAMILY_REGISTER_PRIO 2
+
+struct posix_socket_ops;
+struct posix_socket_driver;
+
+/**
+ * The POSIX socket driver defines the operations to be used for the
+ * specified AF family as well as the memory allocator.
+ */
+struct posix_socket_driver {
+  /* The AF family ID */
+       const int af_family;
+  const char *libname;
+  /* The interfaces for this socket */
+       const struct posix_socket_ops *ops;
+  /* The memory allocator to be used for this socket driver */
+  struct uk_alloc *allocator;
+  /* Private data for this socket driver. */
+  void *private;
+  /* Entry for list of socket drivers. */
+       UK_TAILQ_ENTRY(struct posix_socket_driver) _list;
+};
+
+
+/**
+ * The initialization function called for this socket family.  It's here that
+ * additional configuration for the driver can be made after it has been
+ * registered.  For instance, an alternative memory allocator can be provided.
+ *
+ * @param d
+ *  The socket driver.
+ */
+typedef int (*posix_socket_driver_init_func_t)(struct posix_socket_driver *d);
+
+/**
+ * Create a connection on a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param family
+ *  Specifies a communication family domain and thus driver.
+ * @param type
+ *  Specifies communication semantics.
+ * @param protocol
+ *  Specifies a particular protocol to be used with the socket. 
+ */
+typedef void *(*posix_socket_create_func_t)(struct posix_socket_driver *d,
+          int family, int type, int protocol);
+
+
+/**
+ * Accept a connection on a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param addr
+ *  The address of the peer socket.
+ * @param addr_len
+ *  Specifies the size, in bytes, of the address structure pointed to by addr.
+ */
+typedef void *(*posix_socket_accept_func_t)(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len);
+
+
+/**
+ * Bind a name to a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param addr
+ *  The assigned address.
+ * @param addr_len
+ *  Specifies the size, in bytes, of the address structure pointed to by addr.
+ */
+typedef int (*posix_socket_bind_func_t)(struct posix_socket_driver *d,
+          void *sock, const struct sockaddr *addr, socklen_t addr_len);
+
+
+/**
+ * Shut down part of a full-duplex connection.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param how
+ *  The flag to specify the means of shuting down the socket.
+ */
+typedef int (*posix_socket_shutdown_func_t)(struct posix_socket_driver *d,
+          void *sock, int how);
+
+
+/**
+ * Get name of connected peer socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param addr
+ *  The assigned address.
+ * @param addr_len
+ *  Specifies the size, in bytes, of the address structure pointed to by addr.
+ */
+typedef int (*posix_socket_getpeername_func_t)(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len);
+
+
+/**
+ * Get socket name.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param addr
+ *  The assigned address.
+ * @param addr_len
+ *  Specifies the size, in bytes, of the address structure pointed to by addr.
+ */
+typedef int (*posix_socket_getsockname_func_t)(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len);
+
+/**
+ * Get socket name.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param addr
+ *  The assigned address.
+ * @param addr_len
+ *  Specifies the size, in bytes, of the address structure pointed to by addr.
+ */
+typedef int (*posix_socket_getnameinfo_func_t)(struct posix_socket_driver *d,
+          const struct sockaddr *restrict sa, socklen_t sl, char *restrict 
node,
+          socklen_t nodelen, char *restrict serv, socklen_t servlen, int 
flags);
+
+/**
+ * Get options on the socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param level
+ *  Maniipulate the socket at either the API level or protocol level.
+ * @param optname
+ *  Any specified options are passed uninterpreted to the appropriate protocol
+ *  module for interpretation.
+ * @param optval
+ *  The option value.
+ * @param optlen
+ *  The option value length.
+ */
+typedef int (*posix_socket_getsockopt_func_t)(struct posix_socket_driver *d,
+          void *sock, int level, int optname, void *restrict optval,
+          socklen_t *restrict optlen);
+
+
+/**
+ * Set options on the socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param level
+ *  Maniipulate the socket at either the API level or protocol level.
+ * @param optname
+ *  Any specified options are passed uninterpreted to the appropriate protocol
+ *  module for interpretation.
+ * @param optval
+ *  The option value.
+ * @param optlen
+ *  The option value length.
+ */
+typedef int (*posix_socket_setsockopt_func_t)(struct posix_socket_driver *d,
+          void *sock, int level, int optname, const void *optval,
+          socklen_t optlen);
+
+
+/**
+ * Initiate a connection on a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param addr
+ *  The address to connect to on the socket.
+ * @param addr_len
+ *  Specifies the size, in bytes, of the address structure pointed to by addr.
+ */
+typedef int (*posix_socket_connect_func_t)(struct posix_socket_driver *d,
+          void *sock, const struct sockaddr *addr, socklen_t addr_len);
+
+
+/**
+ * Listen for connections on a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param backlog
+ *  Defines the maximum length to which the queue of pending connections for 
+ *  the socket.
+ */
+typedef int (*posix_socket_listen_func_t)(struct posix_socket_driver *d,
+          void *sock, int backlog);
+
+
+/**
+ * Receive a message from a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param buf
+ *  The buffer for recieved data from the socket.
+ * @param len
+ *  The size of the buffer.
+ * @param flags
+ *  Bitwise OR of zero or more flags for the socket.
+ */
+typedef ssize_t (*posix_socket_recv_func_t)(struct posix_socket_driver *d,
+          void *sock, void *buf, size_t len, int flags);
+
+
+/**
+ * Read from a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param buf
+ *  The buffer for recieved data from the socket.
+ * @param len
+ *  The size of the buffer.
+ * @param flags
+ *  Bitmap of options for receiving a message.
+ * @param from
+ *  The source address.
+ * @param fromlen
+ *  The source address length.
+ */
+typedef ssize_t (*posix_socket_recvfrom_func_t)(struct posix_socket_driver *d,
+          void *sock, void *restrict buf, size_t len, int flags,
+          struct sockaddr *from, socklen_t *restrict fromlen);
+
+
+/**
+ * Read from a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param msg
+ *  Message structure to minimize the number of directly supplied arguments.
+ * @param flags
+ *  Bitwise OR of zero or more flags for the socket.
+ */
+typedef ssize_t (*posix_socket_recvmsg_func_t)(struct posix_socket_driver *d,
+          void *sock, struct msghdr *msg, int flags);
+
+
+/**
+ * Send a message on a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param buf
+ *  The buffer for sending data to the socket.
+ * @param len
+ *  The length of the data to send on the socket.
+ * @param flags
+ *  Bitwise OR of zero or more flags for the socket.
+ */
+typedef ssize_t (*posix_socket_send_func_t)(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t len, int flags);
+
+
+/**
+ * Send a message on a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param msg
+ *  Message structure to minimize the number of directly supplied arguments.
+ * @param flags
+ *  Bitwise OR of zero or more flags for the socket.
+ */
+typedef ssize_t (*posix_socket_sendmsg_func_t)(struct posix_socket_driver *d,
+          void *sock, const struct msghdr *msg, int flags);
+
+
+/**
+ * Send a message on a socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ * @param buf
+ *  The buffer for sending data to the socket.
+ * @param len
+ *  The length of the data to send on the socket.
+ * @param flags
+ *  Bitwise OR of zero or more flags for the socket.
+ * @param dest_addr
+ *  The destination address to send data.
+ * @param addrlen
+ *  The length of the address to send data to.
+ */
+typedef ssize_t (*posix_socket_sendto_func_t)(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t len, int flags,
+          const struct sockaddr *dest_addr, socklen_t addrlen);
+
+
+/**
+ * Create a pair of connected sockets.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param family
+ *  The domain of the sockets.
+ * @param type
+ *  The specified type of the sockets.
+ * @param protocol
+ *  Optionally the protocol.
+ * @param usockvec
+ *  The structure used in referencing the new sockets are returned in
+ *  usockvec[0] and usockvec[1].
+ */
+typedef int (*posix_socket_socketpair_func_t)(struct posix_socket_driver *d,
+          int family, int type, int protocol, void **usockvec);
+
+
+/**
+ * Read from a socket file descriptor.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param buf
+ *  The buffer to read the data from the socket into.
+ * @param count
+ *  The number of bytes to be read.
+ */
+typedef int (*posix_socket_read_func_t)(struct posix_socket_driver *d,
+          void *sock, void *buf, size_t count);
+
+
+/**
+ * Write to a socket file descriptor.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param buf
+ *  The pointer to the buffer to write to the socket.
+ * @param count
+ *  The number of bytes to be written.
+ */
+typedef int (*posix_socket_write_func_t)(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t count);
+
+/**
+ * Close the socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @param sock
+ *  Reference to the socket.
+ */
+typedef int (*posix_socket_close_func_t)(struct posix_socket_driver *d,
+          void *sock);
+
+
+/**
+ * Manipulate the socket.
+ *
+ * @param driver
+ *  The socket driver.
+ * @TODO
+ */
+typedef int (*posix_socket_ioctl_func_t)(struct posix_socket_driver *d,
+          void *sock, int request, void *argp);
+
+
+/**
+ * A structure containing the functions exported by the Unikraft socket driver
+ */
+struct posix_socket_ops {
+  /* The initialization function on socket registration. */
+  posix_socket_driver_init_func_t   init;
+  /* POSIX interfaces */
+  posix_socket_create_func_t        create;
+  posix_socket_accept_func_t        accept;
+  posix_socket_bind_func_t          bind;
+  posix_socket_shutdown_func_t      shutdown;
+  posix_socket_getpeername_func_t   getpeername;
+  posix_socket_getsockname_func_t   getsockname;
+  posix_socket_getnameinfo_func_t   getnameinfo;
+  posix_socket_getsockopt_func_t    getsockopt;
+  posix_socket_setsockopt_func_t    setsockopt;
+  posix_socket_connect_func_t       connect;
+  posix_socket_listen_func_t        listen;
+  posix_socket_recv_func_t          recv;
+  posix_socket_recvfrom_func_t      recvfrom;
+  posix_socket_recvmsg_func_t       recvmsg;
+  posix_socket_send_func_t          send;
+  posix_socket_sendmsg_func_t       sendmsg;
+  posix_socket_sendto_func_t        sendto;
+  posix_socket_socketpair_func_t    socketpair;
+  /* vfscore ops */
+  posix_socket_read_func_t          read;
+  posix_socket_write_func_t         write;
+  posix_socket_close_func_t         close;
+  posix_socket_ioctl_func_t         ioctl;
+};
+
+static inline void *
+posix_socket_do_create(struct posix_socket_driver *d,
+          int family, int type, int protocol)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->create);
+  return d->ops->create(d, family, type, protocol);
+}
+
+static inline void *
+posix_socket_create(struct posix_socket_driver *d,
+          int family, int type, int protocol)
+{
+  if (unlikely(!d))
+    return NULL;
+
+  return posix_socket_do_create(d, family, type, protocol);
+}
+
+static inline void *
+posix_socket_do_accept(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->accept);
+  return d->ops->accept(d, sock, addr, addr_len);
+}
+
+static inline void *
+posix_socket_accept(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  if (unlikely(!d))
+    return NULL;
+
+  return posix_socket_do_accept(d, sock, addr, addr_len);
+}
+
+
+static inline int
+posix_socket_do_bind(struct posix_socket_driver *d,
+          void *sock, const struct sockaddr *addr, socklen_t addr_len)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->bind);
+  return d->ops->bind(d, sock, addr, addr_len);
+}
+
+static inline int
+posix_socket_bind(struct posix_socket_driver *d,
+          void *sock, const struct sockaddr *addr, socklen_t addr_len)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_bind(d, sock, addr, addr_len);
+}
+
+
+static inline int
+posix_socket_do_shutdown(struct posix_socket_driver *d,
+          void *sock, int how)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->shutdown);
+       return d->ops->shutdown(d, sock, how);
+}
+
+static inline int
+posix_socket_shutdown(struct posix_socket_driver *d,
+          void *sock, int how)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_shutdown(d, sock, how);
+}
+
+
+static inline int
+posix_socket_do_getpeername(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->getpeername);
+       return d->ops->getpeername(d, sock, addr, addr_len);
+}
+
+static inline int
+posix_socket_getpeername(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_getpeername(d, sock, addr, addr_len);
+}
+
+
+static inline int
+posix_socket_do_getsockname(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->getsockname);
+       return d->ops->getsockname(d, sock, addr, addr_len);
+}
+
+static inline int
+posix_socket_getsockname(struct posix_socket_driver *d,
+          void *sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_getsockname(d, sock, addr, addr_len);
+}
+
+
+static inline int
+posix_socket_do_getnameinfo(struct posix_socket_driver *d,
+          const struct sockaddr *restrict sa, socklen_t sl, char *restrict 
node,
+          socklen_t nodelen, char *restrict serv, socklen_t servlen, int flags)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->getnameinfo);
+       return d->ops->getnameinfo(d, sa, sl, node, nodelen, serv, servlen, 
flags);
+}
+
+static inline int
+posix_socket_getnameinfo(struct posix_socket_driver *d,
+          const struct sockaddr *restrict sa, socklen_t sl, char *restrict 
node,
+          socklen_t nodelen, char *restrict serv, socklen_t servlen, int flags)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_getnameinfo(d, sa, sl, node, nodelen, serv, servlen,
+          flags);
+}
+
+
+static inline int
+posix_socket_do_getsockopt(struct posix_socket_driver *d,
+          void *sock, int level, int optname, void *restrict optval,
+          socklen_t *restrict optlen)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->getsockopt);
+  return d->ops->getsockopt(d, sock, level, optname, optval, optlen);
+}
+
+static inline int
+posix_socket_getsockopt(struct posix_socket_driver *d,
+          void *sock, int level, int optname, void *restrict optval,
+          socklen_t *restrict optlen)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_getsockopt(d, sock, level, optname, optval, optlen);
+}
+
+
+static inline int
+
+posix_socket_do_setsockopt(struct posix_socket_driver *d,
+          void *sock, int level, int optname, const void *optval,
+          socklen_t optlen)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->setsockopt);
+  return d->ops->setsockopt(d, sock, level, optname, optval, optlen);
+}
+
+static inline int
+posix_socket_setsockopt(struct posix_socket_driver *d,
+          void *sock, int level, int optname, const void *optval,
+          socklen_t optlen)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_setsockopt(d, sock, level, optname, optval, optlen);
+}
+
+
+static inline int
+posix_socket_do_connect(struct posix_socket_driver *d,
+          void *sock, const struct sockaddr *addr, socklen_t addr_len)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->connect);
+  return d->ops->connect(d, sock, addr, addr_len);
+}
+
+static inline int
+posix_socket_connect(struct posix_socket_driver *d,
+          void *sock, const struct sockaddr *addr, socklen_t addr_len)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_connect(d, sock, addr, addr_len);
+}
+
+
+static inline int
+posix_socket_do_listen(struct posix_socket_driver *d,
+          void *sock, int backlog)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->listen);
+  return d->ops->listen(d, sock, backlog);
+}
+
+static inline int
+posix_socket_listen(struct posix_socket_driver *d,
+          void *sock, int backlog)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_listen(d, sock, backlog);
+}
+
+
+static inline ssize_t
+posix_socket_do_recv(struct posix_socket_driver *d,
+          void *sock, void *buf, size_t len, int flags)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->recv);
+  return d->ops->recv(d, sock, buf, len, flags);
+}
+
+static inline ssize_t
+posix_socket_recv(struct posix_socket_driver *d,
+          void *sock, void *buf, size_t len, int flags)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_recv(d, sock, buf, len, flags);
+}
+
+
+static inline ssize_t
+posix_socket_do_recvfrom(struct posix_socket_driver *d,
+          void *sock, void *buf, size_t len, int flags, struct sockaddr *from, 
+          socklen_t *fromlen)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->recvfrom);
+  return d->ops->recvfrom(d, sock, buf, len, flags, from, fromlen);
+}
+
+static inline ssize_t
+posix_socket_recvfrom(struct posix_socket_driver *d,
+          void *sock, void *restrict buf, size_t len, int flags,
+          struct sockaddr *from, socklen_t *fromlen)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_recvfrom(d, sock, buf, len, flags, from, fromlen);
+}
+
+
+static inline ssize_t
+posix_socket_do_recvmsg(struct posix_socket_driver *d,
+          void *sock, struct msghdr *msg, int flags)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->recvmsg);
+  return d->ops->recvmsg(d, sock, msg, flags);
+}
+
+static inline ssize_t
+posix_socket_recvmsg(struct posix_socket_driver *d,
+          void *sock, struct msghdr *msg, int flags)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_recvmsg(d, sock, msg, flags);
+}
+
+
+static inline ssize_t
+posix_socket_do_send(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t len, int flags)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->send);
+  return d->ops->send(d, sock, buf, len, flags);
+}
+
+static inline ssize_t
+posix_socket_send(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t len, int flags)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_send(d, sock, buf, len, flags);
+}
+
+
+static inline ssize_t
+posix_socket_do_sendmsg(struct posix_socket_driver *d,
+          void *sock, const struct msghdr *msg, int flags)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->sendmsg);
+  return d->ops->sendmsg(d, sock, msg, flags);
+}
+
+static inline ssize_t
+posix_socket_sendmsg(struct posix_socket_driver *d,
+          void *sock, const struct msghdr *msg, int flags)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_sendmsg(d, sock, msg, flags);
+}
+
+
+static inline ssize_t
+posix_socket_do_sendto(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t len, int flags,
+          const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->sendto);
+  return d->ops->sendto(d, sock, buf, len, flags, dest_addr, addrlen);
+}
+
+static inline ssize_t
+posix_socket_sendto(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t len, int flags,
+          const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_sendto(d, sock, buf, len, flags, dest_addr, addrlen);
+}
+
+
+static inline int
+posix_socket_do_socketpair(struct posix_socket_driver *d,
+          int family, int type, int protocol, void **usockvec)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->socketpair);
+  return d->ops->socketpair(d, family, type, protocol, usockvec);
+}
+
+static inline int
+posix_socket_socketpair(struct posix_socket_driver *d,
+          int family, int type, int protocol, void **usockvec)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_socketpair(d, family, type, protocol, usockvec);
+}
+
+
+static inline int
+posix_socket_do_read(struct posix_socket_driver *d,
+          void *sock, void *buf, size_t count)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->read);
+  return d->ops->read(d, sock, buf, count);
+}
+
+static inline int
+posix_socket_read(struct posix_socket_driver *d,
+          void *sock, void *buf, size_t count)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_read(d, sock, buf, count);
+}
+
+
+static inline int
+posix_socket_do_write(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t count)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->write);
+  return d->ops->write(d, sock, buf, count); 
+}
+
+static inline int
+posix_socket_write(struct posix_socket_driver *d,
+          void *sock, const void *buf, size_t count)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_write(d, sock, buf, count);
+}
+
+
+static inline int
+posix_socket_do_close(struct posix_socket_driver *d,
+          void *sock)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->close);
+  return d->ops->close(d, sock);
+}
+
+static inline int
+posix_socket_close(struct posix_socket_driver *d,
+          void *sock)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_close(d, sock);
+}
+
+
+static inline int
+posix_socket_do_ioctl(struct posix_socket_driver *d,
+          void *sock, int request, void *argp)
+{
+  UK_ASSERT(d);
+  UK_ASSERT(d->ops->ioctl);
+  return d->ops->ioctl(d, sock, request, argp);
+}
+
+static inline int
+posix_socket_ioctl(struct posix_socket_driver *d,
+          void *sock, int request, void *argp)
+{
+  if (unlikely(!d))
+    return -ENOSYS;
+
+  return posix_socket_do_ioctl(d, sock, request, argp);
+}
+
+/**
+ * Return the driver to the corresponding AF family number
+ *
+ * @param af_family
+ *  Af family number
+ */
+struct posix_socket_driver *
+posix_socket_driver_get(int af_family);
+
+/**
+ * Shortcut for doing a registration a socket to an AF number.
+ */
+#define new_posix_socket_family(d, fam, alloc, ops) \
+  do {                                              \
+    (d)->allocator = (alloc);                       \
+    (d)->ops       = (ops);                         \
+  } while(0)
+
+/**
+ * Returns the number of registered sockets.
+ */
+unsigned int
+posix_socket_family_count(void);
+
+/* Do not use this function directly */
+void
+_posix_socket_family_register(struct posix_socket_driver *d,
+          int fam,
+          struct posix_socket_ops *ops,
+          struct uk_alloc *alloc);
+
+/**
+ * Registers a socket family driver to the socket system.
+ */
+#define _POSIX_SOCKET_FAMILY_REGISTER_CTOR(fam, ctor) \
+  UK_CTOR_PRIO(ctor, POSIX_SOCKET_FAMILY_REGISTER_PRIO)
+
+#define _POSIX_SOCKET_FAMILY_REGFNNAME(x, y) x##_posix_socket_af_##y##_register
+#define _POSIX_SOCKET_FAMILY_DRVRNAME(x, y) x##_posix_socket_af_##y
+
+/*
+ * Creates a static struct posix_socket_driver with a unique name for the AF
+ * family which can later be referenced.
+ */
+#define _POSIX_SOCKET_FAMILY_REGISTER(lib, fam, ops, alloc)                    
 \
+  static struct posix_socket_driver _POSIX_SOCKET_FAMILY_DRVRNAME(lib, fam) = 
{ \
+    .af_family = fam,                                                          
 \
+    .libname   = STRINGIFY(lib)                                                
 \
+  };                                                                           
 \
+  static void                                                                  
 \
+  _POSIX_SOCKET_FAMILY_REGFNNAME(lib, fam)(void)                               
 \
+  {                                                                            
 \
+    _posix_socket_family_register(&_POSIX_SOCKET_FAMILY_DRVRNAME(lib, fam),    
 \
+        fam, ops, alloc);                                                      
 \
+  }                                                                            
 \
+  _POSIX_SOCKET_FAMILY_REGISTER_CTOR(fam, _POSIX_SOCKET_FAMILY_REGFNNAME(lib, 
fam))
+
+#define POSIX_SOCKET_FAMILY_REGISTER(fam, ops, alloc) \
+  _POSIX_SOCKET_FAMILY_REGISTER(__LIBNAME__, fam, ops, alloc)
+
+/* Do not use this function directly: */
+void
+_posix_socket_family_unregister(struct posix_socket_driver *driver);
+
+#ifdef __cplusplus
+}
+
+#endif /* __cplusplus */
+#endif /*  __UK_SOCKET_DRIVER_H__ */
\ No newline at end of file
diff --git a/lib/posix-socket/include/uk/socket_vnops.h 
b/lib/posix-socket/include/uk/socket_vnops.h
new file mode 100644
index 0000000..243622a
--- /dev/null
+++ b/lib/posix-socket/include/uk/socket_vnops.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Alexander Jung <alexander.jung@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, NEC Corporation.
+ *                     All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * 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.
+ */
+
+#ifndef __UK_SOCKET_VNOPS__
+#define __UK_SOCKET_VNOPS__
+
+#include <vfscore/file.h>
+#include <vfscore/vnode.h>
+
+struct posix_socket_driver;
+
+#define POSIX_SOCKET_SET_ERRNO(errcode) \
+  (errno = -(errcode))
+
+#define SOCKFILE_DATA_AS_INT(data) \
+  *((int *) data)
+
+struct posix_socket_file {
+  /* The fd or data used internaly by the socket implementation. */
+  void *sock_data;
+  /* Internal reference to the vfscore_file when not geenerally available. */
+       struct vfscore_file *vfs_file;
+  /* The driver to use for this socket. */
+  struct posix_socket_driver *driver;
+};
+
+int
+posix_socket_vfscore_close(struct vnode *s_vnode,
+          struct vfscore_file *vfscore_file);
+    
+int
+posix_socket_vfscore_read(struct vnode *s_vnode,
+          struct vfscore_file *vfscore_file __unused,
+          struct uio *buf, int ioflag __unused);
+int
+posix_socket_vfscore_write(struct vnode *s_vnode,
+          struct uio *buf, int ioflag __unused);
+int
+posix_socket_vfscore_ioctl(struct vnode *s_vnode,
+          struct vfscore_file *vfscore_file __unused,
+          unsigned long request,
+          void *buf);
+
+/**
+ *
+ */
+struct posix_socket_file *
+posix_socket_file_get(int sock_fd);
+
+/**
+ * 
+ */
+struct posix_socket_driver *
+posix_socket_get_family(int sock_fd);
+
+/**
+ * Allocate a file descriptor in vfscore for the given socket driver.
+ *
+ * @param d
+ *  The driver used to create the socket.
+ * @param sock_data
+ *  The socket implementation's private data.
+ */
+int
+socket_alloc_fd(struct posix_socket_driver *d, void *sock_data);
+
+#endif /* __UK_SOCKET_VNOPS__ */
diff --git a/lib/posix-socket/socket.c b/lib/posix-socket/socket.c
new file mode 100644
index 0000000..9634e29
--- /dev/null
+++ b/lib/posix-socket/socket.c
@@ -0,0 +1,722 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Alexander Jung <alexander.jung@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, NEC Corporation.
+ *                     All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <uk/socket.h>
+#include <uk/errptr.h>
+#include <uk/print.h>
+#include <uk/trace.h>
+#include <errno.h>
+
+UK_TRACEPOINT(trace_posix_socket_create, "%d %d %d", int, int, int);
+UK_TRACEPOINT(trace_posix_socket_create_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_create_err, "%d", int);
+
+int
+socket(int family, int type, int protocol)
+{
+  int ret = 0;
+  int vfs_fd = 0xff;
+  void *sock = NULL;
+  struct posix_socket_driver *d;
+
+  trace_posix_socket_create(family, type, protocol);
+
+  d = posix_socket_driver_get(family);
+  if (d == NULL) {
+    uk_pr_crit("no socket implementation for family: %d\n", family);
+    ret = -ENOSYS;
+    goto EXIT_ERR;
+  }
+
+  /* Create the socket using the driver */
+  sock = posix_socket_create(d, family, type, protocol);
+  if (sock == NULL) {
+    uk_pr_debug("failed to create socket %d\n", errno);
+    ret = -1;
+    goto EXIT_ERR;
+  }
+
+  /* Allocate the file descriptor */
+  vfs_fd = socket_alloc_fd(d, sock);
+  if (vfs_fd < 0) {
+    uk_pr_debug("failed to allocate descriptor %d\n", errno);
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(vfs_fd);
+    goto SOCKET_CLEANUP;
+  }
+
+  /* Returning the file descriptor to the user */
+  ret = vfs_fd;
+
+EXIT:
+  trace_posix_socket_create_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_create_err(ret);
+  return ret;
+SOCKET_CLEANUP:
+  posix_socket_close(d, sock);
+  goto EXIT;
+}
+
+UK_TRACEPOINT(trace_posix_socket_accept, "%d %p %p", int,
+          struct sockaddr *restrict, socklen_t *restrict);
+UK_TRACEPOINT(trace_posix_socket_accept_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_accept_err, "%d", int);
+
+int accept(int sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  int vfs_fd;
+  int ret = 0;
+  void *new_sock;
+       struct posix_socket_file *file;
+
+  trace_posix_socket_accept(sock, addr, addr_len);
+
+       file = posix_socket_file_get(sock);
+       if (PTRISERR(file)) {
+               uk_pr_debug("failed to retrieve socket file descriptor: %p\n", 
file);
+               ret = -1;
+               POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+               goto EXIT;
+       }
+
+       /* Accept an incoming connection */
+       new_sock = posix_socket_accept(file->driver, file->sock_data, addr, 
addr_len);
+       if (new_sock == NULL) {
+               uk_pr_debug("failed to accept incoming connection\n");
+               ret = -1;
+               goto EXIT_FDROP;
+       }
+
+       /* Allocate the file descriptor for the accepted connection */
+       vfs_fd = socket_alloc_fd(file->driver, new_sock);
+       if (vfs_fd < 0) {
+               uk_pr_debug("failed to allocate descriptor for accepted 
connection\n");
+               ret = -1;
+               POSIX_SOCKET_SET_ERRNO(vfs_fd);
+               goto SOCKET_CLEANUP;
+       }
+
+       ret = vfs_fd;
+
+EXIT_FDROP:
+       vfscore_put_file(file->vfs_file); /* release refcount */
+  trace_posix_socket_accept_err(ret);
+  return ret;
+EXIT:
+  trace_posix_socket_accept_ret(ret);
+       return ret;
+SOCKET_CLEANUP:
+  posix_socket_close(file->driver, file->sock_data);
+       goto EXIT_FDROP;
+}
+
+UK_TRACEPOINT(trace_posix_socket_bind, "%d %p %d", int, const struct sockaddr 
*,
+          socklen_t);
+UK_TRACEPOINT(trace_posix_socket_bind_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_bind_err, "%d", int);
+
+int bind(int sock, const struct sockaddr *addr, socklen_t addr_len)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_bind(sock, addr, addr_len);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Bind an incoming connection */
+  ret = posix_socket_bind(file->driver, file->sock_data, addr, addr_len);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+  
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to bind with socket\n", 
file->driver->libname);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_bind_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_bind_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_shutdown, "%d %d", int, int);
+UK_TRACEPOINT(trace_posix_socket_shutdown_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_shutdown_err, "%d", int);
+
+int shutdown(int sock, int how)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_shutdown(sock, how);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Shutdown socket */
+  ret = posix_socket_shutdown(file->driver, file->sock_data, how);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to shutdown socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_shutdown_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_shutdown_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_getpeername, "%d %p %d", int,
+          struct sockaddr *restrict, socklen_t *restrict);
+UK_TRACEPOINT(trace_posix_socket_getpeername_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_getpeername_err, "%d", int);
+
+int getpeername(int sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_getpeername(sock, addr, addr_len);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Get peern name of socket */
+  ret = posix_socket_getpeername(file->driver, file->sock_data, addr, 
addr_len);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to getpeername of socket\n", 
file->driver->libname);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_getpeername_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_getpeername_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_getsockname, "%d %p %p", int,
+          struct sockaddr *restrict, socklen_t *restrict);
+UK_TRACEPOINT(trace_posix_socket_getsockname_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_getsockname_err, "%d", int);
+
+int getsockname(int sock, struct sockaddr *restrict addr,
+          socklen_t *restrict addr_len)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_getsockname(sock, addr, addr_len);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Get socket name of socket */
+  ret = posix_socket_getsockname(file->driver, file->sock_data, addr, 
addr_len);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to getsockname of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_getsockname_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_getsockname_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_getsockopt, "%d %d %d %p %d", int, int, int,
+          void *, socklen_t *);
+UK_TRACEPOINT(trace_posix_socket_getsockopt_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_getsockopt_err, "%d", int);
+
+int getsockopt(int sock, int level, int optname, void *restrict optval,
+          socklen_t *restrict optlen)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_getsockopt(sock, level, optname, optval, optlen);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Get socket options */
+  ret = posix_socket_getsockopt(file->driver, file->sock_data, level, optname,
+          optval, optlen);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to getsockopt of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_getsockopt_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_getsockopt_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_setsockopt, "%d %d %d %p %d", int, int, int,
+          const void *, socklen_t);
+UK_TRACEPOINT(trace_posix_socket_setsockopt_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_setsockopt_err, "%d", int);
+
+int setsockopt(int sock, int level, int optname, const void *optval,
+          socklen_t optlen)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_setsockopt(sock, level, optname, optval, optlen);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Set socket options */
+  ret = posix_socket_setsockopt(file->driver, file->sock_data, level, optname,
+          optval, optlen);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to setsockopt of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_setsockopt_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_setsockopt_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_getnameinfo, "%p %d %s %d %s %d %d",
+          const struct sockaddr *, socklen_t, char *, socklen_t, char *,
+          socklen_t, int);
+UK_TRACEPOINT(trace_posix_socket_getnameinfo_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_getnameinfo_err, "%d", int);
+
+int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
+          char *restrict node, socklen_t nodelen, char *restrict serv,
+          socklen_t servlen, int flags)
+{
+  uk_pr_crit("%s: not implemented", __func__);
+  errno = ENOTSUP;
+  return -1;
+}
+
+UK_TRACEPOINT(trace_posix_socket_connect, "%d %p %d", int,
+          const struct sockaddr *, socklen_t);
+UK_TRACEPOINT(trace_posix_socket_connect_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_connect_err, "%d", int);
+
+int connect(int sock, const struct sockaddr *addr, socklen_t addr_len)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_connect(sock, addr, addr_len);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Connect to the socket */
+  ret = posix_socket_connect(file->driver, file->sock_data, addr, addr_len);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to connect to socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_connect_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_connect_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_listen, "%d %d", int, int);
+UK_TRACEPOINT(trace_posix_socket_listen_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_listen_err, "%d", int);
+
+int listen(int sock, int backlog)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_listen(sock, backlog);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Listen to the socket */
+  ret = posix_socket_listen(file->driver, file->sock_data, backlog);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to listen to socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_listen_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_listen_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_recv, "%d %p %d %d", int, void *, size_t, 
int);
+UK_TRACEPOINT(trace_posix_socket_recv_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_recv_err, "%d", int);
+
+ssize_t recv(int sock, void *buf, size_t len, int flags)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_recv(sock, buf, len, flags);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Recieve a buffer from a socket */
+  ret = posix_socket_recv(file->driver, file->sock_data, buf, len, flags);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to recv of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_recv_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_recv_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_recvfrom, "%d %p %d %d %p %p", int, void *,
+          size_t, int, struct sockaddr *, socklen_t *);
+UK_TRACEPOINT(trace_posix_socket_recvfrom_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_recvfrom_err, "%d", int);
+
+ssize_t recvfrom(int sock, void *buf, size_t len, int flags,
+          struct sockaddr *from, socklen_t *fromlen)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_recvfrom(sock, buf, len, flags, from, fromlen);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Recieve a buffer from a socket */
+  ret = posix_socket_recvfrom(file->driver, file->sock_data, buf, len, flags,
+          from, fromlen);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to recvfrom of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_recvfrom_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_recvfrom_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_recvmsg, "%d %p %d", int, struct msghdr*, 
int);
+UK_TRACEPOINT(trace_posix_socket_recvmsg_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_recvmsg_err, "%d", int);
+
+ssize_t recvmsg(int sock, struct msghdr *msg, int flags)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_recvmsg(sock, msg, flags);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Recieve a structured message from a socket */
+  ret = posix_socket_recvmsg(file->driver, file->sock_data, msg, flags);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to recvmsg of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_recvmsg_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_recvmsg_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_send, "%d %p %d %d", int, const void *, 
size_t,
+          int);
+UK_TRACEPOINT(trace_posix_socket_send_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_send_err, "%d", int);
+
+ssize_t send(int sock, const void *buf, size_t len, int flags)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_send(sock, buf, len, flags);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Send a structured message to a sockets */
+  ret = posix_socket_send(file->driver, file->sock_data, buf, len, flags);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to send of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_send_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_send_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_sendmsg, "%d %p %d", int, const struct 
msghdr*,
+          int);
+UK_TRACEPOINT(trace_posix_socket_sendmsg_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_sendmsg_err, "%d", int);
+
+ssize_t sendmsg(int sock, const struct msghdr *msg, int flags)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_sendmsg(sock, msg, flags);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Send a structured message to a sockets */
+  ret = posix_socket_sendmsg(file->driver, file->sock_data, msg, flags);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to sendmsg of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_sendmsg_ret(ret);
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_sendmsg_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_sendto, "%d %p %d %d %p %d", int, const void 
*,
+          size_t, int, const struct sockaddr *, socklen_t);
+UK_TRACEPOINT(trace_posix_socket_sendto_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_sendto_err, "%d", int);
+
+ssize_t sendto(int sock, const void *buf, size_t len, int flags,
+          const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  trace_posix_socket_sendto(sock, buf, len, flags, dest_addr, addrlen);
+
+  file = posix_socket_file_get(sock);
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT_ERR;
+  }
+
+  /* Send to an address over a socket */
+  ret = posix_socket_sendto(file->driver, file->sock_data, buf, len, flags,
+          dest_addr, addrlen);
+
+  /* release refcount */
+  vfscore_put_file(file->vfs_file);
+
+  if (ret < 0) {
+    uk_pr_debug("driver:%s failed to sendto of socket:%p\n",
+          file->driver->libname, file->sock_data);
+    goto EXIT_ERR;
+  }
+
+  trace_posix_socket_sendto_ret(ret);  
+  return ret;
+EXIT_ERR:
+  trace_posix_socket_sendto_err(ret);
+  return ret;
+}
+
+UK_TRACEPOINT(trace_posix_socket_socketpair, "%d %d %d %p", int, int, int,
+            int *);
+UK_TRACEPOINT(trace_posix_socket_socketpair_ret, "%d", int);
+UK_TRACEPOINT(trace_posix_socket_socketpair_err, "%d", int);
+
+int socketpair(int family, int type, int protocol, int *usockvec)
+{
+  uk_pr_crit("%s: not implemented", __func__);
+  errno = ENOTSUP;
+  return -1;
+}
diff --git a/lib/posix-socket/socket_vnops.c b/lib/posix-socket/socket_vnops.c
new file mode 100644
index 0000000..6409b27
--- /dev/null
+++ b/lib/posix-socket/socket_vnops.c
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
+ *          Alexander Jung <alexander.jung@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, NEC Laboratories Europe GmbH, NEC Corporation.
+ *                     All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * 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.
+ */
+
+#include <uk/socket_driver.h>
+#include <vfscore/vnode.h>
+#include <vfscore/mount.h>
+#include <vfscore/fs.h>
+#include <uk/socket_vnops.h>
+#include <uk/errptr.h>
+#include <inttypes.h>
+
+static uint64_t s_inode = 0;
+
+#define posix_socket_getattr ((vnop_getattr_t) vfscore_vop_einval)
+#define posix_socket_inactive ((vnop_inactive_t) vfscore_vop_nullop)
+
+/* vnode operations */
+struct vnops posix_socket_vnops = {
+  .vop_close = posix_socket_vfscore_close,
+  .vop_read = posix_socket_vfscore_read,
+  .vop_write = posix_socket_vfscore_write,
+  .vop_ioctl = posix_socket_vfscore_ioctl,
+  .vop_getattr = posix_socket_getattr,
+  .vop_inactive = posix_socket_inactive,
+};
+
+#define posix_socket_vget ((vfsop_vget_t) vfscore_nullop)
+
+/* file system operations */
+static struct vfsops posix_socket_vfsops = {
+  .vfs_vget = posix_socket_vget,
+  .vfs_vnops = &posix_socket_vnops,
+};
+
+/* bogus mount point used by all sockets */
+static struct mount posix_socket_mount = {
+  .m_op = &posix_socket_vfsops
+};
+
+struct posix_socket_file *
+posix_socket_file_get(int sock_fd)
+{
+  struct posix_socket_file *file = NULL;
+  struct vfscore_file *fos;
+
+  fos = vfscore_get_file(sock_fd);
+
+  if (!fos) {
+    uk_pr_err("Failed with invalid descriptor\n");
+    file = ERR2PTR(-EINVAL);
+    goto EXIT;
+  }
+  
+  if (fos->f_dentry->d_vnode->v_type != VSOCK) {
+    uk_pr_err("File descriptor is not a socket\n");
+    file = ERR2PTR(-EINVAL);
+    goto EXIT;
+  }
+  
+  file = fos->f_data;
+
+EXIT:
+  return file;
+}
+
+int
+socket_alloc_fd(struct posix_socket_driver *d, void *sock_data)
+{
+  int ret = 0;
+  int vfs_fd;
+  struct posix_socket_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;
+    uk_pr_err("failed to allocate file descriptor number\n");
+    goto ERR_EXIT;
+  }
+
+  /* Allocate file, dentry, and vnode */
+  file = uk_calloc(d->allocator, 1, sizeof(*file));
+  if (!file) {
+    ret = -ENOMEM;
+    uk_pr_err("failed to allocate socket file: out of memory\n");
+    goto ERR_MALLOC_FILE;
+  }
+
+  vfs_file = uk_calloc(d->allocator, 1, sizeof(*vfs_file));
+  if (!vfs_file) {
+    ret = -ENOMEM;
+    uk_pr_err("failed to allocate socket vfs_file: out of memory\n");
+    goto ERR_MALLOC_VFS_FILE;
+  }
+
+  ret = vfscore_vget(&posix_socket_mount, s_inode++, &s_vnode);
+  UK_ASSERT(ret == 0); /* we should not find it in cache */
+
+  if (!s_vnode) {
+    ret = -ENOMEM;
+    uk_pr_err("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;
+    uk_pr_err("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->vfs_file = vfs_file;
+  file->sock_data = sock_data;
+  file->driver = d;
+
+  uk_pr_debug("allocated socket %d for %s (%p)\n",
+            vfs_fd,
+            d->libname,
+            file->sock_data);
+
+  /* Store within the vfs structure */
+  ret = vfscore_install_fd(vfs_fd, file->vfs_file);
+  if (ret) {
+    uk_pr_err("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(d->allocator, vfs_file);
+ERR_MALLOC_VFS_FILE:
+  uk_free(d->allocator, file);
+ERR_MALLOC_FILE:
+  vfscore_put_fd(vfs_fd);
+ERR_EXIT:
+  UK_ASSERT(ret < 0);
+  return ret;
+}
+
+int
+posix_socket_vfscore_close(struct vnode *s_vnode,
+          struct vfscore_file *vfscore_file)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+  file = s_vnode->v_data;
+
+  uk_pr_debug("%s fd:%d driver:%s: sock_data:%p\n",
+            __func__,
+            file->vfs_file->fd,
+            file->driver->libname,
+            file->sock_data);
+
+  /* Close and release the socket */
+  ret = posix_socket_close(file->driver, file->sock_data);
+  
+  /*
+   * 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(file->driver->allocator, file);
+
+  if (ret < 0)
+    return errno;
+  
+  return ret;
+}
+
+int
+posix_socket_vfscore_write(struct vnode *s_vnode,
+          struct uio *buf, int ioflag __unused)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+
+  file = s_vnode->v_data;
+  uk_pr_debug("%s fd:%d driver:%s sock_data:%p\n",
+          __func__,
+          file->vfs_file->fd,
+          file->driver->libname,
+          file->sock_data);
+
+  /* Write to the socket */
+  ret = posix_socket_write(file->driver, file->sock_data, buf->uio_iov, 
buf->uio_iovcnt);
+  
+  /*
+   * Some socket implementations, such as LwIP, may set the errno and return 
to 
+   * -1 as an error, but vfs expects us to return a positive errno.
+   */
+  if (ret < 0)
+    return errno;
+
+  buf->uio_resid -= ret;
+  return 0;
+}
+
+int
+posix_socket_vfscore_read(struct vnode *s_vnode,
+          struct vfscore_file *vfscore_file __unused,
+          struct uio *buf, int ioflag __unused)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+  
+  file = s_vnode->v_data;
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT;
+  }
+
+  uk_pr_debug("%s fd:%d driver:%s sock_data:%p\n",
+            __func__,
+            file->vfs_file->fd,
+            file->driver->libname,
+            file->sock_data);
+
+  ret = posix_socket_read(file->driver, file->sock_data, buf->uio_iov, 
buf->uio_iovcnt);
+  if (ret < 0) {
+    ret = errno;
+    goto EXIT;
+  }
+  
+  buf->uio_resid -= ret;
+
+EXIT:
+  return ret;
+}
+
+int
+posix_socket_vfscore_ioctl(struct vnode *s_vnode,
+          struct vfscore_file *vfscore_file __unused,
+          unsigned long request,
+          void *buf)
+{
+  int ret = 0;
+  struct posix_socket_file *file = NULL;
+  
+  file = s_vnode->v_data;
+  if (PTRISERR(file)) {
+    uk_pr_debug("failed to identify socket descriptor\n");
+    ret = -1;
+    POSIX_SOCKET_SET_ERRNO(PTR2ERR(file));
+    goto EXIT;
+  }
+
+  uk_pr_debug("%s fd:%d driver:%s sock_data:%p\n",
+            __func__,
+            file->vfs_file->fd,
+            file->driver->libname,
+            file->sock_data);
+
+  ret = posix_socket_ioctl(file->driver, file->sock_data, request, buf);
+  if (ret < 0)
+    ret = errno;
+
+EXIT:
+  return ret;
+}
-- 
2.20.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.