Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156990406
D55229.id171688.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D55229.id171688.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D55229: nd6: Add support for Optimistic DAD (RFC 4429)
Attached
Detach File
Event Timeline
Log In to Comment