You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/10/26 13:01:59 UTC

[incubator-nuttx] 01/02: arch/sim: add native socket support based on usrsock

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit b90d0941380512ce81f36fb4ad68288dafa3e772
Author: chao.an <an...@xiaomi.com>
AuthorDate: Sun Aug 29 17:52:02 2021 +0800

    arch/sim: add native socket support based on usrsock
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 arch/sim/Kconfig                   |  17 +-
 arch/sim/src/Makefile              |   5 +
 arch/sim/src/nuttx-names.in        |   9 +
 arch/sim/src/sim/up_idle.c         |   4 +
 arch/sim/src/sim/up_initialize.c   |   6 +
 arch/sim/src/sim/up_internal.h     |   7 +
 arch/sim/src/sim/up_usrsock.c      | 443 +++++++++++++++++++++++++++++++
 arch/sim/src/sim/up_usrsock_host.c | 515 +++++++++++++++++++++++++++++++++++++
 arch/sim/src/sim/up_usrsock_host.h | 317 +++++++++++++++++++++++
 9 files changed, 1321 insertions(+), 2 deletions(-)

diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig
index 5cc6a33..ea2d962 100644
--- a/arch/sim/Kconfig
+++ b/arch/sim/Kconfig
@@ -127,15 +127,28 @@ config SIM_WALLTIME_SIGNAL
 
 endchoice
 
+choice
+	prompt "Simulated Network Interface"
+	default SIM_NETDEV
+	depends on NET
+	optional
+
 config SIM_NETDEV
 	bool "Simulated Network Device"
-	default y
 	select ARCH_HAVE_NETDEV_STATISTICS
 	select SCHED_LPWORK
-	depends on NET_ETHERNET
+	select NET_ETHERNET
 	---help---
 		Build in support for a simulated network device.
 
+config SIM_NETUSRSOCK
+	bool "Simulated Network Device with Native Stack via usrsock"
+	select NET_USRSOCK
+	---help---
+		Built-in support for a simulated network device using native stack via usrsock
+
+endchoice
+
 if SIM_NETDEV
 
 choice
diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile
index a106114..71a8c4c 100644
--- a/arch/sim/src/Makefile
+++ b/arch/sim/src/Makefile
@@ -170,6 +170,11 @@ else ifeq ($(CONFIG_SIM_NETDEV_VPNKIT),y)
   HOSTSRCS += protocol.c negotiate.c
 endif
 
+ifeq ($(CONFIG_SIM_NETUSRSOCK),y)
+  HOSTSRCS += up_usrsock_host.c
+  CSRCS += up_usrsock.c
+endif
+
 ifeq ($(CONFIG_SIM_HCISOCKET),y)
   HOSTSRCS += up_hcisocket_host.c
   CSRCS += up_hcisocket.c
diff --git a/arch/sim/src/nuttx-names.in b/arch/sim/src/nuttx-names.in
index 4b576d2..2c43b3a 100644
--- a/arch/sim/src/nuttx-names.in
+++ b/arch/sim/src/nuttx-names.in
@@ -31,6 +31,7 @@
 #endif
 
 NXSYMBOLS(__cxa_atexit)
+NXSYMBOLS(accept)
 NXSYMBOLS(atexit)
 NXSYMBOLS(bind)
 NXSYMBOLS(calloc)
@@ -45,13 +46,18 @@ NXSYMBOLS(dup)
 NXSYMBOLS(exit)
 NXSYMBOLS(fchmod)
 NXSYMBOLS(fchown)
+NXSYMBOLS(fcntl)
 NXSYMBOLS(free)
 NXSYMBOLS(fstat)
 NXSYMBOLS(fsync)
 NXSYMBOLS(ftruncate)
 NXSYMBOLS(futimens)
+NXSYMBOLS(getpeername)
+NXSYMBOLS(getsockname)
+NXSYMBOLS(getsockopt)
 NXSYMBOLS(if_nametoindex)
 NXSYMBOLS(ioctl)
+NXSYMBOLS(listen)
 NXSYMBOLS(longjmp)
 NXSYMBOLS(lseek)
 NXSYMBOLS(malloc)
@@ -87,14 +93,17 @@ NXSYMBOLS(read)
 NXSYMBOLS(readdir)
 NXSYMBOLS(readv)
 NXSYMBOLS(realloc)
+NXSYMBOLS(recvfrom)
 NXSYMBOLS(rename)
 NXSYMBOLS(rewinddir)
 NXSYMBOLS(rmdir)
 NXSYMBOLS(sched_yield)
 NXSYMBOLS(select)
 NXSYMBOLS(sendmsg)
+NXSYMBOLS(sendto)
 NXSYMBOLS(setitimer)
 NXSYMBOLS(setjmp)
+NXSYMBOLS(setsockopt)
 NXSYMBOLS(shutdown)
 NXSYMBOLS(sigaction)
 NXSYMBOLS(sigaddset)
diff --git a/arch/sim/src/sim/up_idle.c b/arch/sim/src/sim/up_idle.c
index be66287..abd80f6 100644
--- a/arch/sim/src/sim/up_idle.c
+++ b/arch/sim/src/sim/up_idle.c
@@ -90,6 +90,10 @@ void up_idle(void)
   netdriver_loop();
 #endif
 
+#ifdef CONFIG_SIM_NETUSRSOCK
+  usrsock_loop();
+#endif
+
 #ifdef CONFIG_RPTUN
   up_rptun_loop();
 #endif
diff --git a/arch/sim/src/sim/up_initialize.c b/arch/sim/src/sim/up_initialize.c
index ea5f031..1af2c6a 100644
--- a/arch/sim/src/sim/up_initialize.c
+++ b/arch/sim/src/sim/up_initialize.c
@@ -246,6 +246,12 @@ void up_initialize(void)
   netdriver_init();         /* Our "real" network driver */
 #endif
 
+#ifdef CONFIG_SIM_NETUSRSOCK
+  /* Register the usrsock native socket device */
+
+  usrsock_init();
+#endif
+
 #ifdef CONFIG_NET_LOOPBACK
   /* Initialize the local loopback device */
 
diff --git a/arch/sim/src/sim/up_internal.h b/arch/sim/src/sim/up_internal.h
index f8ef29c..c2ae3e2 100644
--- a/arch/sim/src/sim/up_internal.h
+++ b/arch/sim/src/sim/up_internal.h
@@ -316,6 +316,13 @@ void netdriver_setmacaddr(unsigned char *macaddr);
 void netdriver_setmtu(int mtu);
 void netdriver_loop(void);
 
+/* up_usrsock.c *************************************************************/
+
+#ifdef CONFIG_SIM_NETUSRSOCK
+int usrsock_init(void);
+void usrsock_loop(void);
+#endif
+
 /* up_rptun.c ***************************************************************/
 
 #ifdef CONFIG_RPTUN
diff --git a/arch/sim/src/sim/up_usrsock.c b/arch/sim/src/sim/up_usrsock.c
new file mode 100644
index 0000000..5cd0185
--- /dev/null
+++ b/arch/sim/src/sim/up_usrsock.c
@@ -0,0 +1,443 @@
+/****************************************************************************
+ * arch/sim/src/sim/up_usrsock.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <poll.h>
+#include <syslog.h>
+#include <string.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/net/usrsock.h>
+
+#include "up_usrsock_host.h"
+
+/****************************************************************************
+ * Private Type Declarations
+ ****************************************************************************/
+
+struct usrsock_s
+{
+  struct file usock;
+  uint8_t data[4096];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+typedef int (*usrsock_handler_t)(FAR struct usrsock_s *usrsock,
+                                 FAR const void *data, size_t len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct usrsock_s g_usrsock;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int usrsock_send(FAR struct usrsock_s *usrsock,
+                        FAR const void *buf, size_t len)
+{
+  FAR uint8_t *data = (FAR uint8_t *)buf;
+  ssize_t ret;
+
+  while (len > 0)
+    {
+      ret = file_write(&usrsock->usock, data, len);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      data += ret;
+      len  -= ret;
+    }
+
+  return 0;
+}
+
+static int usrsock_send_ack(FAR struct usrsock_s *usrsock,
+                            uint8_t xid, int32_t result)
+{
+  struct usrsock_message_req_ack_s ack;
+
+  ack.head.msgid = USRSOCK_MESSAGE_RESPONSE_ACK;
+  ack.head.flags = (result == -EINPROGRESS);
+
+  ack.xid    = xid;
+  ack.result = result;
+
+  return usrsock_send(usrsock, &ack, sizeof(ack));
+}
+
+static int usrsock_send_dack(FAR struct usrsock_s *usrsock,
+                             FAR struct usrsock_message_datareq_ack_s *ack,
+                             uint8_t xid, int32_t result,
+                             uint16_t valuelen,
+                             uint16_t valuelen_nontrunc)
+{
+  ack->reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK;
+  ack->reqack.head.flags = 0;
+
+  ack->reqack.xid    = xid;
+  ack->reqack.result = result;
+
+  if (result < 0)
+    {
+      result             = 0;
+      valuelen           = 0;
+      valuelen_nontrunc  = 0;
+    }
+  else if (valuelen > valuelen_nontrunc)
+    {
+      valuelen           = valuelen_nontrunc;
+    }
+
+  ack->valuelen          = valuelen;
+  ack->valuelen_nontrunc = valuelen_nontrunc;
+
+  return usrsock_send(usrsock, ack, sizeof(*ack) + valuelen + result);
+}
+
+static int usrsock_send_event(FAR struct usrsock_s *usrsock,
+                              int16_t usockid, uint16_t events)
+{
+  struct usrsock_message_socket_event_s event;
+
+  event.head.msgid = USRSOCK_MESSAGE_SOCKET_EVENT;
+  event.head.flags = USRSOCK_MESSAGE_FLAG_EVENT;
+
+  event.usockid = usockid;
+  event.events  = events;
+
+  return usrsock_send(usrsock, &event, sizeof(event));
+}
+
+static int usrsock_socket_handler(FAR struct usrsock_s *usrsock,
+                                  FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_socket_s *req = data;
+  int fd = usrsock_host_socket(req->domain, req->type, req->protocol);
+
+  usrsock_send_ack(usrsock, req->head.xid, fd);
+  if (fd > 0)
+    {
+      usrsock_send_event(usrsock, fd, USRSOCK_EVENT_SENDTO_READY);
+    }
+
+  return fd;
+}
+
+static int usrsock_close_handler(FAR struct usrsock_s *usrsock,
+                                 FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_close_s *req = data;
+  int ret = usrsock_host_close(req->usockid);
+
+  return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_connect_handler(FAR struct usrsock_s *usrsock,
+                                   FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_connect_s *req = data;
+  int ret = usrsock_host_connect(req->usockid,
+                                 (FAR const struct sockaddr *)(req + 1),
+                                 req->addrlen);
+
+  return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_sendto_handler(FAR struct usrsock_s *usrsock,
+                                  FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_sendto_s *req = data;
+  int ret = usrsock_host_sendto(req->usockid,
+                                (FAR const void *)(req + 1) + req->addrlen,
+                                req->buflen, req->flags,
+                                req->addrlen ?
+                                (FAR const struct sockaddr *)(req + 1) :
+                                NULL, req->addrlen);
+
+  usrsock_send_ack(usrsock, req->head.xid, ret);
+  if (ret > 0)
+    {
+      ret = usrsock_send_event(usrsock, req->usockid,
+                               USRSOCK_EVENT_SENDTO_READY);
+    }
+
+  return ret;
+}
+
+static int usrsock_recvfrom_handler(FAR struct usrsock_s *usrsock,
+                                    FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_recvfrom_s *req = data;
+  FAR struct usrsock_message_datareq_ack_s *ack;
+  socklen_t outaddrlen = req->max_addrlen;
+  socklen_t inaddrlen = req->max_addrlen;
+  size_t buflen = req->max_buflen;
+  int ret;
+
+  ack = (struct usrsock_message_datareq_ack_s *)usrsock->data;
+  if (sizeof(*ack) + inaddrlen + buflen > sizeof(usrsock->data))
+    {
+      buflen = sizeof(usrsock->data) - sizeof(*ack) - inaddrlen;
+    }
+
+  ret = usrsock_host_recvfrom(req->usockid,
+                              (FAR void *)(ack + 1) + inaddrlen,
+                              buflen, req->flags,
+                              outaddrlen ?
+                              (FAR struct sockaddr *)(ack + 1) : NULL,
+                              outaddrlen ? &outaddrlen : NULL);
+  if (ret > 0 && outaddrlen < inaddrlen)
+    {
+      memcpy((FAR void *)(ack + 1) + outaddrlen,
+             (FAR void *)(ack + 1) + inaddrlen, ret);
+    }
+
+  return usrsock_send_dack(usrsock, ack, req->head.xid,
+                           ret, inaddrlen, outaddrlen);
+}
+
+static int usrsock_setsockopt_handler(FAR struct usrsock_s *usrsock,
+                                      FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_setsockopt_s *req = data;
+  int ret = usrsock_host_setsockopt(req->usockid, req->level,
+                                    req->option, req + 1, req->valuelen);
+
+  return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_getsockopt_handler(FAR struct usrsock_s *usrsock,
+                                      FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_getsockopt_s *req = data;
+  FAR struct usrsock_message_datareq_ack_s *ack;
+  socklen_t optlen = req->max_valuelen;
+  int ret;
+
+  ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+  ret = usrsock_host_getsockopt(req->usockid,
+                                req->level, req->option,
+                                ack + 1, &optlen);
+
+  return usrsock_send_dack(usrsock, ack, req->head.xid,
+                           ret, optlen, optlen);
+}
+
+static int usrsock_getsockname_handler(FAR struct usrsock_s *usrsock,
+                                       FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_getsockname_s *req = data;
+  FAR struct usrsock_message_datareq_ack_s *ack;
+  socklen_t outaddrlen = req->max_addrlen;
+  socklen_t inaddrlen = req->max_addrlen;
+  int ret;
+
+  ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+  ret = usrsock_host_getsockname(req->usockid,
+          (FAR struct sockaddr *)(ack + 1), &outaddrlen);
+
+  return usrsock_send_dack(usrsock, ack, req->head.xid,
+                           ret, inaddrlen, outaddrlen);
+}
+
+static int usrsock_getpeername_handler(FAR struct usrsock_s *usrsock,
+                                       FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_getpeername_s *req = data;
+  FAR struct usrsock_message_datareq_ack_s *ack;
+  socklen_t outaddrlen = req->max_addrlen;
+  socklen_t inaddrlen = req->max_addrlen;
+  int ret;
+
+  ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+  ret = usrsock_host_getpeername(req->usockid,
+          (FAR struct sockaddr *)(ack + 1), &outaddrlen);
+
+  return usrsock_send_dack(usrsock, ack, req->head.xid,
+                           ret, inaddrlen, outaddrlen);
+}
+
+static int usrsock_bind_handler(FAR struct usrsock_s *usrsock,
+                                FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_bind_s *req = data;
+  int ret = usrsock_host_bind(req->usockid,
+                              (FAR const struct sockaddr *)(req + 1),
+                              req->addrlen);
+
+  return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_listen_handler(FAR struct usrsock_s *usrsock,
+                                  FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_listen_s *req = data;
+  int ret = usrsock_host_listen(req->usockid, req->backlog);
+
+  return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_accept_handler(FAR struct usrsock_s *usrsock,
+                                  FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_accept_s *req = data;
+  FAR struct usrsock_message_datareq_ack_s *ack;
+  socklen_t outaddrlen = req->max_addrlen;
+  socklen_t inaddrlen = req->max_addrlen;
+  int sockfd;
+  int ret;
+
+  ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+  sockfd = usrsock_host_accept(req->usockid,
+                               outaddrlen ?
+                               (FAR struct sockaddr *)(ack + 1) : NULL,
+                               outaddrlen ? &outaddrlen : NULL);
+  if (sockfd > 0)
+    {
+      /* Append index as usockid to the payload */
+
+      if (outaddrlen <= inaddrlen)
+        {
+          *(FAR int16_t *)((FAR void *)(ack + 1) + outaddrlen) = sockfd;
+        }
+      else
+        {
+          *(FAR int16_t *)((FAR void *)(ack + 1) + inaddrlen) = sockfd;
+        }
+
+      ret = sizeof(int16_t); /* Return usockid size */
+    }
+  else
+    {
+      ret = sockfd;
+    }
+
+  usrsock_send_dack(usrsock, ack, req->head.xid, ret,
+                    inaddrlen, outaddrlen);
+  if (ret > 0)
+    {
+      usrsock_send_event(usrsock, sockfd, USRSOCK_EVENT_SENDTO_READY);
+    }
+
+  return ret;
+}
+
+static int usrsock_ioctl_handler(FAR struct usrsock_s *usrsock,
+                                 FAR const void *data, size_t len)
+{
+  FAR const struct usrsock_request_ioctl_s *req = data;
+  FAR struct usrsock_message_datareq_ack_s *ack;
+  int ret;
+
+  ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+  memcpy(ack + 1, req + 1, req->arglen);
+  ret = usrsock_host_ioctl(req->usockid, req->cmd,
+                           (unsigned long)(ack + 1));
+
+  return usrsock_send_dack(usrsock, ack, req->head.xid, ret,
+                           req->arglen, req->arglen);
+}
+
+static const usrsock_handler_t g_usrsock_handler[] =
+{
+  [USRSOCK_REQUEST_SOCKET]      = usrsock_socket_handler,
+  [USRSOCK_REQUEST_CLOSE]       = usrsock_close_handler,
+  [USRSOCK_REQUEST_CONNECT]     = usrsock_connect_handler,
+  [USRSOCK_REQUEST_SENDTO]      = usrsock_sendto_handler,
+  [USRSOCK_REQUEST_RECVFROM]    = usrsock_recvfrom_handler,
+  [USRSOCK_REQUEST_SETSOCKOPT]  = usrsock_setsockopt_handler,
+  [USRSOCK_REQUEST_GETSOCKOPT]  = usrsock_getsockopt_handler,
+  [USRSOCK_REQUEST_GETSOCKNAME] = usrsock_getsockname_handler,
+  [USRSOCK_REQUEST_GETPEERNAME] = usrsock_getpeername_handler,
+  [USRSOCK_REQUEST_BIND]        = usrsock_bind_handler,
+  [USRSOCK_REQUEST_LISTEN]      = usrsock_listen_handler,
+  [USRSOCK_REQUEST_ACCEPT]      = usrsock_accept_handler,
+  [USRSOCK_REQUEST_IOCTL]       = usrsock_ioctl_handler,
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int usrsock_event_callback(int16_t usockid, uint16_t events)
+{
+  return usrsock_send_event(&g_usrsock, usockid, events);
+}
+
+int usrsock_init(void)
+{
+  return file_open(&g_usrsock.usock, "/dev/usrsock", O_RDWR);
+}
+
+void usrsock_loop(void)
+{
+  FAR struct usrsock_request_common_s *common;
+  uint8_t data[4096];
+  int ret;
+  struct pollfd pfd =
+    {
+      .ptr    = &g_usrsock.usock,
+      .events = POLLIN | POLLFILE,
+    };
+
+  ret = poll(&pfd, 1, 0);
+  if (ret > 0)
+    {
+      ret = file_read(&g_usrsock.usock, data, sizeof(data));
+      if (ret > 0)
+        {
+          common = (FAR struct usrsock_request_common_s *)data;
+
+          if (common->reqid >= 0 &&
+              common->reqid < USRSOCK_REQUEST__MAX)
+            {
+              ret = g_usrsock_handler[common->reqid](&g_usrsock,
+                                                     data, ret);
+              if (ret < 0)
+                {
+                  syslog(LOG_ERR, "Usrsock request %d failed: %d\n",
+                                  common->reqid, ret);
+                }
+            }
+          else
+            {
+              syslog(LOG_ERR, "Invalid request id: %d\n",
+                              common->reqid);
+            }
+        }
+    }
+
+  usrsock_host_loop();
+}
diff --git a/arch/sim/src/sim/up_usrsock_host.c b/arch/sim/src/sim/up_usrsock_host.c
new file mode 100644
index 0000000..d6428fc
--- /dev/null
+++ b/arch/sim/src/sim/up_usrsock_host.c
@@ -0,0 +1,515 @@
+/****************************************************************************
+ * arch/sim/src/sim/up_usrsock_host.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+
+#include <netinet/in.h>
+
+#include "up_usrsock_host.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static int    g_active_maxfd = -1;
+static fd_set g_active_read_fds;
+static fd_set g_active_write_fds;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void usrsock_host_clear_fd(int fd, fd_set *fds)
+{
+  if (FD_ISSET(fd, fds))
+    {
+      FD_CLR(fd, fds);
+
+      if (fd == g_active_maxfd)
+        {
+          while (fd--)
+            {
+              if (FD_ISSET(fd, &g_active_read_fds))
+                {
+                  break;
+                }
+              else if (FD_ISSET(fd, &g_active_write_fds))
+                {
+                  break;
+                }
+            }
+
+          g_active_maxfd = fd;
+        }
+    }
+}
+
+static void usrsock_host_set_fd(int fd, fd_set *fds)
+{
+  if (!FD_ISSET(fd, fds))
+    {
+      FD_SET(fd, fds);
+      if (fd > g_active_maxfd)
+        {
+          g_active_maxfd = fd;
+        }
+    }
+}
+
+static void sockaddr_to_native(const struct nuttx_sockaddr *addr,
+                               const nuttx_socklen_t addrlen,
+                               struct sockaddr *naddr,
+                               socklen_t *naddrlen)
+{
+  naddr->sa_family = addr->sa_family;
+  memcpy(naddr->sa_data, addr->sa_data, sizeof(naddr->sa_data));
+
+  *naddrlen = addrlen;
+}
+
+static void sockaddr_to_nuttx(const struct sockaddr *naddr,
+                              const socklen_t naddrlen,
+                              struct nuttx_sockaddr *addr,
+                              nuttx_socklen_t *addrlen)
+{
+  addr->sa_family = naddr->sa_family;
+  memcpy(addr->sa_data, naddr->sa_data, sizeof(addr->sa_data));
+
+  *addrlen = naddrlen;
+}
+
+static void sock_nonblock(int socket, int enable)
+{
+  if (enable)
+    {
+      fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
+    }
+  else
+    {
+      fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK);
+    }
+}
+
+static int usrsock_host_sockopt(int sockfd, int level, int optname,
+                                const void *optval, nuttx_socklen_t *optlen,
+                                bool set)
+{
+  int ret = -EINVAL;
+
+  if (level == NUTTX_SOL_SOCKET)
+    {
+      level = SOL_SOCKET;
+    }
+  else if (level == NUTTX_IPPROTO_TCP)
+    {
+      level = IPPROTO_TCP;
+    }
+  else if (level == NUTTX_IPPROTO_UDP)
+    {
+      level = IPPROTO_UDP;
+    }
+  else if (level == NUTTX_IPPROTO_IP)
+    {
+      level = IPPROTO_IP;
+    }
+  else
+    {
+      return ret;
+    }
+
+  if (optname == NUTTX_SO_REUSEADDR)
+    {
+      optname = SO_REUSEADDR;
+    }
+  else if (optname == NUTTX_SO_ERROR)
+    {
+      optname = SO_ERROR;
+    }
+  else
+    {
+      syslog(LOG_ERR, "Invalid optname: %x\n", optname);
+      return ret;
+    }
+
+  if (set)
+    {
+      ret = setsockopt(sockfd, level, optname, optval, *optlen);
+    }
+  else
+    {
+      ret = getsockopt(sockfd, level, optname, (void *)optval, optlen);
+    }
+
+  return ret < 0 ? -errno : 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int usrsock_host_socket(int domain, int type, int protocol)
+{
+  int ret;
+
+  if (domain == NUTTX_PF_INET)
+    {
+      domain = PF_INET;
+    }
+  else
+    {
+      return -EINVAL;
+    }
+
+  if (type == NUTTX_SOCK_STREAM)
+    {
+      type = SOCK_STREAM;
+    }
+  else if (type == NUTTX_SOCK_DGRAM)
+    {
+      type = SOCK_DGRAM;
+    }
+  else
+    {
+      return -EINVAL;
+    }
+
+  if (protocol == NUTTX_IPPROTO_IP)
+    {
+      protocol = IPPROTO_IP;
+    }
+  else if (protocol == NUTTX_IPPROTO_ICMP)
+    {
+      protocol = IPPROTO_ICMP;
+    }
+  else if (protocol == NUTTX_IPPROTO_TCP)
+    {
+      protocol = IPPROTO_TCP;
+    }
+  else if (protocol == NUTTX_IPPROTO_UDP)
+    {
+      protocol = IPPROTO_UDP;
+    }
+  else
+    {
+      return -EINVAL;
+    }
+
+  ret = socket(domain, type, protocol);
+  if (ret < 0)
+    {
+      return -errno;
+    }
+
+  sock_nonblock(ret, true);
+  usrsock_host_set_fd(ret, &g_active_read_fds);
+
+  return ret;
+}
+
+int usrsock_host_close(int sockfd)
+{
+  usrsock_host_clear_fd(sockfd, &g_active_read_fds);
+  usrsock_host_clear_fd(sockfd, &g_active_write_fds);
+
+  return close(sockfd);
+}
+
+int usrsock_host_connect(int sockfd,
+                         const struct nuttx_sockaddr *addr,
+                         nuttx_socklen_t addrlen)
+{
+  struct sockaddr naddr;
+  socklen_t naddrlen;
+  int ret;
+
+  sockaddr_to_native(addr, addrlen, &naddr, &naddrlen);
+
+  sock_nonblock(sockfd, false);
+  ret = connect(sockfd, &naddr, naddrlen);
+  sock_nonblock(sockfd, true);
+  if (ret < 0)
+    {
+      return -errno;
+    }
+
+  usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+  return ret;
+}
+
+ssize_t usrsock_host_sendto(int sockfd, const void *buf,
+                            size_t len, int flags,
+                            const struct nuttx_sockaddr *dest_addr,
+                            nuttx_socklen_t addrlen)
+{
+  struct sockaddr naddr;
+  socklen_t naddrlen;
+  int ret;
+
+  if (dest_addr && addrlen >= sizeof(*dest_addr))
+    {
+      sockaddr_to_native(dest_addr, addrlen, &naddr, &naddrlen);
+      ret = sendto(sockfd, buf, len, flags, &naddr, naddrlen);
+    }
+  else
+    {
+      ret = sendto(sockfd, buf, len, flags, NULL, 0);
+    }
+
+  if (ret < 0)
+    {
+      if (errno == EAGAIN)
+        {
+          usrsock_host_set_fd(sockfd, &g_active_write_fds);
+        }
+      else
+        {
+          usrsock_event_callback(sockfd, NUTTX_USRSOCK_EVENT_REMOTE_CLOSED);
+        }
+    }
+
+  return ret >= 0 ? ret : -errno;
+}
+
+ssize_t usrsock_host_recvfrom(int sockfd, void *buf, size_t len, int flags,
+                              struct nuttx_sockaddr *src_addr,
+                              nuttx_socklen_t *addrlen)
+{
+  struct sockaddr naddr;
+  socklen_t naddrlen;
+  int ret;
+
+  if (src_addr && addrlen && *addrlen >= sizeof(*src_addr))
+    {
+      sockaddr_to_native(src_addr, *addrlen, &naddr, &naddrlen);
+      ret = recvfrom(sockfd, buf, len, flags, &naddr, &naddrlen);
+    }
+  else
+    {
+      ret = recvfrom(sockfd, buf, len, flags, NULL, NULL);
+    }
+
+  if (ret <= 0)
+    {
+      if (ret == 0 || errno != EAGAIN)
+        {
+          usrsock_event_callback(sockfd, NUTTX_USRSOCK_EVENT_REMOTE_CLOSED);
+        }
+
+      return -errno;
+    }
+
+  if (src_addr && addrlen && *addrlen >= sizeof(*src_addr))
+    {
+      sockaddr_to_nuttx(&naddr, naddrlen, src_addr, addrlen);
+    }
+
+  usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+  return ret;
+}
+
+int usrsock_host_setsockopt(int sockfd, int level, int optname,
+                            const void *optval, nuttx_socklen_t optlen)
+{
+  return usrsock_host_sockopt(sockfd, level, optname,
+                              optval, &optlen, true);
+}
+
+int usrsock_host_getsockopt(int sockfd, int level, int optname,
+                            void *optval, nuttx_socklen_t *optlen)
+{
+  return usrsock_host_sockopt(sockfd, level, optname,
+                              optval, optlen, false);
+}
+
+int usrsock_host_getsockname(int sockfd,
+                             struct nuttx_sockaddr *addr,
+                             nuttx_socklen_t *addrlen)
+{
+  socklen_t naddrlen = sizeof(struct sockaddr);
+  struct sockaddr naddr;
+  int ret;
+
+  ret = getsockname(sockfd, &naddr, &naddrlen);
+  if (ret < 0)
+    {
+      return -errno;
+    }
+
+  if (addr && addrlen && *addrlen >= sizeof(*addr))
+    {
+      sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen);
+    }
+
+  return ret;
+}
+
+int usrsock_host_getpeername(int sockfd,
+                             struct nuttx_sockaddr *addr,
+                             nuttx_socklen_t *addrlen)
+{
+  socklen_t naddrlen = sizeof(struct sockaddr);
+  struct sockaddr naddr;
+  int ret;
+
+  ret = getpeername(sockfd, &naddr, &naddrlen);
+  if (ret < 0)
+    {
+      return -errno;
+    }
+
+  if (addr && addrlen && *addrlen >= sizeof(*addr))
+    {
+      sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen);
+    }
+
+  return ret;
+}
+
+int usrsock_host_bind(int sockfd,
+                      const struct nuttx_sockaddr *addr,
+                      nuttx_socklen_t addrlen)
+{
+  struct sockaddr naddr;
+  socklen_t naddrlen;
+
+  sockaddr_to_native(addr, addrlen, &naddr, &naddrlen);
+
+  return bind(sockfd, &naddr, naddrlen) < 0 ? -errno : 0;
+}
+
+int usrsock_host_listen(int sockfd, int backlog)
+{
+  int ret;
+
+  ret = listen(sockfd, backlog);
+  if (ret < 0)
+    {
+      return -errno;
+    }
+
+  usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+  return ret;
+}
+
+int usrsock_host_accept(int sockfd, struct nuttx_sockaddr *addr,
+                        nuttx_socklen_t *addrlen)
+{
+  struct sockaddr naddr;
+  socklen_t naddrlen;
+  int ret;
+
+  ret = accept(sockfd, &naddr, &naddrlen);
+  if (ret <= 0)
+    {
+      return -errno;
+    }
+
+  if (addr && addrlen && *addrlen >= sizeof(*addr))
+    {
+      sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen);
+    }
+
+  sock_nonblock(ret, true);
+  usrsock_host_set_fd(ret, &g_active_read_fds);
+  usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+  return ret;
+}
+
+int usrsock_host_ioctl(int fd, unsigned long request, ...)
+{
+  return 0;
+}
+
+void usrsock_host_loop(void)
+{
+  struct timeval timeout;
+  fd_set write_fds;
+  fd_set read_fds;
+  uint16_t events;
+  int ret;
+  int i;
+
+  if (g_active_maxfd <= 0)
+    {
+      return;
+    }
+
+  memset(&timeout, 0x0, sizeof(timeout));
+  memcpy(&read_fds,  &g_active_read_fds,  sizeof(read_fds));
+  memcpy(&write_fds, &g_active_write_fds, sizeof(write_fds));
+
+  ret = select(g_active_maxfd + 1, &read_fds, &write_fds, NULL, &timeout);
+  if (ret == 0)
+    {
+      return;
+    }
+
+  for (i = 0; i <= g_active_maxfd; i++)
+    {
+      events = 0;
+
+      if (FD_ISSET(i, &read_fds))
+        {
+          usrsock_host_clear_fd(i, &g_active_read_fds);
+          events |= NUTTX_USRSOCK_EVENT_RECVFROM_AVAIL;
+        }
+
+      if (FD_ISSET(i, &write_fds))
+        {
+          usrsock_host_clear_fd(i, &g_active_write_fds);
+          events |= NUTTX_USRSOCK_EVENT_SENDTO_READY;
+        }
+
+      if (events)
+        {
+          usrsock_event_callback(i, events);
+
+          if (--ret == 0)
+            {
+              break;
+            }
+        }
+    }
+}
diff --git a/arch/sim/src/sim/up_usrsock_host.h b/arch/sim/src/sim/up_usrsock_host.h
new file mode 100644
index 0000000..1374d2c
--- /dev/null
+++ b/arch/sim/src/sim/up_usrsock_host.h
@@ -0,0 +1,317 @@
+/****************************************************************************
+ * arch/sim/src/sim/up_usrsock_host.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_SIM_SRC_SIM_UP_USRSOCK_HOST_H
+#define __ARCH_SIM_SRC_SIM_UP_USRSOCK_HOST_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#ifndef __SIM__
+#  include <sys/socket.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef __SIM__
+
+#define NUTTX_IPPROTO_IP            0
+#define NUTTX_IPPROTO_HOPOPTS       0
+#define NUTTX_IPPROTO_ICMP          1
+#define NUTTX_IPPROTO_IGMP          2
+#define NUTTX_IPPROTO_IPIP          4
+#define NUTTX_IPPROTO_TCP           6
+#define NUTTX_IPPROTO_EGP           8
+#define NUTTX_IPPROTO_PUP           12
+#define NUTTX_IPPROTO_UDP           17
+#define NUTTX_IPPROTO_IDP           22
+#define NUTTX_IPPROTO_TP            29
+#define NUTTX_IPPROTO_DCCP          33
+#define NUTTX_IPPROTO_IPV6          41
+#define NUTTX_IPPROTO_ROUTING       43
+#define NUTTX_IPPROTO_FRAGMENT      44
+#define NUTTX_IPPROTO_RSVP          46
+#define NUTTX_IPPROTO_GRE           47
+#define NUTTX_IPPROTO_ESP           50
+#define NUTTX_IPPROTO_AH            51
+#define NUTTX_IPPROTO_ICMP6         58
+#define NUTTX_IPPROTO_NONE          59
+#define NUTTX_IPPROTO_DSTOPTS       60
+#define NUTTX_IPPROTO_MTP           92
+#define NUTTX_IPPROTO_ENCAP         98
+#define NUTTX_IPPROTO_BEETPH        94
+#define NUTTX_IPPROTO_PIM           103
+#define NUTTX_IPPROTO_COMP          108
+#define NUTTX_IPPROTO_SCTP          132
+#define NUTTX_IPPROTO_UDPLITE       136
+#define NUTTX_IPPROTO_MPLS          137
+#define NUTTX_IPPROTO_RAW           255
+
+#define NUTTX_PF_UNSPEC             0
+#define NUTTX_PF_UNIX               1
+#define NUTTX_PF_LOCAL              1
+#define NUTTX_PF_INET               2
+#define NUTTX_PF_INET6              10
+#define NUTTX_PF_NETLINK            16
+#define NUTTX_PF_ROUTE              NUTTX_PF_NETLINK
+#define NUTTX_PF_PACKET             17
+#define NUTTX_PF_CAN                29
+#define NUTTX_PF_BLUETOOTH          31
+#define NUTTX_PF_IEEE802154         36
+#define NUTTX_PF_PKTRADIO           64
+#define NUTTX_PF_RPMSG              65
+
+#define NUTTX_AF_UNSPEC             NUTTX_PF_UNSPEC
+#define NUTTX_AF_UNIX               NUTTX_PF_UNIX
+#define NUTTX_AF_LOCAL              NUTTX_PF_LOCAL
+#define NUTTX_AF_INET               NUTTX_PF_INET
+#define NUTTX_AF_INET6              NUTTX_PF_INET6
+#define NUTTX_AF_NETLINK            NUTTX_PF_NETLINK
+#define NUTTX_AF_ROUTE              NUTTX_PF_ROUTE
+#define NUTTX_AF_PACKET             NUTTX_PF_PACKET
+#define NUTTX_AF_CAN                NUTTX_PF_CAN
+#define NUTTX_AF_BLUETOOTH          NUTTX_PF_BLUETOOTH
+#define NUTTX_AF_IEEE802154         NUTTX_PF_IEEE802154
+#define NUTTX_AF_PKTRADIO           NUTTX_PF_PKTRADIO
+#define NUTTX_AF_RPMSG              NUTTX_PF_RPMSG
+
+#define NUTTX_SOCK_UNSPEC            0
+#define NUTTX_SOCK_STREAM            1
+#define NUTTX_SOCK_DGRAM             2
+#define NUTTX_SOCK_RAW               3
+#define NUTTX_SOCK_RDM               4
+#define NUTTX_SOCK_SEQPACKET         5
+#define NUTTX_SOCK_PACKET           10
+#define NUTTX_SOCK_CLOEXEC          02000000
+#define NUTTX_SOCK_NONBLOCK         00004000
+
+#define NUTTX_SOCK_MAX              (NUTTX_SOCK_PACKET + 1)
+#define NUTTX_SOCK_TYPE_MASK        0xf
+
+#define NUTTX_MSG_OOB               0x0001
+#define NUTTX_MSG_PEEK              0x0002
+#define NUTTX_MSG_DONTROUTE         0x0004
+#define NUTTX_MSG_CTRUNC            0x0008
+#define NUTTX_MSG_PROXY             0x0010
+#define NUTTX_MSG_TRUNC             0x0020
+#define NUTTX_MSG_DONTWAIT          0x0040
+#define NUTTX_MSG_EOR               0x0080
+#define NUTTX_MSG_WAITALL           0x0100
+#define NUTTX_MSG_FIN               0x0200
+#define NUTTX_MSG_SYN               0x0400
+#define NUTTX_MSG_CONFIRM           0x0800
+#define NUTTX_MSG_RST               0x1000
+#define NUTTX_MSG_ERRQUEUE          0x2000
+#define NUTTX_MSG_NOSIGNAL          0x4000
+#define NUTTX_MSG_MORE              0x8000
+
+#define NUTTX_SOL_SOCKET            1
+#define NUTTX_SO_ACCEPTCONN         0
+#define NUTTX_SO_BROADCAST          1
+#define NUTTX_SO_DEBUG              2
+#define NUTTX_SO_DONTROUTE          3
+#define NUTTX_SO_ERROR              4
+#define NUTTX_SO_KEEPALIVE          5
+#define NUTTX_SO_LINGER             6
+#define NUTTX_SO_OOBINLINE          7
+#define NUTTX_SO_RCVBUF             8
+#define NUTTX_SO_RCVLOWAT           9
+#define NUTTX_SO_RCVTIMEO           10
+#define NUTTX_SO_REUSEADDR          11
+#define NUTTX_SO_SNDBUF             12
+#define NUTTX_SO_SNDLOWAT           13
+#define NUTTX_SO_SNDTIMEO           14
+#define NUTTX_SO_TYPE               15
+#define NUTTX_SO_TIMESTAMP          16
+
+#define NUTTX_SO_SNDBUFFORCE        32
+#define NUTTX_SO_RCVBUFFORCE        33
+#define NUTTX_SO_RXQ_OVFL           40
+
+#define NUTTX_SOL_IP                NUTTX_IPPROTO_IP
+#define NUTTX_SOL_IPV6              NUTTX_IPPROTO_IPV6
+#define NUTTX_SOL_TCP               NUTTX_IPPROTO_TCP
+#define NUTTX_SOL_UDP               NUTTX_IPPROTO_UDP
+
+#define NUTTX_SOL_HCI               0
+#define NUTTX_SOL_L2CAP             6
+#define NUTTX_SOL_SCO               17
+#define NUTTX_SOL_RFCOMM            18
+
+#define NUTTX___SO_PROTOCOL         16
+
+#define NUTTX_SHUT_RD               1
+#define NUTTX_SHUT_WR               2
+#define NUTTX_SHUT_RDWR             3
+
+#define NUTTX_SCM_RIGHTS            0x01
+#define NUTTX_SCM_CREDENTIALS       0x02
+#define NUTTX_SCM_SECURITY          0x03
+
+#define NUTTX_IP_MULTICAST_IF           (NUTTX__SO_PROTOCOL + 1)
+#define NUTTX_IP_MULTICAST_TTL          (NUTTX__SO_PROTOCOL + 2)
+#define NUTTX_IP_MULTICAST_LOOP         (NUTTX__SO_PROTOCOL + 3)
+#define NUTTX_IP_ADD_MEMBERSHIP         (NUTTX__SO_PROTOCOL + 4)
+#define NUTTX_IP_DROP_MEMBERSHIP        (NUTTX__SO_PROTOCOL + 5)
+#define NUTTX_IP_UNBLOCK_SOURCE         (NUTTX__SO_PROTOCOL + 6)
+#define NUTTX_IP_BLOCK_SOURCE           (NUTTX__SO_PROTOCOL + 7)
+#define NUTTX_IP_ADD_SOURCE_MEMBERSHIP  (NUTTX__SO_PROTOCOL + 8)
+#define NUTTX_IP_DROP_SOURCE_MEMBERSHIP (NUTTX__SO_PROTOCOL + 9)
+#define NUTTX_IP_MSFILTER               (NUTTX__SO_PROTOCOL + 10)
+#define NUTTX_IP_MULTICAST_ALL          (NUTTX__SO_PROTOCOL + 11)
+#define NUTTX_IP_PKTINFO                (NUTTX__SO_PROTOCOL + 12)
+#define NUTTX_IP_TOS                    (NUTTX__SO_PROTOCOL + 13)
+#define NUTTX_IP_TTL                    (NUTTX__SO_PROTOCOL + 14)
+
+/* Event message flags */
+
+#define NUTTX_USRSOCK_EVENT_ABORT          (1 << 1)
+#define NUTTX_USRSOCK_EVENT_SENDTO_READY   (1 << 2)
+#define NUTTX_USRSOCK_EVENT_RECVFROM_AVAIL (1 << 3)
+#define NUTTX_USRSOCK_EVENT_REMOTE_CLOSED  (1 << 4)
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+
+typedef unsigned int nuttx_socklen_t;
+
+#ifdef CONFIG_NET_IPv6
+struct nuttx_sockaddr_storage
+{
+  sa_family_t ss_family;       /* Address family */
+  char        ss_data[26];     /* 26-bytes of address data */
+};
+#else
+struct nuttx_sockaddr_storage
+{
+  sa_family_t ss_family;       /* Address family */
+  char        ss_data[14];     /* 14-bytes of address data */
+};
+#endif
+
+struct nuttx_sockaddr
+{
+  sa_family_t sa_family;       /* Address family: See AF_* definitions */
+  char        sa_data[14];     /* 14-bytes data (actually variable length) */
+};
+
+struct nuttx_linger
+{
+  int  l_onoff;   /* Indicates whether linger option is enabled. */
+  int  l_linger;  /* Linger time, in seconds. */
+};
+
+struct nuttx_iovec
+{
+  void  *iov_base;  /* Base address of I/O memory region */
+  size_t iov_len;   /* Size of the memory pointed to by iov_base */
+};
+
+struct nuttx_msghdr
+{
+  void *msg_name;               /* Socket name */
+  socklen_t msg_namelen;        /* Length of name */
+  struct nuttx_iovec *msg_iov;  /* Data blocks */
+  unsigned long msg_iovlen;     /* Number of blocks */
+  void *msg_control;            /* Per protocol magic
+                                 * (eg BSD file descriptor passing)
+                                 */
+  unsigned long msg_controllen; /* Length of cmsg list */
+  unsigned int msg_flags;
+};
+
+struct nuttx_cmsghdr
+{
+  unsigned long cmsg_len;       /* Data byte count, including hdr */
+  int cmsg_level;               /* Originating protocol */
+  int cmsg_type;                /* Protocol-specific type */
+};
+
+#endif /* __SIM__ */
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __SIM__
+int usrsock_event_callback(int16_t usockid, uint16_t events);
+
+int usrsock_host_socket(int domain, int type, int protocol);
+int usrsock_host_close(int sockfd);
+int usrsock_host_connect(int sockfd, const struct nuttx_sockaddr *addr,
+                         nuttx_socklen_t addrlen);
+ssize_t usrsock_host_sendto(int sockfd, const void *buf, size_t len,
+                            int flags,
+                            const struct nuttx_sockaddr *dest_addr,
+                            nuttx_socklen_t addrlen);
+ssize_t usrsock_host_recvfrom(int sockfd, void *buf, size_t len, int flags,
+                              struct nuttx_sockaddr *src_addr,
+                              nuttx_socklen_t *addrlen);
+int usrsock_host_setsockopt(int sockfd, int level, int optname,
+                            const void *optval, nuttx_socklen_t optlen);
+int usrsock_host_getsockopt(int sockfd, int level, int optname,
+                            void *optval, nuttx_socklen_t *optlen);
+int usrsock_host_getsockname(int sockfd,
+                             struct nuttx_sockaddr *addr,
+                             nuttx_socklen_t *addrlen);
+int usrsock_host_getpeername(int sockfd,
+                             struct nuttx_sockaddr *addr,
+                             nuttx_socklen_t *addrlen);
+int usrsock_host_bind(int sockfd, const struct nuttx_sockaddr *addr,
+                      nuttx_socklen_t addrlen);
+int usrsock_host_listen(int sockfd, int backlog);
+int usrsock_host_accept(int sockfd, struct nuttx_sockaddr *addr,
+                        nuttx_socklen_t *addrlen);
+int usrsock_host_ioctl(int fd, unsigned long request, ...);
+#else
+int usrsock_host_socket(int domain, int type, int protocol);
+int usrsock_host_close(int sockfd);
+int usrsock_host_connect(int sockfd, const struct sockaddr *addr,
+                         socklen_t addrlen);
+ssize_t usrsock_host_sendto(int sockfd, const void *buf, size_t len,
+                            int flags,
+                            const struct sockaddr *dest_addr,
+                            socklen_t addrlen);
+ssize_t usrsock_host_recvfrom(int sockfd, void *buf, size_t len, int flags,
+                              struct sockaddr *src_addr,
+                              socklen_t *addrlen);
+int usrsock_host_setsockopt(int sockfd, int level, int optname,
+                            const void *optval, socklen_t optlen);
+int usrsock_host_getsockopt(int sockfd, int level, int optname,
+                            void *optval, socklen_t *optlen);
+int usrsock_host_getsockname(int sockfd, struct sockaddr *addr,
+                             socklen_t *addrlen);
+int usrsock_host_getpeername(int sockfd, struct sockaddr *addr,
+                             socklen_t *addrlen);
+int usrsock_host_bind(int sockfd, const struct sockaddr *addr,
+                      socklen_t addrlen);
+int usrsock_host_listen(int sockfd, int backlog);
+int usrsock_host_accept(int sockfd, struct sockaddr *addr,
+                        socklen_t *addrlen);
+int usrsock_host_ioctl(int fd, unsigned long request, ...);
+
+void usrsock_host_loop(void);
+#endif /* __SIM__ */
+
+#endif /* __ARCH_SIM_SRC_SIM_UP_USRSOCK_HOST_H */