aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/netfilter/ebt_ulog.c125
1 files changed, 88 insertions, 37 deletions
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 442b0321acb9..0ddd612787e3 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -41,6 +41,7 @@
41#include <linux/netfilter_bridge/ebtables.h> 41#include <linux/netfilter_bridge/ebtables.h>
42#include <linux/netfilter_bridge/ebt_ulog.h> 42#include <linux/netfilter_bridge/ebt_ulog.h>
43#include <net/netfilter/nf_log.h> 43#include <net/netfilter/nf_log.h>
44#include <net/netns/generic.h>
44#include <net/sock.h> 45#include <net/sock.h>
45#include "../br_private.h" 46#include "../br_private.h"
46 47
@@ -62,13 +63,22 @@ typedef struct {
62 spinlock_t lock; /* the per-queue lock */ 63 spinlock_t lock; /* the per-queue lock */
63} ebt_ulog_buff_t; 64} ebt_ulog_buff_t;
64 65
65static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; 66static int ebt_ulog_net_id __read_mostly;
66static struct sock *ebtulognl; 67struct ebt_ulog_net {
68 unsigned int nlgroup[EBT_ULOG_MAXNLGROUPS];
69 ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS];
70 struct sock *ebtulognl;
71};
72
73static struct ebt_ulog_net *ebt_ulog_pernet(struct net *net)
74{
75 return net_generic(net, ebt_ulog_net_id);
76}
67 77
68/* send one ulog_buff_t to userspace */ 78/* send one ulog_buff_t to userspace */
69static void ulog_send(unsigned int nlgroup) 79static void ulog_send(struct ebt_ulog_net *ebt, unsigned int nlgroup)
70{ 80{
71 ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup]; 81 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[nlgroup];
72 82
73 del_timer(&ub->timer); 83 del_timer(&ub->timer);
74 84
@@ -80,7 +90,7 @@ static void ulog_send(unsigned int nlgroup)
80 ub->lastnlh->nlmsg_type = NLMSG_DONE; 90 ub->lastnlh->nlmsg_type = NLMSG_DONE;
81 91
82 NETLINK_CB(ub->skb).dst_group = nlgroup + 1; 92 NETLINK_CB(ub->skb).dst_group = nlgroup + 1;
83 netlink_broadcast(ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC); 93 netlink_broadcast(ebt->ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC);
84 94
85 ub->qlen = 0; 95 ub->qlen = 0;
86 ub->skb = NULL; 96 ub->skb = NULL;
@@ -89,10 +99,15 @@ static void ulog_send(unsigned int nlgroup)
89/* timer function to flush queue in flushtimeout time */ 99/* timer function to flush queue in flushtimeout time */
90static void ulog_timer(unsigned long data) 100static void ulog_timer(unsigned long data)
91{ 101{
92 spin_lock_bh(&ulog_buffers[data].lock); 102 struct ebt_ulog_net *ebt = container_of((void *)data,
93 if (ulog_buffers[data].skb) 103 struct ebt_ulog_net,
94 ulog_send(data); 104 nlgroup[*(unsigned int *)data]);
95 spin_unlock_bh(&ulog_buffers[data].lock); 105
106 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[*(unsigned int *)data];
107 spin_lock_bh(&ub->lock);
108 if (ub->skb)
109 ulog_send(ebt, *(unsigned int *)data);
110 spin_unlock_bh(&ub->lock);
96} 111}
97 112
98static struct sk_buff *ulog_alloc_skb(unsigned int size) 113static struct sk_buff *ulog_alloc_skb(unsigned int size)
@@ -123,8 +138,10 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
123 ebt_ulog_packet_msg_t *pm; 138 ebt_ulog_packet_msg_t *pm;
124 size_t size, copy_len; 139 size_t size, copy_len;
125 struct nlmsghdr *nlh; 140 struct nlmsghdr *nlh;
141 struct net *net = dev_net(in ? in : out);
142 struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
126 unsigned int group = uloginfo->nlgroup; 143 unsigned int group = uloginfo->nlgroup;
127 ebt_ulog_buff_t *ub = &ulog_buffers[group]; 144 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group];
128 spinlock_t *lock = &ub->lock; 145 spinlock_t *lock = &ub->lock;
129 ktime_t kt; 146 ktime_t kt;
130 147
@@ -146,7 +163,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
146 if (!(ub->skb = ulog_alloc_skb(size))) 163 if (!(ub->skb = ulog_alloc_skb(size)))
147 goto unlock; 164 goto unlock;
148 } else if (size > skb_tailroom(ub->skb)) { 165 } else if (size > skb_tailroom(ub->skb)) {
149 ulog_send(group); 166 ulog_send(ebt, group);
150 167
151 if (!(ub->skb = ulog_alloc_skb(size))) 168 if (!(ub->skb = ulog_alloc_skb(size)))
152 goto unlock; 169 goto unlock;
@@ -205,7 +222,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
205 ub->lastnlh = nlh; 222 ub->lastnlh = nlh;
206 223
207 if (ub->qlen >= uloginfo->qthreshold) 224 if (ub->qlen >= uloginfo->qthreshold)
208 ulog_send(group); 225 ulog_send(ebt, group);
209 else if (!timer_pending(&ub->timer)) { 226 else if (!timer_pending(&ub->timer)) {
210 ub->timer.expires = jiffies + flushtimeout * HZ / 100; 227 ub->timer.expires = jiffies + flushtimeout * HZ / 100;
211 add_timer(&ub->timer); 228 add_timer(&ub->timer);
@@ -277,47 +294,39 @@ static struct nf_logger ebt_ulog_logger __read_mostly = {
277 .me = THIS_MODULE, 294 .me = THIS_MODULE,
278}; 295};
279 296
280static int __init ebt_ulog_init(void) 297static int __net_init ebt_ulog_net_init(struct net *net)
281{ 298{
282 int ret;
283 int i; 299 int i;
300 struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
301
284 struct netlink_kernel_cfg cfg = { 302 struct netlink_kernel_cfg cfg = {
285 .groups = EBT_ULOG_MAXNLGROUPS, 303 .groups = EBT_ULOG_MAXNLGROUPS,
286 }; 304 };
287 305
288 if (nlbufsiz >= 128*1024) {
289 pr_warning("Netlink buffer has to be <= 128kB,"
290 " please try a smaller nlbufsiz parameter.\n");
291 return -EINVAL;
292 }
293
294 /* initialize ulog_buffers */ 306 /* initialize ulog_buffers */
295 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { 307 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
296 setup_timer(&ulog_buffers[i].timer, ulog_timer, i); 308 ebt->nlgroup[i] = i;
297 spin_lock_init(&ulog_buffers[i].lock); 309 setup_timer(&ebt->ulog_buffers[i].timer, ulog_timer,
310 (unsigned long)&ebt->nlgroup[i]);
311 spin_lock_init(&ebt->ulog_buffers[i].lock);
298 } 312 }
299 313
300 ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, &cfg); 314 ebt->ebtulognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg);
301 if (!ebtulognl) 315 if (!ebt->ebtulognl)
302 ret = -ENOMEM; 316 return -ENOMEM;
303 else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0)
304 netlink_kernel_release(ebtulognl);
305 317
306 if (ret == 0) 318 nf_log_set(net, NFPROTO_BRIDGE, &ebt_ulog_logger);
307 nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); 319 return 0;
308
309 return ret;
310} 320}
311 321
312static void __exit ebt_ulog_fini(void) 322static void __net_exit ebt_ulog_net_fini(struct net *net)
313{ 323{
314 ebt_ulog_buff_t *ub;
315 int i; 324 int i;
325 struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
316 326
317 nf_log_unregister(&ebt_ulog_logger); 327 nf_log_unset(net, &ebt_ulog_logger);
318 xt_unregister_target(&ebt_ulog_tg_reg);
319 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { 328 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
320 ub = &ulog_buffers[i]; 329 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[i];
321 del_timer(&ub->timer); 330 del_timer(&ub->timer);
322 331
323 if (ub->skb) { 332 if (ub->skb) {
@@ -325,7 +334,49 @@ static void __exit ebt_ulog_fini(void)
325 ub->skb = NULL; 334 ub->skb = NULL;
326 } 335 }
327 } 336 }
328 netlink_kernel_release(ebtulognl); 337 netlink_kernel_release(ebt->ebtulognl);
338}
339
340static struct pernet_operations ebt_ulog_net_ops = {
341 .init = ebt_ulog_net_init,
342 .exit = ebt_ulog_net_fini,
343 .id = &ebt_ulog_net_id,
344 .size = sizeof(struct ebt_ulog_net),
345};
346
347static int __init ebt_ulog_init(void)
348{
349 int ret;
350
351 if (nlbufsiz >= 128*1024) {
352 pr_warn("Netlink buffer has to be <= 128kB,"
353 "please try a smaller nlbufsiz parameter.\n");
354 return -EINVAL;
355 }
356
357 ret = register_pernet_subsys(&ebt_ulog_net_ops);
358 if (ret)
359 goto out_pernet;
360
361 ret = xt_register_target(&ebt_ulog_tg_reg);
362 if (ret)
363 goto out_target;
364
365 nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger);
366
367 return 0;
368
369out_target:
370 unregister_pernet_subsys(&ebt_ulog_net_ops);
371out_pernet:
372 return ret;
373}
374
375static void __exit ebt_ulog_fini(void)
376{
377 nf_log_unregister(&ebt_ulog_logger);
378 xt_unregister_target(&ebt_ulog_tg_reg);
379 unregister_pernet_subsys(&ebt_ulog_net_ops);
329} 380}
330 381
331module_init(ebt_ulog_init); 382module_init(ebt_ulog_init);