You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ma...@apache.org on 2022/11/23 09:10:08 UTC

[incubator-nuttx] branch revert-7651-sensor created (now bd7fa72817)

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

masayuki pushed a change to branch revert-7651-sensor
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


      at bd7fa72817 Revert "net/get/setsockopt: add si_get/setsockopt interface to simply get/setsockopt"

This branch includes the following new commits:

     new 415cb0a31f Revert "net/local: support cmd SO_PEERCRED"
     new bd7fa72817 Revert "net/get/setsockopt: add si_get/setsockopt interface to simply get/setsockopt"

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[incubator-nuttx] 01/02: Revert "net/local: support cmd SO_PEERCRED"

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

masayuki pushed a commit to branch revert-7651-sensor
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 415cb0a31f19730a1154b148013670672ed6de8c
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Wed Nov 23 18:10:02 2022 +0900

    Revert "net/local: support cmd SO_PEERCRED"
    
    This reverts commit ccf0c3566ee9c0537c97cb81a784105376eeaefc.
---
 include/sys/socket.h     | 10 ------
 net/local/local.h        |  1 -
 net/local/local_conn.c   |  7 ----
 net/local/local_sockif.c | 92 ------------------------------------------------
 4 files changed, 110 deletions(-)

diff --git a/include/sys/socket.h b/include/sys/socket.h
index aa633ec7a4..f7df0ce45a 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -202,9 +202,6 @@
                             */
 #define SO_BINDTODEVICE 17 /* Bind this socket to a specific network device.
                             */
-#define SO_PEERCRED     18 /* Return the credentials of the peer process
-                            * connected to this socket.
-                            */
 
 /* The options are unsupported but included for compatibility
  * and portability
@@ -333,13 +330,6 @@ struct cmsghdr
   int cmsg_type;                /* Protocol-specific type */
 };
 
-struct ucred
-{
-  pid_t pid;
-  uid_t uid;
-  gid_t gid;
-};
-
 /****************************************************************************
  * Inline Functions
  ****************************************************************************/
diff --git a/net/local/local.h b/net/local/local.h
index 075254f048..47235a318d 100644
--- a/net/local/local.h
+++ b/net/local/local.h
@@ -129,7 +129,6 @@ struct local_conn_s
   uint16_t lc_cfpcount;          /* Control file pointer counter */
   FAR struct file *
      lc_cfps[LOCAL_NCONTROLFDS]; /* Socket message control filep */
-  struct ucred lc_cred;          /* The credentials of connection instance */
 #endif /* CONFIG_NET_LOCAL_SCM */
 
   mutex_t lc_sendlock;           /* Make sending multi-thread safe */
diff --git a/net/local/local_conn.c b/net/local/local_conn.c
index efaac03a7d..0abba63b58 100644
--- a/net/local/local_conn.c
+++ b/net/local/local_conn.c
@@ -29,7 +29,6 @@
 #include <assert.h>
 #include <errno.h>
 #include <debug.h>
-#include <unistd.h>
 
 #include <nuttx/kmalloc.h>
 #include <nuttx/queue.h>
@@ -130,12 +129,6 @@ FAR struct local_conn_s *local_alloc(void)
 
       nxmutex_init(&conn->lc_sendlock);
 
-#ifdef CONFIG_NET_LOCAL_SCM
-      conn->lc_cred.pid = getpid();
-      conn->lc_cred.uid = getuid();
-      conn->lc_cred.gid = getgid();
-#endif
-
       /* Add the connection structure to the list of listeners */
 
       net_lock();
diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c
index 4d639e3f3a..a34776f348 100644
--- a/net/local/local_sockif.c
+++ b/net/local/local_sockif.c
@@ -72,12 +72,6 @@ static int        local_close(FAR struct socket *psock);
 static int        local_ioctl(FAR struct socket *psock,
                     int cmd, unsigned long arg);
 static int        local_socketpair(FAR struct socket *psocks[2]);
-#ifdef CONFIG_NET_SOCKOPTS
-static int        local_getsockopt(FAR struct socket *psock, int level,
-                    int option, FAR void *value, FAR socklen_t *value_len);
-static int        local_setsockopt(FAR struct socket *psock, int level,
-                    int option, FAR const void *value, socklen_t value_len);
-#endif
 
 /****************************************************************************
  * Public Data
@@ -100,10 +94,6 @@ const struct sock_intf_s g_local_sockif =
   local_close,       /* si_close */
   local_ioctl,       /* si_ioctl */
   local_socketpair   /* si_socketpair */
-#ifdef CONFIG_NET_SOCKOPTS
-  , local_getsockopt /* si_getsockopt */
-  , local_setsockopt /* si_setsockopt */
-#endif
 };
 
 /****************************************************************************
@@ -444,88 +434,6 @@ static int local_getpeername(FAR struct socket *psock,
   return local_getsockname(psock, addr, addrlen);
 }
 
-#ifdef CONFIG_NET_SOCKOPTS
-
-/****************************************************************************
- * Name: local_getsockopt
- *
- * Description:
- *   local_getsockopt() retrieve the value for the option specified by the
- *   'option' argument at the protocol level specified by the 'level'
- *   argument. If the size of the option value is greater than 'value_len',
- *   the value stored in the object pointed to by the 'value' argument will
- *   be silently truncated. Otherwise, the length pointed to by the
- *   'value_len' argument will be modified to indicate the actual length
- *   of the 'value'.
- *
- *   The 'level' argument specifies the protocol level of the option. To
- *   retrieve options at the socket level, specify the level argument as
- *   SOL_SOCKET.
- *
- *   See <sys/socket.h> a complete list of values for the 'option' argument.
- *
- * Input Parameters:
- *   psock     Socket structure of the socket to query
- *   level     Protocol level to set the option
- *   option    identifies the option to get
- *   value     Points to the argument value
- *   value_len The length of the argument value
- *
- ****************************************************************************/
-
-static int local_getsockopt(FAR struct socket *psock, int level, int option,
-                            FAR void *value, FAR socklen_t *value_len)
-{
-  DEBUGASSERT(psock != NULL && psock->s_conn != NULL &&
-              psock->s_domain == PF_LOCAL);
-
-#ifdef CONFIG_NET_LOCAL_SCM
-  if (level == SOL_SOCKET && option == SO_PEERCRED)
-    {
-      FAR struct local_conn_s *conn = psock->s_conn;
-      if (*value_len != sizeof(struct ucred))
-        {
-          return -EINVAL;
-        }
-
-      memcpy(value, &conn->lc_peer->lc_cred, sizeof(struct ucred));
-      return OK;
-    }
-#endif
-
-  return -ENOPROTOOPT;
-}
-
-/****************************************************************************
- * Name: local_setsockopt
- *
- * Description:
- *   local_setsockopt() sets the option specified by the 'option' argument,
- *   at the protocol level specified by the 'level' argument, to the value
- *   pointed to by the 'value' argument for the usrsock connection.
- *
- *   The 'level' argument specifies the protocol level of the option. To set
- *   options at the socket level, specify the level argument as SOL_SOCKET.
- *
- *   See <sys/socket.h> a complete list of values for the 'option' argument.
- *
- * Input Parameters:
- *   psock     Socket structure of the socket to query
- *   level     Protocol level to set the option
- *   option    identifies the option to set
- *   value     Points to the argument value
- *   value_len The length of the argument value
- *
- ****************************************************************************/
-
-static int local_setsockopt(FAR struct socket *psock, int level, int option,
-                            FAR const void *value, socklen_t value_len)
-{
-  return -ENOPROTOOPT;
-}
-
-#endif
-
 /****************************************************************************
  * Name: local_listen
  *


[incubator-nuttx] 02/02: Revert "net/get/setsockopt: add si_get/setsockopt interface to simply get/setsockopt"

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

masayuki pushed a commit to branch revert-7651-sensor
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit bd7fa72817840fc058be4d33af70b3fb69c1f8ca
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Wed Nov 23 18:10:02 2022 +0900

    Revert "net/get/setsockopt: add si_get/setsockopt interface to simply get/setsockopt"
    
    This reverts commit e6f8ccda4a7e533effc8483a2d2a53f7839d4d62.
---
 include/nuttx/net/net.h          |   9 +-
 net/can/can.h                    |   8 +-
 net/can/can_callback.c           |   2 +-
 net/can/can_getsockopt.c         |  20 +-
 net/can/can_recvmsg.c            |  10 +-
 net/can/can_setsockopt.c         |  34 +--
 net/can/can_sockif.c             |   8 +-
 net/inet/inet_sockif.c           | 471 +--------------------------------------
 net/socket/getsockopt.c          | 198 ++++++++++++++--
 net/socket/setsockopt.c          | 283 ++++++++++++++++++++++-
 net/usrsock/usrsock.h            |  14 +-
 net/usrsock/usrsock_getsockopt.c |  22 +-
 net/usrsock/usrsock_setsockopt.c |  20 +-
 net/usrsock/usrsock_sockif.c     |   7 +-
 14 files changed, 486 insertions(+), 620 deletions(-)

diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index bdabcbaf83..cc7fab801e 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -166,12 +166,6 @@ struct sock_intf_s
   CODE int        (*si_ioctl)(FAR struct socket *psock,
                     int cmd, unsigned long arg);
   CODE int        (*si_socketpair)(FAR struct socket *psocks[2]);
-#ifdef CONFIG_NET_SOCKOPTS
-  CODE int        (*si_getsockopt)(FAR struct socket *psock, int level,
-                    int option, FAR void *value, FAR socklen_t *value_len);
-  CODE int        (*si_setsockopt)(FAR struct socket *psock, int level,
-                    int option, FAR const void *value, socklen_t value_len);
-#endif
 #ifdef CONFIG_NET_SENDFILE
   CODE ssize_t    (*si_sendfile)(FAR struct socket *psock,
                     FAR struct file *infile, FAR off_t *offset,
@@ -216,6 +210,9 @@ struct socket_conn_s
 #ifdef CONFIG_NET_SOLINGER
   socktimeo_t   s_linger;    /* Linger timeout value (in deciseconds) */
 #endif
+#ifdef CONFIG_NET_TIMESTAMP
+  int32_t       s_timestamp; /* Socket timestamp enabled/disabled */
+#endif
 #ifdef CONFIG_NET_BINDTODEVICE
   uint8_t       s_boundto;   /* Index of the interface we are bound to.
                               * Unbound: 0, Bound: 1-MAX_IFINDEX */
diff --git a/net/can/can.h b/net/can/can.h
index b1180c11aa..d317fea6f7 100644
--- a/net/can/can.h
+++ b/net/can/can.h
@@ -111,9 +111,6 @@ struct can_conn_s
   int32_t tx_deadline;
 # endif
 #endif
-#ifdef CONFIG_NET_TIMESTAMP
-  int32_t timestamp; /* Socket timestamp enabled/disabled */
-#endif
 };
 
 /****************************************************************************
@@ -356,7 +353,6 @@ void can_readahead_signal(FAR struct can_conn_s *conn);
  *
  * Input Parameters:
  *   psock     Socket structure of socket to operate on
- *   level     Protocol level to set the option
  *   option    identifies the option to set
  *   value     Points to the argument value
  *   value_len The length of the argument value
@@ -369,7 +365,7 @@ void can_readahead_signal(FAR struct can_conn_s *conn);
  ****************************************************************************/
 
 #ifdef CONFIG_NET_CANPROTO_OPTIONS
-int can_setsockopt(FAR struct socket *psock, int level, int option,
+int can_setsockopt(FAR struct socket *psock, int option,
                    FAR const void *value, socklen_t value_len);
 #endif
 
@@ -403,7 +399,7 @@ int can_setsockopt(FAR struct socket *psock, int level, int option,
  ****************************************************************************/
 
 #ifdef CONFIG_NET_CANPROTO_OPTIONS
-int can_getsockopt(FAR struct socket *psock, int level, int option,
+int can_getsockopt(FAR struct socket *psock, int option,
                    FAR void *value, FAR socklen_t *value_len);
 #endif
 
diff --git a/net/can/can_callback.c b/net/can/can_callback.c
index a5f3e17937..394c1d51ac 100644
--- a/net/can/can_callback.c
+++ b/net/can/can_callback.c
@@ -123,7 +123,7 @@ uint16_t can_callback(FAR struct net_driver_s *dev,
 #ifdef CONFIG_NET_TIMESTAMP
       /* TIMESTAMP sockopt is activated, create timestamp and copy to iob */
 
-      if (conn->timestamp)
+      if (conn->sconn.s_timestamp)
         {
           struct timespec *ts = (struct timespec *)
                                                 &dev->d_appdata[dev->d_len];
diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c
index af6253ca3a..17a4b18850 100644
--- a/net/can/can_getsockopt.c
+++ b/net/can/can_getsockopt.c
@@ -74,7 +74,7 @@
  *
  ****************************************************************************/
 
-int can_getsockopt(FAR struct socket *psock, int level, int option,
+int can_getsockopt(FAR struct socket *psock, int option,
                    FAR void *value, FAR socklen_t *value_len)
 {
   FAR struct can_conn_s *conn;
@@ -84,24 +84,6 @@ int can_getsockopt(FAR struct socket *psock, int level, int option,
               psock->s_conn != NULL);
   conn = (FAR struct can_conn_s *)psock->s_conn;
 
-#ifdef CONFIG_NET_TIMESTAMP
-  if (level == SOL_SOCKET && option == SO_TIMESTAMP)
-    {
-      if (*value_len != sizeof(int32_t))
-        {
-          return -EINVAL;
-        }
-
-      *(FAR int32_t *)value = conn->timestamp;
-      return OK;
-    }
-#endif
-
-  if (level != SOL_CAN_RAW)
-    {
-      return -ENOPROTOOPT;
-    }
-
   if (psock->s_type != SOCK_RAW)
     {
       nerr("ERROR:  Not a RAW CAN socket\n");
diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c
index 8ef711de8b..189505f717 100644
--- a/net/can/can_recvmsg.c
+++ b/net/can/can_recvmsg.c
@@ -434,9 +434,9 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
 #endif
             {
 #ifdef CONFIG_NET_TIMESTAMP
-              if ((conn->timestamp && (dev->d_len >
+              if ((conn->sconn.s_timestamp && (dev->d_len >
                   sizeof(struct can_frame) + sizeof(struct timeval)))
-                  || (!conn->timestamp && (dev->d_len >
+                  || (!conn->sconn.s_timestamp && (dev->d_len >
                    sizeof(struct can_frame))))
 #else
               if (dev->d_len > sizeof(struct can_frame))
@@ -454,7 +454,7 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
           can_newdata(dev, pstate);
 
 #ifdef CONFIG_NET_TIMESTAMP
-          if (conn->timestamp)
+          if (conn->sconn.s_timestamp)
             {
               if (pstate->pr_msglen == sizeof(struct timeval))
                 {
@@ -587,7 +587,7 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
   state.pr_buffer = msg->msg_iov->iov_base;
 
 #ifdef CONFIG_NET_TIMESTAMP
-  if (conn->timestamp && msg->msg_controllen >=
+  if (conn->sconn.s_timestamp && msg->msg_controllen >=
         (sizeof(struct cmsghdr) + sizeof(struct timeval)))
     {
       struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
@@ -619,7 +619,7 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
   if (ret > 0)
     {
 #ifdef CONFIG_NET_TIMESTAMP
-      if (conn->timestamp)
+      if (conn->sconn.s_timestamp)
         {
           if (state.pr_msglen == sizeof(struct timeval))
             {
diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c
index efa87ef9d5..2b43c1de98 100644
--- a/net/can/can_setsockopt.c
+++ b/net/can/can_setsockopt.c
@@ -58,7 +58,6 @@
  *
  * Input Parameters:
  *   psock     Socket structure of socket to operate on
- *   level     Protocol level to set the option
  *   option    identifies the option to set
  *   value     Points to the argument value
  *   value_len The length of the argument value
@@ -70,7 +69,7 @@
  *
  ****************************************************************************/
 
-int can_setsockopt(FAR struct socket *psock, int level, int option,
+int can_setsockopt(FAR struct socket *psock, int option,
                    FAR const void *value, socklen_t value_len)
 {
   FAR struct can_conn_s *conn;
@@ -82,37 +81,6 @@ int can_setsockopt(FAR struct socket *psock, int level, int option,
 
   conn = (FAR struct can_conn_s *)psock->s_conn;
 
-#ifdef CONFIG_NET_TIMESTAMP
-
-  /* Generates a timestamp for each incoming packet */
-
-  if (level == SOL_SOCKET && option == SO_TIMESTAMP)
-    {
-      /* Verify that option is at least the size of an integer. */
-
-      if (value_len < sizeof(int32_t))
-        {
-          return -EINVAL;
-        }
-
-      /* Lock the network so that we have exclusive access to the socket
-       * options.
-       */
-
-      net_lock();
-
-      conn->timestamp = *((FAR int32_t *)value);
-
-      net_unlock();
-      return OK;
-    }
-#endif
-
-  if (level != SOL_CAN_RAW)
-    {
-      return -ENOPROTOOPT;
-    }
-
   if (psock->s_type != SOCK_RAW)
     {
       nerr("ERROR:  Not a RAW CAN socket\n");
diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c
index 3fb1623a2f..3e9ccc27b0 100644
--- a/net/can/can_sockif.c
+++ b/net/can/can_sockif.c
@@ -84,13 +84,7 @@ const struct sock_intf_s g_can_sockif =
   can_poll_local,   /* si_poll */
   can_sendmsg,      /* si_sendmsg */
   can_recvmsg,      /* si_recvmsg */
-  can_close,        /* si_close */
-  NULL,             /* si_ioctl */
-  NULL              /* si_socketpair */
-#if defined(CONFIG_NET_SOCKOPTS) && defined(CONFIG_NET_CANPROTO_OPTIONS)
-  , can_getsockopt  /* si_getsockopt */
-  , can_setsockopt  /* si_setsockopt */
-#endif
+  can_close         /* si_close */
 };
 
 /****************************************************************************
diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c
index a7b1030a80..c198c14c87 100644
--- a/net/inet/inet_sockif.c
+++ b/net/inet/inet_sockif.c
@@ -91,12 +91,6 @@ static ssize_t    inet_recvmsg(FAR struct socket *psock,
 static int        inet_ioctl(FAR struct socket *psock,
                     int cmd, unsigned long arg);
 static int        inet_socketpair(FAR struct socket *psocks[2]);
-#ifdef CONFIG_NET_SOCKOPTS
-static int        inet_getsockopt(FAR struct socket *psock, int level,
-                    int option, FAR void *value, FAR socklen_t *value_len);
-static int        inet_setsockopt(FAR struct socket *psock, int level,
-                    int option, FAR const void *value, socklen_t value_len);
-#endif
 #ifdef CONFIG_NET_SENDFILE
 static ssize_t    inet_sendfile(FAR struct socket *psock,
                     FAR struct file *infile, FAR off_t *offset,
@@ -124,12 +118,9 @@ static const struct sock_intf_s g_inet_sockif =
   inet_close,       /* si_close */
   inet_ioctl,       /* si_ioctl */
   inet_socketpair   /* si_socketpair */
-#ifdef CONFIG_NET_SOCKOPTS
-  , inet_getsockopt /* si_getsockopt */
-  , inet_setsockopt /* si_setsockopt */
-#endif
 #ifdef CONFIG_NET_SENDFILE
-  , inet_sendfile   /* si_sendfile */
+  ,
+  inet_sendfile     /* si_sendfile */
 #endif
 };
 
@@ -571,464 +562,6 @@ static int inet_getpeername(FAR struct socket *psock,
     }
 }
 
-#ifdef CONFIG_NET_SOCKOPTS
-
-/****************************************************************************
- * Name: inet_get_socketlevel_option
- *
- * Description:
- *   inet_get_socketlevel_option() retrieve the value for the option
- *   specified by the 'option' argument for the socket specified by the
- *   'psock' argument.  If the size of the option value is greater than
- *   'value_len', the value stored in the object pointed to by the 'value'
- *   argument will be silently truncated. Otherwise, the length pointed to
- *   by the 'value_len' argument will be modified to indicate the actual
- *   length of the 'value'.
- *
- *   The 'level' argument specifies the protocol level of the option. To
- *   retrieve options at the socket level, specify the level argument as
- *   SOL_SOCKET; to retrieve options at the TCP-protocol level, the level
- *   argument is SOL_TCP.
- *
- *   See <sys/socket.h> a complete list of values for the socket-level
- *   'option' argument.  Protocol-specific options are are protocol specific
- *   header files (such as netinet/tcp.h for the case of the TCP protocol).
- *
- * Input Parameters:
- *   psock     Socket structure of the socket to query
- *   level     Protocol level to set the option
- *   option    identifies the option to get
- *   value     Points to the argument value
- *   value_len The length of the argument value
- *
- * Returned Value:
- *   Returns zero (OK) on success.  On failure, it returns a negated errno
- *   value to indicate the nature of the error.  See psock_getsockopt() for
- *   the complete list of appropriate return error codes.
- *
- ****************************************************************************/
-
-static int inet_get_socketlevel_option(FAR struct socket *psock, int option,
-                                       FAR void *value,
-                                       FAR socklen_t *value_len)
-{
-  switch (option)
-    {
-#if CONFIG_NET_RECV_BUFSIZE > 0
-      case SO_RCVBUF:     /* Reports receive buffer size */
-        {
-          if (*value_len != sizeof(int))
-            {
-              return -EINVAL;
-            }
-
-#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
-          if (psock->s_type == SOCK_STREAM)
-            {
-              FAR struct tcp_conn_s *tcp = psock->s_conn;
-              *(FAR int *)value = tcp->rcv_bufs;
-            }
-          else
-#endif
-#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
-          if (psock->s_type == SOCK_DGRAM)
-            {
-              FAR struct udp_conn_s *udp = psock->s_conn;
-              *(FAR int *)value = udp->rcvbufs;
-            }
-          else
-#endif
-            {
-              return -ENOPROTOOPT;
-            }
-        }
-        break;
-#endif
-
-#if CONFIG_NET_SEND_BUFSIZE > 0
-      case SO_SNDBUF:     /* Reports send buffer size */
-        {
-          if (*value_len != sizeof(int))
-            {
-              return -EINVAL;
-            }
-
-#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
-          if (psock->s_type == SOCK_STREAM)
-            {
-              FAR struct tcp_conn_s *tcp = psock->s_conn;
-              *(FAR int *)value = tcp->snd_bufs;
-            }
-          else
-#endif
-#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
-          if (psock->s_type == SOCK_DGRAM)
-            {
-              FAR struct udp_conn_s *udp = psock->s_conn;
-
-              /* Save the send buffer size */
-
-              *(FAR int *)value = udp->sndbufs;
-            }
-          else
-#endif
-            {
-              return -ENOPROTOOPT;
-            }
-        }
-        break;
-#endif
-
-#ifdef CONFIG_NET_TCPPROTO_OPTIONS
-      case SO_KEEPALIVE:
-        {
-          /* Any connection-oriented protocol could potentially support
-           * SO_KEEPALIVE.  However, this option is currently only available
-           * for TCP/IP.
-           *
-           * NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
-           * protocol-level option.  A given TCP connection may service
-           * multiple sockets (via dup'ing of the socket). There is, however,
-           * still only one connection to be monitored and that is a global
-           * attribute across all of the clones that may use the underlying
-           * connection.
-           */
-
-          /* Verifies TCP connections active by enabling the periodic
-           * transmission of probes.
-           */
-
-          return tcp_getsockopt(psock, option, value, value_len);
-        }
-#endif
-
-      default:
-        return -ENOPROTOOPT;
-    }
-
-  return OK;
-}
-
-/****************************************************************************
- * Name: inet_getsockopt
- *
- * Description:
- *   inet_getsockopt() retrieve the value for the option specified by the
- *   'option' argument at the protocol level specified by the 'level'
- *   argument. If the size of the option value is greater than 'value_len',
- *   the value stored in the object pointed to by the 'value' argument will
- *   be silently truncated. Otherwise, the length pointed to by the
- *   'value_len' argument will be modified to indicate the actual length
- *   of the 'value'.
- *
- *   The 'level' argument specifies the protocol level of the option. To
- *   retrieve options at the socket level, specify the level argument as
- *   SOL_SOCKET.
- *
- *   See <sys/socket.h> a complete list of values for the 'option' argument.
- *
- * Input Parameters:
- *   psock     Socket structure of the socket to query
- *   level     Protocol level to set the option
- *   option    identifies the option to get
- *   value     Points to the argument value
- *   value_len The length of the argument value
- *
- ****************************************************************************/
-
-static int inet_getsockopt(FAR struct socket *psock, int level, int option,
-                           FAR void *value, FAR socklen_t *value_len)
-{
-  if (level == SOL_SOCKET)
-    {
-      return inet_get_socketlevel_option(psock, option, value, value_len);
-    }
-#ifdef CONFIG_NET_TCPPROTO_OPTIONS
-  else if (level == IPPROTO_TCP)
-    {
-      return tcp_getsockopt(psock, option, value, value_len);
-    }
-#endif
-  else
-    {
-      return -ENOPROTOOPT;
-    }
-}
-
-/****************************************************************************
- * Name: inet_set_socketlevel_option
- *
- * Description:
- *   inet_set_socketlevel_option() sets the socket-level option specified by
- *   the 'option' argument to the value pointed to by the 'value' argument
- *   for the socket specified by the 'psock' argument.
- *
- *   See <sys/socket.h> a complete list of values for the socket level
- *   'option' argument.
- *
- * Input Parameters:
- *   psock     Socket structure of socket to operate on
- *   option    identifies the option to set
- *   value     Points to the argument value
- *   value_len The length of the argument value
- *
- * Returned Value:
- *   Returns zero (OK) on success.  On failure, it returns a negated errno
- *   value to indicate the nature of the error.  See psock_setcockopt() for
- *   the list of possible error values.
- *
- ****************************************************************************/
-
-static int inet_set_socketlevel_option(FAR struct socket *psock, int option,
-                                       FAR const void *value,
-                                       socklen_t value_len)
-{
-  switch (option)
-    {
-#ifdef CONFIG_NET_TCPPROTO_OPTIONS
-      case SO_KEEPALIVE:
-        {
-          /* Any connection-oriented protocol could potentially support
-           * SO_KEEPALIVE.  However, this option is currently only available
-           * for TCP/IP.
-           *
-           * NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
-           * protocol-level option.  A given TCP connection may service
-           * multiple sockets (via dup'ing of the socket). There is, however,
-           * still only one connection to be monitored and that is a global
-           * attribute across all of the clones that may use the underlying
-           * connection.
-           */
-
-          /* Verifies TCP connections active by enabling the
-           * periodic transmission of probes
-           */
-
-          return tcp_setsockopt(psock, option, value, value_len);
-        }
-#endif
-
-#ifdef CONFIG_NET_SOLINGER
-      case SO_LINGER:
-        {
-          /* Lingers on a close() if data is present */
-
-          FAR struct socket_conn_s *conn = psock->s_conn;
-          FAR struct linger *setting;
-
-          /* Verify that option is at least the size of an 'struct linger'. */
-
-          if (value_len < sizeof(struct linger))
-            {
-              return -EINVAL;
-            }
-
-          /* Get the value.  Is the option being set or cleared? */
-
-          setting = (FAR struct linger *)value;
-
-          /* Lock the network so that we have exclusive access to the socket
-           * options.
-           */
-
-          net_lock();
-
-          /* Set or clear the linger option bit and linger time
-           * (in deciseconds)
-           */
-
-          if (setting->l_onoff)
-            {
-              _SO_SETOPT(conn->s_options, option);
-              conn->s_linger = 10 * setting->l_linger;
-            }
-          else
-            {
-              _SO_CLROPT(conn->s_options, option);
-              conn->s_linger = 0;
-            }
-
-          net_unlock();
-        }
-        break;
-#endif
-
-#if CONFIG_NET_RECV_BUFSIZE > 0
-      case SO_RCVBUF:     /* Sets receive buffer size */
-        {
-          int buffersize;
-
-          /* Verify that option is the size of an 'int'.  Should also check
-           * that 'value' is properly aligned for an 'int'
-           */
-
-          if (value_len != sizeof(int))
-            {
-              return -EINVAL;
-            }
-
-          /* Get the value.  Is the option being set or cleared? */
-
-          buffersize = *(FAR int *)value;
-          if (buffersize < 0)
-            {
-              return -EINVAL;
-            }
-
-          net_lock();
-
-#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
-          if (psock->s_type == SOCK_STREAM)
-            {
-              FAR struct tcp_conn_s *tcp = psock->s_conn;
-
-              /* Save the receive buffer size */
-
-              tcp->rcv_bufs = buffersize;
-            }
-          else
-#endif
-#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
-          if (psock->s_type == SOCK_DGRAM)
-            {
-              FAR struct udp_conn_s *udp = psock->s_conn;
-
-              /* Save the receive buffer size */
-
-              udp->rcvbufs = buffersize;
-            }
-          else
-#endif
-            {
-              net_unlock();
-              return -ENOPROTOOPT;
-            }
-
-          net_unlock();
-        }
-        break;
-#endif
-
-#if CONFIG_NET_SEND_BUFSIZE > 0
-      case SO_SNDBUF:     /* Sets send buffer size */
-        {
-          int buffersize;
-
-          /* Verify that option is the size of an 'int'.  Should also check
-           * that 'value' is properly aligned for an 'int'
-           */
-
-          if (value_len != sizeof(int))
-            {
-              return -EINVAL;
-            }
-
-          /* Get the value.  Is the option being set or cleared? */
-
-          buffersize = *(FAR int *)value;
-
-          if (buffersize < 0)
-            {
-              return -EINVAL;
-            }
-
-          net_lock();
-
-#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
-          if (psock->s_type == SOCK_STREAM)
-            {
-              FAR struct tcp_conn_s *tcp = psock->s_conn;
-
-              /* Save the send buffer size */
-
-              tcp->snd_bufs = buffersize;
-            }
-          else
-#endif
-#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
-          if (psock->s_type == SOCK_DGRAM)
-            {
-              FAR struct udp_conn_s *udp = psock->s_conn;
-
-              /* Save the send buffer size */
-
-              udp->sndbufs = buffersize;
-            }
-          else
-#endif
-            {
-              net_unlock();
-              return -ENOPROTOOPT;
-            }
-
-          net_unlock();
-        }
-        break;
-#endif
-
-      default:
-        return -ENOPROTOOPT;
-    }
-
-  return OK;
-}
-
-/****************************************************************************
- * Name: inet_setsockopt
- *
- * Description:
- *   inet_setsockopt() sets the option specified by the 'option' argument,
- *   at the protocol level specified by the 'level' argument, to the value
- *   pointed to by the 'value' argument for the connection.
- *
- *   The 'level' argument specifies the protocol level of the option. To set
- *   options at the socket level, specify the level argument as SOL_SOCKET.
- *
- *   See <sys/socket.h> a complete list of values for the 'option' argument.
- *
- * Input Parameters:
- *   psock     Socket structure of the socket to query
- *   level     Protocol level to set the option
- *   option    identifies the option to set
- *   value     Points to the argument value
- *   value_len The length of the argument value
- *
- ****************************************************************************/
-
-static int inet_setsockopt(FAR struct socket *psock, int level, int option,
-                           FAR const void *value, socklen_t value_len)
-{
-  switch (level)
-    {
-      case SOL_SOCKET:
-        return inet_set_socketlevel_option(psock, option, value, value_len);
-
-#ifdef CONFIG_NET_TCPPROTO_OPTIONS
-      case IPPROTO_TCP:/* TCP protocol socket options (see include/netinet/tcp.h) */
-        return tcp_setsockopt(psock, option, value, value_len);
-#endif
-
-#ifdef CONFIG_NET_UDPPROTO_OPTIONS
-      case IPPROTO_UDP:/* UDP protocol socket options (see include/netinet/udp.h) */
-        return udp_setsockopt(psock, option, value, value_len);
-#endif
-
-#ifdef CONFIG_NET_IPv4
-      case IPPROTO_IP:/* TCP protocol socket options (see include/netinet/in.h) */
-        return ipv4_setsockopt(psock, option, value, value_len);
-#endif
-
-#ifdef CONFIG_NET_IPv6
-      case IPPROTO_IPV6:/* TCP protocol socket options (see include/netinet/in.h) */
-        return ipv6_setsockopt(psock, option, value, value_len);
-#endif
-      default:
-        return -ENOPROTOOPT;
-    }
-}
-
-#endif
-
 /****************************************************************************
  * Name: inet_listen
  *
diff --git a/net/socket/getsockopt.c b/net/socket/getsockopt.c
index f2f45e73e2..4c3c75878c 100644
--- a/net/socket/getsockopt.c
+++ b/net/socket/getsockopt.c
@@ -33,7 +33,11 @@
 #include <errno.h>
 
 #include "socket/socket.h"
+#include "tcp/tcp.h"
+#include "udp/udp.h"
+#include "usrsock/usrsock.h"
 #include "utils/utils.h"
+#include "can/can.h"
 
 /****************************************************************************
  * Private Functions
@@ -124,18 +128,39 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
           net_dsec2timeval(timeo, (struct timeval *)value);
           *value_len   = sizeof(struct timeval);
         }
-        break;
 
+        return OK;
+    }
+
+#ifdef CONFIG_NET_USRSOCK
+    if (psock->s_type == SOCK_USRSOCK_TYPE)
+      {
+        if (option == SO_TYPE)
+          {
+            FAR struct usrsock_conn_s *uconn = psock->s_conn;
+
+            /* Return the actual socket type */
+
+            *(FAR int *)value = uconn->type;
+            *value_len        = sizeof(int);
+
+            return OK;
+          }
+
+          return -ENOPROTOOPT;
+      }
+#endif
+
+  switch (option)
+    {
       case SO_ACCEPTCONN: /* Reports whether socket listening is enabled */
-        {
-          if (*value_len < sizeof(int))
-            {
-              return -EINVAL;
-            }
+        if (*value_len < sizeof(int))
+          {
+            return -EINVAL;
+          }
 
-          *(FAR int *)value = _SS_ISLISTENING(conn->s_flags);
-          *value_len        = sizeof(int);
-        }
+        *(FAR int *)value = _SS_ISLISTENING(conn->s_flags);
+        *value_len        = sizeof(int);
         break;
 
       /* The following options take a point to an integer boolean value.
@@ -146,8 +171,10 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
       case SO_BROADCAST:  /* Permits sending of broadcast messages */
       case SO_DEBUG:      /* Enables recording of debugging information */
       case SO_DONTROUTE:  /* Requests outgoing messages bypass standard routing */
+#ifndef CONFIG_NET_TCPPROTO_OPTIONS
       case SO_KEEPALIVE:  /* Verifies TCP connections active by enabling the
                            * periodic transmission of probes */
+#endif
       case SO_OOBINLINE:  /* Leaves received out-of-band data inline */
       case SO_REUSEADDR:  /* Allow reuse of local addresses */
         {
@@ -174,6 +201,23 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
         }
         break;
 
+#ifdef CONFIG_NET_TCPPROTO_OPTIONS
+      /* Any connection-oriented protocol could potentially support
+       * SO_KEEPALIVE.  However, this option is currently only available for
+       * TCP/IP.
+       *
+       * NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
+       * protocol-level option.  A given TCP connection may service multiple
+       * sockets (via dup'ing of the socket).  There is, however, still only
+       * one connection to be monitored and that is a global attribute across
+       * all of the clones that may use the underlying connection.
+       */
+
+      case SO_KEEPALIVE:  /* Verifies TCP connections active by enabling the
+                           * periodic transmission of probes */
+        return tcp_getsockopt(psock, option, value, value_len);
+#endif
+
       case SO_TYPE:       /* Reports the socket type */
         {
           /* Verify that option is the size of an 'int'.  Should also check
@@ -204,6 +248,97 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
         }
         break;
 
+#ifdef CONFIG_NET_TIMESTAMP
+      case SO_TIMESTAMP:
+        {
+          if (*value_len != sizeof(int))
+            {
+              return -EINVAL;
+            }
+
+          *(FAR int *)value = (int)conn->s_timestamp;
+        }
+        break;
+#endif
+
+#if CONFIG_NET_RECV_BUFSIZE > 0
+      case SO_RCVBUF:     /* Reports receive buffer size */
+        {
+          if (*value_len != sizeof(int))
+            {
+              return -EINVAL;
+            }
+
+#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
+          if (psock->s_type == SOCK_STREAM)
+            {
+              FAR struct tcp_conn_s *tcp;
+
+              tcp = (FAR struct tcp_conn_s *)conn;
+
+              *(FAR int *)value = tcp->rcv_bufs;
+            }
+          else
+#endif
+#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
+          if (psock->s_type == SOCK_DGRAM)
+            {
+              FAR struct udp_conn_s *udp;
+
+              udp = (FAR struct udp_conn_s *)conn;
+
+              *(FAR int *)value = udp->rcvbufs;
+            }
+          else
+#endif
+            {
+              return -ENOPROTOOPT;
+            }
+
+          break;
+        }
+#endif
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      case SO_SNDBUF:     /* Reports send buffer size */
+        {
+          if (*value_len != sizeof(int))
+            {
+              return -EINVAL;
+            }
+
+#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
+          if (psock->s_type == SOCK_STREAM)
+            {
+              FAR struct tcp_conn_s *tcp;
+
+              tcp = (FAR struct tcp_conn_s *)conn;
+
+              *(FAR int *)value = tcp->snd_bufs;
+            }
+          else
+#endif
+#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
+          if (psock->s_type == SOCK_DGRAM)
+            {
+              FAR struct udp_conn_s *udp;
+
+              udp = (FAR struct udp_conn_s *)conn;
+
+              /* Save the send buffer size */
+
+              *(FAR int *)value = udp->sndbufs;
+            }
+          else
+#endif
+            {
+              return -ENOPROTOOPT;
+            }
+
+          break;
+        }
+#endif
+
       default:
         return -ENOPROTOOPT;
     }
@@ -262,7 +397,7 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
 int psock_getsockopt(FAR struct socket *psock, int level, int option,
                      FAR void *value, FAR socklen_t *value_len)
 {
-  int ret = -ENOPROTOOPT;
+  int ret;
 
   /* Verify that the sockfd corresponds to valid, allocated socket */
 
@@ -271,20 +406,49 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
       return -EBADF;
     }
 
-  /* Perform the socket interface operation */
+  /* Handle retrieval of the socket option according to the level at which
+   * option should be applied.
+   */
 
-  if (psock->s_sockif->si_getsockopt != NULL)
+  switch (level)
     {
-      ret = psock->s_sockif->si_getsockopt(psock, level, option,
-                                           value, value_len);
+      case SOL_SOCKET:   /* Socket-level options (see include/sys/socket.h) */
+       ret = psock_socketlevel_option(psock, option, value, value_len);
+       break;
+
+#ifdef CONFIG_NET_TCPPROTO_OPTIONS
+      case IPPROTO_TCP:  /* TCP protocol socket options (see include/netinet/tcp.h) */
+       ret = tcp_getsockopt(psock, option, value, value_len);
+       break;
+#endif
+
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+      case SOL_CAN_RAW:/* CAN protocol socket options (see include/netpacket/can.h) */
+       ret = can_getsockopt(psock, option, value, value_len);
+       break;
+#endif
+
+      /* These levels are defined in sys/socket.h, but are not yet
+       * implemented.
+       */
+
+      case IPPROTO_IP:   /* TCP protocol socket options (see include/netinet/ip.h) */
+      case IPPROTO_IPV6: /* TCP protocol socket options (see include/netinet/ip6.h) */
+      case IPPROTO_UDP:  /* TCP protocol socket options (see include/netinit/udp.h) */
+      default:           /* The provided level is invalid */
+        ret = -ENOPROTOOPT;
+       break;
     }
 
-  /* Try socket level if the socket interface operation is not available */
+#ifdef CONFIG_NET_USRSOCK
+  /* Try usrsock further if the protocol not available */
 
-  if (ret == -ENOPROTOOPT && level == SOL_SOCKET)
+  if (ret == -ENOPROTOOPT && psock->s_type == SOCK_USRSOCK_TYPE)
     {
-      ret = psock_socketlevel_option(psock, option, value, value_len);
+      ret = usrsock_getsockopt(psock->s_conn, level,
+                               option, value, value_len);
     }
+#endif
 
   return ret;
 }
diff --git a/net/socket/setsockopt.c b/net/socket/setsockopt.c
index a7ede25744..ba72e84696 100644
--- a/net/socket/setsockopt.c
+++ b/net/socket/setsockopt.c
@@ -34,11 +34,15 @@
 #include <arch/irq.h>
 
 #include <nuttx/net/net.h>
-#include <nuttx/net/netdev.h>
 #include <netdev/netdev.h>
 
 #include "socket/socket.h"
+#include "inet/inet.h"
+#include "tcp/tcp.h"
+#include "udp/udp.h"
+#include "usrsock/usrsock.h"
 #include "utils/utils.h"
+#include "can/can.h"
 
 /****************************************************************************
  * Public Functions
@@ -130,14 +134,27 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
             {
               _SO_SETOPT(conn->s_options, option);
             }
+
+          return OK;
         }
-        break;
+    }
+
+#ifdef CONFIG_NET_USRSOCK
+    if (psock->s_type == SOCK_USRSOCK_TYPE)
+      {
+        return -ENOPROTOOPT;
+      }
+#endif
 
+  switch (option)
+    {
       case SO_BROADCAST:  /* Permits sending of broadcast messages */
       case SO_DEBUG:      /* Enables recording of debugging information */
       case SO_DONTROUTE:  /* Requests outgoing messages bypass standard routing */
+#ifndef CONFIG_NET_TCPPROTO_OPTIONS
       case SO_KEEPALIVE:  /* Verifies TCP connections active by enabling the
                            * periodic transmission of probes */
+#endif
       case SO_OOBINLINE:  /* Leaves received out-of-band data inline */
       case SO_REUSEADDR:  /* Allow reuse of local addresses */
         {
@@ -177,6 +194,212 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
         }
         break;
 
+#ifdef CONFIG_NET_TCPPROTO_OPTIONS
+      /* Any connection-oriented protocol could potentially support
+       * SO_KEEPALIVE.  However, this option is currently only available for
+       * TCP/IP.
+       *
+       * NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
+       * protocol-level option.  A given TCP connection may service multiple
+       * sockets (via dup'ing of the socket).  There is, however, still only
+       * one connection to be monitored and that is a global attribute across
+       * all of the clones that may use the underlying connection.
+       */
+
+      case SO_KEEPALIVE:  /* Verifies TCP connections active by enabling the
+                           * periodic transmission of probes */
+        return tcp_setsockopt(psock, option, value, value_len);
+#endif
+
+#ifdef CONFIG_NET_SOLINGER
+      case SO_LINGER:  /* Lingers on a close() if data is present */
+        {
+          FAR struct linger *setting;
+
+          /* Verify that option is at least the size of an 'struct linger'. */
+
+          if (value_len < sizeof(FAR struct linger))
+            {
+              return -EINVAL;
+            }
+
+          /* Get the value.  Is the option being set or cleared? */
+
+          setting = (FAR struct linger *)value;
+
+          /* Lock the network so that we have exclusive access to the socket
+           * options.
+           */
+
+          net_lock();
+
+          /* Set or clear the linger option bit and linger time
+           * (in deciseconds)
+           */
+
+          if (setting->l_onoff)
+            {
+              _SO_SETOPT(conn->s_options, option);
+              conn->s_linger = 10 * setting->l_linger;
+            }
+          else
+            {
+              _SO_CLROPT(conn->s_options, option);
+              conn->s_linger = 0;
+            }
+
+          net_unlock();
+        }
+        break;
+#endif
+
+#ifdef CONFIG_NET_TIMESTAMP
+      case SO_TIMESTAMP:  /* Generates a timestamp for each incoming packet */
+        {
+          /* Verify that option is at least the size of an integer. */
+
+          if (value_len < sizeof(FAR int32_t))
+            {
+              return -EINVAL;
+            }
+
+          /* Lock the network so that we have exclusive access to the socket
+           * options.
+           */
+
+          net_lock();
+
+          conn->s_timestamp = *((FAR int32_t *)value);
+
+          net_unlock();
+        }
+        break;
+#endif
+
+#if CONFIG_NET_RECV_BUFSIZE > 0
+      case SO_RCVBUF:     /* Sets receive buffer size */
+        {
+          int buffersize;
+
+          /* Verify that option is the size of an 'int'.  Should also check
+           * that 'value' is properly aligned for an 'int'
+           */
+
+          if (value_len != sizeof(int))
+            {
+              return -EINVAL;
+            }
+
+          /* Get the value.  Is the option being set or cleared? */
+
+          buffersize = *(FAR int *)value;
+
+          if (buffersize < 0)
+            {
+              return -EINVAL;
+            }
+
+          net_lock();
+
+#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
+          if (psock->s_type == SOCK_STREAM)
+            {
+              FAR struct tcp_conn_s *tcp;
+
+              tcp = (FAR struct tcp_conn_s *)conn;
+
+              /* Save the receive buffer size */
+
+              tcp->rcv_bufs = buffersize;
+            }
+          else
+#endif
+#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
+          if (psock->s_type == SOCK_DGRAM)
+            {
+              FAR struct udp_conn_s *udp;
+
+              udp = (FAR struct udp_conn_s *)conn;
+
+              /* Save the receive buffer size */
+
+              udp->rcvbufs = buffersize;
+            }
+          else
+#endif
+            {
+              net_unlock();
+              return -ENOPROTOOPT;
+            }
+
+          net_unlock();
+
+          break;
+        }
+#endif
+
+#if CONFIG_NET_SEND_BUFSIZE > 0
+      case SO_SNDBUF:     /* Sets send buffer size */
+        {
+          int buffersize;
+
+          /* Verify that option is the size of an 'int'.  Should also check
+           * that 'value' is properly aligned for an 'int'
+           */
+
+          if (value_len != sizeof(int))
+            {
+              return -EINVAL;
+            }
+
+          /* Get the value.  Is the option being set or cleared? */
+
+          buffersize = *(FAR int *)value;
+
+          if (buffersize < 0)
+            {
+              return -EINVAL;
+            }
+
+          net_lock();
+
+#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK)
+          if (psock->s_type == SOCK_STREAM)
+            {
+              FAR struct tcp_conn_s *tcp;
+
+              tcp = (FAR struct tcp_conn_s *)conn;
+
+              /* Save the send buffer size */
+
+              tcp->snd_bufs = buffersize;
+            }
+          else
+#endif
+#if defined(CONFIG_NET_UDP) && !defined(CONFIG_NET_UDP_NO_STACK)
+          if (psock->s_type == SOCK_DGRAM)
+            {
+              FAR struct udp_conn_s *udp;
+
+              udp = (FAR struct udp_conn_s *)conn;
+
+              /* Save the send buffer size */
+
+              udp->sndbufs = buffersize;
+            }
+          else
+#endif
+            {
+              net_unlock();
+              return -ENOPROTOOPT;
+            }
+
+          net_unlock();
+
+          break;
+        }
+#endif
+
 #ifdef CONFIG_NET_BINDTODEVICE
       /* Handle the SO_BINDTODEVICE socket-level option.
        *
@@ -293,7 +516,7 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option,
 int psock_setsockopt(FAR struct socket *psock, int level, int option,
                      FAR const void *value, socklen_t value_len)
 {
-  int ret = -ENOPROTOOPT;
+  int ret;
 
   /* Verify that the sockfd corresponds to valid, allocated socket */
 
@@ -302,20 +525,60 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
       return -EBADF;
     }
 
-  /* Perform the socket interface operation */
+  /* Handle setting of the socket option according to the level at which
+   * option should be applied.
+   */
 
-  if (psock->s_sockif->si_setsockopt != NULL)
+  switch (level)
     {
-      ret = psock->s_sockif->si_setsockopt(psock, level, option,
-                                           value, value_len);
+      case SOL_SOCKET: /* Socket-level options (see include/sys/socket.h) */
+        ret = psock_socketlevel_option(psock, option, value, value_len);
+        break;
+
+#ifdef CONFIG_NET_TCPPROTO_OPTIONS
+      case IPPROTO_TCP:/* TCP protocol socket options (see include/netinet/tcp.h) */
+        ret = tcp_setsockopt(psock, option, value, value_len);
+        break;
+#endif
+
+#ifdef CONFIG_NET_UDPPROTO_OPTIONS
+      case IPPROTO_UDP:/* UDP protocol socket options (see include/netinet/udp.h) */
+        ret = udp_setsockopt(psock, option, value, value_len);
+        break;
+#endif
+
+#ifdef CONFIG_NET_IPv4
+      case IPPROTO_IP:/* TCP protocol socket options (see include/netinet/in.h) */
+        ret = ipv4_setsockopt(psock, option, value, value_len);
+        break;
+#endif
+
+#ifdef CONFIG_NET_IPv6
+      case IPPROTO_IPV6:/* TCP protocol socket options (see include/netinet/in.h) */
+        ret = ipv6_setsockopt(psock, option, value, value_len);
+        break;
+#endif
+
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+      case SOL_CAN_RAW:   /* CAN protocol socket options (see include/netpacket/can.h) */
+        ret = can_setsockopt(psock, option, value, value_len);
+        break;
+#endif
+
+      default:         /* The provided level is invalid */
+        ret = -ENOPROTOOPT;
+        break;
     }
 
-  /* Try socket level if the socket interface operation is not available */
+#ifdef CONFIG_NET_USRSOCK
+  /* Try usrsock further if the protocol not available */
 
-  if (ret == -ENOPROTOOPT && level == SOL_SOCKET)
+  if (ret == -ENOPROTOOPT && psock->s_type == SOCK_USRSOCK_TYPE)
     {
-      ret = psock_socketlevel_option(psock, option, value, value_len);
+      ret = usrsock_setsockopt(psock->s_conn, level,
+                               option, value, value_len);
     }
+#endif
 
   return ret;
 }
diff --git a/net/usrsock/usrsock.h b/net/usrsock/usrsock.h
index 7cbb0fd7dd..061afc3b10 100644
--- a/net/usrsock/usrsock.h
+++ b/net/usrsock/usrsock.h
@@ -546,7 +546,7 @@ ssize_t usrsock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
  *   See <sys/socket.h> a complete list of values for the 'option' argument.
  *
  * Input Parameters:
- *   psock     Socket structure of the socket to query
+ *   conn      usrsock socket connection structure
  *   level     Protocol level to set the option
  *   option    identifies the option to get
  *   value     Points to the argument value
@@ -554,8 +554,9 @@ ssize_t usrsock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
  *
  ****************************************************************************/
 
-int usrsock_getsockopt(FAR struct socket *psock, int level, int option,
-                       FAR void *value, FAR socklen_t *value_len);
+int usrsock_getsockopt(FAR struct usrsock_conn_s *conn, int level,
+                       int option, FAR void *value,
+                       FAR socklen_t *value_len);
 
 /****************************************************************************
  * Name: usrsock_setsockopt
@@ -571,7 +572,7 @@ int usrsock_getsockopt(FAR struct socket *psock, int level, int option,
  *   See <sys/socket.h> a complete list of values for the 'option' argument.
  *
  * Input Parameters:
- *   psock     Socket structure of the socket to query
+ *   conn      usrsock socket connection structure
  *   level     Protocol level to set the option
  *   option    identifies the option to set
  *   value     Points to the argument value
@@ -579,8 +580,9 @@ int usrsock_getsockopt(FAR struct socket *psock, int level, int option,
  *
  ****************************************************************************/
 
-int usrsock_setsockopt(FAR struct socket *psock, int level, int option,
-                       FAR const void *value, socklen_t value_len);
+int usrsock_setsockopt(FAR struct usrsock_conn_s *conn, int level,
+                       int option, FAR const void *value,
+                       FAR socklen_t value_len);
 
 /****************************************************************************
  * Name: usrsock_getsockname
diff --git a/net/usrsock/usrsock_getsockopt.c b/net/usrsock/usrsock_getsockopt.c
index 07f57a26e8..0b8b25e39e 100644
--- a/net/usrsock/usrsock_getsockopt.c
+++ b/net/usrsock/usrsock_getsockopt.c
@@ -160,7 +160,7 @@ static int do_getsockopt_request(FAR struct usrsock_conn_s *conn, int level,
  *   See <sys/socket.h> a complete list of values for the 'option' argument.
  *
  * Input Parameters:
- *   psock     Socket structure of the socket to query
+ *   conn      usrsock socket connection structure
  *   level     Protocol level to set the option
  *   option    identifies the option to get
  *   value     Points to the argument value
@@ -168,10 +168,10 @@ static int do_getsockopt_request(FAR struct usrsock_conn_s *conn, int level,
  *
  ****************************************************************************/
 
-int usrsock_getsockopt(FAR struct socket *psock, int level, int option,
+int usrsock_getsockopt(FAR struct usrsock_conn_s *conn,
+                       int level, int option,
                        FAR void *value, FAR socklen_t *value_len)
 {
-  FAR struct usrsock_conn_s *conn = psock->s_conn;
   struct usrsock_data_reqstate_s state =
   {
   };
@@ -179,22 +179,6 @@ int usrsock_getsockopt(FAR struct socket *psock, int level, int option,
   struct iovec inbufs[1];
   int ret;
 
-  if (level == SOL_SOCKET)
-    {
-      if (option == SO_TYPE)
-        {
-          /* Return the actual socket type */
-
-          *(FAR int *)value = conn->type;
-          *value_len = sizeof(int);
-          return OK;
-        }
-      else
-        {
-          return -ENOPROTOOPT;
-        }
-    }
-
   net_lock();
 
   if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
diff --git a/net/usrsock/usrsock_setsockopt.c b/net/usrsock/usrsock_setsockopt.c
index 922da98e27..70302f6c98 100644
--- a/net/usrsock/usrsock_setsockopt.c
+++ b/net/usrsock/usrsock_setsockopt.c
@@ -149,7 +149,7 @@ static int do_setsockopt_request(FAR struct usrsock_conn_s *conn,
  *   See <sys/socket.h> a complete list of values for the 'option' argument.
  *
  * Input Parameters:
- *   psock     Socket structure of the socket to query
+ *   conn      usrsock socket connection structure
  *   level     Protocol level to set the option
  *   option    identifies the option to set
  *   value     Points to the argument value
@@ -157,10 +157,10 @@ static int do_setsockopt_request(FAR struct usrsock_conn_s *conn,
  *
  ****************************************************************************/
 
-int usrsock_setsockopt(FAR struct socket *psock, int level, int option,
-                       FAR const void *value, socklen_t value_len)
+int usrsock_setsockopt(FAR struct usrsock_conn_s *conn,
+                       int level, int option,
+                       FAR const void *value, FAR socklen_t value_len)
 {
-  FAR struct usrsock_conn_s *conn = psock->s_conn;
   struct usrsock_reqstate_s state =
   {
   };
@@ -168,18 +168,6 @@ int usrsock_setsockopt(FAR struct socket *psock, int level, int option,
   int ret;
 
   DEBUGASSERT(conn);
-  if (level == SOL_SOCKET)
-    {
-      if (option == SO_RCVTIMEO || option == SO_SNDTIMEO)
-        {
-          return -ENOPROTOOPT;
-        }
-      else
-        {
-          return -EINVAL;
-        }
-    }
-
   net_lock();
 
   if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
diff --git a/net/usrsock/usrsock_sockif.c b/net/usrsock/usrsock_sockif.c
index 6f83ca30fa..5791ec6e68 100644
--- a/net/usrsock/usrsock_sockif.c
+++ b/net/usrsock/usrsock_sockif.c
@@ -66,12 +66,7 @@ const struct sock_intf_s g_usrsock_sockif =
   usrsock_sendmsg,            /* si_sendmsg */
   usrsock_recvmsg,            /* si_recvmsg */
   usrsock_sockif_close,       /* si_close */
-  usrsock_ioctl,              /* si_ioctl */
-  NULL                        /* si_socketpair */
-#ifdef CONFIG_NET_SOCKOPTS
-  , usrsock_getsockopt        /* si_getsockopt */
-  , usrsock_setsockopt        /* si_setsockopt */
-#endif
+  usrsock_ioctl               /* si_ioctl */
 };
 
 /****************************************************************************