Author: bz
Date: Tue Oct 30 20:08:48 2018
New Revision: 339929
URL: https://svnweb.freebsd.org/changeset/base/339929

Log:
  Initial implementation of draft-ietf-6man-ipv6only-flag.
  
  This change defines the RA "6" (IPv6-Only) flag which routers
  may advertise, kernel logic to check if all routers on a link
  have the flag set and accordingly update a per-interface flag.
  
  If all routers agree that it is an IPv6-only link, ether_output_frame(),
  based on the interface flag, will filter out all ETHERTYPE_IP/ARP
  frames, drop them, and return EAFNOSUPPORT to upper layers.
  
  The change also updates ndp to show the "6" flag, ifconfig to
  display the IPV6_ONLY nd6 flag if set, and rtadvd to allow
  announcing the flag.
  
  Further changes to tcpdump (contrib code) are availble and will
  be upstreamed.
  
  Tested the code (slightly earlier version) with 2 FreeBSD
  IPv6 routers, a FreeBSD laptop on ethernet as well as wifi,
  and with Win10 and OSX clients (which did not fall over with
  the "6" flag set but not understood).
  
  We may also want to (a) implement and RX filter, and (b) over
  time enahnce user space to, say, stop dhclient from running
  when the interface flag is set.  Also we might want to start
  IPv6 before IPv4 in the future.
  
  All the code is hidden under the EXPERIMENTAL option and not
  compiled by default as the draft is a work-in-progress and
  we cannot rely on the fact that IANA will assign the bits
  as requested by the draft and hence they may change.
  
  Dear 6man, you have running code.
  
  Discussed with:       Bob Hinden, Brian E Carpenter

Modified:
  head/sbin/ifconfig/Makefile
  head/sbin/ifconfig/af_nd6.c
  head/sys/net/if_ethersubr.c
  head/sys/netinet/icmp6.h
  head/sys/netinet6/nd6.h
  head/sys/netinet6/nd6_rtr.c
  head/usr.sbin/ndp/Makefile
  head/usr.sbin/ndp/ndp.c
  head/usr.sbin/rtadvd/Makefile
  head/usr.sbin/rtadvd/config.c
  head/usr.sbin/rtadvd/rtadvd.c
  head/usr.sbin/rtadvd/rtadvd.h

Modified: head/sbin/ifconfig/Makefile
==============================================================================
--- head/sbin/ifconfig/Makefile Tue Oct 30 19:10:41 2018        (r339928)
+++ head/sbin/ifconfig/Makefile Tue Oct 30 20:08:48 2018        (r339929)
@@ -51,6 +51,9 @@ SRCS+=        ifpfsync.c              # pfsync(4) support
 SRCS+= ifbridge.c              # bridge support
 SRCS+= iflagg.c                # lagg support
 
+.if ${MK_EXPERIMENTAL} != "no"
+CFLAGS+= -DDRAFT_IETF_6MAN_IPV6ONLY_FLAG
+.endif
 .if ${MK_INET6_SUPPORT} != "no"
 CFLAGS+= -DINET6
 .endif

Modified: head/sbin/ifconfig/af_nd6.c
==============================================================================
--- head/sbin/ifconfig/af_nd6.c Tue Oct 30 19:10:41 2018        (r339928)
+++ head/sbin/ifconfig/af_nd6.c Tue Oct 30 20:08:48 2018        (r339929)
@@ -57,9 +57,17 @@ static const char rcsid[] =
 #include "ifconfig.h"
 
 #define        MAX_SYSCTL_TRY  5
+#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
 #define        ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
                "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
+               "\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD" \
+               "\012IPV6_ONLY" \
+               "\020DEFAULTIF"
+#else
+#define        ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
+               "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
                "\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD\020DEFAULTIF"
+#endif
 
 static int isnd6defif(int);
 void setnd6flags(const char *, int, int, const struct afswtch *);

Modified: head/sys/net/if_ethersubr.c
==============================================================================
--- head/sys/net/if_ethersubr.c Tue Oct 30 19:10:41 2018        (r339928)
+++ head/sys/net/if_ethersubr.c Tue Oct 30 20:08:48 2018        (r339929)
@@ -475,6 +475,26 @@ ether_output_frame(struct ifnet *ifp, struct mbuf *m)
                        return (0);
        }
 
+#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) {
+               struct ether_header *eh;
+
+               eh = mtod(m, struct ether_header *);
+               switch (ntohs(eh->ether_type)) {
+               case ETHERTYPE_IP:
+               case ETHERTYPE_ARP:
+                       m_freem(m);
+                       return (EAFNOSUPPORT);
+                       /* NOTREACHED */
+                       break;
+               };
+       }
+#endif
+#endif
+
        /*
         * Queue message on interface, update output statistics if
         * successful, and start output if interface not yet active.

Modified: head/sys/netinet/icmp6.h
==============================================================================
--- head/sys/netinet/icmp6.h    Tue Oct 30 19:10:41 2018        (r339928)
+++ head/sys/netinet/icmp6.h    Tue Oct 30 20:08:48 2018        (r339929)
@@ -244,6 +244,10 @@ struct nd_router_advert {  /* router advertisement */
 #define ND_RA_FLAG_RTPREF_LOW  0x18 /* 00011000 */
 #define ND_RA_FLAG_RTPREF_RSV  0x10 /* 00010000 */
 
+#ifdef EXPERIMENTAL
+#define        ND_RA_FLAG_IPV6_ONLY    0x02 /* draft-ietf-6man-ipv6only-flag */
+#endif
+
 #define nd_ra_router_lifetime  nd_ra_hdr.icmp6_data16[1]
 
 struct nd_neighbor_solicit {   /* neighbor solicitation */

Modified: head/sys/netinet6/nd6.h
==============================================================================
--- head/sys/netinet6/nd6.h     Tue Oct 30 19:10:41 2018        (r339928)
+++ head/sys/netinet6/nd6.h     Tue Oct 30 20:08:48 2018        (r339929)
@@ -90,6 +90,9 @@ struct nd_ifinfo {
 #define        ND6_IFF_NO_RADR         0x40
 #define ND6_IFF_NO_PREFER_IFACE        0x80 /* XXX: not related to ND. */
 #define ND6_IFF_NO_DAD         0x100
+#ifdef EXPERIMENTAL
+#define        ND6_IFF_IPV6_ONLY       0x200 /* draft-ietf-6man-ipv6only-flag 
*/
+#endif
 
 #ifdef _KERNEL
 #define ND_IFINFO(ifp) \

Modified: head/sys/netinet6/nd6_rtr.c
==============================================================================
--- head/sys/netinet6/nd6_rtr.c Tue Oct 30 19:10:41 2018        (r339928)
+++ head/sys/netinet6/nd6_rtr.c Tue Oct 30 20:08:48 2018        (r339929)
@@ -204,7 +204,38 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len)
        m_freem(m);
 }
 
+#ifdef EXPERIMENTAL
 /*
+ * 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"
+ * (IPv6-Only) flag.  If they do set, otherwise unset, the
+ * interface flag we later use to filter on.
+ */
+static void
+defrtr_ipv6_only_ifp(struct ifnet *ifp)
+{
+       struct nd_defrouter *dr;
+       bool ipv6_only;
+
+       ipv6_only = true;
+       ND6_RLOCK();
+       TAILQ_FOREACH(dr, &V_nd_defrouter, dr_entry)
+               if (dr->ifp == ifp &&
+                   (dr->raflags & ND_RA_FLAG_IPV6_ONLY) == 0)
+                       ipv6_only = false;
+       ND6_RUNLOCK();
+
+       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);
+}
+#endif
+
+/*
  * Receive Router Advertisement Message.
  *
  * Based on RFC 2461
@@ -319,6 +350,9 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
                }
        }
        dr = defrtrlist_update(&dr0);
+#ifdef EXPERIMENTAL
+       defrtr_ipv6_only_ifp(ifp);
+#endif
     }
 
        /*
@@ -691,6 +725,10 @@ defrouter_del(struct nd_defrouter *dr)
         */
        if (ND_IFINFO(dr->ifp)->flags & ND6_IFF_ACCEPT_RTADV)
                rt6_flush(&dr->rtaddr, dr->ifp);
+
+#ifdef EXPERIMENTAL
+       defrtr_ipv6_only_ifp(dr->ifp);
+#endif
 
        if (dr->installed) {
                deldr = dr;

Modified: head/usr.sbin/ndp/Makefile
==============================================================================
--- head/usr.sbin/ndp/Makefile  Tue Oct 30 19:10:41 2018        (r339928)
+++ head/usr.sbin/ndp/Makefile  Tue Oct 30 20:08:48 2018        (r339929)
@@ -13,6 +13,8 @@
 # A PARTICULAR PURPOSE.
 # $FreeBSD$
 
+.include <src.opts.mk>
+
 .PATH: ${SRCTOP}/contrib/tcpdump
 
 PROG=  ndp
@@ -21,6 +23,11 @@ SRCS=        ndp.c gmt2local.c
 
 CFLAGS+= -I. -I${.CURDIR} -I${SRCTOP}/contrib/tcpdump
 CFLAGS+= -D_U_=""
+
+.if ${MK_EXPERIMENTAL} != "no"
+CFLAGS+=       -DEXPERIMENTAL
+CFLAGS+=       -DDRAFT_IETF_6MAN_IPV6ONLY_FLAG
+.endif
 
 WARNS?=        3
 

Modified: head/usr.sbin/ndp/ndp.c
==============================================================================
--- head/usr.sbin/ndp/ndp.c     Tue Oct 30 19:10:41 2018        (r339928)
+++ head/usr.sbin/ndp/ndp.c     Tue Oct 30 20:08:48 2018        (r339929)
@@ -1096,6 +1096,9 @@ rtrlist()
                printf(", flags=%s%s",
                    p->flags & ND_RA_FLAG_MANAGED ? "M" : "",
                    p->flags & ND_RA_FLAG_OTHER   ? "O" : "");
+#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
+               printf("%s", p->flags & ND_RA_FLAG_IPV6_ONLY ? "6" : "");
+#endif
                rtpref = ((p->flags & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff;
                printf(", pref=%s", rtpref_str[rtpref]);
 

Modified: head/usr.sbin/rtadvd/Makefile
==============================================================================
--- head/usr.sbin/rtadvd/Makefile       Tue Oct 30 19:10:41 2018        
(r339928)
+++ head/usr.sbin/rtadvd/Makefile       Tue Oct 30 20:08:48 2018        
(r339929)
@@ -14,10 +14,17 @@
 #
 # $FreeBSD$
 
+.include <src.opts.mk>
+
 PROG=  rtadvd
 MAN=   rtadvd.conf.5 rtadvd.8
 SRCS=  rtadvd.c rrenum.c advcap.c if.c config.c timer.c timer_subr.c   \
        control.c control_server.c
+
+.if ${MK_EXPERIMENTAL} != "no"
+CFLAGS+=       -DEXPERIMENTAL
+CFLAGS+=       -DDRAFT_IETF_6MAN_IPV6ONLY_FLAG
+.endif
 
 LIBADD=        util
 

Modified: head/usr.sbin/rtadvd/config.c
==============================================================================
--- head/usr.sbin/rtadvd/config.c       Tue Oct 30 19:10:41 2018        
(r339928)
+++ head/usr.sbin/rtadvd/config.c       Tue Oct 30 20:08:48 2018        
(r339929)
@@ -437,6 +437,10 @@ getconfig(struct ifinfo *ifi)
                        }
                        val |= ND_RA_FLAG_RTPREF_LOW;
                }
+#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
+               if (strchr(flagstr, '6'))
+                       val |= ND_RA_FLAG_IPV6_ONLY;
+#endif
        } else
                MAYHAVE(val, "raflags", 0);
 
@@ -452,6 +456,9 @@ getconfig(struct ifinfo *ifi)
                    __func__, rai->rai_rtpref, ifi->ifi_ifname);
                goto getconfig_free_rai;
        }
+#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
+       rai->rai_ipv6onlyflg = val & ND_RA_FLAG_IPV6_ONLY;
+#endif
 
        MAYHAVE(val, "rltime", rai->rai_maxinterval * 3);
        if ((uint16_t)val && ((uint16_t)val < rai->rai_maxinterval ||
@@ -1406,6 +1413,10 @@ make_packet(struct rainfo *rai)
                rai->rai_managedflg ? ND_RA_FLAG_MANAGED : 0;
        ra->nd_ra_flags_reserved |=
                rai->rai_otherflg ? ND_RA_FLAG_OTHER : 0;
+#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
+       ra->nd_ra_flags_reserved |=
+               rai->rai_ipv6onlyflg ? ND_RA_FLAG_IPV6_ONLY : 0;
+#endif
        ra->nd_ra_router_lifetime = htons(rai->rai_lifetime);
        ra->nd_ra_reachable = htonl(rai->rai_reachabletime);
        ra->nd_ra_retransmit = htonl(rai->rai_retranstimer);

Modified: head/usr.sbin/rtadvd/rtadvd.c
==============================================================================
--- head/usr.sbin/rtadvd/rtadvd.c       Tue Oct 30 19:10:41 2018        
(r339928)
+++ head/usr.sbin/rtadvd/rtadvd.c       Tue Oct 30 20:08:48 2018        
(r339929)
@@ -1160,6 +1160,19 @@ ra_input(int len, struct nd_router_advert *nra,
                        sizeof(ntopbuf)), on_off[rai->rai_otherflg]);
                inconsistent++;
        }
+#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
+       /* 6 flag */
+       if ((nra->nd_ra_flags_reserved & ND_RA_FLAG_IPV6_ONLY) !=
+           rai->rai_ipv6onlyflg) {
+               syslog(LOG_NOTICE,
+                   "6 flag inconsistent on %s:"
+                   " %s from %s, %s from us",
+                   ifi->ifi_ifname, on_off[!rai->rai_ipv6onlyflg],
+                   inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf,
+                       sizeof(ntopbuf)), on_off[rai->rai_ipv6onlyflg]);
+               inconsistent++;
+       }
+#endif
        /* Reachable Time */
        reachabletime = ntohl(nra->nd_ra_reachable);
        if (reachabletime && rai->rai_reachabletime &&

Modified: head/usr.sbin/rtadvd/rtadvd.h
==============================================================================
--- head/usr.sbin/rtadvd/rtadvd.h       Tue Oct 30 19:10:41 2018        
(r339928)
+++ head/usr.sbin/rtadvd/rtadvd.h       Tue Oct 30 20:08:48 2018        
(r339929)
@@ -196,6 +196,9 @@ struct      rainfo {
        uint16_t        rai_mininterval;        /* MinRtrAdvInterval */
        int     rai_managedflg;         /* AdvManagedFlag */
        int     rai_otherflg;           /* AdvOtherConfigFlag */
+#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
+       int     rai_ipv6onlyflg;        /* AdvIPv6OnlyFlag */
+#endif
 
        int     rai_rtpref;             /* router preference */
        uint32_t        rai_linkmtu;            /* AdvLinkMTU */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to