~ubuntu-branches/ubuntu/lucid/xtables-addons/lucid

« back to all changes in this revision

Viewing changes to extensions/xt_quota2.c

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Chifflier
  • Date: 2009-09-10 21:42:05 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090910214205-neqgwq7y5nctaty7
Tags: 1.18-1
* New Upstream Version
  This version has support for 2.6.31 (Closes: #545542)
* Bump standards version (no changes)
* Depend on quilt (Closes: #533653)

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include "xt_quota2.h"
22
22
#include "compat_xtables.h"
23
23
 
24
 
struct quota_counter {
 
24
/**
 
25
 * @lock:       lock to protect quota writers from each other
 
26
 */
 
27
struct xt_quota_counter {
25
28
        u_int64_t quota;
26
29
        spinlock_t lock;
27
30
        struct list_head list;
28
31
        atomic_t ref;
29
 
        char name[XT_QUOTA_COUNTER_NAME_LENGTH];
 
32
        char name[sizeof(((struct xt_quota_mtinfo2 *)NULL)->name)];
30
33
        struct proc_dir_entry *procfs_entry;
31
34
};
32
35
 
44
47
static int quota_proc_read(char *page, char **start, off_t offset,
45
48
                           int count, int *eof, void *data)
46
49
{
47
 
        struct quota_counter *e = data;
 
50
        struct xt_quota_counter *e = data;
48
51
        int ret;
49
52
 
50
53
        spin_lock_bh(&e->lock);
56
59
static int quota_proc_write(struct file *file, const char __user *input,
57
60
                            unsigned long size, void *data)
58
61
{
59
 
        struct quota_counter *e = data;
 
62
        struct xt_quota_counter *e = data;
60
63
        char buf[sizeof("18446744073709551616")];
61
64
 
62
65
        if (size > sizeof(buf))
66
69
        buf[sizeof(buf)-1] = '\0';
67
70
 
68
71
        spin_lock_bh(&e->lock);
69
 
        e->quota = simple_strtoul(buf, NULL, 0);
 
72
        e->quota = simple_strtoull(buf, NULL, 0);
70
73
        spin_unlock_bh(&e->lock);
71
74
        return size;
72
75
}
73
76
 
 
77
static struct xt_quota_counter *
 
78
q2_new_counter(const struct xt_quota_mtinfo2 *q, bool anon)
 
79
{
 
80
        struct xt_quota_counter *e;
 
81
        unsigned int size;
 
82
 
 
83
        /* Do not need all the procfs things for anonymous counters. */
 
84
        size = anon ? offsetof(typeof(*e), list) : sizeof(*e);
 
85
        e = kmalloc(size, GFP_KERNEL);
 
86
        if (e == NULL)
 
87
                return NULL;
 
88
 
 
89
        e->quota = q->quota;
 
90
        spin_lock_init(&e->lock);
 
91
        if (!anon) {
 
92
                INIT_LIST_HEAD(&e->list);
 
93
                atomic_set(&e->ref, 1);
 
94
                strncpy(e->name, q->name, sizeof(e->name));
 
95
        }
 
96
        return e;
 
97
}
 
98
 
74
99
/**
75
100
 * q2_get_counter - get ref to counter or create new
76
101
 * @name:       name of counter
77
102
 */
78
 
static struct quota_counter *q2_get_counter(const struct xt_quota_mtinfo2 *q)
 
103
static struct xt_quota_counter *
 
104
q2_get_counter(const struct xt_quota_mtinfo2 *q)
79
105
{
80
106
        struct proc_dir_entry *p;
81
 
        struct quota_counter *e;
 
107
        struct xt_quota_counter *e;
 
108
 
 
109
        if (*q->name == '\0')
 
110
                return q2_new_counter(q, true);
82
111
 
83
112
        spin_lock_bh(&counter_list_lock);
84
 
        list_for_each_entry(e, &counter_list, list) {
 
113
        list_for_each_entry(e, &counter_list, list)
85
114
                if (strcmp(e->name, q->name) == 0) {
86
115
                        atomic_inc(&e->ref);
87
116
                        spin_unlock_bh(&counter_list_lock);
88
117
                        return e;
89
118
                }
90
 
        }
91
119
 
92
 
        e = kmalloc(sizeof(struct quota_counter), GFP_KERNEL);
 
120
        e = q2_new_counter(q, false);
93
121
        if (e == NULL)
94
122
                goto out;
95
123
 
96
 
        e->quota = q->quota;
97
 
        spin_lock_init(&e->lock);
98
 
        INIT_LIST_HEAD(&e->list);
99
 
        atomic_set(&e->ref, 1);
100
 
        strncpy(e->name, q->name, sizeof(e->name));
101
 
 
102
124
        p = e->procfs_entry = create_proc_entry(e->name, quota_list_perms,
103
125
                              proc_xt_quota);
104
126
        if (p == NULL || IS_ERR(p))
130
152
                return false;
131
153
 
132
154
        q->name[sizeof(q->name)-1] = '\0';
133
 
        if (*q->name == '\0' || *q->name == '.' ||
134
 
            strchr(q->name, '/') != NULL) {
135
 
                printk(KERN_ERR "xt_quota.2: illegal name\n");
 
155
        if (*q->name == '.' || strchr(q->name, '/') != NULL) {
 
156
                printk(KERN_ERR "xt_quota<%u>: illegal name\n",
 
157
                       par->match->revision);
136
158
                return false;
137
159
        }
138
160
 
139
161
        q->master = q2_get_counter(q);
140
162
        if (q->master == NULL) {
141
 
                printk(KERN_ERR "xt_quota.2: memory alloc failure\n");
 
163
                printk(KERN_ERR "xt_quota<%u>: memory alloc failure\n",
 
164
                       par->match->revision);
142
165
                return false;
143
166
        }
144
167
 
148
171
static void quota_mt2_destroy(const struct xt_mtdtor_param *par)
149
172
{
150
173
        struct xt_quota_mtinfo2 *q = par->matchinfo;
151
 
        struct quota_counter *e = q->master;
 
174
        struct xt_quota_counter *e = q->master;
 
175
 
 
176
        if (*q->name == '\0') {
 
177
                kfree(e);
 
178
                return;
 
179
        }
152
180
 
153
181
        spin_lock_bh(&counter_list_lock);
154
182
        if (!atomic_dec_and_test(&e->ref)) {
157
185
        }
158
186
 
159
187
        list_del(&e->list);
160
 
        spin_unlock_bh(&counter_list_lock);
161
188
        remove_proc_entry(e->name, proc_xt_quota);
 
189
        spin_unlock_bh(&counter_list_lock);
162
190
        kfree(e);
163
191
}
164
192
 
166
194
quota_mt2(const struct sk_buff *skb, const struct xt_match_param *par)
167
195
{
168
196
        struct xt_quota_mtinfo2 *q = (void *)par->matchinfo;
169
 
        struct quota_counter *e = q->master;
 
197
        struct xt_quota_counter *e = q->master;
170
198
        bool ret = q->flags & XT_QUOTA_INVERT;
171
199
 
 
200
        spin_lock_bh(&e->lock);
172
201
        if (q->flags & XT_QUOTA_GROW) {
173
 
                spin_lock_bh(&e->lock);
174
202
                e->quota += (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len;
175
203
                q->quota = e->quota;
176
 
                spin_unlock_bh(&e->lock);
177
204
                ret = true;
178
205
        } else {
179
 
                spin_lock_bh(&e->lock);
180
206
                if (e->quota >= skb->len) {
181
207
                        e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len;
182
208
                        ret = !ret;
185
211
                        e->quota = 0;
186
212
                }
187
213
                q->quota = e->quota;
188
 
                spin_unlock_bh(&e->lock);
189
214
        }
190
 
 
 
215
        spin_unlock_bh(&e->lock);
191
216
        return ret;
192
217
}
193
218
 
194
219
static struct xt_match quota_mt2_reg[] __read_mostly = {
195
220
        {
196
221
                .name       = "quota2",
197
 
                .revision   = 2,
 
222
                .revision   = 3,
198
223
                .family     = NFPROTO_IPV4,
199
224
                .checkentry = quota_mt2_check,
200
225
                .match      = quota_mt2,
204
229
        },
205
230
        {
206
231
                .name       = "quota2",
207
 
                .revision   = 2,
 
232
                .revision   = 3,
208
233
                .family     = NFPROTO_IPV6,
209
234
                .checkentry = quota_mt2_check,
210
235
                .match      = quota_mt2,