151 lines
4.8 KiB
Diff
151 lines
4.8 KiB
Diff
From 665f257e04d6534e2001e3db73c0922a2968b48b Mon Sep 17 00:00:00 2001
|
|
From: Murat Sezgin <msezgin@codeaurora.org>
|
|
Date: Wed, 10 Feb 2016 15:38:12 -0800
|
|
Subject: [PATCH 145/500] net: ipv4/ipv6: Added route table update notify chain
|
|
|
|
Registered modules are notified for the changes in the
|
|
route table.
|
|
|
|
NOTE: This patch is originally suggested by "Jozsef Kadlecsik"
|
|
in the following email chain but never merged to any of the
|
|
kernel versions.
|
|
http://www.spinics.net/lists/netfilter-devel/msg24239.html
|
|
|
|
Cc: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
|
Patch-mainline: netfilter-devel@vger.kernel.org
|
|
|
|
Change-Id: I402710474be0978867dfbbbb8d1a7f8c8f3dab06
|
|
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
|
---
|
|
include/net/ip6_route.h | 3 +++
|
|
include/net/route.h | 3 +++
|
|
net/ipv4/fib_trie.c | 19 +++++++++++++++++++
|
|
net/ipv6/route.c | 22 +++++++++++++++++++++-
|
|
4 files changed, 46 insertions(+), 1 deletion(-)
|
|
|
|
--- a/include/net/ip6_route.h
|
|
+++ b/include/net/ip6_route.h
|
|
@@ -215,6 +215,9 @@ void rt6_multipath_rebalance(struct fib6
|
|
void rt6_uncached_list_add(struct rt6_info *rt);
|
|
void rt6_uncached_list_del(struct rt6_info *rt);
|
|
|
|
+int rt6_register_notifier(struct notifier_block *nb);
|
|
+int rt6_unregister_notifier(struct notifier_block *nb);
|
|
+
|
|
static inline const struct rt6_info *skb_rt6_info(const struct sk_buff *skb)
|
|
{
|
|
const struct dst_entry *dst = skb_dst(skb);
|
|
--- a/include/net/route.h
|
|
+++ b/include/net/route.h
|
|
@@ -238,6 +238,9 @@ struct rtable *rt_dst_alloc(struct net_d
|
|
unsigned int flags, u16 type, bool noxfrm);
|
|
struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt);
|
|
|
|
+int ip_rt_register_notifier(struct notifier_block *nb);
|
|
+int ip_rt_unregister_notifier(struct notifier_block *nb);
|
|
+
|
|
struct in_ifaddr;
|
|
void fib_add_ifaddr(struct in_ifaddr *);
|
|
void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
|
|
--- a/net/ipv4/fib_trie.c
|
|
+++ b/net/ipv4/fib_trie.c
|
|
@@ -1211,6 +1211,9 @@ static bool fib_valid_key_len(u32 key, u
|
|
static void fib_remove_alias(struct trie *t, struct key_vector *tp,
|
|
struct key_vector *l, struct fib_alias *old);
|
|
|
|
+/* Define route change notification chain. */
|
|
+static BLOCKING_NOTIFIER_HEAD(iproute_chain);
|
|
+
|
|
/* Caller must hold RTNL. */
|
|
int fib_table_insert(struct net *net, struct fib_table *tb,
|
|
struct fib_config *cfg, struct netlink_ext_ack *extack)
|
|
@@ -1404,6 +1407,8 @@ int fib_table_insert(struct net *net, st
|
|
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id,
|
|
&cfg->fc_nlinfo, nlflags);
|
|
succeeded:
|
|
+ blocking_notifier_call_chain(&iproute_chain,
|
|
+ RTM_NEWROUTE, fi);
|
|
return 0;
|
|
|
|
out_remove_new_fa:
|
|
@@ -1776,6 +1781,8 @@ int fib_table_delete(struct net *net, st
|
|
if (fa_to_delete->fa_state & FA_S_ACCESSED)
|
|
rt_cache_flush(cfg->fc_nlinfo.nl_net);
|
|
|
|
+ blocking_notifier_call_chain(&iproute_chain,
|
|
+ RTM_DELROUTE, fa_to_delete->fa_info);
|
|
fib_release_info(fa_to_delete->fa_info);
|
|
alias_free_mem_rcu(fa_to_delete);
|
|
return 0;
|
|
@@ -2408,6 +2415,18 @@ void __init fib_trie_init(void)
|
|
0, SLAB_PANIC | SLAB_ACCOUNT, NULL);
|
|
}
|
|
|
|
+int ip_rt_register_notifier(struct notifier_block *nb)
|
|
+{
|
|
+ return blocking_notifier_chain_register(&iproute_chain, nb);
|
|
+}
|
|
+EXPORT_SYMBOL(ip_rt_register_notifier);
|
|
+
|
|
+int ip_rt_unregister_notifier(struct notifier_block *nb)
|
|
+{
|
|
+ return blocking_notifier_chain_unregister(&iproute_chain, nb);
|
|
+}
|
|
+EXPORT_SYMBOL(ip_rt_unregister_notifier);
|
|
+
|
|
struct fib_table *fib_trie_table(u32 id, struct fib_table *alias)
|
|
{
|
|
struct fib_table *tb;
|
|
--- a/net/ipv6/route.c
|
|
+++ b/net/ipv6/route.c
|
|
@@ -198,6 +198,9 @@ static void rt6_uncached_list_flush_dev(
|
|
}
|
|
}
|
|
|
|
+/* Define route change notification chain. */
|
|
+ATOMIC_NOTIFIER_HEAD(ip6route_chain);
|
|
+
|
|
static inline const void *choose_neigh_daddr(const struct in6_addr *p,
|
|
struct sk_buff *skb,
|
|
const void *daddr)
|
|
@@ -3873,6 +3876,9 @@ int ip6_route_add(struct fib6_config *cf
|
|
return PTR_ERR(rt);
|
|
|
|
err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack);
|
|
+ if (!err)
|
|
+ atomic_notifier_call_chain(&ip6route_chain,
|
|
+ RTM_NEWROUTE, rt);
|
|
fib6_info_release(rt);
|
|
|
|
return err;
|
|
@@ -3893,7 +3899,9 @@ static int __ip6_del_rt(struct fib6_info
|
|
spin_lock_bh(&table->tb6_lock);
|
|
err = fib6_del(rt, info);
|
|
spin_unlock_bh(&table->tb6_lock);
|
|
-
|
|
+ if (!err)
|
|
+ atomic_notifier_call_chain(&ip6route_chain,
|
|
+ RTM_DELROUTE, rt);
|
|
out:
|
|
fib6_info_release(rt);
|
|
return err;
|
|
@@ -6372,6 +6380,18 @@ static int ip6_route_dev_notify(struct n
|
|
return NOTIFY_OK;
|
|
}
|
|
|
|
+int rt6_register_notifier(struct notifier_block *nb)
|
|
+{
|
|
+ return atomic_notifier_chain_register(&ip6route_chain, nb);
|
|
+}
|
|
+EXPORT_SYMBOL(rt6_register_notifier);
|
|
+
|
|
+int rt6_unregister_notifier(struct notifier_block *nb)
|
|
+{
|
|
+ return atomic_notifier_chain_unregister(&ip6route_chain, nb);
|
|
+}
|
|
+EXPORT_SYMBOL(rt6_unregister_notifier);
|
|
+
|
|
/*
|
|
* /proc
|
|
*/
|