2 * xt_quota2 - enhanced xt_quota that can count upwards and in packets
3 * as a minimal accounting match.
4 * by Jan Engelhardt <jengelh@medozas.de>, 2008
6 * Originally based on xt_quota.c:
7 * netfilter module to enforce network quotas
8 * Sam Johnston <samj@samj.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License; either
12 * version 2 of the License, as published by the Free Software Foundation.
14 #include <linux/list.h>
15 #include <linux/module.h>
16 #include <linux/proc_fs.h>
17 #include <linux/skbuff.h>
18 #include <linux/spinlock.h>
19 #include <linux/workqueue.h>
20 #include <asm/atomic.h>
21 #include <net/netlink.h>
23 #include <linux/netfilter/x_tables.h>
24 #include <linux/netfilter/xt_quota2.h>
26 #define QUOTA2_SYSFS_WORK_MAX_SIZE 64
27 #define QUOTA2_SYSFS_NUM_ENVP 3
29 #ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG
30 /* For compatibility, these definitions are copied from the
31 * deprecated header file <linux/netfilter_ipv4/ipt_ULOG.h> */
32 #define ULOG_MAC_LEN 80
33 #define ULOG_PREFIX_LEN 32
35 /* Format of the ULOG packets passed through netlink */
36 typedef struct ulog_packet_msg {
41 char indev_name[IFNAMSIZ];
42 char outdev_name[IFNAMSIZ];
44 char prefix[ULOG_PREFIX_LEN];
45 unsigned char mac_len;
46 unsigned char mac[ULOG_MAC_LEN];
47 unsigned char payload[0];
52 * @lock: lock to protect quota writers from each other
54 struct xt_quota_counter {
57 struct list_head list;
59 char name[sizeof(((struct xt_quota_mtinfo2 *)NULL)->name)];
60 struct proc_dir_entry *procfs_entry;
61 char last_iface[QUOTA2_SYSFS_WORK_MAX_SIZE];
62 char last_prefix[QUOTA2_SYSFS_WORK_MAX_SIZE];
63 struct work_struct work;
66 #define to_quota_counter(x) container_of(x, struct xt_quota_counter, work)
68 static struct class *quota_class;
69 static struct device *quota_device;
70 static struct kobject *quota_kobj;
72 static LIST_HEAD(counter_list);
73 static DEFINE_SPINLOCK(counter_list_lock);
75 static struct proc_dir_entry *proc_xt_quota;
76 static unsigned int quota_list_perms = S_IRUGO | S_IWUSR;
77 static kuid_t quota_list_uid = KUIDT_INIT(0);
78 static kgid_t quota_list_gid = KGIDT_INIT(0);
79 module_param_named(perms, quota_list_perms, uint, S_IRUGO | S_IWUSR);
81 static void quota2_work(struct work_struct *work)
83 char alert_msg[QUOTA2_SYSFS_WORK_MAX_SIZE];
84 char iface_name[QUOTA2_SYSFS_WORK_MAX_SIZE];
85 char *envp[QUOTA2_SYSFS_NUM_ENVP] = {alert_msg, iface_name, NULL};
86 struct xt_quota_counter *counter = to_quota_counter(work);
88 snprintf(alert_msg, sizeof(alert_msg), "ALERT_NAME=%s", counter->name);
89 snprintf(iface_name, sizeof(iface_name), "INTERFACE=%s",
92 kobject_uevent_env(quota_kobj, KOBJ_CHANGE, envp);
95 static void quota2_log(const struct net_device *in,
96 const struct net_device *out,
97 struct xt_quota_counter *q,
103 strlcpy(q->last_prefix, prefix, QUOTA2_SYSFS_WORK_MAX_SIZE);
106 strlcpy(q->last_iface, in->name, QUOTA2_SYSFS_WORK_MAX_SIZE);
108 strlcpy(q->last_iface, out->name, QUOTA2_SYSFS_WORK_MAX_SIZE);
110 strlcpy(q->last_iface, "UNKNOWN", QUOTA2_SYSFS_WORK_MAX_SIZE);
112 schedule_work(&q->work);
115 static ssize_t quota_proc_read(struct file *file, char __user *buf,
116 size_t size, loff_t *ppos)
118 struct xt_quota_counter *e = PDE_DATA(file_inode(file));
122 spin_lock_bh(&e->lock);
123 tmp_size = scnprintf(tmp, sizeof(tmp), "%llu\n", e->quota);
124 spin_unlock_bh(&e->lock);
125 return simple_read_from_buffer(buf, size, ppos, tmp, tmp_size);
128 static ssize_t quota_proc_write(struct file *file, const char __user *input,
129 size_t size, loff_t *ppos)
131 struct xt_quota_counter *e = PDE_DATA(file_inode(file));
132 char buf[sizeof("18446744073709551616")];
134 if (size > sizeof(buf))
136 if (copy_from_user(buf, input, size) != 0)
138 buf[sizeof(buf)-1] = '\0';
140 spin_lock_bh(&e->lock);
141 e->quota = simple_strtoull(buf, NULL, 0);
142 spin_unlock_bh(&e->lock);
146 static const struct file_operations q2_counter_fops = {
147 .read = quota_proc_read,
148 .write = quota_proc_write,
149 .llseek = default_llseek,
152 static struct xt_quota_counter *
153 q2_new_counter(const struct xt_quota_mtinfo2 *q, bool anon)
155 struct xt_quota_counter *e;
158 /* Do not need all the procfs things for anonymous counters. */
159 size = anon ? offsetof(typeof(*e), list) : sizeof(*e);
160 e = kmalloc(size, GFP_KERNEL);
165 spin_lock_init(&e->lock);
167 INIT_LIST_HEAD(&e->list);
168 atomic_set(&e->ref, 1);
169 strlcpy(e->name, q->name, sizeof(e->name));
170 strlcpy(e->last_prefix, "UNSET", sizeof(e->last_prefix));
171 strlcpy(e->last_iface, "UNSET", sizeof(e->last_iface));
172 INIT_WORK(&e->work, quota2_work);
178 * q2_get_counter - get ref to counter or create new
179 * @name: name of counter
181 static struct xt_quota_counter *
182 q2_get_counter(const struct xt_quota_mtinfo2 *q)
184 struct proc_dir_entry *p;
185 struct xt_quota_counter *e = NULL;
186 struct xt_quota_counter *new_e;
188 if (*q->name == '\0')
189 return q2_new_counter(q, true);
191 /* No need to hold a lock while getting a new counter */
192 new_e = q2_new_counter(q, false);
196 spin_lock_bh(&counter_list_lock);
197 list_for_each_entry(e, &counter_list, list)
198 if (strcmp(e->name, q->name) == 0) {
200 spin_unlock_bh(&counter_list_lock);
202 pr_debug("xt_quota2: old counter name=%s", e->name);
206 pr_debug("xt_quota2: new_counter name=%s", e->name);
207 list_add_tail(&e->list, &counter_list);
208 /* The entry having a refcount of 1 is not directly destructible.
209 * This func has not yet returned the new entry, thus iptables
210 * has not references for destroying this entry.
211 * For another rule to try to destroy it, it would 1st need for this
212 * func* to be re-invoked, acquire a new ref for the same named quota.
213 * Nobody will access the e->procfs_entry either.
214 * So release the lock. */
215 spin_unlock_bh(&counter_list_lock);
217 /* create_proc_entry() is not spin_lock happy */
218 p = e->procfs_entry = proc_create_data(e->name, quota_list_perms,
219 proc_xt_quota, &q2_counter_fops, e);
221 if (IS_ERR_OR_NULL(p)) {
222 spin_lock_bh(&counter_list_lock);
224 spin_unlock_bh(&counter_list_lock);
227 proc_set_user(p, quota_list_uid, quota_list_gid);
235 static int quota_mt2_check(const struct xt_mtchk_param *par)
237 struct xt_quota_mtinfo2 *q = par->matchinfo;
239 pr_debug("xt_quota2: check() flags=0x%04x", q->flags);
241 if (q->flags & ~XT_QUOTA_MASK)
244 q->name[sizeof(q->name)-1] = '\0';
245 if (*q->name == '.' || strchr(q->name, '/') != NULL) {
246 printk(KERN_ERR "xt_quota.3: illegal name\n");
250 q->master = q2_get_counter(q);
251 if (q->master == NULL) {
252 printk(KERN_ERR "xt_quota.3: memory alloc failure\n");
259 static void quota_mt2_destroy(const struct xt_mtdtor_param *par)
261 struct xt_quota_mtinfo2 *q = par->matchinfo;
262 struct xt_quota_counter *e = q->master;
264 if (*q->name == '\0') {
269 spin_lock_bh(&counter_list_lock);
270 if (!atomic_dec_and_test(&e->ref)) {
271 spin_unlock_bh(&counter_list_lock);
276 remove_proc_entry(e->name, proc_xt_quota);
277 spin_unlock_bh(&counter_list_lock);
282 quota_mt2(const struct sk_buff *skb, struct xt_action_param *par)
284 struct xt_quota_mtinfo2 *q = (void *)par->matchinfo;
285 struct xt_quota_counter *e = q->master;
286 bool ret = q->flags & XT_QUOTA_INVERT;
288 spin_lock_bh(&e->lock);
289 if (q->flags & XT_QUOTA_GROW) {
291 * While no_change is pointless in "grow" mode, we will
292 * implement it here simply to have a consistent behavior.
294 if (!(q->flags & XT_QUOTA_NO_CHANGE)) {
295 e->quota += (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len;
299 if (e->quota >= skb->len) {
300 if (!(q->flags & XT_QUOTA_NO_CHANGE))
301 e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len;
304 /* We are transitioning, log that fact. */
306 quota2_log(par->in, par->out, e, q->name);
308 /* we do not allow even small packets from now on */
312 spin_unlock_bh(&e->lock);
316 static struct xt_match quota_mt2_reg[] __read_mostly = {
320 .family = NFPROTO_IPV4,
321 .checkentry = quota_mt2_check,
323 .destroy = quota_mt2_destroy,
324 .matchsize = sizeof(struct xt_quota_mtinfo2),
330 .family = NFPROTO_IPV6,
331 .checkentry = quota_mt2_check,
333 .destroy = quota_mt2_destroy,
334 .matchsize = sizeof(struct xt_quota_mtinfo2),
339 static int __init quota_mt2_init(void)
342 pr_debug("xt_quota2: init()");
344 quota_class = class_create(THIS_MODULE, "xt_quota2");
345 ret = PTR_ERR(quota_class);
346 if (IS_ERR(quota_class)) {
347 pr_err("xt_quota2: couldn't create class");
348 class_destroy(quota_class);
352 quota_device = device_create(quota_class, NULL, MKDEV(0, 0), NULL,
354 ret = PTR_ERR(quota_device);
355 if (IS_ERR(quota_device)) {
356 pr_err("xt_quota2: couldn't create device");
357 device_destroy(quota_class, MKDEV(0, 0));
358 class_destroy(quota_class);
362 quota_kobj = "a_device->kobj;
364 proc_xt_quota = proc_mkdir("xt_quota", init_net.proc_net);
365 if (proc_xt_quota == NULL)
368 ret = xt_register_matches(quota_mt2_reg, ARRAY_SIZE(quota_mt2_reg));
370 remove_proc_entry("xt_quota", init_net.proc_net);
371 pr_debug("xt_quota2: init() %d", ret);
375 static void __exit quota_mt2_exit(void)
377 xt_unregister_matches(quota_mt2_reg, ARRAY_SIZE(quota_mt2_reg));
378 remove_proc_entry("xt_quota", init_net.proc_net);
379 device_destroy(quota_class, MKDEV(0, 0));
380 class_destroy(quota_class);
383 module_init(quota_mt2_init);
384 module_exit(quota_mt2_exit);
385 MODULE_DESCRIPTION("Xtables: countdown quota match; up counter");
386 MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
387 MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
388 MODULE_LICENSE("GPL");
389 MODULE_ALIAS("ipt_quota2");
390 MODULE_ALIAS("ip6t_quota2");