Commit 35e015e1 authored by Matteo Croce's avatar Matteo Croce Committed by David S. Miller

ipv6: fix net.ipv6.conf.all interface DAD handlers

Currently, writing into
net.ipv6.conf.all.{accept_dad,use_optimistic,optimistic_dad} has no effect.
Fix handling of these flags by:

- using the maximum of global and per-interface values for the
  accept_dad flag. That is, if at least one of the two values is
  non-zero, enable DAD on the interface. If at least one value is
  set to 2, enable DAD and disable IPv6 operation on the interface if
  MAC-based link-local address was found

- using the logical OR of global and per-interface values for the
  optimistic_dad flag. If at least one of them is set to one, optimistic
  duplicate address detection (RFC 4429) is enabled on the interface

- using the logical OR of global and per-interface values for the
  use_optimistic flag. If at least one of them is set to one,
  optimistic addresses won't be marked as deprecated during source address
  selection on the interface.

While at it, as we're modifying the prototype for ipv6_use_optimistic_addr(),
drop inline, and let the compiler decide.

Fixes: 7fd2561e ("net: ipv6: Add a sysctl to make optimistic addresses useful candidates")
Signed-off-by: default avatarMatteo Croce <mcroce@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6819a14e
...@@ -1680,6 +1680,9 @@ accept_dad - INTEGER ...@@ -1680,6 +1680,9 @@ accept_dad - INTEGER
2: Enable DAD, and disable IPv6 operation if MAC-based duplicate 2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
link-local address has been found. link-local address has been found.
DAD operation and mode on a given interface will be selected according
to the maximum value of conf/{all,interface}/accept_dad.
force_tllao - BOOLEAN force_tllao - BOOLEAN
Enable sending the target link-layer address option even when Enable sending the target link-layer address option even when
responding to a unicast neighbor solicitation. responding to a unicast neighbor solicitation.
...@@ -1727,16 +1730,23 @@ suppress_frag_ndisc - INTEGER ...@@ -1727,16 +1730,23 @@ suppress_frag_ndisc - INTEGER
optimistic_dad - BOOLEAN optimistic_dad - BOOLEAN
Whether to perform Optimistic Duplicate Address Detection (RFC 4429). Whether to perform Optimistic Duplicate Address Detection (RFC 4429).
0: disabled (default) 0: disabled (default)
1: enabled 1: enabled
Optimistic Duplicate Address Detection for the interface will be enabled
if at least one of conf/{all,interface}/optimistic_dad is set to 1,
it will be disabled otherwise.
use_optimistic - BOOLEAN use_optimistic - BOOLEAN
If enabled, do not classify optimistic addresses as deprecated during If enabled, do not classify optimistic addresses as deprecated during
source address selection. Preferred addresses will still be chosen source address selection. Preferred addresses will still be chosen
before optimistic addresses, subject to other ranking in the source before optimistic addresses, subject to other ranking in the source
address selection algorithm. address selection algorithm.
0: disabled (default) 0: disabled (default)
1: enabled 1: enabled
This will be enabled if at least one of
conf/{all,interface}/use_optimistic is set to 1, disabled otherwise.
stable_secret - IPv6 address stable_secret - IPv6 address
This IPv6 address will be used as a secret to generate IPv6 This IPv6 address will be used as a secret to generate IPv6
......
...@@ -1399,10 +1399,18 @@ static inline int ipv6_saddr_preferred(int type) ...@@ -1399,10 +1399,18 @@ static inline int ipv6_saddr_preferred(int type)
return 0; return 0;
} }
static inline bool ipv6_use_optimistic_addr(struct inet6_dev *idev) static bool ipv6_use_optimistic_addr(struct net *net,
struct inet6_dev *idev)
{ {
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
return idev && idev->cnf.optimistic_dad && idev->cnf.use_optimistic; if (!idev)
return false;
if (!net->ipv6.devconf_all->optimistic_dad && !idev->cnf.optimistic_dad)
return false;
if (!net->ipv6.devconf_all->use_optimistic && !idev->cnf.use_optimistic)
return false;
return true;
#else #else
return false; return false;
#endif #endif
...@@ -1472,7 +1480,7 @@ static int ipv6_get_saddr_eval(struct net *net, ...@@ -1472,7 +1480,7 @@ static int ipv6_get_saddr_eval(struct net *net,
/* Rule 3: Avoid deprecated and optimistic addresses */ /* Rule 3: Avoid deprecated and optimistic addresses */
u8 avoid = IFA_F_DEPRECATED; u8 avoid = IFA_F_DEPRECATED;
if (!ipv6_use_optimistic_addr(score->ifa->idev)) if (!ipv6_use_optimistic_addr(net, score->ifa->idev))
avoid |= IFA_F_OPTIMISTIC; avoid |= IFA_F_OPTIMISTIC;
ret = ipv6_saddr_preferred(score->addr_type) || ret = ipv6_saddr_preferred(score->addr_type) ||
!(score->ifa->flags & avoid); !(score->ifa->flags & avoid);
...@@ -2460,7 +2468,8 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, ...@@ -2460,7 +2468,8 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
int max_addresses = in6_dev->cnf.max_addresses; int max_addresses = in6_dev->cnf.max_addresses;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
if (in6_dev->cnf.optimistic_dad && if ((net->ipv6.devconf_all->optimistic_dad ||
in6_dev->cnf.optimistic_dad) &&
!net->ipv6.devconf_all->forwarding && sllao) !net->ipv6.devconf_all->forwarding && sllao)
addr_flags |= IFA_F_OPTIMISTIC; addr_flags |= IFA_F_OPTIMISTIC;
#endif #endif
...@@ -3051,7 +3060,8 @@ void addrconf_add_linklocal(struct inet6_dev *idev, ...@@ -3051,7 +3060,8 @@ void addrconf_add_linklocal(struct inet6_dev *idev,
u32 addr_flags = flags | IFA_F_PERMANENT; u32 addr_flags = flags | IFA_F_PERMANENT;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
if (idev->cnf.optimistic_dad && if ((dev_net(idev->dev)->ipv6.devconf_all->optimistic_dad ||
idev->cnf.optimistic_dad) &&
!dev_net(idev->dev)->ipv6.devconf_all->forwarding) !dev_net(idev->dev)->ipv6.devconf_all->forwarding)
addr_flags |= IFA_F_OPTIMISTIC; addr_flags |= IFA_F_OPTIMISTIC;
#endif #endif
...@@ -3810,6 +3820,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp) ...@@ -3810,6 +3820,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
goto out; goto out;
if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
dev_net(dev)->ipv6.devconf_all->accept_dad < 1 ||
idev->cnf.accept_dad < 1 || idev->cnf.accept_dad < 1 ||
!(ifp->flags&IFA_F_TENTATIVE) || !(ifp->flags&IFA_F_TENTATIVE) ||
ifp->flags & IFA_F_NODAD) { ifp->flags & IFA_F_NODAD) {
...@@ -3841,7 +3852,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp) ...@@ -3841,7 +3852,7 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
*/ */
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)) { if (ipv6_use_optimistic_addr(dev_net(dev), idev)) {
/* Because optimistic nodes can use this address, /* Because optimistic nodes can use this address,
* notify listeners. If DAD fails, RTM_DELADDR is sent. * notify listeners. If DAD fails, RTM_DELADDR is sent.
*/ */
...@@ -3897,7 +3908,9 @@ static void addrconf_dad_work(struct work_struct *w) ...@@ -3897,7 +3908,9 @@ static void addrconf_dad_work(struct work_struct *w)
action = DAD_ABORT; action = DAD_ABORT;
ifp->state = INET6_IFADDR_STATE_POSTDAD; ifp->state = INET6_IFADDR_STATE_POSTDAD;
if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6 && if ((dev_net(idev->dev)->ipv6.devconf_all->accept_dad > 1 ||
idev->cnf.accept_dad > 1) &&
!idev->cnf.disable_ipv6 &&
!(ifp->flags & IFA_F_STABLE_PRIVACY)) { !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
struct in6_addr addr; struct in6_addr addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment