aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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/ipv4
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/ipv4')
-rw-r--r--net/ipv4/netfilter.c64
-rw-r--r--net/ipv4/netfilter/ip_queue.c27
2 files changed, 62 insertions, 29 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 6594d1c9697e..ae0779d82c5d 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -1,10 +1,11 @@
1#include <linux/config.h> 1/* IPv4 specific functions of netfilter core */
2 2
3#include <linux/config.h>
3#ifdef CONFIG_NETFILTER 4#ifdef CONFIG_NETFILTER
4 5
5/* IPv4 specific functions of netfilter core */
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/netfilter.h> 7#include <linux/netfilter.h>
8#include <linux/netfilter_ipv4.h>
8 9
9#include <linux/tcp.h> 10#include <linux/tcp.h>
10#include <linux/udp.h> 11#include <linux/udp.h>
@@ -76,4 +77,63 @@ int ip_route_me_harder(struct sk_buff **pskb)
76 return 0; 77 return 0;
77} 78}
78EXPORT_SYMBOL(ip_route_me_harder); 79EXPORT_SYMBOL(ip_route_me_harder);
80
81/*
82 * Extra routing may needed on local out, as the QUEUE target never
83 * returns control to the table.
84 */
85
86struct ip_rt_info {
87 u_int32_t daddr;
88 u_int32_t saddr;
89 u_int8_t tos;
90};
91
92static void queue_save(const struct sk_buff *skb, struct nf_info *info)
93{
94 struct ip_rt_info *rt_info = nf_info_reroute(info);
95
96 if (info->hook == NF_IP_LOCAL_OUT) {
97 const struct iphdr *iph = skb->nh.iph;
98
99 rt_info->tos = iph->tos;
100 rt_info->daddr = iph->daddr;
101 rt_info->saddr = iph->saddr;
102 }
103}
104
105static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
106{
107 const struct ip_rt_info *rt_info = nf_info_reroute(info);
108
109 if (info->hook == NF_IP_LOCAL_OUT) {
110 struct iphdr *iph = (*pskb)->nh.iph;
111
112 if (!(iph->tos == rt_info->tos
113 && iph->daddr == rt_info->daddr
114 && iph->saddr == rt_info->saddr))
115 return ip_route_me_harder(pskb);
116 }
117 return 0;
118}
119
120static struct nf_queue_rerouter ip_reroute = {
121 .rer_size = sizeof(struct ip_rt_info),
122 .save = queue_save,
123 .reroute = queue_reroute,
124};
125
126static int init(void)
127{
128 return nf_register_queue_rerouter(PF_INET, &ip_reroute);
129}
130
131static void fini(void)
132{
133 nf_unregister_queue_rerouter(PF_INET);
134}
135
136module_init(init);
137module_exit(fini);
138
79#endif /* CONFIG_NETFILTER */ 139#endif /* CONFIG_NETFILTER */
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index b237f7fcad92..78892980f42c 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -43,17 +43,10 @@
43#define NET_IPQ_QMAX 2088 43#define NET_IPQ_QMAX 2088
44#define NET_IPQ_QMAX_NAME "ip_queue_maxlen" 44#define NET_IPQ_QMAX_NAME "ip_queue_maxlen"
45 45
46struct ipq_rt_info {
47 __u8 tos;
48 __u32 daddr;
49 __u32 saddr;
50};
51
52struct ipq_queue_entry { 46struct ipq_queue_entry {
53 struct list_head list; 47 struct list_head list;
54 struct nf_info *info; 48 struct nf_info *info;
55 struct sk_buff *skb; 49 struct sk_buff *skb;
56 struct ipq_rt_info rt_info;
57}; 50};
58 51
59typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); 52typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long);
@@ -305,14 +298,6 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
305 entry->info = info; 298 entry->info = info;
306 entry->skb = skb; 299 entry->skb = skb;
307 300
308 if (entry->info->hook == NF_IP_LOCAL_OUT) {
309 struct iphdr *iph = skb->nh.iph;
310
311 entry->rt_info.tos = iph->tos;
312 entry->rt_info.daddr = iph->daddr;
313 entry->rt_info.saddr = iph->saddr;
314 }
315
316 nskb = ipq_build_packet_message(entry, &status); 301 nskb = ipq_build_packet_message(entry, &status);
317 if (nskb == NULL) 302 if (nskb == NULL)
318 goto err_out_free; 303 goto err_out_free;
@@ -393,18 +378,6 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
393 memcpy(e->skb->data, v->payload, v->data_len); 378 memcpy(e->skb->data, v->payload, v->data_len);
394 e->skb->ip_summed = CHECKSUM_NONE; 379 e->skb->ip_summed = CHECKSUM_NONE;
395 380
396 /*
397 * Extra routing may needed on local out, as the QUEUE target never
398 * returns control to the table.
399 */
400 if (e->info->hook == NF_IP_LOCAL_OUT) {
401 struct iphdr *iph = e->skb->nh.iph;
402
403 if (!(iph->tos == e->rt_info.tos
404 && iph->daddr == e->rt_info.daddr
405 && iph->saddr == e->rt_info.saddr))
406 return ip_route_me_harder(&e->skb);
407 }
408 return 0; 381 return 0;
409} 382}
410 383