aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-10-08 05:35:10 -0400
committerPatrick McHardy <kaber@trash.net>2008-10-08 05:35:10 -0400
commit3bb0d1c00f86b13bb184193a8f0189ddd6f0459f (patch)
tree8568fd96a42abf8d64eb83c8afcb1adcdc4bd394 /net
parent84541cc13a3bb31a58c096dde3517461e3ad91c2 (diff)
netfilter: netns nf_conntrack: GRE conntracking in netns
* make keymap list per-netns * per-netns keymal lock (not strictly necessary) * flush keymap at netns stop and module unload. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_pptp.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c97
2 files changed, 75 insertions, 24 deletions
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 5db7df5d19b7..e47d5de41cc2 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -602,7 +602,7 @@ static int __init nf_conntrack_pptp_init(void)
602static void __exit nf_conntrack_pptp_fini(void) 602static void __exit nf_conntrack_pptp_fini(void)
603{ 603{
604 nf_conntrack_helper_unregister(&pptp); 604 nf_conntrack_helper_unregister(&pptp);
605 nf_ct_gre_keymap_flush(); 605 nf_ct_gre_keymap_flush(&init_net);
606} 606}
607 607
608module_init(nf_conntrack_pptp_init); 608module_init(nf_conntrack_pptp_init);
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 5b1273a01fe3..a2cdbcbf64c4 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -29,8 +29,11 @@
29#include <linux/list.h> 29#include <linux/list.h>
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <linux/in.h> 31#include <linux/in.h>
32#include <linux/netdevice.h>
32#include <linux/skbuff.h> 33#include <linux/skbuff.h>
33 34#include <net/dst.h>
35#include <net/net_namespace.h>
36#include <net/netns/generic.h>
34#include <net/netfilter/nf_conntrack_l4proto.h> 37#include <net/netfilter/nf_conntrack_l4proto.h>
35#include <net/netfilter/nf_conntrack_helper.h> 38#include <net/netfilter/nf_conntrack_helper.h>
36#include <net/netfilter/nf_conntrack_core.h> 39#include <net/netfilter/nf_conntrack_core.h>
@@ -40,19 +43,23 @@
40#define GRE_TIMEOUT (30 * HZ) 43#define GRE_TIMEOUT (30 * HZ)
41#define GRE_STREAM_TIMEOUT (180 * HZ) 44#define GRE_STREAM_TIMEOUT (180 * HZ)
42 45
43static DEFINE_RWLOCK(nf_ct_gre_lock); 46static int proto_gre_net_id;
44static LIST_HEAD(gre_keymap_list); 47struct netns_proto_gre {
48 rwlock_t keymap_lock;
49 struct list_head keymap_list;
50};
45 51
46void nf_ct_gre_keymap_flush(void) 52void nf_ct_gre_keymap_flush(struct net *net)
47{ 53{
54 struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
48 struct nf_ct_gre_keymap *km, *tmp; 55 struct nf_ct_gre_keymap *km, *tmp;
49 56
50 write_lock_bh(&nf_ct_gre_lock); 57 write_lock_bh(&net_gre->keymap_lock);
51 list_for_each_entry_safe(km, tmp, &gre_keymap_list, list) { 58 list_for_each_entry_safe(km, tmp, &net_gre->keymap_list, list) {
52 list_del(&km->list); 59 list_del(&km->list);
53 kfree(km); 60 kfree(km);
54 } 61 }
55 write_unlock_bh(&nf_ct_gre_lock); 62 write_unlock_bh(&net_gre->keymap_lock);
56} 63}
57EXPORT_SYMBOL(nf_ct_gre_keymap_flush); 64EXPORT_SYMBOL(nf_ct_gre_keymap_flush);
58 65
@@ -67,19 +74,20 @@ static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
67} 74}
68 75
69/* look up the source key for a given tuple */ 76/* look up the source key for a given tuple */
70static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t) 77static __be16 gre_keymap_lookup(struct net *net, struct nf_conntrack_tuple *t)
71{ 78{
79 struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
72 struct nf_ct_gre_keymap *km; 80 struct nf_ct_gre_keymap *km;
73 __be16 key = 0; 81 __be16 key = 0;
74 82
75 read_lock_bh(&nf_ct_gre_lock); 83 read_lock_bh(&net_gre->keymap_lock);
76 list_for_each_entry(km, &gre_keymap_list, list) { 84 list_for_each_entry(km, &net_gre->keymap_list, list) {
77 if (gre_key_cmpfn(km, t)) { 85 if (gre_key_cmpfn(km, t)) {
78 key = km->tuple.src.u.gre.key; 86 key = km->tuple.src.u.gre.key;
79 break; 87 break;
80 } 88 }
81 } 89 }
82 read_unlock_bh(&nf_ct_gre_lock); 90 read_unlock_bh(&net_gre->keymap_lock);
83 91
84 pr_debug("lookup src key 0x%x for ", key); 92 pr_debug("lookup src key 0x%x for ", key);
85 nf_ct_dump_tuple(t); 93 nf_ct_dump_tuple(t);
@@ -91,20 +99,22 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
91int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, 99int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
92 struct nf_conntrack_tuple *t) 100 struct nf_conntrack_tuple *t)
93{ 101{
102 struct net *net = nf_ct_net(ct);
103 struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
94 struct nf_conn_help *help = nfct_help(ct); 104 struct nf_conn_help *help = nfct_help(ct);
95 struct nf_ct_gre_keymap **kmp, *km; 105 struct nf_ct_gre_keymap **kmp, *km;
96 106
97 kmp = &help->help.ct_pptp_info.keymap[dir]; 107 kmp = &help->help.ct_pptp_info.keymap[dir];
98 if (*kmp) { 108 if (*kmp) {
99 /* check whether it's a retransmission */ 109 /* check whether it's a retransmission */
100 read_lock_bh(&nf_ct_gre_lock); 110 read_lock_bh(&net_gre->keymap_lock);
101 list_for_each_entry(km, &gre_keymap_list, list) { 111 list_for_each_entry(km, &net_gre->keymap_list, list) {
102 if (gre_key_cmpfn(km, t) && km == *kmp) { 112 if (gre_key_cmpfn(km, t) && km == *kmp) {
103 read_unlock_bh(&nf_ct_gre_lock); 113 read_unlock_bh(&net_gre->keymap_lock);
104 return 0; 114 return 0;
105 } 115 }
106 } 116 }
107 read_unlock_bh(&nf_ct_gre_lock); 117 read_unlock_bh(&net_gre->keymap_lock);
108 pr_debug("trying to override keymap_%s for ct %p\n", 118 pr_debug("trying to override keymap_%s for ct %p\n",
109 dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); 119 dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
110 return -EEXIST; 120 return -EEXIST;
@@ -119,9 +129,9 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
119 pr_debug("adding new entry %p: ", km); 129 pr_debug("adding new entry %p: ", km);
120 nf_ct_dump_tuple(&km->tuple); 130 nf_ct_dump_tuple(&km->tuple);
121 131
122 write_lock_bh(&nf_ct_gre_lock); 132 write_lock_bh(&net_gre->keymap_lock);
123 list_add_tail(&km->list, &gre_keymap_list); 133 list_add_tail(&km->list, &net_gre->keymap_list);
124 write_unlock_bh(&nf_ct_gre_lock); 134 write_unlock_bh(&net_gre->keymap_lock);
125 135
126 return 0; 136 return 0;
127} 137}
@@ -130,12 +140,14 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add);
130/* destroy the keymap entries associated with specified master ct */ 140/* destroy the keymap entries associated with specified master ct */
131void nf_ct_gre_keymap_destroy(struct nf_conn *ct) 141void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
132{ 142{
143 struct net *net = nf_ct_net(ct);
144 struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
133 struct nf_conn_help *help = nfct_help(ct); 145 struct nf_conn_help *help = nfct_help(ct);
134 enum ip_conntrack_dir dir; 146 enum ip_conntrack_dir dir;
135 147
136 pr_debug("entering for ct %p\n", ct); 148 pr_debug("entering for ct %p\n", ct);
137 149
138 write_lock_bh(&nf_ct_gre_lock); 150 write_lock_bh(&net_gre->keymap_lock);
139 for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { 151 for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
140 if (help->help.ct_pptp_info.keymap[dir]) { 152 if (help->help.ct_pptp_info.keymap[dir]) {
141 pr_debug("removing %p from list\n", 153 pr_debug("removing %p from list\n",
@@ -145,7 +157,7 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
145 help->help.ct_pptp_info.keymap[dir] = NULL; 157 help->help.ct_pptp_info.keymap[dir] = NULL;
146 } 158 }
147 } 159 }
148 write_unlock_bh(&nf_ct_gre_lock); 160 write_unlock_bh(&net_gre->keymap_lock);
149} 161}
150EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy); 162EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
151 163
@@ -164,6 +176,7 @@ static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple,
164static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, 176static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
165 struct nf_conntrack_tuple *tuple) 177 struct nf_conntrack_tuple *tuple)
166{ 178{
179 struct net *net = dev_net(skb->dev ? skb->dev : skb->dst->dev);
167 const struct gre_hdr_pptp *pgrehdr; 180 const struct gre_hdr_pptp *pgrehdr;
168 struct gre_hdr_pptp _pgrehdr; 181 struct gre_hdr_pptp _pgrehdr;
169 __be16 srckey; 182 __be16 srckey;
@@ -190,7 +203,7 @@ static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
190 } 203 }
191 204
192 tuple->dst.u.gre.key = pgrehdr->call_id; 205 tuple->dst.u.gre.key = pgrehdr->call_id;
193 srckey = gre_keymap_lookup(tuple); 206 srckey = gre_keymap_lookup(net, tuple);
194 tuple->src.u.gre.key = srckey; 207 tuple->src.u.gre.key = srckey;
195 208
196 return true; 209 return true;
@@ -285,15 +298,53 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
285#endif 298#endif
286}; 299};
287 300
301static int proto_gre_net_init(struct net *net)
302{
303 struct netns_proto_gre *net_gre;
304 int rv;
305
306 net_gre = kmalloc(sizeof(struct netns_proto_gre), GFP_KERNEL);
307 if (!net_gre)
308 return -ENOMEM;
309 rwlock_init(&net_gre->keymap_lock);
310 INIT_LIST_HEAD(&net_gre->keymap_list);
311
312 rv = net_assign_generic(net, proto_gre_net_id, net_gre);
313 if (rv < 0)
314 kfree(net_gre);
315 return rv;
316}
317
318static void proto_gre_net_exit(struct net *net)
319{
320 struct netns_proto_gre *net_gre = net_generic(net, proto_gre_net_id);
321
322 nf_ct_gre_keymap_flush(net);
323 kfree(net_gre);
324}
325
326static struct pernet_operations proto_gre_net_ops = {
327 .init = proto_gre_net_init,
328 .exit = proto_gre_net_exit,
329};
330
288static int __init nf_ct_proto_gre_init(void) 331static int __init nf_ct_proto_gre_init(void)
289{ 332{
290 return nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4); 333 int rv;
334
335 rv = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_gre4);
336 if (rv < 0)
337 return rv;
338 rv = register_pernet_gen_device(&proto_gre_net_id, &proto_gre_net_ops);
339 if (rv < 0)
340 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
341 return rv;
291} 342}
292 343
293static void nf_ct_proto_gre_fini(void) 344static void nf_ct_proto_gre_fini(void)
294{ 345{
295 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4); 346 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_gre4);
296 nf_ct_gre_keymap_flush(); 347 unregister_pernet_gen_device(proto_gre_net_id, &proto_gre_net_ops);
297} 348}
298 349
299module_init(nf_ct_proto_gre_init); 350module_init(nf_ct_proto_gre_init);