From 1b9cb7082816002b5a94d33b91ea0ae8c8b37fb5 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 12 Jul 2017 15:07:32 -0600 Subject: [PATCH] Sockets: Initial steps to adde a socket interface to the networking. Each address family will have an interface that describes how to perform socket operations on that address family. Currently only a couple of methods are defined in the table as a proof of concept. More to come. Currently there are only tables for the INET/INET6 family, the Unix LOCAL family, and the raw PACKET family. Hopefully there will be AF_IEEE802154 and AF_BLUETOOTH comming down the pike. --- include/nuttx/net/net.h | 22 +- net/local/Make.defs | 1 + net/local/local.h | 7 + net/local/local_sockif.c | 305 +++++++++++++++++++++++++++ net/pkt/Make.defs | 1 + net/pkt/pkt.h | 4 + net/pkt/pkt_sockif.c | 242 ++++++++++++++++++++++ net/socket/Make.defs | 12 +- net/socket/accept.c | 1 + net/socket/inet_sockif.c | 435 +++++++++++++++++++++++++++++++++++++++ net/socket/net_clone.c | 1 + net/socket/net_sockif.c | 111 ++++++++++ net/socket/send.c | 128 ++---------- net/socket/sendto.c | 118 ++--------- net/socket/socket.c | 420 +++---------------------------------- net/socket/socket.h | 21 ++ 16 files changed, 1222 insertions(+), 607 deletions(-) create mode 100644 net/local/local_sockif.c create mode 100644 net/pkt/pkt_sockif.c create mode 100644 net/socket/inet_sockif.c create mode 100644 net/socket/net_sockif.c diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index e12fb99d1ed..92d09a2623b 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -94,11 +94,27 @@ typedef uint16_t sockopt_t; typedef uint16_t socktimeo_t; +/* This callbacks are socket operations that may be performed on a socket of + * a given address family. + */ + +struct socket; /* Forward reference */ + +struct sock_intf_s +{ + CODE int (*si_setup)(FAR struct socket *psock, int protocol); + CODE ssize_t (*si_send)(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags); + CODE ssize_t (*si_sendto)(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen); +}; + /* This is the internal representation of a socket reference by a file * descriptor. */ -struct devif_callback_s; /* Forward reference */ +struct devif_callback_s; /* Forward reference */ struct socket { @@ -120,6 +136,10 @@ struct socket FAR void *s_conn; /* Connection: struct tcp_conn_s or udp_conn_s */ + /* Socket interface */ + + FAR const struct sock_intf_s *s_sockif; + #ifdef CONFIG_NET_TCP_WRITE_BUFFERS /* Callback instance for TCP send */ diff --git a/net/local/Make.defs b/net/local/Make.defs index 1d6f0cbd974..46b26daac6b 100644 --- a/net/local/Make.defs +++ b/net/local/Make.defs @@ -39,6 +39,7 @@ ifeq ($(CONFIG_NET_LOCAL),y) NET_CSRCS += local_conn.c local_release.c local_bind.c local_fifo.c NET_CSRCS += local_recvfrom.c local_sendpacket.c local_recvutils.c +NET_CSRCS += local_sockif.c ifeq ($(CONFIG_NET_LOCAL_STREAM),y) NET_CSRCS += local_connect.c local_listen.c local_accept.c local_send.c diff --git a/net/local/local.h b/net/local/local.h index db4fffc0faf..222d846cc0f 100644 --- a/net/local/local.h +++ b/net/local/local.h @@ -51,6 +51,8 @@ #include #include +#include + #ifdef CONFIG_NET_LOCAL /**************************************************************************** @@ -77,6 +79,7 @@ /**************************************************************************** * Public Type Definitions ****************************************************************************/ + /* Local, Unix domain socket types */ enum local_type_e @@ -204,6 +207,10 @@ extern "C" # define EXTERN extern #endif +/* The local socket interface */ + +EXTERN const struct sock_intf_s g_local_sockif; + #ifdef CONFIG_NET_LOCAL_STREAM /* A list of all SOCK_STREAM listener connections */ diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c new file mode 100644 index 00000000000..c7e9c1ba54c --- /dev/null +++ b/net/local/local_sockif.c @@ -0,0 +1,305 @@ +/**************************************************************************** + * net/local/local_sockif.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include "local/local.h" + +#ifdef CONFIG_NET_LOCAL + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static ssize_t local_setup(FAR struct socket *psock, int protocol); +static ssize_t local_send(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags); +static ssize_t local_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct sock_intf_s g_local_sockif = +{ + local_setup, /* si_setup */ + local_send, /* si_send */ + local_sendto, /* si_sendto */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: local_sockif_alloc + * + * Description: + * Allocate and attach a local, Unix domain connection structure. + * + ****************************************************************************/ + +static int local_sockif_alloc(FAR struct socket *psock) +{ + /* Allocate the local connection structure */ + + FAR struct local_conn_s *conn = local_alloc(); + if (conn == NULL) + { + /* Failed to reserve a connection structure */ + + return -ENOMEM; + } + + /* Set the reference count on the connection structure. This reference + * count will be incremented only if the socket is dup'ed + */ + + DEBUGASSERT(conn->lc_crefs == 0); + conn->lc_crefs = 1; + + /* Save the pre-allocated connection in the socket structure */ + + psock->s_conn = conn; + return OK; +} + +/**************************************************************************** + * Name: local_setup + * + * Description: + * Called for socket() to verify that the provided socket type and + * protocol are usable by this address family. Perform any family- + * specific socket fields. + * + * Parameters: + * psock A pointer to a user allocated socket structure to be initialized. + * protocol (see sys/socket.h) + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise, a negater errno value is + * returned. + * + ****************************************************************************/ + +static int local_setup(FAR struct socket *psock, int protocol) +{ + /* Allocate the appropriate connection structure. This reserves the + * the connection structure is is unallocated at this point. It will + * not actually be initialized until the socket is connected. + * + * Only SOCK_STREAM and SOCK_DGRAM and possible SOCK_RAW are supported. + */ + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + if (protocol != 0 && protocol != IPPROTO_TCP) + { + return -EPROTONOSUPPORT; + } + + /* Allocate and attach the local connection structure */ + + return local_sockif_alloc(psock); +#endif /* CONFIG_NET_TCP */ + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + if (protocol != 0 && protocol != IPPROTO_UDP) + { + return -EPROTONOSUPPORT; + } + + /* Allocate and attach the local connection structure */ + + return local_sockif_alloc(psock); +#endif /* CONFIG_NET_UDP */ + + default: + return -EPROTONOSUPPORT; + } +} + +/**************************************************************************** + * Name: local_send + * + * Description: + * Implements the send() operation for the case of the local, Unix socket. + * + * Parameters: + * psock An instance of the internal socket structure. + * buf Data to send + * len Length of data to send + * flags Send flags + * + * Returned Value: + * On success, returns the number of characters sent. On error, -1 is + * returned, and errno is set appropriately (see send() for the list of + * appropriate errors values. + * + ****************************************************************************/ + +static ssize_t local_send(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags) +{ + ssize_t ret; + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + { + /* Local TCP packet send */ + + ret = psock_local_send(psock, buf, len, flags); + } + break; +#endif /* CONFIG_NET_TCP */ + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + { + /* Local UDP packet send */ +#warning Missing logic + ret = -ENOSYS; + } + break; +#endif /* CONFIG_NET_UDP */ + + default: + { + /* EDESTADDRREQ. Signifies that the socket is not connection-mode + * and no peer address is set. + */ + + ret = -EDESTADDRREQ; + } + break; + } + + return ret; +} + +/**************************************************************************** + * Name: local_sendto + * + * Description: + * Implements the sendto() operation for the case of the local, Unix socket. + * + * Parameters: + * psock A pointer to a NuttX-specific, internal socket structure + * buf Data to send + * len Length of data to send + * flags Send flags + * to Address of recipient + * tolen The length of the address structure + * + * Returned Value: + * On success, returns the number of characters sent. On error, -1 is + * returned, and errno is set appropriately (see send_to() for the list of + * appropriate errors values. + * + ****************************************************************************/ + +ssize_t local_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen) +{ + ssize_t nsent; + + /* Verify that a valid address has been provided */ + + if (to->sa_family != AF_LOCAL || tolen < sizeof(sa_family_t)) + { + nerr("ERROR: Unrecognized address family: %d\n", + to->sa_family); + return -EAFNOSUPPORT; + } + +#ifdef CONFIG_NET_UDP + /* If this is a connected socket, then return EISCONN */ + + if (psock->s_type != SOCK_DGRAM) + { + nerr("ERROR: Connected socket\n"); + return -EISCONN; + } + + /* Now handle the local UDP sendto() operation */ + + nsent = psock_local_sendto(psock, buf, len, flags, to, tolen); +#else + nsent = -EISCONN; +#endif /* CONFIG_NET_LOCAL_DGRAM */ + + return nsent; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: + * + * Description: + * + * Parameters: + * + * Returned Value: + * + * Assumptions: + * + ****************************************************************************/ + +#endif /* CONFIG_NET_LOCAL */ diff --git a/net/pkt/Make.defs b/net/pkt/Make.defs index ced242a430c..f3e97740ba9 100644 --- a/net/pkt/Make.defs +++ b/net/pkt/Make.defs @@ -39,6 +39,7 @@ ifeq ($(CONFIG_NET_PKT),y) # Socket layer +SOCK_CSRCS += pkt_sockif.c SOCK_CSRCS += pkt_send.c # Transport layer diff --git a/net/pkt/pkt.h b/net/pkt/pkt.h index b7b6e0b0a92..041246b2fc1 100644 --- a/net/pkt/pkt.h +++ b/net/pkt/pkt.h @@ -91,6 +91,10 @@ extern "C" # define EXTERN extern #endif +/* The packet socket interface */ + +EXTERN const struct sock_intf_s g_pkt_sockif; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/net/pkt/pkt_sockif.c b/net/pkt/pkt_sockif.c new file mode 100644 index 00000000000..2f698de2b1a --- /dev/null +++ b/net/pkt/pkt_sockif.c @@ -0,0 +1,242 @@ +/**************************************************************************** + * net/socket/pkt_sockif.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "pkt/pkt.h" + +#ifdef CONFIG_NET_PKT + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static ssize_t pkt_setup(FAR struct socket *psock, int protocol); +static ssize_t pkt_send(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags); +static ssize_t pkt_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct sock_intf_s g_pkt_sockif = +{ + pkt_setup, /* si_setup */ + pkt_send, /* si_send */ + pkt_sendto, /* si_sendto */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pkt_sockif_alloc + * + * Description: + * Allocate and attach a raw packet connection structure. + * + ****************************************************************************/ + +static int pkt_sockif_alloc(FAR struct socket *psock) +{ + /* Allocate the packet socket connection structure and save in the new + * socket instance. + */ + + FAR struct pkt_conn_s *conn = pkt_alloc(); + if (conn == NULL) + { + /* Failed to reserve a connection structure */ + + return -ENOMEM; + } + + /* Set the reference count on the connection structure. This reference + * count will be incremented only if the socket is dup'ed + */ + + DEBUGASSERT(conn->crefs == 0); + conn->crefs = 1; + + /* Save the pre-allocated connection in the socket structure */ + + psock->s_conn = conn; + return OK; +} + +/**************************************************************************** + * Name: pkt_setup + * + * Description: + * Called for socket() to verify that the provided socket type and + * protocol are usable by this address family. Perform any family- + * specific socket fields. + * + * Parameters: + * psock A pointer to a user allocated socket structure to be + * initialized. + * protocol (see sys/socket.h) + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise, a negater errno value is + * returned. + * + ****************************************************************************/ + +static int pkt_setup(FAR struct socket *psock, int protocol) +{ + /* Allocate the appropriate connection structure. This reserves the + * the connection structure is is unallocated at this point. It will + * not actually be initialized until the socket is connected. + * + * Only SOCK_RAW is supported. + */ + + if (psock->s_type == SOCK_RAW) + { + return pkt_sockif_alloc(psock); + } + else + { + return -EPROTONOSUPPORT; + } +} + +/**************************************************************************** + * Name: pkt_send + * + * Description: + * Socket send() method for the raw packet socket. + * + * Parameters: + * psock An instance of the internal socket structure. + * buf Data to send + * len Length of data to send + * flags Send flags + * + * Returned Value: + * On success, returns the number of characters sent. On error, -1 is + * returned, and errno is set appropriately (see send() for the list of + * appropriate errors values. + * + ****************************************************************************/ + +static ssize_t pkt_send(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags) +{ + ssize_t ret; + + /* Only SOCK_RAW is supported */ + + if (psock->s_type == SOCK_RAW) + { + /* Raw packet send */ + + ret = psock_pkt_send(psock, buf, len); + } + else + { + /* EDESTADDRREQ. Signifies that the socket is not connection-mode and no peer + * address is set. + */ + + ret = -EDESTADDRREQ; + } + + return ret; +} + +/**************************************************************************** + * Name: pkt_sendto + * + * Description: + * Implements the sendto() operation for the case of the raw packet socket. + * + * Parameters: + * psock A pointer to a NuttX-specific, internal socket structure + * buf Data to send + * len Length of data to send + * flags Send flags + * to Address of recipient + * tolen The length of the address structure + * + * Returned Value: + * On success, returns the number of characters sent. On error, -1 is + * returned, and errno is set appropriately (see send_to() for the list of + * appropriate errors values. + * + ****************************************************************************/ + +static ssize_t pkt_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen) +{ + nerr("ERROR: sendto() not supported for raw packet sockets\n"); + return -EAFNOSUPPORT; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: + * + * Description: + * + * Parameters: + * + * Returned Value: + * + * Assumptions: + * + ****************************************************************************/ + +#endif /* CONFIG_NET_PKT */ diff --git a/net/socket/Make.defs b/net/socket/Make.defs index 6f433cd97a8..93a3d1b8c54 100644 --- a/net/socket/Make.defs +++ b/net/socket/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # net/socket/Make.defs # -# Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. +# Copyright (C) 2014-2015, 2017 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -39,6 +39,16 @@ SOCK_CSRCS += bind.c connect.c getsockname.c recv.c recvfrom.c send.c SOCK_CSRCS += sendto.c socket.c net_sockets.c net_close.c net_dupsd.c SOCK_CSRCS += net_dupsd2.c net_clone.c net_poll.c net_vfcntl.c +# Socket address families + +SOCK_CSRCS += net_sockif.c + +ifeq ($(CONFIG_NET_IPv4),y) +SOCK_CSRCS += inet_sockif.c +else ifeq ($(CONFIG_NET_IPv6),y) +SOCK_CSRCS += inet_sockif.c +endif + # TCP/IP support ifeq ($(CONFIG_NET_TCP),y) diff --git a/net/socket/accept.c b/net/socket/accept.c index a93e490b9e2..b295542c28f 100644 --- a/net/socket/accept.c +++ b/net/socket/accept.c @@ -224,6 +224,7 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr, newsock->s_domain = psock->s_domain; newsock->s_type = SOCK_STREAM; + newsock->s_sockif = psock->s_sockif; /* Perform the correct accept operation for this address domain */ diff --git a/net/socket/inet_sockif.c b/net/socket/inet_sockif.c new file mode 100644 index 00000000000..62f8de0eb56 --- /dev/null +++ b/net/socket/inet_sockif.c @@ -0,0 +1,435 @@ +/**************************************************************************** + * net/socket/inet_sockif.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "tcp/tcp.h" +#include "udp/udp.h" +#include "socket/socket.h" + +#if defined(CONFIG_NET_IPv4) || defined(CONFIG_NET_IPv6) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int inet_setup(FAR struct socket *psock, int protocol); +static ssize_t inet_send(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags); +static ssize_t inet_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct sock_intf_s g_inet_sockif = +{ + inet_setup, /* si_setup */ + inet_send, /* si_send */ + inet_sendto, /* si_sendto */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: inet_tcp_alloc + * + * Description: + * Allocate and attach a TCP connection structure. + * + ****************************************************************************/ + +#ifdef NET_TCP_HAVE_STACK +static int inet_tcp_alloc(FAR struct socket *psock) +{ + /* Allocate the TCP connection structure */ + + FAR struct tcp_conn_s *conn = tcp_alloc(psock->s_domain); + if (conn == NULL) + { + /* Failed to reserve a connection structure */ + + nerr("ERROR: Failed to reserve TCP connection structure\n"); + return -ENOMEM; + } + + /* Set the reference count on the connection structure. This reference + * count will be incremented only if the socket is dup'ed + */ + + DEBUGASSERT(conn->crefs == 0); + conn->crefs = 1; + + /* Save the pre-allocated connection in the socket structure */ + + psock->s_conn = conn; + return OK; +} +#endif /* NET_TCP_HAVE_STACK */ + +/**************************************************************************** + * Name: inet_udp_alloc + * + * Description: + * Allocate and attach a UDP connection structure. + * + ****************************************************************************/ + +#ifdef NET_UDP_HAVE_STACK +static int inet_udp_alloc(FAR struct socket *psock) +{ + /* Allocate the UDP connection structure */ + + FAR struct udp_conn_s *conn = udp_alloc(psock->s_domain); + if (conn == NULL) + { + /* Failed to reserve a connection structure */ + + nerr("ERROR: Failed to reserve UDP connection structure\n"); + return -ENOMEM; + } + + /* Set the reference count on the connection structure. This reference + * count will be incremented only if the socket is dup'ed + */ + + DEBUGASSERT(conn->crefs == 0); + conn->crefs = 1; + + /* Save the pre-allocated connection in the socket structure */ + + psock->s_conn = conn; + return OK; +} +#endif /* NET_UDP_HAVE_STACK */ + +/**************************************************************************** + * Name: inet_setup + * + * Description: + * Called for socket() to verify that the provided socket type and + * protocol are usable by this address family. Perform any family- + * specific socket fields. + * + * NOTE: This is common logic for both the AF_INET and AF_INET6 address + * families. + * + * Parameters: + * psock A pointer to a user allocated socket structure to be initialized. + * protocol (see sys/socket.h) + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise, a negater errno value is + * returned. + * + ****************************************************************************/ + +static int inet_setup(FAR struct socket *psock, int protocol) +{ + /* Allocate the appropriate connection structure. This reserves the + * the connection structure is is unallocated at this point. It will + * not actually be initialized until the socket is connected. + * + * Only SOCK_STREAM and SOCK_DGRAM and possible SOCK_RAW are supported. + */ + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + if (protocol != 0 && protocol != IPPROTO_TCP) + { + nerr("ERROR: Unsupported stream protocol: %d\n", protocol); + return -EPROTONOSUPPORT; + } + +#ifdef NET_TCP_HAVE_STACK + /* Allocate and attach the TCP connection structure */ + + return inet_tcp_alloc(psock); +#else + return = -ENETDOWN; +#endif +#endif /* CONFIG_NET_TCP */ + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + if (protocol != 0 && protocol != IPPROTO_UDP) + { + nerr("ERROR: Unsupported datagram protocol: %d\n", protocol); + return -EPROTONOSUPPORT; + } + +#ifdef NET_UDP_HAVE_STACK + /* Allocate and attach the UDP connection structure */ + + return inet_udp_alloc(psock); +#else + return -ENETDOWN; +#endif +#endif /* CONFIG_NET_UDP */ + + default: + nerr("ERROR: Unsupported type: %d\n", psock->s_type); + return -EPROTONOSUPPORT; + } +} + +/**************************************************************************** + * Name: inet_send + * + * Description: + * The inet_send() call may be used only when the socket is in a connected + * state (so that the intended recipient is known). + * + * Parameters: + * psock An instance of the internal socket structure. + * buf Data to send + * len Length of data to send + * flags Send flags + * + * Returned Value: + * On success, returns the number of characters sent. On error, -1 is + * returned, and errno is set appropriately (see send() for the list of + * appropriate errors values. + * + ****************************************************************************/ + +static ssize_t inet_send(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags) +{ + ssize_t ret; + + switch (psock->s_type) + { +#ifdef CONFIG_NET_TCP + case SOCK_STREAM: + { +#ifdef CONFIG_NET_6LOWPAN + /* Try 6LoWPAN TCP packet send */ + + ret = psock_6lowpan_tcp_send(psock, buf, len); + +#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_TCP_HAVE_STACK) + if (ret < 0) + { + /* TCP/IP packet send */ + + ret = psock_tcp_send(psock, buf, len); + } +#endif /* CONFIG_NETDEV_MULTINIC && NET_TCP_HAVE_STACK */ +#elif defined(NET_TCP_HAVE_STACK) + ret = psock_tcp_send(psock, buf, len); +#else + ret = -ENOSYS; +#endif /* CONFIG_NET_6LOWPAN */ + } + break; +#endif /* CONFIG_NET_TCP */ + +#ifdef CONFIG_NET_UDP + case SOCK_DGRAM: + { +#if defined(CONFIG_NET_6LOWPAN) + /* Try 6LoWPAN UDP packet send */ + + ret = psock_6lowpan_udp_send(psock, buf, len); + +#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_UDP_HAVE_STACK) + if (ret < 0) + { + /* UDP/IP packet send */ + + ret = psock_udp_send(psock, buf, len); + } +#endif /* CONFIG_NETDEV_MULTINIC && NET_UDP_HAVE_STACK */ +#elif defined(NET_UDP_HAVE_STACK) + /* Only UDP/IP packet send */ + + ret = psock_udp_send(psock, buf, len); +#else + ret = -ENOSYS; +#endif /* CONFIG_NET_6LOWPAN */ + } + break; +#endif /* CONFIG_NET_UDP */ + + default: + { + /* EDESTADDRREQ. Signifies that the socket is not connection-mode + * and no peer address is set. + */ + + nerr("ERROR: Bad socket type: %d\n", psock->s_type); + ret = -EDESTADDRREQ; + } + break; + } + + return ret; +} + +/**************************************************************************** + * Name: inet_sendto + * + * Description: + * Implements the sendto() operation for the case of the AF_INET and + * AF_INET6 sockets. + * + * Parameters: + * psock A pointer to a NuttX-specific, internal socket structure + * buf Data to send + * len Length of data to send + * flags Send flags + * to Address of recipient + * tolen The length of the address structure + * + * Returned Value: + * On success, returns the number of characters sent. On error, -1 is + * returned, and errno is set appropriately (see send_to() for the list of + * appropriate errors values. + * + ****************************************************************************/ + +static ssize_t inet_sendto(FAR struct socket *psock, FAR const void *buf, + size_t len, int flags, FAR const struct sockaddr *to, + socklen_t tolen) +{ + socklen_t minlen; + ssize_t nsent; + + /* Verify that a valid address has been provided */ + + switch (to->sa_family) + { +#ifdef CONFIG_NET_IPv4 + case AF_INET: + minlen = sizeof(struct sockaddr_in); + break; +#endif + +#ifdef CONFIG_NET_IPv6 + case AF_INET6: + minlen = sizeof(struct sockaddr_in6); + break; +#endif + +#ifdef CONFIG_NET_LOCAL_DGRAM + case AF_LOCAL: + minlen = sizeof(sa_family_t); + break; +#endif + + default: + nerr("ERROR: Unrecognized address family: %d\n", to->sa_family); + return -EAFNOSUPPORT; + } + + if (tolen < minlen) + { + nerr("ERROR: Invalid address length: %d < %d\n", tolen, minlen); + return -EBADF; + } + +#ifdef CONFIG_NET_UDP + /* If this is a connected socket, then return EISCONN */ + + if (psock->s_type != SOCK_DGRAM) + { + nerr("ERROR: Connected socket\n"); + return -EBADF; + } + + /* Now handle the INET sendto() operation */ + +#if defined(CONFIG_NET_6LOWPAN) + /* Try 6LoWPAN UDP packet sendto() */ + + nsent = psock_6lowpan_udp_sendto(psock, buf, len, flags, to, tolen); + +#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_UDP_HAVE_STACK) + if (nsent < 0) + { + /* UDP/IP packet sendto */ + + nsent = psock_udp_sendto(psock, buf, len, flags, to, tolen); + } +#endif /* CONFIG_NETDEV_MULTINIC && NET_UDP_HAVE_STACK */ +#elif defined(NET_UDP_HAVE_STACK) + nsent = psock_udp_sendto(psock, buf, len, flags, to, tolen); +#else + nsent = -ENOSYS; +#endif /* CONFIG_NET_6LOWPAN */ +#else + nsent = -EISCONN; +#endif /* CONFIG_NET_UDP */ + + return nsent; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: + * + * Description: + * + * Parameters: + * + * Returned Value: + * + * Assumptions: + * + ****************************************************************************/ + +#endif /* CONFIG_NET_IPv4 || CONFIG_NET_IPv6 */ diff --git a/net/socket/net_clone.c b/net/socket/net_clone.c index d720eb8731b..c134116d7f4 100644 --- a/net/socket/net_clone.c +++ b/net/socket/net_clone.c @@ -79,6 +79,7 @@ int net_clone(FAR struct socket *psock1, FAR struct socket *psock2) psock2->s_domain = psock1->s_domain; /* IP domain: PF_INET, PF_INET6, or PF_PACKET */ psock2->s_type = psock1->s_type; /* Protocol type: Only SOCK_STREAM or SOCK_DGRAM */ + psock2->s_sockif = psock1->s_sockif; /* Socket interface */ psock2->s_flags = psock1->s_flags; /* See _SF_* definitions */ #ifdef CONFIG_NET_SOCKOPTS psock2->s_options = psock1->s_options; /* Selected socket options */ diff --git a/net/socket/net_sockif.c b/net/socket/net_sockif.c new file mode 100644 index 00000000000..76e273ff97d --- /dev/null +++ b/net/socket/net_sockif.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * net/socket/net_sockif.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "local/local.h" +#include "pkt/pkt.h" +#include "socket/socket.h" + +#ifdef CONFIG_NET + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_sockif + * + * Description: + * Return the socket interface associated with this address family. + * + * Parameters: + * family - Address family + * + * Returned Value: + * On success, a non-NULL instance of struct sock_intf_s is returned. NULL + * is returned only if the address family is not supported. + * + ****************************************************************************/ + +FAR const struct sock_intf_s *net_sockif(sa_family_t family) +{ + FAR const struct sock_intf_s *sockif = NULL; + + /* Get the socket interface */ + + switch (family) + { +#if defined(CONFIG_NET_IPv4) || defined(CONFIG_NET_IPv6) +#ifdef CONFIG_NET_IPv4 + case PF_INET: +#endif +#ifdef CONFIG_NET_IPv6 + case PF_INET6: +#endif + sockif = &g_inet_sockif; + break; +#endif + +#ifdef CONFIG_NET_LOCAL + case PF_LOCAL: + sockif = &g_local_sockif; + break; +#endif + +#ifdef CONFIG_NET_PKT + case PF_PACKET: + sockif = &g_pkt_sockif; + break; +#endif + + default: + nerr("ERROR: Address family unsupported: %d\n", family); + } + + return sockif; +} + +#endif /* CONFIG_NET */ diff --git a/net/socket/send.c b/net/socket/send.c index c47158aca25..1b8a39d47c3 100644 --- a/net/socket/send.c +++ b/net/socket/send.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include @@ -126,132 +128,32 @@ ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len, { ssize_t ret; + DEBUGASSERT(psock != NULL && buf != NULL); + /* Treat as a cancellation point */ (void)enter_cancellation_point(); - switch (psock->s_type) - { -#if defined(CONFIG_NET_PKT) - case SOCK_RAW: - { - /* Raw packet send */ - - ret = psock_pkt_send(psock, buf, len); - } - break; -#endif - -#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) - case SOCK_STREAM: - { -#ifdef CONFIG_NET_LOCAL_STREAM -#ifdef CONFIG_NET_TCP - if (psock->s_domain == PF_LOCAL) -#endif - { - /* Local TCP packet send */ - - ret = psock_local_send(psock, buf, len, flags); - } -#endif /* CONFIG_NET_LOCAL_STREAM */ - -#ifdef CONFIG_NET_TCP -#ifdef CONFIG_NET_LOCAL_STREAM - else -#endif - { -#ifdef CONFIG_NET_6LOWPAN - /* Try 6LoWPAN TCP packet send */ - - ret = psock_6lowpan_tcp_send(psock, buf, len); - -#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_TCP_HAVE_STACK) - if (ret < 0) - { - /* TCP/IP packet send */ - - ret = psock_tcp_send(psock, buf, len); - } -#endif /* CONFIG_NETDEV_MULTINIC && NET_TCP_HAVE_STACK */ -#elif defined(NET_TCP_HAVE_STACK) - ret = psock_tcp_send(psock, buf, len); -#else - ret = -ENOSYS; -#endif /* CONFIG_NET_6LOWPAN */ - } -#endif /* CONFIG_NET_TCP */ - } - break; -#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL_STREAM */ - -#ifdef CONFIG_NET_UDP - case SOCK_DGRAM: - { -#ifdef CONFIG_NET_LOCAL_DGRAM -#ifdef CONFIG_NET_UDP - if (psock->s_domain == PF_LOCAL) -#endif - { - /* Local UDP packet send */ -#warning Missing logic - ret = -ENOSYS; - } -#endif /* CONFIG_NET_LOCAL_DGRAM */ - -#ifdef CONFIG_NET_UDP -#ifdef CONFIG_NET_LOCAL_DGRAM - else -#endif - { -#if defined(CONFIG_NET_6LOWPAN) - /* Try 6LoWPAN UDP packet send */ - - ret = psock_6lowpan_udp_send(psock, buf, len); - -#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_UDP_HAVE_STACK) - if (ret < 0) - { - /* UDP/IP packet send */ - - ret = psock_udp_send(psock, buf, len); - } -#endif /* CONFIG_NETDEV_MULTINIC && NET_UDP_HAVE_STACK */ -#elif defined(NET_UDP_HAVE_STACK) - /* Only UDP/IP packet send */ - - ret = psock_udp_send(psock, buf, len); -#else - ret = -ENOSYS; -#endif /* CONFIG_NET_6LOWPAN */ - } -#endif /* CONFIG_NET_UDP */ - } - break; -#endif /* CONFIG_NET_UDP */ + /* Special case user sockets */ #ifdef CONFIG_NET_USRSOCK - case SOCK_USRSOCK_TYPE: - { - ret = usrsock_sendto(psock, buf, len, NULL, 0); - } - break; + if (psock->s_type SOCK_USRSOCK_TYPE) + { + ret = usrsock_sendto(psock, buf, len, NULL, 0); + } + else #endif /*CONFIG_NET_USRSOCK*/ + { + /* Let the address family's send() method handle the operation */ - default: - { - /* EDESTADDRREQ. Signifies that the socket is not connection-mode - * and no peer address is set. - */ - - ret = -EDESTADDRREQ; - } - break; + DEBUGASSERT(psock->s_sockif != NULL && psock->s_sockif->si_send != NULL); + ret = psock->s_sockif->si_send(psock, buf, len, flags); } leave_cancellation_point(); if (ret < 0) { + nerr("ERROR: socket si_send() (or usrsock_sendto()) failed: %d\n", ret); set_errno(-ret); ret = ERROR; } diff --git a/net/socket/sendto.c b/net/socket/sendto.c index 7b7c15f6c0e..6a7dd9a51aa 100644 --- a/net/socket/sendto.c +++ b/net/socket/sendto.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -127,18 +128,16 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen) { - socklen_t minlen; -#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM) || \ - defined(CONFIG_NET_USRSOCK) ssize_t nsent; -#endif int errcode; + DEBUGASSERT(psock != NULL && buf != NULL); + /* If to is NULL or tolen is zero, then this function is same as send (for * connected socket types) */ - if (!to || !tolen) + if (to == NULL || tolen <= 0) { #if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) || \ defined(CONFIG_NET_USRSOCK) @@ -156,122 +155,35 @@ ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf, /* Perform the usrsock sendto operation */ nsent = usrsock_sendto(psock, buf, len, to, tolen); - if (nsent < 0) - { - errcode = -nsent; - goto errout; - } - - return nsent; } -#endif - - /* Verify that a valid address has been provided */ - - switch (to->sa_family) - { -#ifdef CONFIG_NET_IPv4 - case AF_INET: - minlen = sizeof(struct sockaddr_in); - break; -#endif - -#ifdef CONFIG_NET_IPv6 - case AF_INET6: - minlen = sizeof(struct sockaddr_in6); - break; -#endif - -#ifdef CONFIG_NET_LOCAL_DGRAM - case AF_LOCAL: - minlen = sizeof(sa_family_t); - break; -#endif - - default: - nerr("ERROR: Unrecognized address family: %d\n", to->sa_family); - errcode = EAFNOSUPPORT; - goto errout; - } - - if (tolen < minlen) - { - nerr("ERROR: Invalid address length: %d < %d\n", tolen, minlen); - errcode = EBADF; - goto errout; - } - - /* Verify that the psock corresponds to valid, allocated socket */ - - if (!psock || psock->s_crefs <= 0) - { - nerr("ERROR: Invalid socket\n"); - errcode = EBADF; - goto errout; - } - - /* If this is a connected socket, then return EISCONN */ - - if (psock->s_type != SOCK_DGRAM) - { - nerr("ERROR: Connected socket\n"); - errcode = EISCONN; - goto errout; - } - -#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM) - /* Now handle the sendto() operation according to the socket domain, - * currently either IP or Unix domains. - */ - -#ifdef CONFIG_NET_LOCAL_DGRAM -#ifdef CONFIG_NET_UDP - if (psock->s_domain == PF_LOCAL) -#endif - { - nsent = psock_local_sendto(psock, buf, len, flags, to, tolen); - } -#endif /* CONFIG_NET_LOCAL_DGRAM */ - -#ifdef CONFIG_NET_UDP -#ifdef CONFIG_NET_LOCAL_DGRAM else #endif { -#if defined(CONFIG_NET_6LOWPAN) - /* Try 6LoWPAN UDP packet sendto() */ + /* Verify that the psock corresponds to valid, allocated socket */ - nsent = psock_6lowpan_udp_sendto(psock, buf, len, flags, to, tolen); - -#if defined(CONFIG_NETDEV_MULTINIC) && defined(NET_UDP_HAVE_STACK) - if (nsent < 0) + if (!psock || psock->s_crefs <= 0) { - /* UDP/IP packet sendto */ - - nsent = psock_udp_sendto(psock, buf, len, flags, to, tolen); + nerr("ERROR: Invalid socket\n"); + errcode = EBADF; + goto errout; } -#endif /* CONFIG_NETDEV_MULTINIC && NET_UDP_HAVE_STACK */ -#elif defined(NET_UDP_HAVE_STACK) - nsent = psock_udp_sendto(psock, buf, len, flags, to, tolen); -#else - nsent = -ENOSYS; -#endif /* CONFIG_NET_6LOWPAN */ + + /* Let the address family's send() method handle the operation */ + + DEBUGASSERT(psock->s_sockif != NULL && psock->s_sockif->si_send != NULL); + nsent = psock->s_sockif->si_send(psock, buf, len, flags); } -#endif /* CONFIG_NET_UDP */ /* Check if the domain-specific sendto() logic failed */ if (nsent < 0) { - nerr("ERROR: UDP or Unix domain sendto() failed: %ld\n", (long)nsent); + nerr("ERROR: Family-specific send failed: %ld\n", (long)nsent); errcode = -nsent; goto errout; } return nsent; -#else - errcode = ENOSYS; -#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL_DGRAM */ errout: set_errno(errcode); diff --git a/net/socket/socket.c b/net/socket/socket.c index a0db45768a8..8c63c8095ff 100644 --- a/net/socket/socket.c +++ b/net/socket/socket.c @@ -38,168 +38,21 @@ ****************************************************************************/ #include -#ifdef CONFIG_NET #include #include #include #include -#include - -#include "socket/socket.h" -#include "tcp/tcp.h" -#include "udp/udp.h" -#include "pkt/pkt.h" -#include "local/local.h" #include "usrsock/usrsock.h" +#include "socket/socket.h" + +#ifdef CONFIG_NET /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: psock_tcp_alloc - * - * Description: - * Allocate and attach a TCP connection structure. - * - ****************************************************************************/ - -#ifdef NET_TCP_HAVE_STACK -static int psock_tcp_alloc(FAR struct socket *psock) -{ - /* Allocate the TCP connection structure */ - - FAR struct tcp_conn_s *conn = tcp_alloc(psock->s_domain); - if (!conn) - { - /* Failed to reserve a connection structure */ - - return -ENOMEM; - } - - /* Set the reference count on the connection structure. This reference - * count will be incremented only if the socket is dup'ed - */ - - DEBUGASSERT(conn->crefs == 0); - conn->crefs = 1; - - /* Save the pre-allocated connection in the socket structure */ - - psock->s_conn = conn; - return OK; -} -#endif /* NET_TCP_HAVE_STACK */ - -/**************************************************************************** - * Name: psock_udp_alloc - * - * Description: - * Allocate and attach a UDP connection structure. - * - ****************************************************************************/ - -#ifdef NET_UDP_HAVE_STACK -static int psock_udp_alloc(FAR struct socket *psock) -{ - /* Allocate the UDP connection structure */ - - FAR struct udp_conn_s *conn = udp_alloc(psock->s_domain); - if (!conn) - { - /* Failed to reserve a connection structure */ - - return -ENOMEM; - } - - /* Set the reference count on the connection structure. This reference - * count will be incremented only if the socket is dup'ed - */ - - DEBUGASSERT(conn->crefs == 0); - conn->crefs = 1; - - /* Save the pre-allocated connection in the socket structure */ - - psock->s_conn = conn; - return OK; -} -#endif /* NET_UDP_HAVE_STACK */ - -/**************************************************************************** - * Name: psock_pkt_alloc - * - * Description: - * Allocate and attach a raw packet connection structure. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_PKT -static int psock_pkt_alloc(FAR struct socket *psock) -{ - /* Allocate the packet socket connection structure and save in the new - * socket instance. - */ - - FAR struct pkt_conn_s *conn = pkt_alloc(); - if (!conn) - { - /* Failed to reserve a connection structure */ - - return -ENOMEM; - } - - /* Set the reference count on the connection structure. This reference - * count will be incremented only if the socket is dup'ed - */ - - DEBUGASSERT(conn->crefs == 0); - conn->crefs = 1; - - /* Save the pre-allocated connection in the socket structure */ - - psock->s_conn = conn; - return OK; -} -#endif /* CONFIG_NET_PKT */ - -/**************************************************************************** - * Name: psock_local_alloc - * - * Description: - * Allocate and attach a local, Unix domain connection structure. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_LOCAL -static int psock_local_alloc(FAR struct socket *psock) -{ - /* Allocate the local connection structure */ - - FAR struct local_conn_s *conn = local_alloc(); - if (!conn) - { - /* Failed to reserve a connection structure */ - - return -ENOMEM; - } - - /* Set the reference count on the connection structure. This reference - * count will be incremented only if the socket is dup'ed - */ - - DEBUGASSERT(conn->lc_crefs == 0); - conn->lc_crefs = 1; - - /* Save the pre-allocated connection in the socket structure */ - - psock->s_conn = conn; - return OK; -} -#endif /* CONFIG_NET_LOCAL */ - /**************************************************************************** * Name: usrsock_socket_setup * @@ -316,148 +169,21 @@ static int usrsock_socket_setup(int domain, int type, int protocol, int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) { -#ifdef CONFIG_NET_LOCAL - bool ipdomain = false; -#endif - bool dgramok = false; - int ret; + FAR const struct sock_intf_s *sockif = NULL; int errcode; - + int ret; + #ifdef CONFIG_NET_USRSOCK ret = usrsock_socket_setup(domain, type, protocol, psock); if (ret < 0) { + nerr("ERROR: usrsock_socket_setup() failed: %d\n", ret); errcode = -ret; goto errout; } #endif /* CONFIG_NET_USRSOCK */ - /* Only PF_INET, PF_INET6 or PF_PACKET domains supported */ - - switch (domain) - { -#ifdef CONFIG_NET_IPv4 - case PF_INET: -#ifdef CONFIG_NET_LOCAL - ipdomain = true; -#endif - dgramok = true; - break; -#endif - -#ifdef CONFIG_NET_IPv6 - case PF_INET6: -#ifdef CONFIG_NET_LOCAL - ipdomain = true; -#endif - dgramok = true; - break; -#endif - -#ifdef CONFIG_NET_LOCAL - case PF_LOCAL: - dgramok = true; - break; -#endif - -#ifdef CONFIG_NET_PKT - case PF_PACKET: - break; -#endif - - default: - errcode = EAFNOSUPPORT; - goto errout; - } - -#if defined(CONFIG_NET_LOCAL) && !defined(CONFIG_NET_LOCAL_STREAM) && !defined(CONFIG_NET_LOCAL_DGRAM) - UNUSED(ipdomain); -#endif - - /* Only SOCK_STREAM, SOCK_DGRAM and possible SOCK_RAW are supported */ - - switch (type) - { -#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) - case SOCK_STREAM: -#ifdef CONFIG_NET_TCP -#ifdef CONFIG_NET_LOCAL_STREAM - if (ipdomain) -#endif - { - if ((protocol != 0 && protocol != IPPROTO_TCP) || !dgramok) - { - errcode = EPROTONOSUPPORT; - goto errout; - } - } -#endif /* CONFIG_NET_TCP */ - -#ifdef CONFIG_NET_LOCAL_STREAM -#ifdef CONFIG_NET_TCP - else -#endif - { - if (protocol != 0 || !dgramok) - { - errcode = EPROTONOSUPPORT; - goto errout; - } - } -#endif /* CONFIG_NET_LOCAL_STREAM */ - - break; -#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL_STREAM */ - -#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM) - case SOCK_DGRAM: -#ifdef CONFIG_NET_UDP -#ifdef CONFIG_NET_LOCAL_DGRAM - if (ipdomain) -#endif - { - if ((protocol != 0 && protocol != IPPROTO_UDP) || !dgramok) - { - errcode = EPROTONOSUPPORT; - goto errout; - } - } -#endif /* CONFIG_NET_UDP */ - -#ifdef CONFIG_NET_LOCAL_DGRAM -#ifdef CONFIG_NET_UDP - else -#endif - { - if (protocol != 0 || !dgramok) - { - errcode = EPROTONOSUPPORT; - goto errout; - } - } -#endif /* CONFIG_NET_LOCAL_DGRAM */ - - break; -#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL_DGRAM */ - -#ifdef CONFIG_NET_PKT - case SOCK_RAW: - if (dgramok) - { - errcode = EPROTONOSUPPORT; - goto errout; - } - - break; -#endif - - default: - errcode = EPROTONOSUPPORT; - goto errout; - } - - /* Everything looks good. Initialize the socket structure */ - /* Save the protocol type */ + /* Initialize the socket structure */ psock->s_domain = domain; psock->s_type = type; @@ -466,115 +192,29 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) psock->s_sndcb = NULL; #endif - /* Allocate the appropriate connection structure. This reserves the - * the connection structure is is unallocated at this point. It will - * not actually be initialized until the socket is connected. + /* Get the socket interface */ + + sockif = net_sockif(domain); + if (sockif == NULL) + { + nerr("ERROR: socket address family unsupported: %d\n", domain); + errcode = EAFNOSUPPORT; + goto errout; + } + + /* The remaining of the socket initialization depends on the address + * family. */ - errcode = ENOMEM; /* Assume failure to allocate connection instance */ - switch (type) + DEBUGASSERT(sockif->si_setup != NULL); + psock->s_sockif = sockif; + + ret = sockif->si_setup(psock, protocol); + if (ret < 0) { -#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) - case SOCK_STREAM: - { -#ifdef CONFIG_NET_TCP -#ifdef CONFIG_NET_LOCAL_STREAM - if (ipdomain) -#endif - { -#ifdef NET_TCP_HAVE_STACK - /* Allocate and attach the TCP connection structure */ - - ret = psock_tcp_alloc(psock); -#else - ret = -ENETDOWN; -#endif - } -#endif /* CONFIG_NET_TCP */ - -#ifdef CONFIG_NET_LOCAL_STREAM -#ifdef CONFIG_NET_TCP - else -#endif - { - /* Allocate and attach the local connection structure */ - - ret = psock_local_alloc(psock); - } -#endif /* CONFIG_NET_LOCAL_STREAM */ - - /* Check for failures to allocate the connection structure. */ - - if (ret < 0) - { - /* Failed to reserve a connection structure */ - - errcode = -ret; - goto errout; - } - } - break; -#endif - -#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL_DGRAM) - case SOCK_DGRAM: - { -#ifdef CONFIG_NET_UDP -#ifdef CONFIG_NET_LOCAL_DGRAM - if (ipdomain) -#endif - { -#ifdef NET_UDP_HAVE_STACK - /* Allocate and attach the UDP connection structure */ - - ret = psock_udp_alloc(psock); -#else - ret = -ENETDOWN; -#endif - } -#endif /* CONFIG_NET_UDP */ - -#ifdef CONFIG_NET_LOCAL_DGRAM -#ifdef CONFIG_NET_UDP - else -#endif - { - /* Allocate and attach the local connection structure */ - - ret = psock_local_alloc(psock); - } -#endif /* CONFIG_NET_LOCAL_DGRAM */ - - /* Check for failures to allocate the connection structure. */ - - if (ret < 0) - { - /* Failed to reserve a connection structure */ - - errcode = -ret; - goto errout; - } - } - break; -#endif - -#ifdef CONFIG_NET_PKT - case SOCK_RAW: - { - ret = psock_pkt_alloc(psock); - if (ret < 0) - { - /* Failed to reserve a connection structure */ - - errcode = -ret; - goto errout; - } - } - break; -#endif - - default: - break; + nerr("ERROR: socket si_setup() failed: %d\n", ret); + errcode = -ret; + goto errout; } return OK; @@ -632,6 +272,7 @@ int socket(int domain, int type, int protocol) sockfd = sockfd_allocate(0); if (sockfd < 0) { + nerr("ERROR: Failed to allodate a socket descriptor\n"); set_errno(ENFILE); return ERROR; } @@ -650,8 +291,9 @@ int socket(int domain, int type, int protocol) ret = psock_socket(domain, type, protocol, psock); if (ret < 0) { - /* Error already set by psock_socket() */ + /* errno already set by psock_socket() */ + nerr("ERROR: psock_socket() failed: %d\n", ret); goto errout; } diff --git a/net/socket/socket.h b/net/socket/socket.h index d4b05258090..36788d465ab 100644 --- a/net/socket/socket.h +++ b/net/socket/socket.h @@ -149,6 +149,10 @@ extern "C" #define EXTERN extern #endif +#if defined(CONFIG_NET_IPv4) || defined(CONFIG_NET_IPv6) +EXTERN const struct sock_intf_s g_inet_sockif; +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -223,6 +227,23 @@ void sockfd_release(int sockfd); FAR struct socket *sockfd_socket(int sockfd); +/**************************************************************************** + * Name: net_sockif + * + * Description: + * Return the socket interface associated with this address family. + * + * Parameters: + * family - Address family + * + * Returned Value: + * On success, a non-NULL instance of struct sock_intf_s is returned. NULL + * is returned only if the address family is not supported. + * + ****************************************************************************/ + +FAR const struct sock_intf_s *net_sockif(sa_family_t family); + /**************************************************************************** * Name: net_startmonitor *