aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-04-06 17:18:09 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-04-10 01:25:40 -0400
commitbce8032ef3cc58170ab3550e9e271dba7b4c4764 (patch)
tree13dbdf12a6c567c3292daad4604eb55f7abd167e
parenta0aed49bdb2bbb4234789f241cffb607fd2e213d (diff)
[NETFILTER]: Introduce infrastructure for address family specific operations
Change the queue rerouter intrastructure to a generic usable infrastructure for address family specific operations as a base for some cleanups. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter.h23
-rw-r--r--net/ipv4/netfilter.c17
-rw-r--r--net/ipv6/netfilter.c17
-rw-r--r--net/netfilter/core.c23
-rw-r--r--net/netfilter/nf_queue.c49
5 files changed, 70 insertions, 59 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 5aa931607923..6ee168c4978a 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -283,16 +283,25 @@ extern void nf_invalidate_cache(int pf);
283 Returns true or false. */ 283 Returns true or false. */
284extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); 284extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len);
285 285
286struct nf_queue_rerouter { 286struct nf_afinfo {
287 void (*save)(const struct sk_buff *skb, struct nf_info *info); 287 unsigned short family;
288 int (*reroute)(struct sk_buff **skb, const struct nf_info *info); 288 void (*saveroute)(const struct sk_buff *skb,
289 int rer_size; 289 struct nf_info *info);
290 int (*reroute)(struct sk_buff **skb,
291 const struct nf_info *info);
292 int route_key_size;
290}; 293};
291 294
292#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info)) 295extern struct nf_afinfo *nf_afinfo[];
296static inline struct nf_afinfo *nf_get_afinfo(unsigned short family)
297{
298 return rcu_dereference(nf_afinfo[family]);
299}
293 300
294extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer); 301extern int nf_register_afinfo(struct nf_afinfo *afinfo);
295extern int nf_unregister_queue_rerouter(int pf); 302extern void nf_unregister_afinfo(struct nf_afinfo *afinfo);
303
304#define nf_info_reroute(x) ((void *)x + sizeof(struct nf_info))
296 305
297#include <net/flow.h> 306#include <net/flow.h>
298extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); 307extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b5ad9ac2fbcc..b25339c11ea0 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -133,7 +133,7 @@ struct ip_rt_info {
133 u_int8_t tos; 133 u_int8_t tos;
134}; 134};
135 135
136static void queue_save(const struct sk_buff *skb, struct nf_info *info) 136static void nf_ip_saveroute(const struct sk_buff *skb, struct nf_info *info)
137{ 137{
138 struct ip_rt_info *rt_info = nf_info_reroute(info); 138 struct ip_rt_info *rt_info = nf_info_reroute(info);
139 139
@@ -146,7 +146,7 @@ static void queue_save(const struct sk_buff *skb, struct nf_info *info)
146 } 146 }
147} 147}
148 148
149static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info) 149static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
150{ 150{
151 const struct ip_rt_info *rt_info = nf_info_reroute(info); 151 const struct ip_rt_info *rt_info = nf_info_reroute(info);
152 152
@@ -161,20 +161,21 @@ static int queue_reroute(struct sk_buff **pskb, const struct nf_info *info)
161 return 0; 161 return 0;
162} 162}
163 163
164static struct nf_queue_rerouter ip_reroute = { 164static struct nf_afinfo nf_ip_afinfo = {
165 .rer_size = sizeof(struct ip_rt_info), 165 .family = AF_INET,
166 .save = queue_save, 166 .saveroute = nf_ip_saveroute,
167 .reroute = queue_reroute, 167 .reroute = nf_ip_reroute,
168 .route_key_size = sizeof(struct ip_rt_info),
168}; 169};
169 170
170static int ipv4_netfilter_init(void) 171static int ipv4_netfilter_init(void)
171{ 172{
172 return nf_register_queue_rerouter(PF_INET, &ip_reroute); 173 return nf_register_afinfo(&nf_ip_afinfo);
173} 174}
174 175
175static void ipv4_netfilter_fini(void) 176static void ipv4_netfilter_fini(void)
176{ 177{
177 nf_unregister_queue_rerouter(PF_INET); 178 nf_unregister_afinfo(&nf_ip_afinfo);
178} 179}
179 180
180module_init(ipv4_netfilter_init); 181module_init(ipv4_netfilter_init);
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index d750cfc019dc..f514a0113b9f 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -54,7 +54,7 @@ struct ip6_rt_info {
54 struct in6_addr saddr; 54 struct in6_addr saddr;
55}; 55};
56 56
57static void save(const struct sk_buff *skb, struct nf_info *info) 57static void nf_ip6_saveroute(const struct sk_buff *skb, struct nf_info *info)
58{ 58{
59 struct ip6_rt_info *rt_info = nf_info_reroute(info); 59 struct ip6_rt_info *rt_info = nf_info_reroute(info);
60 60
@@ -66,7 +66,7 @@ static void save(const struct sk_buff *skb, struct nf_info *info)
66 } 66 }
67} 67}
68 68
69static int reroute(struct sk_buff **pskb, const struct nf_info *info) 69static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info)
70{ 70{
71 struct ip6_rt_info *rt_info = nf_info_reroute(info); 71 struct ip6_rt_info *rt_info = nf_info_reroute(info);
72 72
@@ -79,15 +79,16 @@ static int reroute(struct sk_buff **pskb, const struct nf_info *info)
79 return 0; 79 return 0;
80} 80}
81 81
82static struct nf_queue_rerouter ip6_reroute = { 82static struct nf_afinfo nf_ip6_afinfo = {
83 .rer_size = sizeof(struct ip6_rt_info), 83 .family = AF_INET6,
84 .save = &save, 84 .saveroute = nf_ip6_saveroute,
85 .reroute = &reroute, 85 .reroute = nf_ip6_reroute,
86 .route_key_size = sizeof(struct ip6_rt_info),
86}; 87};
87 88
88int __init ipv6_netfilter_init(void) 89int __init ipv6_netfilter_init(void)
89{ 90{
90 return nf_register_queue_rerouter(PF_INET6, &ip6_reroute); 91 return nf_register_afinfo(&nf_ip6_afinfo);
91} 92}
92 93
93/* This can be called from inet6_init() on errors, so it cannot 94/* This can be called from inet6_init() on errors, so it cannot
@@ -95,5 +96,5 @@ int __init ipv6_netfilter_init(void)
95 */ 96 */
96void ipv6_netfilter_fini(void) 97void ipv6_netfilter_fini(void)
97{ 98{
98 nf_unregister_queue_rerouter(PF_INET6); 99 nf_unregister_afinfo(&nf_ip6_afinfo);
99} 100}
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 645d62105571..8455a32ea5c4 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -27,6 +27,29 @@
27 27
28#include "nf_internals.h" 28#include "nf_internals.h"
29 29
30static DEFINE_SPINLOCK(afinfo_lock);
31
32struct nf_afinfo *nf_afinfo[NPROTO];
33EXPORT_SYMBOL(nf_afinfo);
34
35int nf_register_afinfo(struct nf_afinfo *afinfo)
36{
37 spin_lock(&afinfo_lock);
38 rcu_assign_pointer(nf_afinfo[afinfo->family], afinfo);
39 spin_unlock(&afinfo_lock);
40 return 0;
41}
42EXPORT_SYMBOL_GPL(nf_register_afinfo);
43
44void nf_unregister_afinfo(struct nf_afinfo *afinfo)
45{
46 spin_lock(&afinfo_lock);
47 rcu_assign_pointer(nf_afinfo[afinfo->family], NULL);
48 spin_unlock(&afinfo_lock);
49 synchronize_rcu();
50}
51EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
52
30/* In this code, we can be waiting indefinitely for userspace to 53/* In this code, we can be waiting indefinitely for userspace to
31 * service a packet if a hook returns NF_QUEUE. We could keep a count 54 * service a packet if a hook returns NF_QUEUE. We could keep a count
32 * of skbuffs queued for userspace, and not deregister a hook unless 55 * of skbuffs queued for userspace, and not deregister a hook unless
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index d9f0d7ef103b..ee8f70889f47 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,6 @@
17 * for queueing and must reinject all packets it receives, no matter what. 17 * for queueing and must reinject all packets it receives, no matter what.
18 */ 18 */
19static struct nf_queue_handler *queue_handler[NPROTO]; 19static struct nf_queue_handler *queue_handler[NPROTO];
20static struct nf_queue_rerouter *queue_rerouter[NPROTO];
21 20
22static DEFINE_RWLOCK(queue_handler_lock); 21static DEFINE_RWLOCK(queue_handler_lock);
23 22
@@ -59,32 +58,6 @@ int nf_unregister_queue_handler(int pf)
59} 58}
60EXPORT_SYMBOL(nf_unregister_queue_handler); 59EXPORT_SYMBOL(nf_unregister_queue_handler);
61 60
62int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer)
63{
64 if (pf >= NPROTO)
65 return -EINVAL;
66
67 write_lock_bh(&queue_handler_lock);
68 rcu_assign_pointer(queue_rerouter[pf], rer);
69 write_unlock_bh(&queue_handler_lock);
70
71 return 0;
72}
73EXPORT_SYMBOL_GPL(nf_register_queue_rerouter);
74
75int nf_unregister_queue_rerouter(int pf)
76{
77 if (pf >= NPROTO)
78 return -EINVAL;
79
80 write_lock_bh(&queue_handler_lock);
81 rcu_assign_pointer(queue_rerouter[pf], NULL);
82 write_unlock_bh(&queue_handler_lock);
83 synchronize_rcu();
84 return 0;
85}
86EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
87
88void nf_unregister_queue_handlers(struct nf_queue_handler *qh) 61void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
89{ 62{
90 int pf; 63 int pf;
@@ -116,7 +89,7 @@ int nf_queue(struct sk_buff **skb,
116 struct net_device *physindev = NULL; 89 struct net_device *physindev = NULL;
117 struct net_device *physoutdev = NULL; 90 struct net_device *physoutdev = NULL;
118#endif 91#endif
119 struct nf_queue_rerouter *rerouter; 92 struct nf_afinfo *afinfo;
120 93
121 /* QUEUE == DROP if noone is waiting, to be safe. */ 94 /* QUEUE == DROP if noone is waiting, to be safe. */
122 read_lock(&queue_handler_lock); 95 read_lock(&queue_handler_lock);
@@ -126,7 +99,14 @@ int nf_queue(struct sk_buff **skb,
126 return 1; 99 return 1;
127 } 100 }
128 101
129 info = kmalloc(sizeof(*info)+queue_rerouter[pf]->rer_size, GFP_ATOMIC); 102 afinfo = nf_get_afinfo(pf);
103 if (!afinfo) {
104 read_unlock(&queue_handler_lock);
105 kfree_skb(*skb);
106 return 1;
107 }
108
109 info = kmalloc(sizeof(*info) + afinfo->route_key_size, GFP_ATOMIC);
130 if (!info) { 110 if (!info) {
131 if (net_ratelimit()) 111 if (net_ratelimit())
132 printk(KERN_ERR "OOM queueing packet %p\n", 112 printk(KERN_ERR "OOM queueing packet %p\n",
@@ -158,10 +138,7 @@ int nf_queue(struct sk_buff **skb,
158 if (physoutdev) dev_hold(physoutdev); 138 if (physoutdev) dev_hold(physoutdev);
159 } 139 }
160#endif 140#endif
161 rerouter = rcu_dereference(queue_rerouter[pf]); 141 afinfo->saveroute(*skb, info);
162 if (rerouter)
163 rerouter->save(*skb, info);
164
165 status = queue_handler[pf]->outfn(*skb, info, queuenum, 142 status = queue_handler[pf]->outfn(*skb, info, queuenum,
166 queue_handler[pf]->data); 143 queue_handler[pf]->data);
167 144
@@ -190,7 +167,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
190{ 167{
191 struct list_head *elem = &info->elem->list; 168 struct list_head *elem = &info->elem->list;
192 struct list_head *i; 169 struct list_head *i;
193 struct nf_queue_rerouter *rerouter; 170 struct nf_afinfo *afinfo;
194 171
195 rcu_read_lock(); 172 rcu_read_lock();
196 173
@@ -228,8 +205,8 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
228 } 205 }
229 206
230 if (verdict == NF_ACCEPT) { 207 if (verdict == NF_ACCEPT) {
231 rerouter = rcu_dereference(queue_rerouter[info->pf]); 208 afinfo = nf_get_afinfo(info->pf);
232 if (rerouter && rerouter->reroute(&skb, info) < 0) 209 if (!afinfo || afinfo->reroute(&skb, info) < 0)
233 verdict = NF_DROP; 210 verdict = NF_DROP;
234 } 211 }
235 212