Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Mar 2019 15:39:06 -0800 (PST)
From:      "Rodney W. Grimes" <freebsd@gndrsh.dnsmgr.net>
To:        "Bjoern A. Zeeb" <bz@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r344859 - in head: sbin/ifconfig sys/net sys/netinet6
Message-ID:  <201903062339.x26Nd6nx088089@ gndrsh.dnsmgr.net>
In-Reply-To: <201903062331.x26NVgmw071539@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
> Author: bz
> Date: Wed Mar  6 23:31:42 2019
> New Revision: 344859
> URL: https://svnweb.freebsd.org/changeset/base/344859
> 
> Log:
>   Update for IETF draft-ietf-6man-ipv6only-flag.
>   
>   All changes are hidden behind the EXPERIMENTAL option and are not compiled
>   in by default.

It is probably time to make EXPERIMENTAL finer grain,
there are likely more than one experiment to be avaliable
in the tree at the same time, and having them all use this
one knob is a bit of a pita.

Thanks,
Rod

>   Add ND6_IFF_IPV6_ONLY_MANUAL to be able to set the interface into no-IPv4-mode
>   manually without router advertisement options.  This will allow developers to
>   test software for the appropriate behaviour even on dual-stack networks or
>   IPv6-Only networks without the option being set in RA messages.
>   Update ifconfig to allow setting and displaying the flag.
>   
>   Update the checks for the filters to check for either the automatic or the manual
>   flag to be set.  Add REVARP to the list of filtered IPv4-related protocols and add
>   an input filter similar to the output filter.
>   
>   Add a check, when receiving the IPv6-Only RA flag to see if the receiving
>   interface has any IPv4 configured.  If it does, ignore the IPv6-Only flag.
>   
>   Add a per-VNET global sysctl, which is on by default, to not process the automatic
>   RA IPv6-Only flag.  This way an administrator (if this is compiled in) has control
>   over the behaviour in case the node still relies on IPv4.
> 
> Modified:
>   head/sbin/ifconfig/Makefile
>   head/sbin/ifconfig/af_inet6.c
>   head/sbin/ifconfig/af_nd6.c
>   head/sys/net/if_ethersubr.c
>   head/sys/netinet6/in6_proto.c
>   head/sys/netinet6/ip6_var.h
>   head/sys/netinet6/nd6.h
>   head/sys/netinet6/nd6_rtr.c
> 
> Modified: head/sbin/ifconfig/Makefile
> ==============================================================================
> --- head/sbin/ifconfig/Makefile	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sbin/ifconfig/Makefile	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -55,6 +55,7 @@ SRCS+=	iflagg.c		# lagg support
>  
>  .if ${MK_EXPERIMENTAL} != "no"
>  CFLAGS+= -DDRAFT_IETF_6MAN_IPV6ONLY_FLAG
> +CFLAGS+= -DEXPERIMENTAL
>  .endif
>  .if ${MK_INET6_SUPPORT} != "no"
>  CFLAGS+= -DINET6
> 
> Modified: head/sbin/ifconfig/af_inet6.c
> ==============================================================================
> --- head/sbin/ifconfig/af_inet6.c	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sbin/ifconfig/af_inet6.c	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -505,6 +505,10 @@ static struct cmd inet6_cmds[] = {
>  	DEF_CMD_ARG("pltime",        			setip6pltime),
>  	DEF_CMD_ARG("vltime",        			setip6vltime),
>  	DEF_CMD("eui64",	0,			setip6eui64),
> +#ifdef EXPERIMENTAL
> +	DEF_CMD("ipv6_only",	ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags),
> +	DEF_CMD("-ipv6_only",	-ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags),
> +#endif
>  };
>  
>  static struct afswtch af_inet6 = {
> 
> Modified: head/sbin/ifconfig/af_nd6.c
> ==============================================================================
> --- head/sbin/ifconfig/af_nd6.c	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sbin/ifconfig/af_nd6.c	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -61,7 +61,7 @@ static const char rcsid[] =
>  #define	ND6BITS	"\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
>  		"\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
>  		"\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD" \
> -		"\012IPV6_ONLY" \
> +		"\012IPV6_ONLY\013IPV6_ONLY_MANUAL" \
>  		"\020DEFAULTIF"
>  #else
>  #define	ND6BITS	"\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
> 
> Modified: head/sys/net/if_ethersubr.c
> ==============================================================================
> --- head/sys/net/if_ethersubr.c	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sys/net/if_ethersubr.c	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -476,14 +476,15 @@ ether_output_frame(struct ifnet *ifp, struct mbuf *m)
>  #ifdef EXPERIMENTAL
>  #if defined(INET6) && defined(INET)
>  	/* draft-ietf-6man-ipv6only-flag */
> -	/* Catch ETHERTYPE_IP, and ETHERTYPE_ARP if we are v6-only. */
> -	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IPV6_ONLY) != 0) {
> +	/* Catch ETHERTYPE_IP, and ETHERTYPE_[REV]ARP if we are v6-only. */
> +	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IPV6_ONLY_MASK) != 0) {
>  		struct ether_header *eh;
>  
>  		eh = mtod(m, struct ether_header *);
>  		switch (ntohs(eh->ether_type)) {
>  		case ETHERTYPE_IP:
>  		case ETHERTYPE_ARP:
> +		case ETHERTYPE_REVARP:
>  			m_freem(m);
>  			return (EAFNOSUPPORT);
>  			/* NOTREACHED */
> @@ -533,6 +534,25 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m
>  	eh = mtod(m, struct ether_header *);
>  	etype = ntohs(eh->ether_type);
>  	random_harvest_queue_ether(m, sizeof(*m));
> +
> +#ifdef EXPERIMENTAL
> +#if defined(INET6) && defined(INET)
> +	/* draft-ietf-6man-ipv6only-flag */
> +	/* Catch ETHERTYPE_IP, and ETHERTYPE_[REV]ARP if we are v6-only. */
> +	if ((ND_IFINFO(ifp)->flags & ND6_IFF_IPV6_ONLY_MASK) != 0) {
> +
> +		switch (etype) {
> +		case ETHERTYPE_IP:
> +		case ETHERTYPE_ARP:
> +		case ETHERTYPE_REVARP:
> +			m_freem(m);
> +			return;
> +			/* NOTREACHED */
> +			break;
> +		};
> +	}
> +#endif
> +#endif
>  
>  	CURVNET_SET_QUIET(ifp->if_vnet);
>  
> 
> Modified: head/sys/netinet6/in6_proto.c
> ==============================================================================
> --- head/sys/netinet6/in6_proto.c	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sys/netinet6/in6_proto.c	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -641,3 +641,10 @@ SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_ONLINKNSRFC
>  	nd6_onlink_ns_rfc4861, CTLFLAG_VNET | CTLFLAG_RW,
>  	&VNET_NAME(nd6_onlink_ns_rfc4861), 0,
>  	"Accept 'on-link' ICMPv6 NS messages in compliance with RFC 4861");
> +#ifdef EXPERIMENTAL
> +SYSCTL_INT(_net_inet6_icmp6, OID_AUTO,
> +	nd6_ignore_ipv6_only_ra, CTLFLAG_VNET | CTLFLAG_RW,
> +	&VNET_NAME(nd6_ignore_ipv6_only_ra), 0,
> +	"Ignore the 'IPv6-Only flag' in RA messages in compliance with "
> +	"draft-ietf-6man-ipv6only-flag");
> +#endif
> 
> Modified: head/sys/netinet6/ip6_var.h
> ==============================================================================
> --- head/sys/netinet6/ip6_var.h	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sys/netinet6/ip6_var.h	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -355,6 +355,11 @@ VNET_DECLARE(int, ip6stealth);
>  #define	V_ip6stealth			VNET(ip6stealth)
>  #endif
>  
> +#ifdef EXPERIMENTAL
> +VNET_DECLARE(int, nd6_ignore_ipv6_only_ra);
> +#define	V_nd6_ignore_ipv6_only_ra	VNET(nd6_ignore_ipv6_only_ra)
> +#endif
> +
>  extern struct	pr_usrreqs rip6_usrreqs;
>  struct sockopt;
>  
> 
> Modified: head/sys/netinet6/nd6.h
> ==============================================================================
> --- head/sys/netinet6/nd6.h	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sys/netinet6/nd6.h	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -91,7 +91,10 @@ struct nd_ifinfo {
>  #define ND6_IFF_NO_PREFER_IFACE	0x80 /* XXX: not related to ND. */
>  #define ND6_IFF_NO_DAD		0x100
>  #ifdef EXPERIMENTAL
> +/* XXX: not related to ND. */
>  #define	ND6_IFF_IPV6_ONLY	0x200 /* draft-ietf-6man-ipv6only-flag */
> +#define	ND6_IFF_IPV6_ONLY_MANUAL	0x400
> +#define	ND6_IFF_IPV6_ONLY_MASK	(ND6_IFF_IPV6_ONLY|ND6_IFF_IPV6_ONLY_MANUAL)
>  #endif
>  
>  #ifdef _KERNEL
> 
> Modified: head/sys/netinet6/nd6_rtr.c
> ==============================================================================
> --- head/sys/netinet6/nd6_rtr.c	Wed Mar  6 23:09:27 2019	(r344858)
> +++ head/sys/netinet6/nd6_rtr.c	Wed Mar  6 23:31:42 2019	(r344859)
> @@ -106,6 +106,10 @@ VNET_DEFINE(u_int32_t, ip6_temp_valid_lifetime) = DEF_
>  
>  VNET_DEFINE(int, ip6_temp_regen_advance) = TEMPADDR_REGEN_ADVANCE;
>  
> +#ifdef EXPERIMENTAL
> +VNET_DEFINE(int, nd6_ignore_ipv6_only_ra) = 1;
> +#endif
> +
>  /* RTPREF_MEDIUM has to be 0! */
>  #define RTPREF_HIGH	1
>  #define RTPREF_MEDIUM	0
> @@ -208,7 +212,7 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len)
>  /*
>   * An initial update routine for draft-ietf-6man-ipv6only-flag.
>   * We need to iterate over all default routers for the given
> - * interface to see whether they are all advertising the "6"
> + * interface to see whether they are all advertising the "S"
>   * (IPv6-Only) flag.  If they do set, otherwise unset, the
>   * interface flag we later use to filter on.
>   */
> @@ -216,8 +220,16 @@ static void
>  defrtr_ipv6_only_ifp(struct ifnet *ifp)
>  {
>  	struct nd_defrouter *dr;
> -	bool ipv6_only;
> +	bool ipv6_only, ipv6_only_old;
> +#ifdef INET
> +	struct epoch_tracker et;
> +	struct ifaddr *ifa;
> +	bool has_ipv4_addr;
> +#endif
>  
> +	if (V_nd6_ignore_ipv6_only_ra != 0)
> +		return;
> +
>  	ipv6_only = true;
>  	ND6_RLOCK();
>  	TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry)
> @@ -227,13 +239,53 @@ defrtr_ipv6_only_ifp(struct ifnet *ifp)
>  	ND6_RUNLOCK();
>  
>  	IF_AFDATA_WLOCK(ifp);
> +	ipv6_only_old = ND_IFINFO(ifp)->flags & ND6_IFF_IPV6_ONLY;
> +	IF_AFDATA_WUNLOCK(ifp);
> +
> +	/* If nothing changed, we have an early exit. */
> +	if (ipv6_only == ipv6_only_old)
> +		return;
> +
> +#ifdef INET
> +	/*
> +	 * Should we want to set the IPV6-ONLY flag, check if the
> +	 * interface has a non-0/0 and non-link-local IPv4 address
> +	 * configured on it.  If it has we will assume working
> +	 * IPv4 operations and will clear the interface flag.
> +	 */
> +	has_ipv4_addr = false;
> +	if (ipv6_only) {
> +		NET_EPOCH_ENTER(et);
> +		CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
> +			if (ifa->ifa_addr->sa_family != AF_INET)
> +				continue;
> +			if (in_canforward(
> +			    satosin(ifa->ifa_addr)->sin_addr)) {
> +				has_ipv4_addr = true;
> +				break;
> +			}
> +		}
> +		NET_EPOCH_EXIT(et);
> +	}
> +	if (ipv6_only && has_ipv4_addr) {
> +		log(LOG_NOTICE, "%s rcvd RA w/ IPv6-Only flag set but has IPv4 "
> +		    "configured, ignoring IPv6-Only flag.\n", ifp->if_xname);
> +		ipv6_only = false;
> +	}
> +#endif
> +
> +	IF_AFDATA_WLOCK(ifp);
>  	if (ipv6_only)
>  		ND_IFINFO(ifp)->flags |= ND6_IFF_IPV6_ONLY;
>  	else
>  		ND_IFINFO(ifp)->flags &= ~ND6_IFF_IPV6_ONLY;
>  	IF_AFDATA_WUNLOCK(ifp);
> -}
> +
> +#ifdef notyet
> +	/* Send notification of flag change. */
>  #endif
> +}
> +#endif	/* EXPERIMENTAL */
>  
>  /*
>   * Receive Router Advertisement Message.
> 
> 

-- 
Rod Grimes                                                 rgrimes@freebsd.org



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903062339.x26Nd6nx088089>