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. All rights reserved.
8 * Written by Timo Teras <ext-timo.teras@nokia.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * version 2 as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 #include <linux/module.h>
26 #include <linux/skbuff.h>
27 #include <linux/timer.h>
28 #include <linux/list.h>
29 #include <linux/spinlock.h>
30 #include <linux/notifier.h>
31 #include <linux/netfilter.h>
32 #include <linux/rtnetlink.h>
33 #include <linux/netfilter/x_tables.h>
34 #include <linux/netfilter_ipv4/ipt_IDLETIMER.h>
35 #include <linux/kobject.h>
36 #include <linux/workqueue.h>
39 #define DEBUGP(format, args...) printk("%s:%s:" format, \
40 __FILE__, __FUNCTION__ , ## args)
42 #define DEBUGP(format, args...)
46 * Internal timer management.
48 static ssize_t utimer_attr_show(struct device *, struct device_attribute *attr, char *buf);
49 static ssize_t utimer_attr_store(struct device *, struct device_attribute *attr,
50 const char *buf, size_t count);
54 struct list_head entry;
55 struct timer_list timer;
56 struct work_struct work;
59 static LIST_HEAD(active_utimer_head);
60 static DEFINE_SPINLOCK(list_lock);
61 static DEVICE_ATTR(idletimer, 0644, utimer_attr_show, utimer_attr_store);
63 static void utimer_delete(struct utimer_t *timer)
65 DEBUGP("Deleting timer '%s'\n", timer->name);
67 list_del(&timer->entry);
68 del_timer_sync(&timer->timer);
72 static void utimer_work(struct work_struct *work)
74 struct utimer_t *timer = container_of(work, struct utimer_t, work);
75 struct net_device *netdev;
77 netdev = dev_get_by_name(&init_net, timer->name);
80 sysfs_notify(&netdev->dev.kobj, NULL,
86 static void utimer_expired(unsigned long data)
88 struct utimer_t *timer = (struct utimer_t *) data;
90 DEBUGP("Timer '%s' expired\n", timer->name);
92 spin_lock_bh(&list_lock);
94 spin_unlock_bh(&list_lock);
96 schedule_work(&timer->work);
99 static struct utimer_t *utimer_create(const char *name)
101 struct utimer_t *timer;
103 timer = kmalloc(sizeof(struct utimer_t), GFP_ATOMIC);
107 list_add(&timer->entry, &active_utimer_head);
108 strlcpy(timer->name, name, sizeof(timer->name));
110 init_timer(&timer->timer);
111 timer->timer.function = utimer_expired;
112 timer->timer.data = (unsigned long) timer;
114 INIT_WORK(&timer->work, utimer_work);
116 DEBUGP("Created timer '%s'\n", timer->name);
121 static struct utimer_t *__utimer_find(const char *name)
123 struct utimer_t *entry;
125 list_for_each_entry(entry, &active_utimer_head, entry) {
126 if (strcmp(name, entry->name) == 0) {
134 static void utimer_modify(const char *name,
135 unsigned long expires)
137 struct utimer_t *timer;
139 DEBUGP("Modifying timer '%s'\n", name);
140 spin_lock_bh(&list_lock);
141 timer = __utimer_find(name);
143 timer = utimer_create(name);
144 mod_timer(&timer->timer, expires);
145 spin_unlock_bh(&list_lock);
148 static ssize_t utimer_attr_show(struct device *dev, struct device_attribute *attr, char *buf)
150 struct utimer_t *timer;
151 unsigned long expires = 0;
152 struct net_device *netdev = container_of(dev, struct net_device, dev);
154 spin_lock_bh(&list_lock);
155 timer = __utimer_find(netdev->name);
157 expires = timer->timer.expires;
158 spin_unlock_bh(&list_lock);
161 return sprintf(buf, "%lu\n", (expires-jiffies) / HZ);
163 return sprintf(buf, "0\n");
166 static ssize_t utimer_attr_store(struct device *dev, struct device_attribute *attr,
167 const char *buf, size_t count)
170 struct net_device *netdev = container_of(dev, struct net_device, dev);
172 if (sscanf(buf, "%d", &expires) == 1) {
174 utimer_modify(netdev->name,
175 jiffies+HZ*(unsigned long)expires);
181 static int utimer_notifier_call(struct notifier_block *this,
182 unsigned long event, void *ptr)
184 struct net_device *dev = ptr;
185 int ret = NOTIFY_DONE;
189 DEBUGP("NETDEV_UP: %s\n", dev->name);
190 ret = device_create_file(&dev->dev,
191 &dev_attr_idletimer);
194 DEBUGP("NETDEV_DOWN: %s\n", dev->name);
195 device_remove_file(&dev->dev,
196 &dev_attr_idletimer);
203 static struct notifier_block utimer_notifier_block = {
204 .notifier_call = utimer_notifier_call,
208 static int utimer_init(void)
210 return register_netdevice_notifier(&utimer_notifier_block);
213 static void utimer_fini(void)
215 struct utimer_t *entry, *next;
216 struct net_device *dev;
218 list_for_each_entry_safe(entry, next, &active_utimer_head, entry)
219 utimer_delete(entry);
222 unregister_netdevice_notifier(&utimer_notifier_block);
223 for_each_netdev(&init_net, dev)
224 utimer_notifier_call(&utimer_notifier_block,
230 * The actual iptables plugin.
232 static unsigned int ipt_idletimer_target(struct sk_buff *pskb,
233 const struct net_device *in,
234 const struct net_device *out,
235 unsigned int hooknum,
236 const struct xt_target *xttarget,
237 const void *targinfo)
239 struct ipt_idletimer_info *target = (struct ipt_idletimer_info*) targinfo;
240 unsigned long expires;
242 expires = jiffies + HZ*target->timeout;
245 utimer_modify(in->name, expires);
248 utimer_modify(out->name, expires);
253 static bool ipt_idletimer_checkentry(const char *tablename,
255 const struct xt_target *target,
257 unsigned int hookmask)
259 struct ipt_idletimer_info *info =
260 (struct ipt_idletimer_info *) targinfo;
262 if (info->timeout == 0) {
263 DEBUGP("timeout value is zero\n");
270 static struct xt_target ipt_idletimer = {
272 .target = ipt_idletimer_target,
273 .checkentry = ipt_idletimer_checkentry,
275 .targetsize = sizeof(struct ipt_idletimer_info),
278 static int __init init(void)
286 if (xt_register_target(&ipt_idletimer)) {
294 static void __exit fini(void)
296 xt_unregister_target(&ipt_idletimer);
303 MODULE_AUTHOR("Timo Teras <ext-timo.teras@nokia.com>");
304 MODULE_DESCRIPTION("iptables idletimer target module");
305 MODULE_LICENSE("GPL");