net/get/setsockopt: add si_get/setsockopt interface to simply get/setsockopt

move private option to protocol sockif

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2022-11-22 21:15:06 +08:00 committed by Xiang Xiao
parent c5704eb1e7
commit e6f8ccda4a
14 changed files with 620 additions and 486 deletions

View file

@ -166,6 +166,12 @@ 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,
@ -210,9 +216,6 @@ 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 */

View file

@ -111,6 +111,9 @@ struct can_conn_s
int32_t tx_deadline;
# endif
#endif
#ifdef CONFIG_NET_TIMESTAMP
int32_t timestamp; /* Socket timestamp enabled/disabled */
#endif
};
/****************************************************************************
@ -353,6 +356,7 @@ 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
@ -365,7 +369,7 @@ void can_readahead_signal(FAR struct can_conn_s *conn);
****************************************************************************/
#ifdef CONFIG_NET_CANPROTO_OPTIONS
int can_setsockopt(FAR struct socket *psock, int option,
int can_setsockopt(FAR struct socket *psock, int level, int option,
FAR const void *value, socklen_t value_len);
#endif
@ -399,7 +403,7 @@ int can_setsockopt(FAR struct socket *psock, int option,
****************************************************************************/
#ifdef CONFIG_NET_CANPROTO_OPTIONS
int can_getsockopt(FAR struct socket *psock, int option,
int can_getsockopt(FAR struct socket *psock, int level, int option,
FAR void *value, FAR socklen_t *value_len);
#endif

View file

@ -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->sconn.s_timestamp)
if (conn->timestamp)
{
struct timespec *ts = (struct timespec *)
&dev->d_appdata[dev->d_len];

View file

@ -74,7 +74,7 @@
*
****************************************************************************/
int can_getsockopt(FAR struct socket *psock, int option,
int can_getsockopt(FAR struct socket *psock, int level, int option,
FAR void *value, FAR socklen_t *value_len)
{
FAR struct can_conn_s *conn;
@ -84,6 +84,24 @@ int can_getsockopt(FAR struct socket *psock, 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");

View file

@ -434,9 +434,9 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
#endif
{
#ifdef CONFIG_NET_TIMESTAMP
if ((conn->sconn.s_timestamp && (dev->d_len >
if ((conn->timestamp && (dev->d_len >
sizeof(struct can_frame) + sizeof(struct timeval)))
|| (!conn->sconn.s_timestamp && (dev->d_len >
|| (!conn->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->sconn.s_timestamp)
if (conn->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->sconn.s_timestamp && msg->msg_controllen >=
if (conn->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->sconn.s_timestamp)
if (conn->timestamp)
{
if (state.pr_msglen == sizeof(struct timeval))
{

View file

@ -58,6 +58,7 @@
*
* 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
@ -69,7 +70,7 @@
*
****************************************************************************/
int can_setsockopt(FAR struct socket *psock, int option,
int can_setsockopt(FAR struct socket *psock, int level, int option,
FAR const void *value, socklen_t value_len)
{
FAR struct can_conn_s *conn;
@ -81,6 +82,37 @@ int can_setsockopt(FAR struct socket *psock, 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");

View file

@ -84,7 +84,13 @@ 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 */
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
};
/****************************************************************************

View file

@ -91,6 +91,12 @@ 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,
@ -118,9 +124,12 @@ 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
};
@ -562,6 +571,464 @@ 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
*

View file

@ -33,11 +33,7 @@
#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
@ -128,39 +124,18 @@ 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.
@ -171,10 +146,8 @@ 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 */
{
@ -201,23 +174,6 @@ 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
@ -248,97 +204,6 @@ 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;
}
@ -397,7 +262,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;
int ret = -ENOPROTOOPT;
/* Verify that the sockfd corresponds to valid, allocated socket */
@ -406,49 +271,20 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
return -EBADF;
}
/* Handle retrieval of the socket option according to the level at which
* option should be applied.
*/
/* Perform the socket interface operation */
switch (level)
if (psock->s_sockif->si_getsockopt != NULL)
{
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;
ret = psock->s_sockif->si_getsockopt(psock, level, option,
value, value_len);
}
#ifdef CONFIG_NET_USRSOCK
/* Try usrsock further if the protocol not available */
/* Try socket level if the socket interface operation is not available */
if (ret == -ENOPROTOOPT && psock->s_type == SOCK_USRSOCK_TYPE)
if (ret == -ENOPROTOOPT && level == SOL_SOCKET)
{
ret = usrsock_getsockopt(psock->s_conn, level,
option, value, value_len);
ret = psock_socketlevel_option(psock, option, value, value_len);
}
#endif
return ret;
}

View file

@ -34,15 +34,11 @@
#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
@ -134,27 +130,14 @@ 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 */
{
@ -194,212 +177,6 @@ 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.
*
@ -516,7 +293,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;
int ret = -ENOPROTOOPT;
/* Verify that the sockfd corresponds to valid, allocated socket */
@ -525,60 +302,20 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
return -EBADF;
}
/* Handle setting of the socket option according to the level at which
* option should be applied.
*/
/* Perform the socket interface operation */
switch (level)
if (psock->s_sockif->si_setsockopt != NULL)
{
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;
ret = psock->s_sockif->si_setsockopt(psock, level, option,
value, value_len);
}
#ifdef CONFIG_NET_USRSOCK
/* Try usrsock further if the protocol not available */
/* Try socket level if the socket interface operation is not available */
if (ret == -ENOPROTOOPT && psock->s_type == SOCK_USRSOCK_TYPE)
if (ret == -ENOPROTOOPT && level == SOL_SOCKET)
{
ret = usrsock_setsockopt(psock->s_conn, level,
option, value, value_len);
ret = psock_socketlevel_option(psock, option, value, value_len);
}
#endif
return ret;
}

View file

@ -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:
* conn usrsock socket connection structure
* 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
@ -554,9 +554,8 @@ ssize_t usrsock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
*
****************************************************************************/
int usrsock_getsockopt(FAR struct usrsock_conn_s *conn, int level,
int option, FAR void *value,
FAR socklen_t *value_len);
int usrsock_getsockopt(FAR struct socket *psock, int level, int option,
FAR void *value, FAR socklen_t *value_len);
/****************************************************************************
* Name: usrsock_setsockopt
@ -572,7 +571,7 @@ int usrsock_getsockopt(FAR struct usrsock_conn_s *conn, int level,
* See <sys/socket.h> a complete list of values for the 'option' argument.
*
* Input Parameters:
* conn usrsock socket connection structure
* 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
@ -580,9 +579,8 @@ int usrsock_getsockopt(FAR struct usrsock_conn_s *conn, int level,
*
****************************************************************************/
int usrsock_setsockopt(FAR struct usrsock_conn_s *conn, int level,
int option, FAR const void *value,
FAR socklen_t value_len);
int usrsock_setsockopt(FAR struct socket *psock, int level, int option,
FAR const void *value, socklen_t value_len);
/****************************************************************************
* Name: usrsock_getsockname

View file

@ -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:
* conn usrsock socket connection structure
* 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
@ -168,10 +168,10 @@ static int do_getsockopt_request(FAR struct usrsock_conn_s *conn, int level,
*
****************************************************************************/
int usrsock_getsockopt(FAR struct usrsock_conn_s *conn,
int level, int option,
int usrsock_getsockopt(FAR struct socket *psock, 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,6 +179,22 @@ int usrsock_getsockopt(FAR struct usrsock_conn_s *conn,
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 ||

View file

@ -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:
* conn usrsock socket connection structure
* 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
@ -157,10 +157,10 @@ static int do_setsockopt_request(FAR struct usrsock_conn_s *conn,
*
****************************************************************************/
int usrsock_setsockopt(FAR struct usrsock_conn_s *conn,
int level, int option,
FAR const void *value, FAR socklen_t value_len)
int usrsock_setsockopt(FAR struct socket *psock, int level, int option,
FAR const void *value, socklen_t value_len)
{
FAR struct usrsock_conn_s *conn = psock->s_conn;
struct usrsock_reqstate_s state =
{
};
@ -168,6 +168,18 @@ int usrsock_setsockopt(FAR struct usrsock_conn_s *conn,
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 ||

View file

@ -66,7 +66,12 @@ 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 */
usrsock_ioctl, /* si_ioctl */
NULL /* si_socketpair */
#ifdef CONFIG_NET_SOCKOPTS
, usrsock_getsockopt /* si_getsockopt */
, usrsock_setsockopt /* si_setsockopt */
#endif
};
/****************************************************************************