Commit 0e42c721 authored by David S. Miller's avatar David S. Miller

Merge branch 'netconf-delnetconf'

David Ahern says:

====================
netconf: Add support for RTM_DELNETCONF

netconf notifications are sent as devices register but not when they
are deleted leaving userspace caches out of sync. Add support for
RTM_DELNETCONF to ipv4, ipv6 and mpls.

MPLS is missing RTM_NEWNETCONF as devices are created, so add it as well.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 50c0add5 1182e4d0
...@@ -153,8 +153,8 @@ struct in_ifaddr { ...@@ -153,8 +153,8 @@ struct in_ifaddr {
int register_inetaddr_notifier(struct notifier_block *nb); int register_inetaddr_notifier(struct notifier_block *nb);
int unregister_inetaddr_notifier(struct notifier_block *nb); int unregister_inetaddr_notifier(struct notifier_block *nb);
void inet_netconf_notify_devconf(struct net *net, int type, int ifindex, void inet_netconf_notify_devconf(struct net *net, int event, int type,
struct ipv4_devconf *devconf); int ifindex, struct ipv4_devconf *devconf);
struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref); struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref);
static inline struct net_device *ip_dev_find(struct net *net, __be32 addr) static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
......
...@@ -262,8 +262,8 @@ int register_inet6addr_notifier(struct notifier_block *nb); ...@@ -262,8 +262,8 @@ int register_inet6addr_notifier(struct notifier_block *nb);
int unregister_inet6addr_notifier(struct notifier_block *nb); int unregister_inet6addr_notifier(struct notifier_block *nb);
int inet6addr_notifier_call_chain(unsigned long val, void *v); int inet6addr_notifier_call_chain(unsigned long val, void *v);
void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, void inet6_netconf_notify_devconf(struct net *net, int event, int type,
struct ipv6_devconf *devconf); int ifindex, struct ipv6_devconf *devconf);
/** /**
* __in6_dev_get - get inet6_dev pointer from netdevice * __in6_dev_get - get inet6_dev pointer from netdevice
......
...@@ -122,6 +122,8 @@ enum { ...@@ -122,6 +122,8 @@ enum {
RTM_NEWNETCONF = 80, RTM_NEWNETCONF = 80,
#define RTM_NEWNETCONF RTM_NEWNETCONF #define RTM_NEWNETCONF RTM_NEWNETCONF
RTM_DELNETCONF,
#define RTM_DELNETCONF RTM_DELNETCONF
RTM_GETNETCONF = 82, RTM_GETNETCONF = 82,
#define RTM_GETNETCONF RTM_GETNETCONF #define RTM_GETNETCONF RTM_GETNETCONF
......
...@@ -1802,6 +1802,9 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, ...@@ -1802,6 +1802,9 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
goto nla_put_failure; goto nla_put_failure;
if (!devconf)
goto out;
if ((all || type == NETCONFA_FORWARDING) && if ((all || type == NETCONFA_FORWARDING) &&
nla_put_s32(skb, NETCONFA_FORWARDING, nla_put_s32(skb, NETCONFA_FORWARDING,
IPV4_DEVCONF(*devconf, FORWARDING)) < 0) IPV4_DEVCONF(*devconf, FORWARDING)) < 0)
...@@ -1823,6 +1826,7 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, ...@@ -1823,6 +1826,7 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0) IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0)
goto nla_put_failure; goto nla_put_failure;
out:
nlmsg_end(skb, nlh); nlmsg_end(skb, nlh);
return 0; return 0;
...@@ -1831,8 +1835,8 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, ...@@ -1831,8 +1835,8 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
return -EMSGSIZE; return -EMSGSIZE;
} }
void inet_netconf_notify_devconf(struct net *net, int type, int ifindex, void inet_netconf_notify_devconf(struct net *net, int event, int type,
struct ipv4_devconf *devconf) int ifindex, struct ipv4_devconf *devconf)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err = -ENOBUFS; int err = -ENOBUFS;
...@@ -1842,7 +1846,7 @@ void inet_netconf_notify_devconf(struct net *net, int type, int ifindex, ...@@ -1842,7 +1846,7 @@ void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
goto errout; goto errout;
err = inet_netconf_fill_devconf(skb, ifindex, devconf, 0, 0, err = inet_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
RTM_NEWNETCONF, 0, type); event, 0, type);
if (err < 0) { if (err < 0) {
/* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */ /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
WARN_ON(err == -EMSGSIZE); WARN_ON(err == -EMSGSIZE);
...@@ -2021,10 +2025,12 @@ static void inet_forward_change(struct net *net) ...@@ -2021,10 +2025,12 @@ static void inet_forward_change(struct net *net)
IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
IPV4_DEVCONF_DFLT(net, FORWARDING) = on; IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv4.devconf_all); net->ipv4.devconf_all);
inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING,
NETCONFA_IFINDEX_DEFAULT, NETCONFA_IFINDEX_DEFAULT,
net->ipv4.devconf_dflt); net->ipv4.devconf_dflt);
...@@ -2037,7 +2043,8 @@ static void inet_forward_change(struct net *net) ...@@ -2037,7 +2043,8 @@ static void inet_forward_change(struct net *net)
in_dev = __in_dev_get_rtnl(dev); in_dev = __in_dev_get_rtnl(dev);
if (in_dev) { if (in_dev) {
IN_DEV_CONF_SET(in_dev, FORWARDING, on); IN_DEV_CONF_SET(in_dev, FORWARDING, on);
inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING,
dev->ifindex, &in_dev->cnf); dev->ifindex, &in_dev->cnf);
} }
} }
...@@ -2082,19 +2089,22 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write, ...@@ -2082,19 +2089,22 @@ static int devinet_conf_proc(struct ctl_table *ctl, int write,
if (i == IPV4_DEVCONF_RP_FILTER - 1 && if (i == IPV4_DEVCONF_RP_FILTER - 1 &&
new_value != old_value) { new_value != old_value) {
ifindex = devinet_conf_ifindex(net, cnf); ifindex = devinet_conf_ifindex(net, cnf);
inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_RP_FILTER,
ifindex, cnf); ifindex, cnf);
} }
if (i == IPV4_DEVCONF_PROXY_ARP - 1 && if (i == IPV4_DEVCONF_PROXY_ARP - 1 &&
new_value != old_value) { new_value != old_value) {
ifindex = devinet_conf_ifindex(net, cnf); ifindex = devinet_conf_ifindex(net, cnf);
inet_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_PROXY_NEIGH,
ifindex, cnf); ifindex, cnf);
} }
if (i == IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1 && if (i == IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1 &&
new_value != old_value) { new_value != old_value) {
ifindex = devinet_conf_ifindex(net, cnf); ifindex = devinet_conf_ifindex(net, cnf);
inet_netconf_notify_devconf(net, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
ifindex, cnf); ifindex, cnf);
} }
} }
...@@ -2129,7 +2139,7 @@ static int devinet_sysctl_forward(struct ctl_table *ctl, int write, ...@@ -2129,7 +2139,7 @@ static int devinet_sysctl_forward(struct ctl_table *ctl, int write,
container_of(cnf, struct in_device, cnf); container_of(cnf, struct in_device, cnf);
if (*valp) if (*valp)
dev_disable_lro(idev->dev); dev_disable_lro(idev->dev);
inet_netconf_notify_devconf(net, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING, NETCONFA_FORWARDING,
idev->dev->ifindex, idev->dev->ifindex,
cnf); cnf);
...@@ -2137,7 +2147,8 @@ static int devinet_sysctl_forward(struct ctl_table *ctl, int write, ...@@ -2137,7 +2147,8 @@ static int devinet_sysctl_forward(struct ctl_table *ctl, int write,
rtnl_unlock(); rtnl_unlock();
rt_cache_flush(net); rt_cache_flush(net);
} else } else
inet_netconf_notify_devconf(net, NETCONFA_FORWARDING, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING,
NETCONFA_IFINDEX_DEFAULT, NETCONFA_IFINDEX_DEFAULT,
net->ipv4.devconf_dflt); net->ipv4.devconf_dflt);
} }
...@@ -2259,7 +2270,8 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, ...@@ -2259,7 +2270,8 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
p->sysctl = t; p->sysctl = t;
inet_netconf_notify_devconf(net, NETCONFA_ALL, ifindex, p); inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_ALL,
ifindex, p);
return 0; return 0;
free: free:
...@@ -2268,16 +2280,18 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, ...@@ -2268,16 +2280,18 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
return -ENOBUFS; return -ENOBUFS;
} }
static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) static void __devinet_sysctl_unregister(struct net *net,
struct ipv4_devconf *cnf, int ifindex)
{ {
struct devinet_sysctl_table *t = cnf->sysctl; struct devinet_sysctl_table *t = cnf->sysctl;
if (!t) if (t) {
return; cnf->sysctl = NULL;
unregister_net_sysctl_table(t->sysctl_header);
kfree(t);
}
cnf->sysctl = NULL; inet_netconf_notify_devconf(net, RTM_DELNETCONF, 0, ifindex, NULL);
unregister_net_sysctl_table(t->sysctl_header);
kfree(t);
} }
static int devinet_sysctl_register(struct in_device *idev) static int devinet_sysctl_register(struct in_device *idev)
...@@ -2299,7 +2313,9 @@ static int devinet_sysctl_register(struct in_device *idev) ...@@ -2299,7 +2313,9 @@ static int devinet_sysctl_register(struct in_device *idev)
static void devinet_sysctl_unregister(struct in_device *idev) static void devinet_sysctl_unregister(struct in_device *idev)
{ {
__devinet_sysctl_unregister(&idev->cnf); struct net *net = dev_net(idev->dev);
__devinet_sysctl_unregister(net, &idev->cnf, idev->dev->ifindex);
neigh_sysctl_unregister(idev->arp_parms); neigh_sysctl_unregister(idev->arp_parms);
} }
...@@ -2374,9 +2390,9 @@ static __net_init int devinet_init_net(struct net *net) ...@@ -2374,9 +2390,9 @@ static __net_init int devinet_init_net(struct net *net)
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
err_reg_ctl: err_reg_ctl:
__devinet_sysctl_unregister(dflt); __devinet_sysctl_unregister(net, dflt, NETCONFA_IFINDEX_DEFAULT);
err_reg_dflt: err_reg_dflt:
__devinet_sysctl_unregister(all); __devinet_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL);
err_reg_all: err_reg_all:
if (tbl != ctl_forward_entry) if (tbl != ctl_forward_entry)
kfree(tbl); kfree(tbl);
...@@ -2398,8 +2414,10 @@ static __net_exit void devinet_exit_net(struct net *net) ...@@ -2398,8 +2414,10 @@ static __net_exit void devinet_exit_net(struct net *net)
tbl = net->ipv4.forw_hdr->ctl_table_arg; tbl = net->ipv4.forw_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->ipv4.forw_hdr); unregister_net_sysctl_table(net->ipv4.forw_hdr);
__devinet_sysctl_unregister(net->ipv4.devconf_dflt); __devinet_sysctl_unregister(net, net->ipv4.devconf_dflt,
__devinet_sysctl_unregister(net->ipv4.devconf_all); NETCONFA_IFINDEX_DEFAULT);
__devinet_sysctl_unregister(net, net->ipv4.devconf_all,
NETCONFA_IFINDEX_ALL);
kfree(tbl); kfree(tbl);
#endif #endif
kfree(net->ipv4.devconf_dflt); kfree(net->ipv4.devconf_dflt);
......
...@@ -631,7 +631,7 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify, ...@@ -631,7 +631,7 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
in_dev = __in_dev_get_rtnl(dev); in_dev = __in_dev_get_rtnl(dev);
if (in_dev) { if (in_dev) {
IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--; IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
inet_netconf_notify_devconf(dev_net(dev), inet_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING, NETCONFA_MC_FORWARDING,
dev->ifindex, &in_dev->cnf); dev->ifindex, &in_dev->cnf);
ip_rt_multicast_event(in_dev); ip_rt_multicast_event(in_dev);
...@@ -820,8 +820,8 @@ static int vif_add(struct net *net, struct mr_table *mrt, ...@@ -820,8 +820,8 @@ static int vif_add(struct net *net, struct mr_table *mrt,
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++; IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, dev->ifindex, inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_MC_FORWARDING,
&in_dev->cnf); dev->ifindex, &in_dev->cnf);
ip_rt_multicast_event(in_dev); ip_rt_multicast_event(in_dev);
/* Fill in the VIF structures */ /* Fill in the VIF structures */
...@@ -1282,7 +1282,8 @@ static void mrtsock_destruct(struct sock *sk) ...@@ -1282,7 +1282,8 @@ static void mrtsock_destruct(struct sock *sk)
ipmr_for_each_table(mrt, net) { ipmr_for_each_table(mrt, net) {
if (sk == rtnl_dereference(mrt->mroute_sk)) { if (sk == rtnl_dereference(mrt->mroute_sk)) {
IPV4_DEVCONF_ALL(net, MC_FORWARDING)--; IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv4.devconf_all); net->ipv4.devconf_all);
RCU_INIT_POINTER(mrt->mroute_sk, NULL); RCU_INIT_POINTER(mrt->mroute_sk, NULL);
...@@ -1344,7 +1345,8 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, ...@@ -1344,7 +1345,8 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval,
if (ret == 0) { if (ret == 0) {
rcu_assign_pointer(mrt->mroute_sk, sk); rcu_assign_pointer(mrt->mroute_sk, sk);
IPV4_DEVCONF_ALL(net, MC_FORWARDING)++; IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv4.devconf_all); net->ipv4.devconf_all);
} }
......
...@@ -549,6 +549,9 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex, ...@@ -549,6 +549,9 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
goto nla_put_failure; goto nla_put_failure;
if (!devconf)
goto out;
if ((all || type == NETCONFA_FORWARDING) && if ((all || type == NETCONFA_FORWARDING) &&
nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0) nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
goto nla_put_failure; goto nla_put_failure;
...@@ -567,6 +570,7 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex, ...@@ -567,6 +570,7 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
devconf->ignore_routes_with_linkdown) < 0) devconf->ignore_routes_with_linkdown) < 0)
goto nla_put_failure; goto nla_put_failure;
out:
nlmsg_end(skb, nlh); nlmsg_end(skb, nlh);
return 0; return 0;
...@@ -575,8 +579,8 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex, ...@@ -575,8 +579,8 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
return -EMSGSIZE; return -EMSGSIZE;
} }
void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, void inet6_netconf_notify_devconf(struct net *net, int event, int type,
struct ipv6_devconf *devconf) int ifindex, struct ipv6_devconf *devconf)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err = -ENOBUFS; int err = -ENOBUFS;
...@@ -586,7 +590,7 @@ void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, ...@@ -586,7 +590,7 @@ void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
goto errout; goto errout;
err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0, err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
RTM_NEWNETCONF, 0, type); event, 0, type);
if (err < 0) { if (err < 0) {
/* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */ /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
WARN_ON(err == -EMSGSIZE); WARN_ON(err == -EMSGSIZE);
...@@ -769,7 +773,8 @@ static void dev_forward_change(struct inet6_dev *idev) ...@@ -769,7 +773,8 @@ static void dev_forward_change(struct inet6_dev *idev)
else else
addrconf_leave_anycast(ifa); addrconf_leave_anycast(ifa);
} }
inet6_netconf_notify_devconf(dev_net(dev), NETCONFA_FORWARDING, inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
NETCONFA_FORWARDING,
dev->ifindex, &idev->cnf); dev->ifindex, &idev->cnf);
} }
...@@ -804,7 +809,8 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) ...@@ -804,7 +809,8 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
if (p == &net->ipv6.devconf_dflt->forwarding) { if (p == &net->ipv6.devconf_dflt->forwarding) {
if ((!newf) ^ (!old)) if ((!newf) ^ (!old))
inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING,
NETCONFA_IFINDEX_DEFAULT, NETCONFA_IFINDEX_DEFAULT,
net->ipv6.devconf_dflt); net->ipv6.devconf_dflt);
rtnl_unlock(); rtnl_unlock();
...@@ -816,13 +822,15 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) ...@@ -816,13 +822,15 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
net->ipv6.devconf_dflt->forwarding = newf; net->ipv6.devconf_dflt->forwarding = newf;
if ((!newf) ^ (!old_dflt)) if ((!newf) ^ (!old_dflt))
inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING,
NETCONFA_IFINDEX_DEFAULT, NETCONFA_IFINDEX_DEFAULT,
net->ipv6.devconf_dflt); net->ipv6.devconf_dflt);
addrconf_forward_change(net, newf); addrconf_forward_change(net, newf);
if ((!newf) ^ (!old)) if ((!newf) ^ (!old))
inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_FORWARDING,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all); net->ipv6.devconf_all);
} else if ((!newf) ^ (!old)) } else if ((!newf) ^ (!old))
...@@ -847,6 +855,7 @@ static void addrconf_linkdown_change(struct net *net, __s32 newf) ...@@ -847,6 +855,7 @@ static void addrconf_linkdown_change(struct net *net, __s32 newf)
idev->cnf.ignore_routes_with_linkdown = newf; idev->cnf.ignore_routes_with_linkdown = newf;
if (changed) if (changed)
inet6_netconf_notify_devconf(dev_net(dev), inet6_netconf_notify_devconf(dev_net(dev),
RTM_NEWNETCONF,
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
dev->ifindex, dev->ifindex,
&idev->cnf); &idev->cnf);
...@@ -869,6 +878,7 @@ static int addrconf_fixup_linkdown(struct ctl_table *table, int *p, int newf) ...@@ -869,6 +878,7 @@ static int addrconf_fixup_linkdown(struct ctl_table *table, int *p, int newf)
if (p == &net->ipv6.devconf_dflt->ignore_routes_with_linkdown) { if (p == &net->ipv6.devconf_dflt->ignore_routes_with_linkdown) {
if ((!newf) ^ (!old)) if ((!newf) ^ (!old))
inet6_netconf_notify_devconf(net, inet6_netconf_notify_devconf(net,
RTM_NEWNETCONF,
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
NETCONFA_IFINDEX_DEFAULT, NETCONFA_IFINDEX_DEFAULT,
net->ipv6.devconf_dflt); net->ipv6.devconf_dflt);
...@@ -881,6 +891,7 @@ static int addrconf_fixup_linkdown(struct ctl_table *table, int *p, int newf) ...@@ -881,6 +891,7 @@ static int addrconf_fixup_linkdown(struct ctl_table *table, int *p, int newf)
addrconf_linkdown_change(net, newf); addrconf_linkdown_change(net, newf);
if ((!newf) ^ (!old)) if ((!newf) ^ (!old))
inet6_netconf_notify_devconf(net, inet6_netconf_notify_devconf(net,
RTM_NEWNETCONF,
NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all); net->ipv6.devconf_all);
...@@ -5675,17 +5686,20 @@ int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write, ...@@ -5675,17 +5686,20 @@ int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
return restart_syscall(); return restart_syscall();
if (valp == &net->ipv6.devconf_dflt->proxy_ndp) if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_PROXY_NEIGH,
NETCONFA_IFINDEX_DEFAULT, NETCONFA_IFINDEX_DEFAULT,
net->ipv6.devconf_dflt); net->ipv6.devconf_dflt);
else if (valp == &net->ipv6.devconf_all->proxy_ndp) else if (valp == &net->ipv6.devconf_all->proxy_ndp)
inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_PROXY_NEIGH,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all); net->ipv6.devconf_all);
else { else {
struct inet6_dev *idev = ctl->extra1; struct inet6_dev *idev = ctl->extra1;
inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_PROXY_NEIGH,
idev->dev->ifindex, idev->dev->ifindex,
&idev->cnf); &idev->cnf);
} }
...@@ -6348,7 +6362,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, ...@@ -6348,7 +6362,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
ifindex = NETCONFA_IFINDEX_DEFAULT; ifindex = NETCONFA_IFINDEX_DEFAULT;
else else
ifindex = idev->dev->ifindex; ifindex = idev->dev->ifindex;
inet6_netconf_notify_devconf(net, NETCONFA_ALL, ifindex, p); inet6_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_ALL,
ifindex, p);
return 0; return 0;
free: free:
...@@ -6357,7 +6372,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, ...@@ -6357,7 +6372,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
return -ENOBUFS; return -ENOBUFS;
} }
static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) static void __addrconf_sysctl_unregister(struct net *net,
struct ipv6_devconf *p, int ifindex)
{ {
struct ctl_table *table; struct ctl_table *table;
...@@ -6368,6 +6384,8 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) ...@@ -6368,6 +6384,8 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
unregister_net_sysctl_table(p->sysctl_header); unregister_net_sysctl_table(p->sysctl_header);
p->sysctl_header = NULL; p->sysctl_header = NULL;
kfree(table); kfree(table);
inet6_netconf_notify_devconf(net, RTM_DELNETCONF, 0, ifindex, NULL);
} }
static int addrconf_sysctl_register(struct inet6_dev *idev) static int addrconf_sysctl_register(struct inet6_dev *idev)
...@@ -6391,7 +6409,8 @@ static int addrconf_sysctl_register(struct inet6_dev *idev) ...@@ -6391,7 +6409,8 @@ static int addrconf_sysctl_register(struct inet6_dev *idev)
static void addrconf_sysctl_unregister(struct inet6_dev *idev) static void addrconf_sysctl_unregister(struct inet6_dev *idev)
{ {
__addrconf_sysctl_unregister(&idev->cnf); __addrconf_sysctl_unregister(dev_net(idev->dev), &idev->cnf,
idev->dev->ifindex);
neigh_sysctl_unregister(idev->nd_parms); neigh_sysctl_unregister(idev->nd_parms);
} }
...@@ -6434,7 +6453,7 @@ static int __net_init addrconf_init_net(struct net *net) ...@@ -6434,7 +6453,7 @@ static int __net_init addrconf_init_net(struct net *net)
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
err_reg_dflt: err_reg_dflt:
__addrconf_sysctl_unregister(all); __addrconf_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL);
err_reg_all: err_reg_all:
kfree(dflt); kfree(dflt);
#endif #endif
...@@ -6447,8 +6466,10 @@ static int __net_init addrconf_init_net(struct net *net) ...@@ -6447,8 +6466,10 @@ static int __net_init addrconf_init_net(struct net *net)
static void __net_exit addrconf_exit_net(struct net *net) static void __net_exit addrconf_exit_net(struct net *net)
{ {
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
__addrconf_sysctl_unregister(net->ipv6.devconf_dflt); __addrconf_sysctl_unregister(net, net->ipv6.devconf_dflt,
__addrconf_sysctl_unregister(net->ipv6.devconf_all); NETCONFA_IFINDEX_DEFAULT);
__addrconf_sysctl_unregister(net, net->ipv6.devconf_all,
NETCONFA_IFINDEX_ALL);
#endif #endif
kfree(net->ipv6.devconf_dflt); kfree(net->ipv6.devconf_dflt);
kfree(net->ipv6.devconf_all); kfree(net->ipv6.devconf_all);
......
...@@ -815,7 +815,7 @@ static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head) ...@@ -815,7 +815,7 @@ static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
in6_dev = __in6_dev_get(dev); in6_dev = __in6_dev_get(dev);
if (in6_dev) { if (in6_dev) {
in6_dev->cnf.mc_forwarding--; in6_dev->cnf.mc_forwarding--;
inet6_netconf_notify_devconf(dev_net(dev), inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING, NETCONFA_MC_FORWARDING,
dev->ifindex, &in6_dev->cnf); dev->ifindex, &in6_dev->cnf);
} }
...@@ -974,7 +974,7 @@ static int mif6_add(struct net *net, struct mr6_table *mrt, ...@@ -974,7 +974,7 @@ static int mif6_add(struct net *net, struct mr6_table *mrt,
in6_dev = __in6_dev_get(dev); in6_dev = __in6_dev_get(dev);
if (in6_dev) { if (in6_dev) {
in6_dev->cnf.mc_forwarding++; in6_dev->cnf.mc_forwarding++;
inet6_netconf_notify_devconf(dev_net(dev), inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING, NETCONFA_MC_FORWARDING,
dev->ifindex, &in6_dev->cnf); dev->ifindex, &in6_dev->cnf);
} }
...@@ -1599,7 +1599,8 @@ static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk) ...@@ -1599,7 +1599,8 @@ static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
write_unlock_bh(&mrt_lock); write_unlock_bh(&mrt_lock);
if (!err) if (!err)
inet6_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all); net->ipv6.devconf_all);
rtnl_unlock(); rtnl_unlock();
...@@ -1620,7 +1621,7 @@ int ip6mr_sk_done(struct sock *sk) ...@@ -1620,7 +1621,7 @@ int ip6mr_sk_done(struct sock *sk)
mrt->mroute6_sk = NULL; mrt->mroute6_sk = NULL;
net->ipv6.devconf_all->mc_forwarding--; net->ipv6.devconf_all->mc_forwarding--;
write_unlock_bh(&mrt_lock); write_unlock_bh(&mrt_lock);
inet6_netconf_notify_devconf(net, inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING, NETCONFA_MC_FORWARDING,
NETCONFA_IFINDEX_ALL, NETCONFA_IFINDEX_ALL,
net->ipv6.devconf_all); net->ipv6.devconf_all);
......
...@@ -1040,8 +1040,8 @@ static int mpls_netconf_msgsize_devconf(int type) ...@@ -1040,8 +1040,8 @@ static int mpls_netconf_msgsize_devconf(int type)
return size; return size;
} }
static void mpls_netconf_notify_devconf(struct net *net, int type, static void mpls_netconf_notify_devconf(struct net *net, int event,
struct mpls_dev *mdev) int type, struct mpls_dev *mdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int err = -ENOBUFS; int err = -ENOBUFS;
...@@ -1050,8 +1050,7 @@ static void mpls_netconf_notify_devconf(struct net *net, int type, ...@@ -1050,8 +1050,7 @@ static void mpls_netconf_notify_devconf(struct net *net, int type,
if (!skb) if (!skb)
goto errout; goto errout;
err = mpls_netconf_fill_devconf(skb, mdev, 0, 0, RTM_NEWNETCONF, err = mpls_netconf_fill_devconf(skb, mdev, 0, 0, event, 0, type);
0, type);
if (err < 0) { if (err < 0) {
/* -EMSGSIZE implies BUG in mpls_netconf_msgsize_devconf() */ /* -EMSGSIZE implies BUG in mpls_netconf_msgsize_devconf() */
WARN_ON(err == -EMSGSIZE); WARN_ON(err == -EMSGSIZE);
...@@ -1184,9 +1183,8 @@ static int mpls_conf_proc(struct ctl_table *ctl, int write, ...@@ -1184,9 +1183,8 @@ static int mpls_conf_proc(struct ctl_table *ctl, int write,
if (i == offsetof(struct mpls_dev, input_enabled) && if (i == offsetof(struct mpls_dev, input_enabled) &&
val != oval) { val != oval) {
mpls_netconf_notify_devconf(net, mpls_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_INPUT, NETCONFA_INPUT, mdev);
mdev);
} }
} }
...@@ -1227,10 +1225,11 @@ static int mpls_dev_sysctl_register(struct net_device *dev, ...@@ -1227,10 +1225,11 @@ static int mpls_dev_sysctl_register(struct net_device *dev,
snprintf(path, sizeof(path), "net/mpls/conf/%s", dev->name); snprintf(path, sizeof(path), "net/mpls/conf/%s", dev->name);
mdev->sysctl = register_net_sysctl(dev_net(dev), path, table); mdev->sysctl = register_net_sysctl(net, path, table);
if (!mdev->sysctl) if (!mdev->sysctl)
goto free; goto free;
mpls_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_ALL, mdev);
return 0; return 0;
free: free:
...@@ -1239,13 +1238,17 @@ static int mpls_dev_sysctl_register(struct net_device *dev, ...@@ -1239,13 +1238,17 @@ static int mpls_dev_sysctl_register(struct net_device *dev,
return -ENOBUFS; return -ENOBUFS;
} }
static void mpls_dev_sysctl_unregister(struct mpls_dev *mdev) static void mpls_dev_sysctl_unregister(struct net_device *dev,
struct mpls_dev *mdev)
{ {
struct net *net = dev_net(dev);
struct ctl_table *table; struct ctl_table *table;
table = mdev->sysctl->ctl_table_arg; table = mdev->sysctl->ctl_table_arg;
unregister_net_sysctl_table(mdev->sysctl); unregister_net_sysctl_table(mdev->sysctl);
kfree(table); kfree(table);
mpls_netconf_notify_devconf(net, RTM_DELNETCONF, 0, mdev);
} }
static struct mpls_dev *mpls_add_dev(struct net_device *dev) static struct mpls_dev *mpls_add_dev(struct net_device *dev)
...@@ -1271,11 +1274,12 @@ static struct mpls_dev *mpls_add_dev(struct net_device *dev) ...@@ -1271,11 +1274,12 @@ static struct mpls_dev *mpls_add_dev(struct net_device *dev)
u64_stats_init(&mpls_stats->syncp); u64_stats_init(&mpls_stats->syncp);
} }
mdev->dev = dev;
err = mpls_dev_sysctl_register(dev, mdev); err = mpls_dev_sysctl_register(dev, mdev);
if (err) if (err)
goto free; goto free;
mdev->dev = dev;
rcu_assign_pointer(dev->mpls_ptr, mdev); rcu_assign_pointer(dev->mpls_ptr, mdev);
return mdev; return mdev;
...@@ -1421,7 +1425,7 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, ...@@ -1421,7 +1425,7 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event,
mpls_ifdown(dev, event); mpls_ifdown(dev, event);
mdev = mpls_dev_get(dev); mdev = mpls_dev_get(dev);
if (mdev) { if (mdev) {
mpls_dev_sysctl_unregister(mdev); mpls_dev_sysctl_unregister(dev, mdev);
RCU_INIT_POINTER(dev->mpls_ptr, NULL); RCU_INIT_POINTER(dev->mpls_ptr, NULL);
call_rcu(&mdev->rcu, mpls_dev_destroy_rcu); call_rcu(&mdev->rcu, mpls_dev_destroy_rcu);
} }
...@@ -1431,7 +1435,7 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, ...@@ -1431,7 +1435,7 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event,
if (mdev) { if (mdev) {
int err; int err;
mpls_dev_sysctl_unregister(mdev); mpls_dev_sysctl_unregister(dev, mdev);
err = mpls_dev_sysctl_register(dev, mdev); err = mpls_dev_sysctl_register(dev, mdev);
if (err) if (err)
return notifier_from_errno(err); return notifier_from_errno(err);
......
...@@ -69,6 +69,7 @@ static struct nlmsg_perm nlmsg_route_perms[] = ...@@ -69,6 +69,7 @@ static struct nlmsg_perm nlmsg_route_perms[] =
{ RTM_GETDCB, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_GETDCB, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
{ RTM_NEWNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_NEWNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
{ RTM_DELNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
{ RTM_GETNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_READ }, { RTM_GETNETCONF, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_NEWMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_NEWMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
{ RTM_DELMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, { RTM_DELMDB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
......
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