Page MenuHomeFreeBSD

D55229.id171688.diff
No OneTemporary

D55229.id171688.diff

diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -271,6 +271,8 @@
printf(" temporary");
if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0)
printf(" prefer_source");
+ if ((flags6 & IN6_IFF_OPTIMISTIC) != 0)
+ printf(" optimistic");
}
@@ -730,6 +732,8 @@
DEF_CMD("eui64", 0, setip6eui64),
DEF_CMD("stableaddr", ND6_IFF_STABLEADDR, setnd6flags),
DEF_CMD("-stableaddr", -ND6_IFF_STABLEADDR, setnd6flags),
+ DEF_CMD("optimistic", IN6_IFF_OPTIMISTIC, setip6flags),
+ DEF_CMD("-optimistic", -IN6_IFF_OPTIMISTIC, setip6flags),
#ifdef EXPERIMENTAL
DEF_CMD("ipv6_only", ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags),
DEF_CMD("-ipv6_only", -ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags),
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -644,7 +644,8 @@
#define IPV6CTL_MAXFRAGSPERPACKET 53 /* Max fragments per packet */
#define IPV6CTL_MAXFRAGBUCKETSIZE 54 /* Max reassembly queues per bucket */
#define IPV6CTL_GRAND_COUNT 55
-#define IPV6CTL_MAXID 56
+#define IPV6CTL_USE_OPTIMISTIC 56
+#define IPV6CTL_MAXID 57
#endif /* __BSD_VISIBLE */
/*
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1090,8 +1090,21 @@
* an interface with ND6_IFF_IFDISABLED.
*/
if (in6if_do_dad(ifp) &&
- (hostIsNew || (ifp->if_inet6->nd_flags & ND6_IFF_IFDISABLED)))
- ia->ia6_flags |= IN6_IFF_TENTATIVE;
+ (hostIsNew || (ifp->if_inet6->nd_flags & ND6_IFF_IFDISABLED))) {
+ /*
+ * RFC 4429 section 3: A router SHOULD NOT configure an
+ * Optimistic Address. Optimistic DAD SHOULD only be used
+ * when the implementation is aware that the address is
+ * based on a most likely unique interface identifier.
+ * XXX: A host that does not know the SLLAO of its router
+ * SHOULD NOT configure a new address as Optimistic.
+ */
+ if (V_ip6_use_optimistic && !V_ip6_forwarding &&
+ (ia->ia6_flags & IN6_IFF_AUTOCONF) != 0)
+ ia->ia6_flags |= IN6_IFF_OPTIMISTIC;
+ else
+ ia->ia6_flags |= IN6_IFF_TENTATIVE;
+ }
/* notify other subsystems */
error = in6_notify_ifa(ifp, ia, ifra, hostIsNew);
@@ -1131,8 +1144,8 @@
}
}
- /* Perform DAD, if the address is TENTATIVE. */
- if ((ia->ia6_flags & IN6_IFF_TENTATIVE)) {
+ /* Perform DAD, if the address is TENTATIVE or OPTIMISTIC. */
+ if ((ia->ia6_flags & IN6_IFF_NEED_DAD) != 0) {
int delay, mindelay, maxdelay;
delay = 0;
@@ -2007,6 +2020,7 @@
int dst_scope = in6_addrscope(dst), blen = -1, tlen;
struct ifaddr *ifa;
struct in6_ifaddr *besta = NULL;
+ struct in6_ifaddr *optimistica = NULL; /* optimistic address */
struct in6_ifaddr *dep[2]; /* last-resort: deprecated */
NET_EPOCH_ASSERT();
@@ -2028,6 +2042,10 @@
continue; /* don't use this interface */
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
continue;
+ if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_OPTIMISTIC) {
+ optimistica = (struct in6_ifaddr *)ifa;
+ continue;
+ }
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
if (V_ip6_use_deprecated)
dep[0] = (struct in6_ifaddr *)ifa;
@@ -2052,6 +2070,9 @@
}
if (besta)
return (besta);
+ /* use optimistic addresses if available */
+ if (optimistica)
+ return (optimistica);
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
@@ -2062,6 +2083,10 @@
continue; /* don't use this interface */
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
continue;
+ if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_OPTIMISTIC) {
+ optimistica = (struct in6_ifaddr *)ifa;
+ continue;
+ }
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
if (V_ip6_use_deprecated)
dep[1] = (struct in6_ifaddr *)ifa;
@@ -2071,6 +2096,9 @@
return (struct in6_ifaddr *)ifa;
}
+ if (optimistica)
+ return (optimistica);
+
/* use the last-resort values, that are, deprecated addresses */
if (dep[0])
return dep[0];
@@ -2095,7 +2123,7 @@
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
ia = (struct in6_ifaddr *)ifa;
- if (ia->ia6_flags & IN6_IFF_TENTATIVE) {
+ if ((ia->ia6_flags & IN6_IFF_NEED_DAD) != 0) {
/*
* The TENTATIVE flag was likely set by hand
* beforehand, implicitly indicating the need for DAD.
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -359,3 +359,6 @@
log_cannot_forward, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(ip6_log_cannot_forward), 1,
"Log packets that cannot be forwarded");
+SYSCTL_BOOL(_net_inet6_ip6, IPV6CTL_USE_OPTIMISTIC, use_optimistic,
+ CTLFLAG_VNET | CTLFLAG_RWTUN, &VNET_NAME(ip6_use_optimistic), 0,
+ "Enable RFC4429 optimistic DAD");
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -478,7 +478,9 @@
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
#define IN6_IFF_TEMPORARY 0x80 /* temporary (anonymous) address. */
#define IN6_IFF_PREFER_SOURCE 0x0100 /* preferred address for SAS */
+#define IN6_IFF_OPTIMISTIC 0x0200 /* optimistic address */
+#define IN6_IFF_NEED_DAD (IN6_IFF_TENTATIVE|IN6_IFF_OPTIMISTIC)
/* do not input/output */
#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -341,9 +341,11 @@
* addresses in the source address
* selection */
VNET_DECLARE(bool, ip6_use_stableaddr); /* Whether to use stable address generation (RFC 7217) */
+VNET_DECLARE(bool, ip6_use_optimistic); /* Whether to use optimistic DAD (RFC 4429) */
#define V_ip6_use_tempaddr VNET(ip6_use_tempaddr)
#define V_ip6_prefer_tempaddr VNET(ip6_prefer_tempaddr)
#define V_ip6_use_stableaddr VNET(ip6_use_stableaddr)
+#define V_ip6_use_optimistic VNET(ip6_use_optimistic)
#define IP6_IDGEN_RETRIES 3 /* RFC 7217 section 7 default max retries */
VNET_DECLARE(u_int, ip6_stableaddr_maxretries);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1021,7 +1021,7 @@
goto addrloop;
}
}
- } else if ((ia6->ia6_flags & IN6_IFF_TENTATIVE) != 0) {
+ } else if ((ia6->ia6_flags & IN6_IFF_NEED_DAD) != 0) {
/*
* Schedule DAD for a tentative address. This happens
* if the interface was down or not running
@@ -1035,7 +1035,8 @@
} else {
/*
* Check status of the interface. If it is down,
- * mark the address as tentative for future DAD.
+ * mark the address as optimistic if available, or
+ * mark it as tentative for future DAD.
*/
ifp = ia6->ia_ifp;
if ((ifp->if_inet6->nd_flags & ND6_IFF_NO_DAD) == 0 &&
@@ -1043,7 +1044,10 @@
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(ifp->if_inet6->nd_flags & ND6_IFF_IFDISABLED))){
ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
- ia6->ia6_flags |= IN6_IFF_TENTATIVE;
+ if (V_ip6_use_optimistic && !V_ip6_forwarding)
+ ia6->ia6_flags |= IN6_IFF_OPTIMISTIC;
+ else
+ ia6->ia6_flags |= IN6_IFF_TENTATIVE;
}
/*
@@ -1756,7 +1760,12 @@
AF_INET6)
continue;
ia = (struct in6_ifaddr *)ifa;
- ia->ia6_flags |= IN6_IFF_TENTATIVE;
+ if (V_ip6_use_optimistic &&
+ !V_ip6_forwarding &&
+ (ia->ia6_flags & IN6_IFF_AUTOCONF) != 0)
+ ia->ia6_flags |= IN6_IFF_OPTIMISTIC;
+ else
+ ia->ia6_flags |= IN6_IFF_TENTATIVE;
}
NET_EPOCH_EXIT(et);
}
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -149,6 +149,7 @@
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
char *lladdr;
int anycast, lladdrlen, proxy, rflag, tentative, tlladdr;
+ int optimistic;
ifa = NULL;
@@ -292,6 +293,7 @@
myaddr6 = *IFA_IN6(ifa);
anycast = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST;
tentative = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE;
+ optimistic = ((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_OPTIMISTIC;
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
goto freeit;
@@ -321,27 +323,30 @@
*
* The processing is defined in RFC 2462.
*/
- if (tentative) {
+ if (tentative || optimistic) {
/*
* If source address is unspecified address, it is for
* duplicate address detection.
*
* If not, the packet is for addess resolution;
+ * Therefore, if the target address is not optimistic,
* silently ignore it.
*/
if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
nd6_dad_ns_input(ifa, ndopts.nd_opts_nonce);
-
- goto freeit;
+ if (tentative)
+ goto freeit;
}
/*
- * If the Target Address is either an anycast address or a unicast
- * address for which the node is providing proxy service, or the Target
- * Link-Layer Address option is not included, the Override flag SHOULD
- * be set to zero. Otherwise, the Override flag SHOULD be set to one.
+ * If the Target Address is an anycast address, an optimistic address,
+ * or a unicast address for which the node is providing proxy service,
+ * or the Target Link-Layer Address option is not included, the Override
+ * flag SHOULD be set to zero.
+ * Otherwise, the Override flag SHOULD be set to one.
*/
- if (anycast == 0 && proxy == 0 && (tlladdr & ND6_NA_OPT_LLA) != 0)
+ if (anycast == 0 && proxy == 0 && optimistic == 0 &&
+ (tlladdr & ND6_NA_OPT_LLA) != 0)
rflag |= ND_NA_FLAG_OVERRIDE;
/*
* If the source address is unspecified address, entries must not
@@ -504,6 +509,9 @@
* We use the source address for the prompting packet
* (saddr6), if saddr6 belongs to the outgoing interface.
* Otherwise, we perform the source address selection as usual.
+ *
+ * RFC 4429 section 2.3: Neighbor Solicitations cannot be
+ * sent from Optimistic Addresses.
*/
if (saddr6 != NULL)
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, saddr6);
@@ -519,7 +527,9 @@
error));
goto bad;
}
- } else
+ } else if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_OPTIMISTIC)
+ goto bad;
+ else
ip6->ip6_src = *saddr6;
if (ifp->if_carp != NULL) {
@@ -774,7 +784,7 @@
* Otherwise, process as defined in RFC 2461.
*/
if (ifa
- && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
+ && (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NEED_DAD)) {
nd6_dad_na_input(ifa);
ifa_free(ifa);
goto freeit;
@@ -1282,7 +1292,7 @@
struct dadq *dp;
char ip6buf[INET6_ADDRSTRLEN];
- KASSERT((ia->ia6_flags & IN6_IFF_TENTATIVE) != 0,
+ KASSERT((ia->ia6_flags & IN6_IFF_NEED_DAD) != 0,
("starting DAD on non-tentative address %p", ifa));
/*
@@ -1294,7 +1304,7 @@
if ((ia->ia6_flags & IN6_IFF_ANYCAST) != 0 ||
V_ip6_dad_count == 0 ||
(ifa->ifa_ifp->if_inet6->nd_flags & ND6_IFF_NO_DAD) != 0) {
- ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
+ ia->ia6_flags &= ~IN6_IFF_NEED_DAD;
return;
}
if ((ifa->ifa_ifp->if_flags & IFF_UP) == 0 ||
@@ -1402,7 +1412,7 @@
ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
goto err;
}
- if ((ia->ia6_flags & IN6_IFF_TENTATIVE) == 0) {
+ if ((ia->ia6_flags & IN6_IFF_NEED_DAD) == 0) {
log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
"%s(%s)\n",
ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
@@ -1471,7 +1481,7 @@
* Reset DAD failures counter if using stable addresses.
*/
if ((ifp->if_inet6->nd_flags & ND6_IFF_IFDISABLED) == 0) {
- ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
+ ia->ia6_flags &= ~IN6_IFF_NEED_DAD;
if ((ifp->if_inet6->nd_flags & ND6_IFF_STABLEADDR) && !(ia->ia6_flags & IN6_IFF_TEMPORARY))
atomic_store_int(&DAD_FAILURES(ifp), 0);
/*
@@ -1517,7 +1527,7 @@
dp->dad_ns_icount, dp->dad_ns_ocount, dp->dad_ns_lcount,
dp->dad_na_icount);
- ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
+ ia->ia6_flags &= ~IN6_IFF_NEED_DAD;
ia->ia6_flags |= IN6_IFF_DUPLICATED;
log(LOG_ERR, "%s: DAD complete for %s - duplicate found\n",
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -96,6 +96,7 @@
VNET_DEFINE(int, ip6_use_tempaddr) = 0;
VNET_DEFINE(bool, ip6_use_stableaddr) = 0;
+VNET_DEFINE(bool, ip6_use_optimistic) = 0;
VNET_DEFINE(int, ip6_desync_factor);
VNET_DEFINE(uint32_t, ip6_temp_max_desync_factor) = TEMP_MAX_DESYNC_FACTOR_BASE;
@@ -2018,7 +2019,10 @@
if (find_pfxlist_reachable_router(ifa->ia6_ndpr)) {
if (ifa->ia6_flags & IN6_IFF_DETACHED) {
ifa->ia6_flags &= ~IN6_IFF_DETACHED;
- ifa->ia6_flags |= IN6_IFF_TENTATIVE;
+ if (V_ip6_use_optimistic && !V_ip6_forwarding)
+ ifa->ia6_flags |= IN6_IFF_OPTIMISTIC;
+ else
+ ifa->ia6_flags |= IN6_IFF_TENTATIVE;
nd6_dad_start((struct ifaddr *)ifa, 0);
}
} else {
@@ -2032,7 +2036,10 @@
if (ifa->ia6_flags & IN6_IFF_DETACHED) {
ifa->ia6_flags &= ~IN6_IFF_DETACHED;
- ifa->ia6_flags |= IN6_IFF_TENTATIVE;
+ if (V_ip6_use_optimistic && !V_ip6_forwarding)
+ ifa->ia6_flags |= IN6_IFF_OPTIMISTIC;
+ else
+ ifa->ia6_flags |= IN6_IFF_TENTATIVE;
/* Do we need a delay in this case? */
nd6_dad_start((struct ifaddr *)ifa, 0);
}
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -906,6 +906,8 @@
nl_flags |= IFA_F_DEPRECATED;
if (flags & IN6_IFF_TENTATIVE)
nl_flags |= IFA_F_TENTATIVE;
+ if (flags & IN6_IFF_OPTIMISTIC)
+ nl_flags |= IFA_F_OPTIMISTIC;
if ((flags & (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY)) == 0)
flags |= IFA_F_PERMANENT;
if (flags & IN6_IFF_DUPLICATED)
diff --git a/usr.sbin/rtsold/if.c b/usr.sbin/rtsold/if.c
--- a/usr.sbin/rtsold/if.c
+++ b/usr.sbin/rtsold/if.c
@@ -163,6 +163,7 @@
close(s);
if (cap_llflags_get(capllflags, name, &llflag) != 0) {
+ /* XXX: RFC 4429 section 2.4: don't try with optimistic address */
warnmsg(LOG_WARNING, __func__,
"cap_llflags_get() failed, anyway I'll try");
return (0);

File Metadata

Mime Type
text/plain
Expires
Mon, May 18, 8:23 PM (14 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33267008
Default Alt Text
D55229.id171688.diff (13 KB)

Event Timeline