From owner-svn-src-all@FreeBSD.ORG Thu Mar 5 21:27:51 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id BFF5752D; Thu, 5 Mar 2015 21:27:51 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A092AB59; Thu, 5 Mar 2015 21:27:51 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t25LRpvn085445; Thu, 5 Mar 2015 21:27:51 GMT (envelope-from hrs@FreeBSD.org) Received: (from hrs@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t25LRnoO085432; Thu, 5 Mar 2015 21:27:49 GMT (envelope-from hrs@FreeBSD.org) Message-Id: <201503052127.t25LRnoO085432@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: hrs set sender to hrs@FreeBSD.org using -f From: Hiroki Sato Date: Thu, 5 Mar 2015 21:27:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r279676 - in head: sbin/ifconfig sys/netinet6 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Mar 2015 21:27:51 -0000 Author: hrs Date: Thu Mar 5 21:27:49 2015 New Revision: 279676 URL: https://svnweb.freebsd.org/changeset/base/279676 Log: - Implement loopback probing state in enhanced DAD algorithm. - Add no_dad and ignoreloop per-IF knob. no_dad disables DAD completely, and ignoreloop is to prevent infinite loop in loopback probing state when loopback is permanently expected. Modified: head/sbin/ifconfig/af_inet6.c head/sbin/ifconfig/af_nd6.c head/sbin/ifconfig/ifconfig.8 head/sys/netinet6/in6.c head/sys/netinet6/nd6.h head/sys/netinet6/nd6_nbr.c Modified: head/sbin/ifconfig/af_inet6.c ============================================================================== --- head/sbin/ifconfig/af_inet6.c Thu Mar 5 20:29:18 2015 (r279675) +++ head/sbin/ifconfig/af_inet6.c Thu Mar 5 21:27:49 2015 (r279676) @@ -485,6 +485,10 @@ static struct cmd inet6_cmds[] = { DEF_CMD("-auto_linklocal",-ND6_IFF_AUTO_LINKLOCAL,setnd6flags), DEF_CMD("no_prefer_iface",ND6_IFF_NO_PREFER_IFACE,setnd6flags), DEF_CMD("-no_prefer_iface",-ND6_IFF_NO_PREFER_IFACE,setnd6flags), + DEF_CMD("no_dad", ND6_IFF_NO_DAD, setnd6flags), + DEF_CMD("-no_dad", -ND6_IFF_NO_DAD, setnd6flags), + DEF_CMD("ignoreloop", ND6_IFF_IGNORELOOP, setnd6flags), + DEF_CMD("-ignoreloop", -ND6_IFF_IGNORELOOP, setnd6flags), DEF_CMD_ARG("pltime", setip6pltime), DEF_CMD_ARG("vltime", setip6vltime), DEF_CMD("eui64", 0, setip6eui64), Modified: head/sbin/ifconfig/af_nd6.c ============================================================================== --- head/sbin/ifconfig/af_nd6.c Thu Mar 5 20:29:18 2015 (r279675) +++ head/sbin/ifconfig/af_nd6.c Thu Mar 5 21:27:49 2015 (r279676) @@ -58,7 +58,8 @@ static const char rcsid[] = #define MAX_SYSCTL_TRY 5 #define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \ - "\007NO_RADR\010NO_PREFER_IFACE\020DEFAULTIF" + "\007NO_RADR\010NO_PREFER_IFACE\011IGNORELOOP\012NO_DAD" \ + "\020DEFAULTIF" static int isnd6defif(int); void setnd6flags(const char *, int, int, const struct afswtch *); Modified: head/sbin/ifconfig/ifconfig.8 ============================================================================== --- head/sbin/ifconfig/ifconfig.8 Thu Mar 5 20:29:18 2015 (r279675) +++ head/sbin/ifconfig/ifconfig.8 Thu Mar 5 21:27:49 2015 (r279676) @@ -28,7 +28,7 @@ .\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 .\" $FreeBSD$ .\" -.Dd December 16, 2014 +.Dd March 6, 2015 .Dt IFCONFIG 8 .Os .Sh NAME @@ -687,6 +687,20 @@ policy table, configurable with .It Cm -no_prefer_iface Clear a flag .Cm no_prefer_iface . +.It Cm no_dad +Set a flag to disable Duplicate Address Detection. +.It Cm -no_dad +Clear a flag +.Cm no_dad . +.It Cm ignoreloop +Set a flag to disable loopback detection in Enhanced Duplicate Address +Detection Algorithm. +When this flag is set, +Duplicate Address Detection will stop in a finite number of probings +even if a loopback configuration is detected. +.It Cm -ignoreloop +Clear a flag +.Cm ignoreloop . .El .Pp The following parameters are specific for IPv6 addresses. Modified: head/sys/netinet6/in6.c ============================================================================== --- head/sys/netinet6/in6.c Thu Mar 5 20:29:18 2015 (r279675) +++ head/sys/netinet6/in6.c Thu Mar 5 21:27:49 2015 (r279676) @@ -1910,7 +1910,8 @@ in6if_do_dad(struct ifnet *ifp) if ((ifp->if_flags & IFF_LOOPBACK) != 0) return (0); - if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) + if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) || + (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD)) return (0); /* Modified: head/sys/netinet6/nd6.h ============================================================================== --- head/sys/netinet6/nd6.h Thu Mar 5 20:29:18 2015 (r279675) +++ head/sys/netinet6/nd6.h Thu Mar 5 21:27:49 2015 (r279676) @@ -87,6 +87,8 @@ struct nd_ifinfo { #define ND6_IFF_AUTO_LINKLOCAL 0x20 #define ND6_IFF_NO_RADR 0x40 #define ND6_IFF_NO_PREFER_IFACE 0x80 /* XXX: not related to ND. */ +#define ND6_IFF_IGNORELOOP 0x100 +#define ND6_IFF_NO_DAD 0x200 #define ND6_CREATE LLE_CREATE #define ND6_EXCLUSIVE LLE_EXCLUSIVE Modified: head/sys/netinet6/nd6_nbr.c ============================================================================== --- head/sys/netinet6/nd6_nbr.c Thu Mar 5 20:29:18 2015 (r279675) +++ head/sys/netinet6/nd6_nbr.c Thu Mar 5 21:27:49 2015 (r279676) @@ -1182,6 +1182,7 @@ struct dadq { int dad_ns_icount; int dad_na_icount; int dad_ns_lcount; /* looped back NS */ + int dad_loopbackprobe; /* probing state for loopback detection */ struct callout dad_timer_ch; struct vnet *dad_vnet; u_int dad_refcnt; @@ -1223,7 +1224,6 @@ static struct dadq * nd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n) { struct dadq *dp; - char ip6buf[INET6_ADDRSTRLEN]; DADQ_RLOCK(); TAILQ_FOREACH(dp, &V_dadq, dad_list) { @@ -1238,10 +1238,6 @@ nd6_dad_find(struct ifaddr *ifa, struct n->nd_opt_nonce_len == (ND_OPT_NONCE_LEN + 2) / 8 && memcmp(&n->nd_opt_nonce[0], &dp->dad_nonce[0], ND_OPT_NONCE_LEN) == 0) { - log(LOG_ERR, "%s: a looped back NS message is " - "detected during DAD for %s.\n", - if_name(ifa->ifa_ifp), - ip6_sprintf(ip6buf, IFA_IN6(ifa))); dp->dad_ns_lcount++; continue; } @@ -1357,7 +1353,7 @@ nd6_dad_start(struct ifaddr *ifa, int de dp->dad_count = V_ip6_dad_count; dp->dad_ns_icount = dp->dad_na_icount = 0; dp->dad_ns_ocount = dp->dad_ns_tcount = 0; - dp->dad_ns_lcount = 0; + dp->dad_ns_lcount = dp->dad_loopbackprobe = 0; refcount_init(&dp->dad_refcnt, 1); nd6_dad_add(dp); if (delay == 0) { @@ -1432,8 +1428,10 @@ nd6_dad_timer(struct dadq *dp) goto err; } - /* timeouted with IFF_{RUNNING,UP} check */ - if (dp->dad_ns_tcount > V_dad_maxtry) { + /* Stop DAD if the interface is down even after dad_maxtry attempts. */ + if ((dp->dad_ns_tcount > V_dad_maxtry) && + (((ifp->if_flags & IFF_UP) == 0) || + ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))) { nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n", if_name(ifa->ifa_ifp))); goto err; @@ -1456,7 +1454,42 @@ nd6_dad_timer(struct dadq *dp) if (dp->dad_ns_icount > 0 || dp->dad_na_icount > 0) /* We've seen NS or NA, means DAD has failed. */ nd6_dad_duplicated(ifa, dp); - else { + else if (V_dad_enhanced != 0 && + dp->dad_ns_lcount > 0 && + dp->dad_ns_lcount > dp->dad_loopbackprobe) { + /* + * A looped back probe is detected, + * Sec. 4.1 in draft-ietf-6man-enhanced-dad-13 + * requires transmission of additional probes until + * the loopback condition becomes clear. + */ + log(LOG_ERR, "%s: a looped back NS message is " + "detected during DAD for %s. " + "Another DAD probes are being sent.\n", + if_name(ifa->ifa_ifp), + ip6_sprintf(ip6buf, IFA_IN6(ifa))); + dp->dad_loopbackprobe = dp->dad_ns_lcount; + /* + * An interface with IGNORELOOP is one which a + * loopback is permanently expected while regular + * traffic works. In that case, stop DAD after + * MAX_MULTICAST_SOLICIT number of NS messages + * regardless of the number of received loopback NS + * by increasing dad_loopbackprobe in advance. + */ + if (ND_IFINFO(ifa->ifa_ifp)->flags & ND6_IFF_IGNORELOOP) + dp->dad_loopbackprobe += V_nd6_mmaxtries; + /* + * Send an NS immediately and increase dad_count by + * V_nd6_mmaxtries - 1. + */ + nd6_dad_ns_output(dp, ifa); + dp->dad_count = + dp->dad_ns_ocount + V_nd6_mmaxtries - 1; + nd6_dad_starttimer(dp, + (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000); + goto done; + } else { /* * We are done with DAD. No NA came, no NS came. * No duplicate address found. Check IFDISABLED flag @@ -1470,6 +1503,12 @@ nd6_dad_timer(struct dadq *dp) "%s: DAD complete for %s - no duplicates found\n", if_name(ifa->ifa_ifp), ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); + if (dp->dad_ns_lcount > 0) + log(LOG_ERR, "%s: DAD completed while " + "a looped back NS message is detected " + "during DAD for %s.\n", + if_name(ifa->ifa_ifp), + ip6_sprintf(ip6buf, IFA_IN6(ifa))); } } err: