summaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
authorDavid Ahern <dsa@cumulusnetworks.com>2017-03-28 17:28:03 -0400
committerDavid S. Miller <davem@davemloft.net>2017-03-29 01:32:42 -0400
commitb5c9641d3d45e58dbcb35090345f863e5ade718d (patch)
tree060f381cbc580619836a2742fecb3dd3647bd5ba /net/ipv4/devinet.c
parent3b0228656dcb07a1c9fc81e8516475c2d7c4300e (diff)
net: devinet: Add support for RTM_DELNETCONF
Send RTM_DELNETCONF notifications when a device is deleted. The message only needs the device index, so modify inet_netconf_fill_devconf to skip devconf references if it is NULL. Allows a userspace cache to remove entries as devices are deleted. Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index fd3218cd1870..6d3602ec640c 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1802,6 +1802,9 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
1802 if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) 1802 if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
1803 goto nla_put_failure; 1803 goto nla_put_failure;
1804 1804
1805 if (!devconf)
1806 goto out;
1807
1805 if ((all || type == NETCONFA_FORWARDING) && 1808 if ((all || type == NETCONFA_FORWARDING) &&
1806 nla_put_s32(skb, NETCONFA_FORWARDING, 1809 nla_put_s32(skb, NETCONFA_FORWARDING,
1807 IPV4_DEVCONF(*devconf, FORWARDING)) < 0) 1810 IPV4_DEVCONF(*devconf, FORWARDING)) < 0)
@@ -1823,6 +1826,7 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
1823 IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0) 1826 IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0)
1824 goto nla_put_failure; 1827 goto nla_put_failure;
1825 1828
1829out:
1826 nlmsg_end(skb, nlh); 1830 nlmsg_end(skb, nlh);
1827 return 0; 1831 return 0;
1828 1832
@@ -2276,16 +2280,18 @@ out:
2276 return -ENOBUFS; 2280 return -ENOBUFS;
2277} 2281}
2278 2282
2279static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) 2283static void __devinet_sysctl_unregister(struct net *net,
2284 struct ipv4_devconf *cnf, int ifindex)
2280{ 2285{
2281 struct devinet_sysctl_table *t = cnf->sysctl; 2286 struct devinet_sysctl_table *t = cnf->sysctl;
2282 2287
2283 if (!t) 2288 if (t) {
2284 return; 2289 cnf->sysctl = NULL;
2290 unregister_net_sysctl_table(t->sysctl_header);
2291 kfree(t);
2292 }
2285 2293
2286 cnf->sysctl = NULL; 2294 inet_netconf_notify_devconf(net, RTM_DELNETCONF, 0, ifindex, NULL);
2287 unregister_net_sysctl_table(t->sysctl_header);
2288 kfree(t);
2289} 2295}
2290 2296
2291static int devinet_sysctl_register(struct in_device *idev) 2297static int devinet_sysctl_register(struct in_device *idev)
@@ -2307,7 +2313,9 @@ static int devinet_sysctl_register(struct in_device *idev)
2307 2313
2308static void devinet_sysctl_unregister(struct in_device *idev) 2314static void devinet_sysctl_unregister(struct in_device *idev)
2309{ 2315{
2310 __devinet_sysctl_unregister(&idev->cnf); 2316 struct net *net = dev_net(idev->dev);
2317
2318 __devinet_sysctl_unregister(net, &idev->cnf, idev->dev->ifindex);
2311 neigh_sysctl_unregister(idev->arp_parms); 2319 neigh_sysctl_unregister(idev->arp_parms);
2312} 2320}
2313 2321
@@ -2382,9 +2390,9 @@ static __net_init int devinet_init_net(struct net *net)
2382 2390
2383#ifdef CONFIG_SYSCTL 2391#ifdef CONFIG_SYSCTL
2384err_reg_ctl: 2392err_reg_ctl:
2385 __devinet_sysctl_unregister(dflt); 2393 __devinet_sysctl_unregister(net, dflt, NETCONFA_IFINDEX_DEFAULT);
2386err_reg_dflt: 2394err_reg_dflt:
2387 __devinet_sysctl_unregister(all); 2395 __devinet_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL);
2388err_reg_all: 2396err_reg_all:
2389 if (tbl != ctl_forward_entry) 2397 if (tbl != ctl_forward_entry)
2390 kfree(tbl); 2398 kfree(tbl);
@@ -2406,8 +2414,10 @@ static __net_exit void devinet_exit_net(struct net *net)
2406 2414
2407 tbl = net->ipv4.forw_hdr->ctl_table_arg; 2415 tbl = net->ipv4.forw_hdr->ctl_table_arg;
2408 unregister_net_sysctl_table(net->ipv4.forw_hdr); 2416 unregister_net_sysctl_table(net->ipv4.forw_hdr);
2409 __devinet_sysctl_unregister(net->ipv4.devconf_dflt); 2417 __devinet_sysctl_unregister(net, net->ipv4.devconf_dflt,
2410 __devinet_sysctl_unregister(net->ipv4.devconf_all); 2418 NETCONFA_IFINDEX_DEFAULT);
2419 __devinet_sysctl_unregister(net, net->ipv4.devconf_all,
2420 NETCONFA_IFINDEX_ALL);
2411 kfree(tbl); 2421 kfree(tbl);
2412#endif 2422#endif
2413 kfree(net->ipv4.devconf_dflt); 2423 kfree(net->ipv4.devconf_dflt);