2 * linux/net/ipv4/netfilter/ipt_IDLETIMER.c
4 * Netfilter module to trigger a timer when packet matches.
5 * After timer expires a kevent will be sent.
7 * Copyright (C) 2004 Nokia Corporation
8 * Written by Timo Teräs <ext-timo.teras@nokia.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
16 #include <linux/module.h>
17 #include <linux/skbuff.h>
18 #include <linux/timer.h>
19 #include <linux/list.h>
20 #include <linux/spinlock.h>
21 #include <linux/notifier.h>
22 #include <linux/netfilter.h>
23 #include <linux/rtnetlink.h>
24 #include <linux/netfilter_ipv4/ip_tables.h>
25 #include <linux/netfilter_ipv4/ipt_IDLETIMER.h>
26 #include <linux/kobject.h>
29 #define DEBUGP(format, args...) printk("%s:%s:" format, \
30 __FILE__, __FUNCTION__ , ## args)
32 #define DEBUGP(format, args...)
36 * Internal timer management.
38 static ssize_t utimer_attr_show(struct class_device *, char *buf);
39 static ssize_t utimer_attr_store(struct class_device *,
40 const char *buf, size_t count);
44 struct list_head entry;
45 struct timer_list timer;
48 static LIST_HEAD(active_utimer_head);
49 static DEFINE_SPINLOCK(list_lock);
50 static CLASS_DEVICE_ATTR(idletimer, 0644, utimer_attr_show, utimer_attr_store);
52 static void utimer_delete(struct utimer_t *timer)
54 DEBUGP("Deleting timer '%s'\n", timer->name);
56 list_del(&timer->entry);
57 del_timer_sync(&timer->timer);
61 static void utimer_expired(unsigned long data)
63 struct utimer_t *timer = (struct utimer_t *) data;
64 struct net_device *netdev;
66 DEBUGP("Timer '%s' expired\n", timer->name);
67 netdev = dev_get_by_name(timer->name);
69 spin_lock_bh(&list_lock);
71 spin_unlock_bh(&list_lock);
74 kobject_uevent(&netdev->class_dev.kobj,
80 static struct utimer_t *utimer_create(const char *name)
82 struct utimer_t *timer;
84 timer = kmalloc(sizeof(struct utimer_t), GFP_ATOMIC);
88 list_add(&timer->entry, &active_utimer_head);
89 strlcpy(timer->name, name, sizeof(timer->name));
91 init_timer(&timer->timer);
92 timer->timer.function = utimer_expired;
93 timer->timer.data = (unsigned long) timer;
95 DEBUGP("Created timer '%s'\n", timer->name);
100 static struct utimer_t *__utimer_find(const char *name)
102 struct utimer_t *entry;
104 list_for_each_entry(entry, &active_utimer_head, entry) {
105 if (strcmp(name, entry->name) == 0) {
113 static void utimer_modify(const char *name,
114 unsigned long expires)
116 struct utimer_t *timer;
118 DEBUGP("Modifying timer '%s'\n", name);
119 spin_lock_bh(&list_lock);
120 timer = __utimer_find(name);
122 timer = utimer_create(name);
123 mod_timer(&timer->timer, expires);
124 spin_unlock_bh(&list_lock);
127 static ssize_t utimer_attr_show(struct class_device *dev, char *buf)
129 struct utimer_t *timer;
130 unsigned long expires = 0;
132 spin_lock_bh(&list_lock);
133 timer = __utimer_find(dev->class_id);
135 expires = timer->timer.expires;
136 spin_unlock_bh(&list_lock);
139 return sprintf(buf, "%lu\n", (expires-jiffies) / HZ);
141 return sprintf(buf, "0\n");
144 static ssize_t utimer_attr_store(struct class_device *dev,
145 const char *buf, size_t count)
149 if (sscanf(buf, "%d", &expires) == 1) {
151 utimer_modify(dev->class_id,
152 jiffies+HZ*(unsigned long)expires);
158 static int utimer_notifier_call(struct notifier_block *this,
159 unsigned long event, void *ptr)
161 struct net_device *dev = ptr;
165 DEBUGP("NETDEV_UP: %s\n", dev->name);
166 class_device_create_file(&dev->class_dev,
167 &class_device_attr_idletimer);
170 DEBUGP("NETDEV_DOWN: %s\n", dev->name);
171 class_device_remove_file(&dev->class_dev,
172 &class_device_attr_idletimer);
179 static struct notifier_block utimer_notifier_block = {
180 .notifier_call = utimer_notifier_call,
184 static int utimer_init(void)
186 return register_netdevice_notifier(&utimer_notifier_block);
189 static void utimer_fini(void)
191 struct utimer_t *entry, *next;
192 struct net_device *dev;
194 list_for_each_entry_safe(entry, next, &active_utimer_head, entry)
195 utimer_delete(entry);
198 unregister_netdevice_notifier(&utimer_notifier_block);
199 for (dev = dev_base; dev; dev = dev->next)
200 utimer_notifier_call(&utimer_notifier_block,
206 * The actual iptables plugin.
208 static unsigned int ipt_idletimer_target(struct sk_buff **pskb,
209 const struct net_device *in,
210 const struct net_device *out,
211 unsigned int hooknum,
212 const void *targinfo,
215 struct ipt_idletimer_info *target = (struct ipt_idletimer_info*) targinfo;
216 unsigned long expires;
218 expires = jiffies + HZ*target->timeout;
221 utimer_modify(in->name, expires);
224 utimer_modify(out->name, expires);
229 static int ipt_idletimer_checkentry(const char *tablename,
232 unsigned int targinfosize,
233 unsigned int hookmask)
235 struct ipt_idletimer_info *info =
236 (struct ipt_idletimer_info *) targinfo;
238 if (targinfosize != IPT_ALIGN(sizeof(struct ipt_idletimer_info))) {
239 DEBUGP("targinfosize %u != 0\n", targinfosize);
243 if (info->timeout == 0) {
244 DEBUGP("timeout value is zero\n");
251 static struct ipt_target ipt_idletimer = {
253 .target = ipt_idletimer_target,
254 .checkentry = ipt_idletimer_checkentry,
258 static int __init init(void)
266 if (ipt_register_target(&ipt_idletimer)) {
274 static void __exit fini(void)
276 ipt_unregister_target(&ipt_idletimer);
283 MODULE_AUTHOR("Timo Teräs <ext-timo.teras@nokia.com>");
284 MODULE_DESCRIPTION("iptables idletimer target module");
285 MODULE_LICENSE("GPL");