From 0330743a9d2106de9c769e93c77187591cda292e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 31 Oct 2018 15:59:05 -0600 Subject: [PATCH] net/inet: Add framework to support IPv4 and IPv6 protocol socket options (i.e., SOL_IP and SOL_IP6). This is build framework only (not actual socket options are yet handled). Handling of these socket options is a necessary step on the way to future ICMPv6 MLD support. --- include/netinet/in.h | 2 +- include/nuttx/net/igmp.h | 6 +- include/nuttx/net/mld.h | 15 +++++ net/igmp/igmp_group.c | 6 -- net/igmp/igmp_initialize.c | 8 --- net/inet/Make.defs | 5 +- net/inet/inet.h | 37 ++++++++++- net/inet/ipv4_setsockopt.c | 130 +++++++++++++++++++++++++++++++++++++ net/inet/ipv6_setsockopt.c | 111 +++++++++++++++++++++++++++++++ net/socket/setsockopt.c | 30 +++++---- 10 files changed, 316 insertions(+), 34 deletions(-) create mode 100644 net/inet/ipv4_setsockopt.c create mode 100644 net/inet/ipv6_setsockopt.c diff --git a/include/netinet/in.h b/include/netinet/in.h index 485f11a67c1..4136e5ac6cf 100644 --- a/include/netinet/in.h +++ b/include/netinet/in.h @@ -114,7 +114,7 @@ #define IP_MSFILTER (__SO_PROTOCOL + 10) /* Access advanced, full- * state filtering API */ #define IP_MULTICAST_ALL (__SO_PROTOCOL + 11) /* Modify the delivery policy - * of mutlicast messages bound + * of multicast messages bound * to INADDR_ANY */ /* SOL_IPV6 protocol-level socket options. */ diff --git a/include/nuttx/net/igmp.h b/include/nuttx/net/igmp.h index d0620dbc7b2..d47ca01fff2 100644 --- a/include/nuttx/net/igmp.h +++ b/include/nuttx/net/igmp.h @@ -64,10 +64,6 @@ * Pre-processor Definitions ****************************************************************************/ -#ifdef CONFIG_NET_IPv6 -# error "IGMP for IPv6 not supported" -#endif - /* IGMP packet types */ #define IGMP_MEMBERSHIP_QUERY 0x11 /* Membership Query */ @@ -111,6 +107,8 @@ #define IS_SCHEDMSG(f) (((f) & IGMP_SCHEDMSG) != 0) #define IS_WAITMSG(f) (((f) & IGMP_WAITMSG) != 0) +/* Time-to-Live must be one */ + #define IGMP_TTL 1 /**************************************************************************** diff --git a/include/nuttx/net/mld.h b/include/nuttx/net/mld.h index 2cf319f318d..068e56edc23 100644 --- a/include/nuttx/net/mld.h +++ b/include/nuttx/net/mld.h @@ -59,6 +59,21 @@ * Pre-processor Definitions ****************************************************************************/ +/* MLD is a sub-protocol of ICMPv6, that is, MLD message types are a subset + * of ICMPv6 messages, and MLD messages are identified in IPv6 packets by a + * preceding Next Header value of IP_PROTO_ICMP6 (58). All MLD messages + * MUST be sent with a link-local IPv6 Source Address, an IPv6 Hop Limit of + * 1, and an IPv6 Router Alert option (RFC2711) in a Hop-by-Hop Options + * header. (The Router Alert option is necessary to cause routers to + * examine MLD messages sent to IPv6 multicast addresses in which the + * routers themselves have no interest.) MLD Reports can be sent with the + * source address set to the unspecified address (RFC3513), if a valid + * link-local IPv6 source address has not been acquired yet for the sending + * interface. + */ + +#define MLD_TTL (1) + /* Maximum response code bit definitions. * * If MRC < 32768 diff --git a/net/igmp/igmp_group.c b/net/igmp/igmp_group.c index a468eb765b5..95e1ef2542c 100644 --- a/net/igmp/igmp_group.c +++ b/net/igmp/igmp_group.c @@ -69,12 +69,6 @@ * Pre-processor Definitions ****************************************************************************/ -/* Configuration ************************************************************/ - -#ifdef CONFIG_NET_IPv6 -# error "IGMP for IPv6 not supported" -#endif - /* Debug ********************************************************************/ #undef IGMP_GRPDEBUG /* Define to enable detailed IGMP group debug */ diff --git a/net/igmp/igmp_initialize.c b/net/igmp/igmp_initialize.c index 89ad5ccfef3..246771f6ca6 100644 --- a/net/igmp/igmp_initialize.c +++ b/net/igmp/igmp_initialize.c @@ -55,14 +55,6 @@ #ifdef CONFIG_NET_IGMP -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#ifdef CONFIG_NET_IPv6 -# error "IGMP for IPv6 not supported" -#endif - /**************************************************************************** * Public Data ****************************************************************************/ diff --git a/net/inet/Make.defs b/net/inet/Make.defs index b0adec909e9..8509acf025b 100644 --- a/net/inet/Make.defs +++ b/net/inet/Make.defs @@ -44,11 +44,12 @@ SOCK_CSRCS += inet_globals.c endif ifeq ($(CONFIG_NET_IPv4),y) -SOCK_CSRCS += ipv4_getsockname.c ipv4_getpeername.c inet_setipid.c +SOCK_CSRCS += ipv4_setsockopt.c ipv4_getsockname.c ipv4_getpeername.c +SOCK_CSRCS += inet_setipid.c endif ifeq ($(CONFIG_NET_IPv6),y) -SOCK_CSRCS += ipv6_getsockname.c ipv6_getpeername.c +SOCK_CSRCS += ipv6_setsockopt.c ipv6_getsockname.c ipv6_getpeername.c endif # Include inet build support diff --git a/net/inet/inet.h b/net/inet/inet.h index 655271119c4..d2987bb6cb9 100644 --- a/net/inet/inet.h +++ b/net/inet/inet.h @@ -142,11 +142,44 @@ void inet_setipid(uint16_t id); FAR const struct sock_intf_s * inet_sockif(sa_family_t family, int type, int protocol); +/**************************************************************************** + * Name: ipv4_setsockopt and ipv6_setsockopt + * + * Description: + * ipv4/6_setsockopt() sets the IPv4- or IPv6-protocol socket option + * specified by the 'option' argument to the value pointed to by the + * 'value' argument for the socket specified by the 'psock' argument. + * + * See for the a complete list of values of IPv4 and IPv6 + * protocol socket options. + * + * 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. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +int ipv4_setsockopt(FAR struct socket *psock, int option, + FAR const void *value, socklen_t value_len); +#endif +#ifdef CONFIG_NET_IPv6 +int ipv6_setsockopt(FAR struct socket *psock, int option, + FAR const void *value, socklen_t value_len); +#endif + /**************************************************************************** * Name: ipv4_getsockname and ipv6_sockname * * Description: - * The ipv4_getsockname() and ipv6_getsocknam() function retrieve the + * The ipv4_getsockname() and ipv6_getsockname() function retrieve the * locally-bound name of the specified INET socket. * * Input Parameters: @@ -175,7 +208,7 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr, * Name: ipv4_getpeername and ipv6_peername * * Description: - * The ipv4_getpeername() and ipv6_getsocknam() function retrieve the + * The ipv4_getpeername() and ipv6_peername() function retrieve the * remote-connected name of the specified INET socket. * * Parameters: diff --git a/net/inet/ipv4_setsockopt.c b/net/inet/ipv4_setsockopt.c new file mode 100644 index 00000000000..bb1ba152b85 --- /dev/null +++ b/net/inet/ipv4_setsockopt.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * net/inet/ipv4_setsockopt.c + * + * Copyright (C) 2018 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 "inet/inet.h" + +#ifdef CONFIG_NET_IPv4 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipv4_setsockopt + * + * Description: + * ipv4_setsockopt() sets the IPv4-protocol socket option specified by the + * 'option' argument to the value pointed to by the 'value' argument for + * the socket specified by the 'psock' argument. + * + * See for the a complete list of values of IPv4 protocol + * socket options. + * + * 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. + * + ****************************************************************************/ + +int ipv4_setsockopt(FAR struct socket *psock, int option, + FAR const void *value, socklen_t value_len) +{ +#ifdef CONFIG_NET_IGMP + /* With IPv4, the multicast-related socket options are simply an alternative + * way to access IGMP. That IGMP functionality can also be accessed via + * IOCTL commands (see netdev/netdev_ioctl.c) + * + * REVISIT: Clone the logic from netdev_ioctl.c here. + */ + + switch (option) + { + case IP_MULTICAST_IF: /* Set local device for a multicast + * socket */ + case IP_MULTICAST_TTL: /* Set/read the time-to-live value of + * outgoing multicast packets */ + case IP_MULTICAST_LOOP: /* Set/read boolean that determines + * whether sent multicast packets + * should be looped back to local + * sockets. */ + case IP_ADD_MEMBERSHIP: /* Join a multicast group */ + case IP_DROP_MEMBERSHIP: /* Leave a multicast group */ + case IP_UNBLOCK_SOURCE: /* Unblock previously blocked multicast + * source */ + case IP_BLOCK_SOURCE: /* Stop receiving multicast data from + * source */ + case IP_ADD_SOURCE_MEMBERSHIP: /* Join a multicast group; allow receive + * only from source */ + case IP_DROP_SOURCE_MEMBERSHIP: /* Leave a source-specific group. Stop + * receiving data from a given multicast + * group that come from a given source */ + case IP_MSFILTER: /* Access advanced, full-state filtering + * API */ + case IP_MULTICAST_ALL: /* Modify the delivery policy of + * multicast messages bound to + * INADDR_ANY */ + default: + break; + } + +#warning Missing logic + return -ENOSYS; +#else + return -ENOPROTOOPT; +#endif +} + +#endif /* CONFIG_NET_IPv4 */ + diff --git a/net/inet/ipv6_setsockopt.c b/net/inet/ipv6_setsockopt.c new file mode 100644 index 00000000000..16a9a4dcb3a --- /dev/null +++ b/net/inet/ipv6_setsockopt.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * net/inet/ipv6_setsockopt.c + * + * Copyright (C) 2018 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 "inet/inet.h" + +#ifdef CONFIG_NET_IPv6 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipv6_setsockopt + * + * Description: + * ipv6_setsockopt() sets the IPv6-protocol socket option specified by the + * 'option' argument to the value pointed to by the 'value' argument for + * the socket specified by the 'psock' argument. + * + * See for the a complete list of values of IPv6 protocol + * socket options. + * + * 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. + * + ****************************************************************************/ + +int ipv6_setsockopt(FAR struct socket *psock, int option, + FAR const void *value, socklen_t value_len) +{ +#ifdef CONFIG_NET_MLD + /* Handle MLD-related socket options */ + + switch (option) + { + case IPV6_JOIN_GROUP: /* Join a multicast group */ + case IPV6_LEAVE_GROUP: /* Quit a multicast group */ + case IPV6_MULTICAST_HOPS: /* Multicast hop limit */ + case IPV6_MULTICAST_IF: /* Interface to use for outgoing multicast + * packets */ + case IPV6_MULTICAST_LOOP: /* Multicast packets are delivered back to + * the local application */ + case IPV6_UNICAST_HOPS: /* Unicast hop limit */ + case IPV6_V6ONLY: /* Restrict AF_INET6 socket to IPv6 + * communications only */ + default: + break; + } + +#warning Missing logic + return -ENOSYS; +#else + return -ENOPROTOOPT; +#endif +} + +#endif /* CONFIG_NET_IPv6 */ + diff --git a/net/socket/setsockopt.c b/net/socket/setsockopt.c index b2a9357cdba..3e4ee30326d 100644 --- a/net/socket/setsockopt.c +++ b/net/socket/setsockopt.c @@ -52,6 +52,7 @@ #include #include "socket/socket.h" +#include "inet/inet.h" #include "tcp/tcp.h" #include "udp/udp.h" #include "usrsock/usrsock.h" @@ -368,33 +369,40 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option, switch (level) { case SOL_SOCKET: /* Socket-level options (see include/sys/socket.h) */ - ret = psock_socketlevel_option(psock, option, value, value_len); - break; + ret = psock_socketlevel_option(psock, option, value, value_len); + break; case SOL_TCP: /* TCP protocol socket options (see include/netinet/tcp.h) */ #ifdef CONFIG_NET_TCPPROTO_OPTIONS - ret = tcp_setsockopt(psock, option, value, value_len); - break; + ret = tcp_setsockopt(psock, option, value, value_len); + break; #endif case SOL_UDP: /* UDP protocol socket options (see include/netinet/udp.h) */ #ifdef CONFIG_NET_UDPPROTO_OPTIONS - ret = udp_setsockopt(psock, option, value, value_len); - break; + ret = udp_setsockopt(psock, option, value, value_len); + break; #endif /* These levels are defined in sys/socket.h, but are not yet * implemented. */ - case SOL_IP: /* TCP protocol socket options (see include/netinet/ip.h) */ - case SOL_IPV6: /* TCP protocol socket options (see include/netinet/ip6.h) */ - ret = -ENOSYS; - break; +#ifdef CONFIG_NET_IPv4 + case SOL_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 SOL_IPV6: /* TCP protocol socket options (see include/netinet/in.h) */ + ret = ipv6_setsockopt(psock, option, value, value_len); + break; +#endif default: /* The provided level is invalid */ ret = -EINVAL; - break; + break; } return ret;