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:
parent
c5704eb1e7
commit
e6f8ccda4a
14 changed files with 620 additions and 486 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue