summaryrefslogtreecommitdiff
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:17:26 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:17:26 +0200
commitb62ed4c93ad71374b54d2c3a72cbc67b506f580c (patch)
tree6ca6ab974bbce902fc9de300fea6aa056170850f /net/ipv6/addrconf.c
parent5895db67c12464003afd16c08049b73aa09e58ea (diff)
parent221fc2f4d0eda59d02af2e751a9282fa013a8e97 (diff)
Merge v6.18.40linux-rolling-lts
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c55
1 files changed, 38 insertions, 17 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b2e1328371d3..c98b1b919f18 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -913,7 +913,7 @@ static int addrconf_fixup_forwarding(const struct ctl_table *table, int *p, int
if (newf)
rt6_purge_dflt_routers(net);
- return 1;
+ return 0;
}
static void addrconf_linkdown_change(struct net *net, __s32 newf)
@@ -955,11 +955,7 @@ static int addrconf_fixup_linkdown(const struct ctl_table *table, int *p, int ne
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
NETCONFA_IFINDEX_DEFAULT,
net->ipv6.devconf_dflt);
- rtnl_net_unlock(net);
- return 0;
- }
-
- if (p == &net->ipv6.devconf_all->ignore_routes_with_linkdown) {
+ } else if (p == &net->ipv6.devconf_all->ignore_routes_with_linkdown) {
WRITE_ONCE(net->ipv6.devconf_dflt->ignore_routes_with_linkdown, newf);
addrconf_linkdown_change(net, newf);
if ((!newf) ^ (!old))
@@ -968,11 +964,21 @@ static int addrconf_fixup_linkdown(const struct ctl_table *table, int *p, int ne
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all);
+ } else {
+ if (!newf ^ !old) {
+ struct inet6_dev *idev = table->extra1;
+
+ inet6_netconf_notify_devconf(net,
+ RTM_NEWNETCONF,
+ NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
+ idev->dev->ifindex,
+ &idev->cnf);
+ }
}
rtnl_net_unlock(net);
- return 1;
+ return 0;
}
#endif
@@ -2168,16 +2174,18 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
struct net *net = dev_net(idev->dev);
int max_addresses;
- if (addrconf_dad_end(ifp)) {
+ spin_lock_bh(&ifp->lock);
+
+ if (ifp->state != INET6_IFADDR_STATE_DAD) {
+ spin_unlock_bh(&ifp->lock);
in6_ifa_put(ifp);
return;
}
+ ifp->state = INET6_IFADDR_STATE_POSTDAD;
net_info_ratelimited("%s: IPv6 duplicate address %pI6c used by %pM detected!\n",
ifp->idev->dev->name, &ifp->addr, eth_hdr(skb)->h_source);
- spin_lock_bh(&ifp->lock);
-
if (ifp->flags & IFA_F_STABLE_PRIVACY) {
struct in6_addr new_addr;
struct inet6_ifaddr *ifp2;
@@ -2225,6 +2233,11 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
in6_ifa_put(ifp2);
lock_errdad:
spin_lock_bh(&ifp->lock);
+ if (ifp->state != INET6_IFADDR_STATE_POSTDAD) {
+ spin_unlock_bh(&ifp->lock);
+ in6_ifa_put(ifp);
+ return;
+ }
}
errdad:
@@ -6343,6 +6356,8 @@ static int addrconf_sysctl_forward(const struct ctl_table *ctl, int write,
lctl.data = &val;
ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
+ if (ret)
+ return ret;
if (write)
ret = addrconf_fixup_forwarding(ctl, valp, val);
@@ -6440,6 +6455,8 @@ static int addrconf_sysctl_disable(const struct ctl_table *ctl, int write,
lctl.data = &val;
ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
+ if (ret)
+ return ret;
if (write)
ret = addrconf_disable_ipv6(ctl, valp, val);
@@ -6451,20 +6468,19 @@ static int addrconf_sysctl_disable(const struct ctl_table *ctl, int write,
static int addrconf_sysctl_proxy_ndp(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
+ struct net *net = ctl->extra2;
int *valp = ctl->data;
- int ret;
int old, new;
+ int ret;
+
+ if (write && !rtnl_net_trylock(net))
+ return restart_syscall();
old = *valp;
ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
new = *valp;
if (write && old != new) {
- struct net *net = ctl->extra2;
-
- if (!rtnl_net_trylock(net))
- return restart_syscall();
-
if (valp == &net->ipv6.devconf_dflt->proxy_ndp) {
inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_PROXY_NEIGH,
@@ -6483,8 +6499,9 @@ static int addrconf_sysctl_proxy_ndp(const struct ctl_table *ctl, int write,
idev->dev->ifindex,
&idev->cnf);
}
- rtnl_net_unlock(net);
}
+ if (write)
+ rtnl_net_unlock(net);
return ret;
}
@@ -6642,6 +6659,8 @@ int addrconf_sysctl_ignore_routes_with_linkdown(const struct ctl_table *ctl,
lctl.data = &val;
ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
+ if (ret)
+ return ret;
if (write)
ret = addrconf_fixup_linkdown(ctl, valp, val);
@@ -6736,6 +6755,8 @@ static int addrconf_sysctl_disable_policy(const struct ctl_table *ctl, int write
lctl = *ctl;
lctl.data = &val;
ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
+ if (ret)
+ return ret;
if (write && (*valp != val))
ret = addrconf_disable_policy(ctl, valp, val);