Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6] / net / netfilter / xt_quota.c
1 /*
2  * netfilter module to enforce network quotas
3  *
4  * Sam Johnston <samj@samj.net>
5  */
6 #include <linux/skbuff.h>
7 #include <linux/spinlock.h>
8
9 #include <linux/netfilter/x_tables.h>
10 #include <linux/netfilter/xt_quota.h>
11
12 MODULE_LICENSE("GPL");
13 MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
14
15 static DEFINE_SPINLOCK(quota_lock);
16
17 static int
18 match(const struct sk_buff *skb,
19       const struct net_device *in, const struct net_device *out,
20       const struct xt_match *match, const void *matchinfo,
21       int offset, unsigned int protoff, int *hotdrop)
22 {
23         struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master;
24         int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0;
25
26         spin_lock_bh(&quota_lock);
27         if (q->quota >= skb->len) {
28                 q->quota -= skb->len;
29                 ret ^= 1;
30         } else {
31                 /* we do not allow even small packets from now on */
32                 q->quota = 0;
33         }
34         spin_unlock_bh(&quota_lock);
35
36         return ret;
37 }
38
39 static int
40 checkentry(const char *tablename, const void *entry,
41            const struct xt_match *match, void *matchinfo,
42            unsigned int matchsize, unsigned int hook_mask)
43 {
44         struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
45
46         if (q->flags & ~XT_QUOTA_MASK)
47                 return 0;
48         /* For SMP, we only want to use one set of counters. */
49         q->master = q;
50         return 1;
51 }
52
53 static struct xt_match quota_match = {
54         .name           = "quota",
55         .family         = AF_INET,
56         .match          = match,
57         .matchsize      = sizeof(struct xt_quota_info),
58         .checkentry     = checkentry,
59         .me             = THIS_MODULE
60 };
61
62 static struct xt_match quota_match6 = {
63         .name           = "quota",
64         .family         = AF_INET6,
65         .match          = match,
66         .matchsize      = sizeof(struct xt_quota_info),
67         .checkentry     = checkentry,
68         .me             = THIS_MODULE
69 };
70
71 static int __init xt_quota_init(void)
72 {
73         int ret;
74
75         ret = xt_register_match(&quota_match);
76         if (ret)
77                 goto err1;
78         ret = xt_register_match(&quota_match6);
79         if (ret)
80                 goto err2;
81         return ret;
82
83 err2:
84         xt_unregister_match(&quota_match);
85 err1:
86         return ret;
87 }
88
89 static void __exit xt_quota_fini(void)
90 {
91         xt_unregister_match(&quota_match6);
92         xt_unregister_match(&quota_match);
93 }
94
95 module_init(xt_quota_init);
96 module_exit(xt_quota_fini);