|
@@ -1170,6 +1170,9 @@ enum {
|
|
IPV6_SADDR_RULE_PRIVACY,
|
|
IPV6_SADDR_RULE_PRIVACY,
|
|
IPV6_SADDR_RULE_ORCHID,
|
|
IPV6_SADDR_RULE_ORCHID,
|
|
IPV6_SADDR_RULE_PREFIX,
|
|
IPV6_SADDR_RULE_PREFIX,
|
|
|
|
+#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
|
|
|
|
+ IPV6_SADDR_RULE_NOT_OPTIMISTIC,
|
|
|
|
+#endif
|
|
IPV6_SADDR_RULE_MAX
|
|
IPV6_SADDR_RULE_MAX
|
|
};
|
|
};
|
|
|
|
|
|
@@ -1197,6 +1200,15 @@ static inline int ipv6_saddr_preferred(int type)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline bool ipv6_use_optimistic_addr(struct inet6_dev *idev)
|
|
|
|
+{
|
|
|
|
+#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
|
|
|
|
+ return idev && idev->cnf.optimistic_dad && idev->cnf.use_optimistic;
|
|
|
|
+#else
|
|
|
|
+ return false;
|
|
|
|
+#endif
|
|
|
|
+}
|
|
|
|
+
|
|
static int ipv6_get_saddr_eval(struct net *net,
|
|
static int ipv6_get_saddr_eval(struct net *net,
|
|
struct ipv6_saddr_score *score,
|
|
struct ipv6_saddr_score *score,
|
|
struct ipv6_saddr_dst *dst,
|
|
struct ipv6_saddr_dst *dst,
|
|
@@ -1257,10 +1269,16 @@ static int ipv6_get_saddr_eval(struct net *net,
|
|
score->scopedist = ret;
|
|
score->scopedist = ret;
|
|
break;
|
|
break;
|
|
case IPV6_SADDR_RULE_PREFERRED:
|
|
case IPV6_SADDR_RULE_PREFERRED:
|
|
|
|
+ {
|
|
/* Rule 3: Avoid deprecated and optimistic addresses */
|
|
/* Rule 3: Avoid deprecated and optimistic addresses */
|
|
|
|
+ u8 avoid = IFA_F_DEPRECATED;
|
|
|
|
+
|
|
|
|
+ if (!ipv6_use_optimistic_addr(score->ifa->idev))
|
|
|
|
+ avoid |= IFA_F_OPTIMISTIC;
|
|
ret = ipv6_saddr_preferred(score->addr_type) ||
|
|
ret = ipv6_saddr_preferred(score->addr_type) ||
|
|
- !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
|
|
|
|
|
|
+ !(score->ifa->flags & avoid);
|
|
break;
|
|
break;
|
|
|
|
+ }
|
|
#ifdef CONFIG_IPV6_MIP6
|
|
#ifdef CONFIG_IPV6_MIP6
|
|
case IPV6_SADDR_RULE_HOA:
|
|
case IPV6_SADDR_RULE_HOA:
|
|
{
|
|
{
|
|
@@ -1306,6 +1324,14 @@ static int ipv6_get_saddr_eval(struct net *net,
|
|
ret = score->ifa->prefix_len;
|
|
ret = score->ifa->prefix_len;
|
|
score->matchlen = ret;
|
|
score->matchlen = ret;
|
|
break;
|
|
break;
|
|
|
|
+#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
|
|
|
|
+ case IPV6_SADDR_RULE_NOT_OPTIMISTIC:
|
|
|
|
+ /* Optimistic addresses still have lower precedence than other
|
|
|
|
+ * preferred addresses.
|
|
|
|
+ */
|
|
|
|
+ ret = !(score->ifa->flags & IFA_F_OPTIMISTIC);
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
default:
|
|
default:
|
|
ret = 0;
|
|
ret = 0;
|
|
}
|
|
}
|
|
@@ -3222,8 +3248,15 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
|
|
* Optimistic nodes can start receiving
|
|
* Optimistic nodes can start receiving
|
|
* Frames right away
|
|
* Frames right away
|
|
*/
|
|
*/
|
|
- if (ifp->flags & IFA_F_OPTIMISTIC)
|
|
|
|
|
|
+ if (ifp->flags & IFA_F_OPTIMISTIC) {
|
|
ip6_ins_rt(ifp->rt);
|
|
ip6_ins_rt(ifp->rt);
|
|
|
|
+ if (ipv6_use_optimistic_addr(idev)) {
|
|
|
|
+ /* Because optimistic nodes can use this address,
|
|
|
|
+ * notify listeners. If DAD fails, RTM_DELADDR is sent.
|
|
|
|
+ */
|
|
|
|
+ ipv6_ifa_notify(RTM_NEWADDR, ifp);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
addrconf_dad_kick(ifp);
|
|
addrconf_dad_kick(ifp);
|
|
out:
|
|
out:
|
|
@@ -4330,6 +4363,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
|
|
array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
|
|
array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;
|
|
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
|
|
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
|
|
array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
|
|
array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
|
|
|
|
+ array[DEVCONF_USE_OPTIMISTIC] = cnf->use_optimistic;
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_IPV6_MROUTE
|
|
#ifdef CONFIG_IPV6_MROUTE
|
|
array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
|
|
array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
|
|
@@ -5155,6 +5189,14 @@ static struct addrconf_sysctl_table
|
|
.proc_handler = proc_dointvec,
|
|
.proc_handler = proc_dointvec,
|
|
|
|
|
|
},
|
|
},
|
|
|
|
+ {
|
|
|
|
+ .procname = "use_optimistic",
|
|
|
|
+ .data = &ipv6_devconf.use_optimistic,
|
|
|
|
+ .maxlen = sizeof(int),
|
|
|
|
+ .mode = 0644,
|
|
|
|
+ .proc_handler = proc_dointvec,
|
|
|
|
+
|
|
|
|
+ },
|
|
#endif
|
|
#endif
|
|
#ifdef CONFIG_IPV6_MROUTE
|
|
#ifdef CONFIG_IPV6_MROUTE
|
|
{
|
|
{
|