aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2005-08-09 22:42:34 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:36:19 -0400
commit2cc7d5730957c4a3f3659d17d2ba5e06d5581c1f (patch)
treec2c3d03d8120831d487bb8fcc73e5dcbe13aebea /net/ipv6
parent4fdb3bb723db469717c6d38fda667d8b0fa86ebd (diff)
[NETFILTER]: Move reroute-after-queue code up to the nf_queue layer.
The rerouting functionality is required by the core, therefore it has to be implemented by the core and not in individual queue handlers. Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/af_inet6.c7
-rw-r--r--net/ipv6/netfilter.c62
-rw-r--r--net/ipv6/netfilter/ip6_queue.c24
3 files changed, 69 insertions, 24 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 28d9bcab0970..574047353628 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -44,6 +44,7 @@
44#include <linux/netdevice.h> 44#include <linux/netdevice.h>
45#include <linux/icmpv6.h> 45#include <linux/icmpv6.h>
46#include <linux/smp_lock.h> 46#include <linux/smp_lock.h>
47#include <linux/netfilter_ipv6.h>
47 48
48#include <net/ip.h> 49#include <net/ip.h>
49#include <net/ipv6.h> 50#include <net/ipv6.h>
@@ -757,6 +758,9 @@ static int __init inet6_init(void)
757 err = igmp6_init(&inet6_family_ops); 758 err = igmp6_init(&inet6_family_ops);
758 if (err) 759 if (err)
759 goto igmp_fail; 760 goto igmp_fail;
761 err = ipv6_netfilter_init();
762 if (err)
763 goto netfilter_fail;
760 /* Create /proc/foo6 entries. */ 764 /* Create /proc/foo6 entries. */
761#ifdef CONFIG_PROC_FS 765#ifdef CONFIG_PROC_FS
762 err = -ENOMEM; 766 err = -ENOMEM;
@@ -813,6 +817,8 @@ proc_tcp6_fail:
813 raw6_proc_exit(); 817 raw6_proc_exit();
814proc_raw6_fail: 818proc_raw6_fail:
815#endif 819#endif
820 ipv6_netfilter_fini();
821netfilter_fail:
816 igmp6_cleanup(); 822 igmp6_cleanup();
817igmp_fail: 823igmp_fail:
818 ndisc_cleanup(); 824 ndisc_cleanup();
@@ -852,6 +858,7 @@ static void __exit inet6_exit(void)
852 ip6_route_cleanup(); 858 ip6_route_cleanup();
853 ipv6_packet_cleanup(); 859 ipv6_packet_cleanup();
854 igmp6_cleanup(); 860 igmp6_cleanup();
861 ipv6_netfilter_fini();
855 ndisc_cleanup(); 862 ndisc_cleanup();
856 icmpv6_cleanup(); 863 icmpv6_cleanup();
857#ifdef CONFIG_SYSCTL 864#ifdef CONFIG_SYSCTL
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 5656d0959aba..c8daef97cf56 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -5,6 +5,8 @@
5 5
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/ipv6.h> 7#include <linux/ipv6.h>
8#include <linux/netfilter.h>
9#include <linux/netfilter_ipv6.h>
8#include <net/dst.h> 10#include <net/dst.h>
9#include <net/ipv6.h> 11#include <net/ipv6.h>
10#include <net/ip6_route.h> 12#include <net/ip6_route.h>
@@ -40,4 +42,64 @@ int ip6_route_me_harder(struct sk_buff *skb)
40} 42}
41EXPORT_SYMBOL(ip6_route_me_harder); 43EXPORT_SYMBOL(ip6_route_me_harder);
42 44
45/*
46 * Extra routing may needed on local out, as the QUEUE target never
47 * returns control to the table.
48 */
49
50struct ip6_rt_info {
51 struct in6_addr daddr;
52 struct in6_addr saddr;
53};
54
55static void save(const struct sk_buff *skb, struct nf_info *info)
56{
57 struct ip6_rt_info *rt_info = nf_info_reroute(info);
58
59 if (info->hook == NF_IP6_LOCAL_OUT) {
60 struct ipv6hdr *iph = skb->nh.ipv6h;
61
62 rt_info->daddr = iph->daddr;
63 rt_info->saddr = iph->saddr;
64 }
65}
66
67static int reroute(struct sk_buff **pskb, const struct nf_info *info)
68{
69 struct ip6_rt_info *rt_info = nf_info_reroute(info);
70
71 if (info->hook == NF_IP6_LOCAL_OUT) {
72 struct ipv6hdr *iph = (*pskb)->nh.ipv6h;
73 if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
74 !ipv6_addr_equal(&iph->saddr, &rt_info->saddr))
75 return ip6_route_me_harder(*pskb);
76 }
77 return 0;
78}
79
80static struct nf_queue_rerouter ip6_reroute = {
81 .rer_size = sizeof(struct ip6_rt_info),
82 .save = &save,
83 .reroute = &reroute,
84};
85
86int __init ipv6_netfilter_init(void)
87{
88 return nf_register_queue_rerouter(PF_INET6, &ip6_reroute);
89}
90
91void ipv6_netfilter_fini(void)
92{
93 nf_unregister_queue_rerouter(PF_INET6);
94}
95
96#else /* CONFIG_NETFILTER */
97int __init ipv6_netfilter_init(void)
98{
99 return 0;
100}
101
102void ipv6_netfilter_fini(void)
103{
104}
43#endif /* CONFIG_NETFILTER */ 105#endif /* CONFIG_NETFILTER */
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 1c3d247a22cc..c45d8f8815de 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -47,16 +47,10 @@
47#define NET_IPQ_QMAX 2088 47#define NET_IPQ_QMAX 2088
48#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" 48#define NET_IPQ_QMAX_NAME "ip6_queue_maxlen"
49 49
50struct ipq_rt_info {
51 struct in6_addr daddr;
52 struct in6_addr saddr;
53};
54
55struct ipq_queue_entry { 50struct ipq_queue_entry {
56 struct list_head list; 51 struct list_head list;
57 struct nf_info *info; 52 struct nf_info *info;
58 struct sk_buff *skb; 53 struct sk_buff *skb;
59 struct ipq_rt_info rt_info;
60}; 54};
61 55
62typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); 56typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
@@ -302,13 +296,6 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
302 entry->info = info; 296 entry->info = info;
303 entry->skb = skb; 297 entry->skb = skb;
304 298
305 if (entry->info->hook == NF_IP_LOCAL_OUT) {
306 struct ipv6hdr *iph = skb->nh.ipv6h;
307
308 entry->rt_info.daddr = iph->daddr;
309 entry->rt_info.saddr = iph->saddr;
310 }
311
312 nskb = ipq_build_packet_message(entry, &status); 299 nskb = ipq_build_packet_message(entry, &status);
313 if (nskb == NULL) 300 if (nskb == NULL)
314 goto err_out_free; 301 goto err_out_free;
@@ -389,17 +376,6 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
389 memcpy(e->skb->data, v->payload, v->data_len); 376 memcpy(e->skb->data, v->payload, v->data_len);
390 e->skb->ip_summed = CHECKSUM_NONE; 377 e->skb->ip_summed = CHECKSUM_NONE;
391 378
392 /*
393 * Extra routing may needed on local out, as the QUEUE target never
394 * returns control to the table.
395 * Not a nice way to cmp, but works
396 */
397 if (e->info->hook == NF_IP_LOCAL_OUT) {
398 struct ipv6hdr *iph = e->skb->nh.ipv6h;
399 if (!ipv6_addr_equal(&iph->daddr, &e->rt_info.daddr) ||
400 !ipv6_addr_equal(&iph->saddr, &e->rt_info.saddr))
401 return ip6_route_me_harder(e->skb);
402 }
403 return 0; 379 return 0;
404} 380}
405 381