From eabe535de7f04e5103f25e813b794c7cc9fdda09 Mon Sep 17 00:00:00 2001 From: "chao.an" Date: Mon, 7 Jun 2021 18:06:44 +0800 Subject: [PATCH] net/inet: add support of FIONREAD Signed-off-by: chao.an --- include/nuttx/net/net.h | 6 +-- include/nuttx/net/netdev.h | 2 - net/inet/inet_sockif.c | 46 +++++++++++++++++++- net/local/local_sockif.c | 48 ++++++++++++++++++++- net/netdev/netdev_ioctl.c | 17 +++----- net/tcp/Make.defs | 2 +- net/tcp/tcp.h | 17 ++++++++ net/tcp/tcp_ioctl.c | 85 +++++++++++++++++++++++++++++++++++++ net/udp/Make.defs | 1 + net/udp/udp.h | 17 ++++++++ net/udp/udp_ioctl.c | 87 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 309 insertions(+), 19 deletions(-) create mode 100644 net/tcp/tcp_ioctl.c create mode 100644 net/udp/udp_ioctl.c diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index cf7ba013e8..9302c6c453 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -195,15 +195,13 @@ struct sock_intf_s CODE ssize_t (*si_recvmsg)(FAR struct socket *psock, FAR struct msghdr *msg, int flags); CODE int (*si_close)(FAR struct socket *psock); + CODE int (*si_ioctl)(FAR struct socket *psock, int cmd, + FAR void *arg, size_t arglen); #ifdef CONFIG_NET_SENDFILE CODE ssize_t (*si_sendfile)(FAR struct socket *psock, FAR struct file *infile, FAR off_t *offset, size_t count); #endif -#ifdef CONFIG_NET_USRSOCK - CODE int (*si_ioctl)(FAR struct socket *psock, int cmd, - FAR void *arg, size_t arglen); -#endif }; /* Each socket refers to a connection structure of type FAR void *. Each diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index 856fe0588d..fe61124e7c 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -624,9 +624,7 @@ int netdev_carrier_off(FAR struct net_driver_s *dev); * ****************************************************************************/ -#ifdef CONFIG_NET_USRSOCK ssize_t net_ioctl_arglen(int cmd); -#endif /**************************************************************************** * Name: net_chksum diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index b47cb4d373..7e5712d691 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -76,6 +76,8 @@ static ssize_t inet_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg, int flags); static ssize_t inet_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, int flags); +static int inet_ioctl(FAR struct socket *psock, int cmd, + FAR void *arg, size_t arglen); #ifdef CONFIG_NET_SENDFILE static ssize_t inet_sendfile(FAR struct socket *psock, FAR struct file *infile, FAR off_t *offset, @@ -100,7 +102,8 @@ static const struct sock_intf_s g_inet_sockif = inet_poll, /* si_poll */ inet_sendmsg, /* si_sendmsg */ inet_recvmsg, /* si_recvmsg */ - inet_close /* si_close */ + inet_close, /* si_close */ + inet_ioctl /* si_ioctl */ #ifdef CONFIG_NET_SENDFILE , inet_sendfile /* si_sendfile */ @@ -1284,6 +1287,47 @@ static ssize_t inet_sendmsg(FAR struct socket *psock, return ret; } +/**************************************************************************** + * Name: inet_ioctl + * + * Description: + * This function performs network device specific operations. + * + * Parameters: + * psock A reference to the socket structure of the socket + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +static int inet_ioctl(FAR struct socket *psock, int cmd, + FAR void *arg, size_t arglen) +{ + /* Verify that the sockfd corresponds to valid, allocated socket */ + + if (psock == NULL || psock->s_conn == NULL) + { + return -EBADF; + } + +#if defined(CONFIG_NET_TCP) && !defined(CONFIG_NET_TCP_NO_STACK) + if (psock->s_type == SOCK_STREAM) + { + return tcp_ioctl(psock->s_conn, cmd, arg, arglen); + } +#endif + +#if defined(CONFIG_NET_UDP) && defined(NET_UDP_HAVE_STACK) + if (psock->s_type == SOCK_DGRAM) + { + return udp_ioctl(psock->s_conn, cmd, arg, arglen); + } +#endif + + return -EINVAL; +} + /**************************************************************************** * Name: inet_sendfile * diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c index 41ce698e88..48ee14b069 100644 --- a/net/local/local_sockif.c +++ b/net/local/local_sockif.c @@ -34,6 +34,7 @@ #include +#include #include #include @@ -67,6 +68,8 @@ static int local_accept(FAR struct socket *psock, static int local_poll(FAR struct socket *psock, FAR struct pollfd *fds, bool setup); static int local_close(FAR struct socket *psock); +static int local_ioctl(FAR struct socket *psock, int cmd, + FAR void *arg, size_t arglen); /**************************************************************************** * Public Data @@ -86,7 +89,8 @@ const struct sock_intf_s g_local_sockif = local_poll, /* si_poll */ local_sendmsg, /* si_sendmsg */ local_recvmsg, /* si_recvmsg */ - local_close /* si_close */ + local_close, /* si_close */ + local_ioctl /* si_ioctl */ }; /**************************************************************************** @@ -682,6 +686,48 @@ static int local_close(FAR struct socket *psock) } } +/**************************************************************************** + * Name: local_ioctl + * + * Description: + * This function performs local device specific operations. + * + * Parameters: + * psock A reference to the socket structure of the socket + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +static int local_ioctl(FAR struct socket *psock, int cmd, + FAR void *arg, size_t arglen) +{ + FAR struct local_conn_s *conn; + int ret = OK; + + conn = (FAR struct local_conn_s *)psock->s_conn; + + switch (cmd) + { + case FIONREAD: + if (conn->lc_infile.f_inode != NULL) + { + ret = file_ioctl(&conn->lc_infile, cmd, arg); + } + else + { + ret = -ENOTCONN; + } + break; + default: + ret = -ENOTTY; + break; + } + + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index d613cf62c0..1189b55e5a 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -1454,7 +1454,7 @@ static int netdev_rt_ioctl(FAR struct socket *psock, int cmd, #endif /**************************************************************************** - * Name: netdev_usrsock_ioctl + * Name: netdev_ioctl * * Description: * Perform user private ioctl operations. @@ -1470,9 +1470,8 @@ static int netdev_rt_ioctl(FAR struct socket *psock, int cmd, * ****************************************************************************/ -#ifdef CONFIG_NET_USRSOCK -static int netdev_usrsock_ioctl(FAR struct socket *psock, int cmd, - unsigned long arg) +static int netdev_ioctl(FAR struct socket *psock, int cmd, + unsigned long arg) { if (psock->s_sockif && psock->s_sockif->si_ioctl) { @@ -1491,7 +1490,6 @@ static int netdev_usrsock_ioctl(FAR struct socket *psock, int cmd, return -ENOTTY; } } -#endif /**************************************************************************** * Public Functions @@ -1512,11 +1510,13 @@ static int netdev_usrsock_ioctl(FAR struct socket *psock, int cmd, * ****************************************************************************/ -#ifdef CONFIG_NET_USRSOCK ssize_t net_ioctl_arglen(int cmd) { switch (cmd) { + case FIONREAD: + return sizeof(int); + case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFDSTADDR: @@ -1607,7 +1607,6 @@ ssize_t net_ioctl_arglen(int cmd) return -ENOTTY; } } -#endif /**************************************************************************** * Name: psock_ioctl and psock_vioctl @@ -1654,12 +1653,10 @@ int psock_vioctl(FAR struct socket *psock, int cmd, va_list ap) arg = va_arg(ap, unsigned long); -#ifdef CONFIG_NET_USRSOCK /* Check for a USRSOCK ioctl command */ - ret = netdev_usrsock_ioctl(psock, cmd, arg); + ret = netdev_ioctl(psock, cmd, arg); if (ret == -ENOTTY) -#endif { /* Check for a standard network IOCTL command. */ diff --git a/net/tcp/Make.defs b/net/tcp/Make.defs index 9705e76cb6..702c35e682 100644 --- a/net/tcp/Make.defs +++ b/net/tcp/Make.defs @@ -53,7 +53,7 @@ endif NET_CSRCS += tcp_conn.c tcp_seqno.c tcp_devpoll.c tcp_finddev.c tcp_timer.c NET_CSRCS += tcp_send.c tcp_input.c tcp_appsend.c tcp_listen.c tcp_close.c NET_CSRCS += tcp_monitor.c tcp_callback.c tcp_backlog.c tcp_ipselect.c -NET_CSRCS += tcp_recvwindow.c tcp_netpoll.c +NET_CSRCS += tcp_recvwindow.c tcp_netpoll.c tcp_ioctl.c # TCP write buffering diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index 6f592c0c20..e1cfe80886 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -1856,6 +1856,23 @@ int tcp_txdrain(FAR struct socket *psock, unsigned int timeout); # define tcp_txdrain(conn, timeout) (0) #endif +/**************************************************************************** + * Name: tcp_ioctl + * + * Description: + * This function performs tcp specific ioctl() operations. + * + * Parameters: + * conn The TCP connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +int tcp_ioctl(FAR struct tcp_conn_s *conn, int cmd, + FAR void *arg, size_t arglen); + #ifdef __cplusplus } #endif diff --git a/net/tcp/tcp_ioctl.c b/net/tcp/tcp_ioctl.c new file mode 100644 index 0000000000..af5bb985e0 --- /dev/null +++ b/net/tcp/tcp_ioctl.c @@ -0,0 +1,85 @@ +/**************************************************************************** + * net/tcp/tcp_ioctl.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "tcp/tcp.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tcp_ioctl + * + * Description: + * This function performs tcp specific ioctl() operations. + * + * Parameters: + * conn The TCP connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +int tcp_ioctl(FAR struct tcp_conn_s *conn, + int cmd, FAR void *arg, size_t arglen) +{ + int ret = OK; + + net_lock(); + + switch (cmd) + { + case FIONREAD: + if (conn->readahead != NULL) + { + *(FAR int *)((uintptr_t)arg) = conn->readahead->io_pktlen; + } + else + { + *(FAR int *)((uintptr_t)arg) = 0; + } + break; + default: + ret = -ENOTTY; + break; + } + + net_unlock(); + + return ret; +} diff --git a/net/udp/Make.defs b/net/udp/Make.defs index c1681abc25..ed420578b8 100644 --- a/net/udp/Make.defs +++ b/net/udp/Make.defs @@ -48,6 +48,7 @@ endif NET_CSRCS += udp_conn.c udp_devpoll.c udp_send.c udp_input.c udp_finddev.c NET_CSRCS += udp_close.c udp_callback.c udp_ipselect.c udp_netpoll.c +NET_CSRCS += udp_ioctl.c # UDP write buffering diff --git a/net/udp/udp.h b/net/udp/udp.h index 04452fec7f..eb5e73dbe8 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -869,6 +869,23 @@ int udp_txdrain(FAR struct socket *psock, unsigned int timeout); # define udp_txdrain(conn, timeout) (0) #endif +/**************************************************************************** + * Name: udp_ioctl + * + * Description: + * This function performs udp specific ioctl() operations. + * + * Parameters: + * conn The TCP connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +int udp_ioctl(FAR struct udp_conn_s *conn, + int cmd, FAR void *arg, size_t arglen); + #undef EXTERN #ifdef __cplusplus } diff --git a/net/udp/udp_ioctl.c b/net/udp/udp_ioctl.c new file mode 100644 index 0000000000..bb458f38bb --- /dev/null +++ b/net/udp/udp_ioctl.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * net/udp/udp_ioctl.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "udp/udp.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: udp_ioctl + * + * Description: + * This function performs udp specific ioctl() operations. + * + * Parameters: + * conn The TCP connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +int udp_ioctl(FAR struct udp_conn_s *conn, + int cmd, FAR void *arg, size_t arglen) +{ + FAR struct iob_s *iob; + int ret = OK; + + net_lock(); + + switch (cmd) + { + case FIONREAD: + iob = iob_peek_queue(&conn->readahead); + if (iob) + { + *(FAR int *)((uintptr_t)arg) = iob->io_pktlen; + } + else + { + *(FAR int *)((uintptr_t)arg) = 0; + } + break; + default: + ret = -ENOTTY; + break; + } + + net_unlock(); + + return ret; +}