diff options
author | David Ahern <dsa@cumulusnetworks.com> | 2017-03-28 17:28:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-03-29 01:32:42 -0400 |
commit | b5c9641d3d45e58dbcb35090345f863e5ade718d (patch) | |
tree | 060f381cbc580619836a2742fecb3dd3647bd5ba /net/ipv4/devinet.c | |
parent | 3b0228656dcb07a1c9fc81e8516475c2d7c4300e (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.c | 32 |
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 | ||
1829 | out: | ||
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 | ||
2279 | static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | 2283 | static 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 | ||
2291 | static int devinet_sysctl_register(struct in_device *idev) | 2297 | static int devinet_sysctl_register(struct in_device *idev) |
@@ -2307,7 +2313,9 @@ static int devinet_sysctl_register(struct in_device *idev) | |||
2307 | 2313 | ||
2308 | static void devinet_sysctl_unregister(struct in_device *idev) | 2314 | static 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 |
2384 | err_reg_ctl: | 2392 | err_reg_ctl: |
2385 | __devinet_sysctl_unregister(dflt); | 2393 | __devinet_sysctl_unregister(net, dflt, NETCONFA_IFINDEX_DEFAULT); |
2386 | err_reg_dflt: | 2394 | err_reg_dflt: |
2387 | __devinet_sysctl_unregister(all); | 2395 | __devinet_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL); |
2388 | err_reg_all: | 2396 | err_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); |