From patchwork Tue Nov 27 20:27:25 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jozsef Kadlecsik X-Patchwork-Id: 202300 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 6AE902C0094 for ; Wed, 28 Nov 2012 07:37:07 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932101Ab2K0UhE (ORCPT ); Tue, 27 Nov 2012 15:37:04 -0500 Received: from smtp1.kfki.hu ([148.6.0.26]:59937 "EHLO smtp1.kfki.hu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756068Ab2K0UhC (ORCPT ); Tue, 27 Nov 2012 15:37:02 -0500 Received: from localhost (localhost [127.0.0.1]) by smtp1.kfki.hu (Postfix) with ESMTP id 330314D401A; Tue, 27 Nov 2012 21:27:26 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at smtp1.kfki.hu Received: from smtp1.kfki.hu ([127.0.0.1]) by localhost (smtp1.kfki.hu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id LOecz4znnfiN; Tue, 27 Nov 2012 21:27:26 +0100 (CET) Received: from blackhole.kfki.hu (blackhole.kfki.hu [148.6.0.114]) by smtp1.kfki.hu (Postfix) with ESMTP id 14B48188082; Tue, 27 Nov 2012 21:27:26 +0100 (CET) Received: by blackhole.kfki.hu (Postfix, from userid 1000) id C91F0208070; Tue, 27 Nov 2012 21:27:25 +0100 (CET) From: Jozsef Kadlecsik To: netdev@vger.kernel.org Cc: netfilter-devel@vger.kernel.org, Jozsef Kadlecsik Subject: [PATCH 1/1] Introduce notification events for routing changes Date: Tue, 27 Nov 2012 21:27:25 +0100 Message-Id: <1354048045-17846-2-git-send-email-kadlec@blackhole.kfki.hu> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1354048045-17846-1-git-send-email-kadlec@blackhole.kfki.hu> References: <1354048045-17846-1-git-send-email-kadlec@blackhole.kfki.hu> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The netfilter MASQUERADE target does not handle the case when the routing changes and the source address of existing connections become invalid. The problem can be solved if routing modifications create events to which the MASQUERADE target can subscribe and then delete the affected connections. The patch adds the required event support for IPv4/IPv6. Signed-off-by: Jozsef Kadlecsik --- include/linux/inetdevice.h | 2 ++ include/linux/netdevice.h | 1 + include/net/ip6_route.h | 3 ++- net/ipv4/fib_trie.c | 17 +++++++++++++++++ net/ipv6/route.c | 21 +++++++++++++++++++++ 5 files changed, 43 insertions(+), 1 deletions(-) diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index d032780..cf16dab 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -170,6 +170,8 @@ struct in_ifaddr { extern int register_inetaddr_notifier(struct notifier_block *nb); extern int unregister_inetaddr_notifier(struct notifier_block *nb); +extern int register_iproute_notifier(struct notifier_block *nb); +extern int unregister_iproute_notifier(struct notifier_block *nb); extern 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) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e9929ab..cd53253 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1559,6 +1559,7 @@ struct packet_offload { #define NETDEV_RELEASE 0x0012 #define NETDEV_NOTIFY_PEERS 0x0013 #define NETDEV_JOIN 0x0014 +#define NETDEV_ROUTE_CHANGED 0x0015 extern int register_netdevice_notifier(struct notifier_block *nb); extern int unregister_netdevice_notifier(struct notifier_block *nb); diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 27d8318..e3c079d 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -149,7 +149,8 @@ extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); extern void rt6_ifdown(struct net *net, struct net_device *dev); extern void rt6_mtu_change(struct net_device *dev, unsigned int mtu); extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); - +extern int register_ip6route_notifier(struct notifier_block *nb); +extern int unregister_ip6route_notifier(struct notifier_block *nb); /* * Store a destination cache entry in a socket diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 31d771c..ee6f968 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -178,6 +178,8 @@ static const int sync_pages = 128; static struct kmem_cache *fn_alias_kmem __read_mostly; static struct kmem_cache *trie_leaf_kmem __read_mostly; +static BLOCKING_NOTIFIER_HEAD(iproute_chain); + /* * caller must hold RTNL */ @@ -1337,6 +1339,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, &cfg->fc_nlinfo, 0); succeeded: + blocking_notifier_call_chain(&iproute_chain, + NETDEV_ROUTE_CHANGED, fi); return 0; out_free_new_fa: @@ -1713,6 +1717,8 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) if (fa->fa_state & FA_S_ACCESSED) rt_cache_flush(cfg->fc_nlinfo.nl_net); + blocking_notifier_call_chain(&iproute_chain, + NETDEV_ROUTE_CHANGED, fa->fa_info); fib_release_info(fa->fa_info); alias_free_mem_rcu(fa); return 0; @@ -1979,6 +1985,17 @@ void __init fib_trie_init(void) 0, SLAB_PANIC, NULL); } +int register_iproute_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&iproute_chain, nb); +} +EXPORT_SYMBOL(register_iproute_notifier); + +int unregister_iproute_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&iproute_chain, nb); +} +EXPORT_SYMBOL(unregister_iproute_notifier); struct fib_table *fib_trie_table(u32 id) { diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8f124f5..5d086d2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -94,6 +94,8 @@ static struct rt6_info *rt6_get_route_info(struct net *net, const struct in6_addr *gwaddr, int ifindex); #endif +static ATOMIC_NOTIFIER_HEAD(ip6route_chain); + static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) { struct rt6_info *rt = (struct rt6_info *) dst; @@ -818,6 +820,10 @@ static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info) err = fib6_add(&table->tb6_root, rt, info); write_unlock_bh(&table->tb6_lock); + if (!err) + atomic_notifier_call_chain(&ip6route_chain, + NETDEV_ROUTE_CHANGED, rt); + return err; } @@ -1652,6 +1658,9 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) err = fib6_del(rt, info); write_unlock_bh(&table->tb6_lock); + if (!err) + atomic_notifier_call_chain(&ip6route_chain, + NETDEV_ROUTE_CHANGED, rt); out: ip6_rt_put(rt); return err; @@ -2788,6 +2797,18 @@ static int ip6_route_dev_notify(struct notifier_block *this, return NOTIFY_OK; } +int register_ip6route_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&ip6route_chain, nb); +} +EXPORT_SYMBOL(register_ip6route_notifier); + +int unregister_ip6route_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&ip6route_chain, nb); +} +EXPORT_SYMBOL(unregister_ip6route_notifier); + /* * /proc */