]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - net/netfilter/nfnetlink_acct.c
Merge tag 'random_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / net / netfilter / nfnetlink_acct.c
1 /*
2  * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org>
3  * (C) 2011 Intra2net AG <http://www.intra2net.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation (or any later at your option).
8  */
9 #include <linux/init.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/skbuff.h>
13 #include <linux/atomic.h>
14 #include <linux/refcount.h>
15 #include <linux/netlink.h>
16 #include <linux/rculist.h>
17 #include <linux/slab.h>
18 #include <linux/types.h>
19 #include <linux/errno.h>
20 #include <net/netlink.h>
21 #include <net/sock.h>
22
23 #include <linux/netfilter.h>
24 #include <linux/netfilter/nfnetlink.h>
25 #include <linux/netfilter/nfnetlink_acct.h>
26
27 MODULE_LICENSE("GPL");
28 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
29 MODULE_DESCRIPTION("nfacct: Extended Netfilter accounting infrastructure");
30
31 struct nf_acct {
32         atomic64_t              pkts;
33         atomic64_t              bytes;
34         unsigned long           flags;
35         struct list_head        head;
36         refcount_t              refcnt;
37         char                    name[NFACCT_NAME_MAX];
38         struct rcu_head         rcu_head;
39         char                    data[0];
40 };
41
42 struct nfacct_filter {
43         u32 value;
44         u32 mask;
45 };
46
47 #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES)
48 #define NFACCT_OVERQUOTA_BIT    2       /* NFACCT_F_OVERQUOTA */
49
50 static int nfnl_acct_new(struct net *net, struct sock *nfnl,
51                          struct sk_buff *skb, const struct nlmsghdr *nlh,
52                          const struct nlattr * const tb[])
53 {
54         struct nf_acct *nfacct, *matching = NULL;
55         char *acct_name;
56         unsigned int size = 0;
57         u32 flags = 0;
58
59         if (!tb[NFACCT_NAME])
60                 return -EINVAL;
61
62         acct_name = nla_data(tb[NFACCT_NAME]);
63         if (strlen(acct_name) == 0)
64                 return -EINVAL;
65
66         list_for_each_entry(nfacct, &net->nfnl_acct_list, head) {
67                 if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
68                         continue;
69
70                 if (nlh->nlmsg_flags & NLM_F_EXCL)
71                         return -EEXIST;
72
73                 matching = nfacct;
74                 break;
75         }
76
77         if (matching) {
78                 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
79                         /* reset counters if you request a replacement. */
80                         atomic64_set(&matching->pkts, 0);
81                         atomic64_set(&matching->bytes, 0);
82                         smp_mb__before_atomic();
83                         /* reset overquota flag if quota is enabled. */
84                         if ((matching->flags & NFACCT_F_QUOTA))
85                                 clear_bit(NFACCT_OVERQUOTA_BIT,
86                                           &matching->flags);
87                         return 0;
88                 }
89                 return -EBUSY;
90         }
91
92         if (tb[NFACCT_FLAGS]) {
93                 flags = ntohl(nla_get_be32(tb[NFACCT_FLAGS]));
94                 if (flags & ~NFACCT_F_QUOTA)
95                         return -EOPNOTSUPP;
96                 if ((flags & NFACCT_F_QUOTA) == NFACCT_F_QUOTA)
97                         return -EINVAL;
98                 if (flags & NFACCT_F_OVERQUOTA)
99                         return -EINVAL;
100                 if ((flags & NFACCT_F_QUOTA) && !tb[NFACCT_QUOTA])
101                         return -EINVAL;
102
103                 size += sizeof(u64);
104         }
105
106         nfacct = kzalloc(sizeof(struct nf_acct) + size, GFP_KERNEL);
107         if (nfacct == NULL)
108                 return -ENOMEM;
109
110         if (flags & NFACCT_F_QUOTA) {
111                 u64 *quota = (u64 *)nfacct->data;
112
113                 *quota = be64_to_cpu(nla_get_be64(tb[NFACCT_QUOTA]));
114                 nfacct->flags = flags;
115         }
116
117         strncpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX);
118
119         if (tb[NFACCT_BYTES]) {
120                 atomic64_set(&nfacct->bytes,
121                              be64_to_cpu(nla_get_be64(tb[NFACCT_BYTES])));
122         }
123         if (tb[NFACCT_PKTS]) {
124                 atomic64_set(&nfacct->pkts,
125                              be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS])));
126         }
127         refcount_set(&nfacct->refcnt, 1);
128         list_add_tail_rcu(&nfacct->head, &net->nfnl_acct_list);
129         return 0;
130 }
131
132 static int
133 nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
134                    int event, struct nf_acct *acct)
135 {
136         struct nlmsghdr *nlh;
137         struct nfgenmsg *nfmsg;
138         unsigned int flags = portid ? NLM_F_MULTI : 0;
139         u64 pkts, bytes;
140         u32 old_flags;
141
142         event = nfnl_msg_type(NFNL_SUBSYS_ACCT, event);
143         nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
144         if (nlh == NULL)
145                 goto nlmsg_failure;
146
147         nfmsg = nlmsg_data(nlh);
148         nfmsg->nfgen_family = AF_UNSPEC;
149         nfmsg->version = NFNETLINK_V0;
150         nfmsg->res_id = 0;
151
152         if (nla_put_string(skb, NFACCT_NAME, acct->name))
153                 goto nla_put_failure;
154
155         old_flags = acct->flags;
156         if (type == NFNL_MSG_ACCT_GET_CTRZERO) {
157                 pkts = atomic64_xchg(&acct->pkts, 0);
158                 bytes = atomic64_xchg(&acct->bytes, 0);
159                 smp_mb__before_atomic();
160                 if (acct->flags & NFACCT_F_QUOTA)
161                         clear_bit(NFACCT_OVERQUOTA_BIT, &acct->flags);
162         } else {
163                 pkts = atomic64_read(&acct->pkts);
164                 bytes = atomic64_read(&acct->bytes);
165         }
166         if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts),
167                          NFACCT_PAD) ||
168             nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes),
169                          NFACCT_PAD) ||
170             nla_put_be32(skb, NFACCT_USE, htonl(refcount_read(&acct->refcnt))))
171                 goto nla_put_failure;
172         if (acct->flags & NFACCT_F_QUOTA) {
173                 u64 *quota = (u64 *)acct->data;
174
175                 if (nla_put_be32(skb, NFACCT_FLAGS, htonl(old_flags)) ||
176                     nla_put_be64(skb, NFACCT_QUOTA, cpu_to_be64(*quota),
177                                  NFACCT_PAD))
178                         goto nla_put_failure;
179         }
180         nlmsg_end(skb, nlh);
181         return skb->len;
182
183 nlmsg_failure:
184 nla_put_failure:
185         nlmsg_cancel(skb, nlh);
186         return -1;
187 }
188
189 static int
190 nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
191 {
192         struct net *net = sock_net(skb->sk);
193         struct nf_acct *cur, *last;
194         const struct nfacct_filter *filter = cb->data;
195
196         if (cb->args[2])
197                 return 0;
198
199         last = (struct nf_acct *)cb->args[1];
200         if (cb->args[1])
201                 cb->args[1] = 0;
202
203         rcu_read_lock();
204         list_for_each_entry_rcu(cur, &net->nfnl_acct_list, head) {
205                 if (last) {
206                         if (cur != last)
207                                 continue;
208
209                         last = NULL;
210                 }
211
212                 if (filter && (cur->flags & filter->mask) != filter->value)
213                         continue;
214
215                 if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).portid,
216                                        cb->nlh->nlmsg_seq,
217                                        NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
218                                        NFNL_MSG_ACCT_NEW, cur) < 0) {
219                         cb->args[1] = (unsigned long)cur;
220                         break;
221                 }
222         }
223         if (!cb->args[1])
224                 cb->args[2] = 1;
225         rcu_read_unlock();
226         return skb->len;
227 }
228
229 static int nfnl_acct_done(struct netlink_callback *cb)
230 {
231         kfree(cb->data);
232         return 0;
233 }
234
235 static const struct nla_policy filter_policy[NFACCT_FILTER_MAX + 1] = {
236         [NFACCT_FILTER_MASK]    = { .type = NLA_U32 },
237         [NFACCT_FILTER_VALUE]   = { .type = NLA_U32 },
238 };
239
240 static struct nfacct_filter *
241 nfacct_filter_alloc(const struct nlattr * const attr)
242 {
243         struct nfacct_filter *filter;
244         struct nlattr *tb[NFACCT_FILTER_MAX + 1];
245         int err;
246
247         err = nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy,
248                                NULL);
249         if (err < 0)
250                 return ERR_PTR(err);
251
252         if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE])
253                 return ERR_PTR(-EINVAL);
254
255         filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
256         if (!filter)
257                 return ERR_PTR(-ENOMEM);
258
259         filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK]));
260         filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE]));
261
262         return filter;
263 }
264
265 static int nfnl_acct_get(struct net *net, struct sock *nfnl,
266                          struct sk_buff *skb, const struct nlmsghdr *nlh,
267                          const struct nlattr * const tb[])
268 {
269         int ret = -ENOENT;
270         struct nf_acct *cur;
271         char *acct_name;
272
273         if (nlh->nlmsg_flags & NLM_F_DUMP) {
274                 struct netlink_dump_control c = {
275                         .dump = nfnl_acct_dump,
276                         .done = nfnl_acct_done,
277                 };
278
279                 if (tb[NFACCT_FILTER]) {
280                         struct nfacct_filter *filter;
281
282                         filter = nfacct_filter_alloc(tb[NFACCT_FILTER]);
283                         if (IS_ERR(filter))
284                                 return PTR_ERR(filter);
285
286                         c.data = filter;
287                 }
288                 return netlink_dump_start(nfnl, skb, nlh, &c);
289         }
290
291         if (!tb[NFACCT_NAME])
292                 return -EINVAL;
293         acct_name = nla_data(tb[NFACCT_NAME]);
294
295         list_for_each_entry(cur, &net->nfnl_acct_list, head) {
296                 struct sk_buff *skb2;
297
298                 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
299                         continue;
300
301                 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
302                 if (skb2 == NULL) {
303                         ret = -ENOMEM;
304                         break;
305                 }
306
307                 ret = nfnl_acct_fill_info(skb2, NETLINK_CB(skb).portid,
308                                          nlh->nlmsg_seq,
309                                          NFNL_MSG_TYPE(nlh->nlmsg_type),
310                                          NFNL_MSG_ACCT_NEW, cur);
311                 if (ret <= 0) {
312                         kfree_skb(skb2);
313                         break;
314                 }
315                 ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid,
316                                         MSG_DONTWAIT);
317                 if (ret > 0)
318                         ret = 0;
319
320                 /* this avoids a loop in nfnetlink. */
321                 return ret == -EAGAIN ? -ENOBUFS : ret;
322         }
323         return ret;
324 }
325
326 /* try to delete object, fail if it is still in use. */
327 static int nfnl_acct_try_del(struct nf_acct *cur)
328 {
329         int ret = 0;
330
331         /* We want to avoid races with nfnl_acct_put. So only when the current
332          * refcnt is 1, we decrease it to 0.
333          */
334         if (refcount_dec_if_one(&cur->refcnt)) {
335                 /* We are protected by nfnl mutex. */
336                 list_del_rcu(&cur->head);
337                 kfree_rcu(cur, rcu_head);
338         } else {
339                 ret = -EBUSY;
340         }
341         return ret;
342 }
343
344 static int nfnl_acct_del(struct net *net, struct sock *nfnl,
345                          struct sk_buff *skb, const struct nlmsghdr *nlh,
346                          const struct nlattr * const tb[])
347 {
348         struct nf_acct *cur, *tmp;
349         int ret = -ENOENT;
350         char *acct_name;
351
352         if (!tb[NFACCT_NAME]) {
353                 list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head)
354                         nfnl_acct_try_del(cur);
355
356                 return 0;
357         }
358         acct_name = nla_data(tb[NFACCT_NAME]);
359
360         list_for_each_entry(cur, &net->nfnl_acct_list, head) {
361                 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX) != 0)
362                         continue;
363
364                 ret = nfnl_acct_try_del(cur);
365                 if (ret < 0)
366                         return ret;
367
368                 break;
369         }
370         return ret;
371 }
372
373 static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = {
374         [NFACCT_NAME] = { .type = NLA_NUL_STRING, .len = NFACCT_NAME_MAX-1 },
375         [NFACCT_BYTES] = { .type = NLA_U64 },
376         [NFACCT_PKTS] = { .type = NLA_U64 },
377         [NFACCT_FLAGS] = { .type = NLA_U32 },
378         [NFACCT_QUOTA] = { .type = NLA_U64 },
379         [NFACCT_FILTER] = {.type = NLA_NESTED },
380 };
381
382 static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = {
383         [NFNL_MSG_ACCT_NEW]             = { .call = nfnl_acct_new,
384                                             .attr_count = NFACCT_MAX,
385                                             .policy = nfnl_acct_policy },
386         [NFNL_MSG_ACCT_GET]             = { .call = nfnl_acct_get,
387                                             .attr_count = NFACCT_MAX,
388                                             .policy = nfnl_acct_policy },
389         [NFNL_MSG_ACCT_GET_CTRZERO]     = { .call = nfnl_acct_get,
390                                             .attr_count = NFACCT_MAX,
391                                             .policy = nfnl_acct_policy },
392         [NFNL_MSG_ACCT_DEL]             = { .call = nfnl_acct_del,
393                                             .attr_count = NFACCT_MAX,
394                                             .policy = nfnl_acct_policy },
395 };
396
397 static const struct nfnetlink_subsystem nfnl_acct_subsys = {
398         .name                           = "acct",
399         .subsys_id                      = NFNL_SUBSYS_ACCT,
400         .cb_count                       = NFNL_MSG_ACCT_MAX,
401         .cb                             = nfnl_acct_cb,
402 };
403
404 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT);
405
406 struct nf_acct *nfnl_acct_find_get(struct net *net, const char *acct_name)
407 {
408         struct nf_acct *cur, *acct = NULL;
409
410         rcu_read_lock();
411         list_for_each_entry_rcu(cur, &net->nfnl_acct_list, head) {
412                 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
413                         continue;
414
415                 if (!try_module_get(THIS_MODULE))
416                         goto err;
417
418                 if (!refcount_inc_not_zero(&cur->refcnt)) {
419                         module_put(THIS_MODULE);
420                         goto err;
421                 }
422
423                 acct = cur;
424                 break;
425         }
426 err:
427         rcu_read_unlock();
428         return acct;
429 }
430 EXPORT_SYMBOL_GPL(nfnl_acct_find_get);
431
432 void nfnl_acct_put(struct nf_acct *acct)
433 {
434         if (refcount_dec_and_test(&acct->refcnt))
435                 kfree_rcu(acct, rcu_head);
436
437         module_put(THIS_MODULE);
438 }
439 EXPORT_SYMBOL_GPL(nfnl_acct_put);
440
441 void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct)
442 {
443         atomic64_inc(&nfacct->pkts);
444         atomic64_add(skb->len, &nfacct->bytes);
445 }
446 EXPORT_SYMBOL_GPL(nfnl_acct_update);
447
448 static void nfnl_overquota_report(struct net *net, struct nf_acct *nfacct)
449 {
450         int ret;
451         struct sk_buff *skb;
452
453         skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
454         if (skb == NULL)
455                 return;
456
457         ret = nfnl_acct_fill_info(skb, 0, 0, NFNL_MSG_ACCT_OVERQUOTA, 0,
458                                   nfacct);
459         if (ret <= 0) {
460                 kfree_skb(skb);
461                 return;
462         }
463         netlink_broadcast(net->nfnl, skb, 0, NFNLGRP_ACCT_QUOTA,
464                           GFP_ATOMIC);
465 }
466
467 int nfnl_acct_overquota(struct net *net, const struct sk_buff *skb,
468                         struct nf_acct *nfacct)
469 {
470         u64 now;
471         u64 *quota;
472         int ret = NFACCT_UNDERQUOTA;
473
474         /* no place here if we don't have a quota */
475         if (!(nfacct->flags & NFACCT_F_QUOTA))
476                 return NFACCT_NO_QUOTA;
477
478         quota = (u64 *)nfacct->data;
479         now = (nfacct->flags & NFACCT_F_QUOTA_PKTS) ?
480                atomic64_read(&nfacct->pkts) : atomic64_read(&nfacct->bytes);
481
482         ret = now > *quota;
483
484         if (now >= *quota &&
485             !test_and_set_bit(NFACCT_OVERQUOTA_BIT, &nfacct->flags)) {
486                 nfnl_overquota_report(net, nfacct);
487         }
488
489         return ret;
490 }
491 EXPORT_SYMBOL_GPL(nfnl_acct_overquota);
492
493 static int __net_init nfnl_acct_net_init(struct net *net)
494 {
495         INIT_LIST_HEAD(&net->nfnl_acct_list);
496
497         return 0;
498 }
499
500 static void __net_exit nfnl_acct_net_exit(struct net *net)
501 {
502         struct nf_acct *cur, *tmp;
503
504         list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head) {
505                 list_del_rcu(&cur->head);
506
507                 if (refcount_dec_and_test(&cur->refcnt))
508                         kfree_rcu(cur, rcu_head);
509         }
510 }
511
512 static struct pernet_operations nfnl_acct_ops = {
513         .init   = nfnl_acct_net_init,
514         .exit   = nfnl_acct_net_exit,
515 };
516
517 static int __init nfnl_acct_init(void)
518 {
519         int ret;
520
521         ret = register_pernet_subsys(&nfnl_acct_ops);
522         if (ret < 0) {
523                 pr_err("nfnl_acct_init: failed to register pernet ops\n");
524                 goto err_out;
525         }
526
527         pr_info("nfnl_acct: registering with nfnetlink.\n");
528         ret = nfnetlink_subsys_register(&nfnl_acct_subsys);
529         if (ret < 0) {
530                 pr_err("nfnl_acct_init: cannot register with nfnetlink.\n");
531                 goto cleanup_pernet;
532         }
533         return 0;
534
535 cleanup_pernet:
536         unregister_pernet_subsys(&nfnl_acct_ops);
537 err_out:
538         return ret;
539 }
540
541 static void __exit nfnl_acct_exit(void)
542 {
543         pr_info("nfnl_acct: unregistering from nfnetlink.\n");
544         nfnetlink_subsys_unregister(&nfnl_acct_subsys);
545         unregister_pernet_subsys(&nfnl_acct_ops);
546 }
547
548 module_init(nfnl_acct_init);
549 module_exit(nfnl_acct_exit);