diff options
-rw-r--r-- | drivers/leds/Kconfig | 3 | ||||
-rw-r--r-- | include/linux/netfilter/Kbuild | 1 | ||||
-rw-r--r-- | include/linux/netfilter/xt_LED.h | 13 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 24 | ||||
-rw-r--r-- | net/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/xt_LED.c | 161 |
6 files changed, 203 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 742713611bc5..556aeca0d860 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -223,4 +223,7 @@ config LEDS_TRIGGER_DEFAULT_ON | |||
223 | This allows LEDs to be initialised in the ON state. | 223 | This allows LEDs to be initialised in the ON state. |
224 | If unsure, say Y. | 224 | If unsure, say Y. |
225 | 225 | ||
226 | comment "iptables trigger is under Netfilter config (LED target)" | ||
227 | depends on LEDS_TRIGGERS | ||
228 | |||
226 | endif # NEW_LEDS | 229 | endif # NEW_LEDS |
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 5a8af875bce2..deeaee5c83f2 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild | |||
@@ -7,6 +7,7 @@ header-y += xt_CLASSIFY.h | |||
7 | header-y += xt_CONNMARK.h | 7 | header-y += xt_CONNMARK.h |
8 | header-y += xt_CONNSECMARK.h | 8 | header-y += xt_CONNSECMARK.h |
9 | header-y += xt_DSCP.h | 9 | header-y += xt_DSCP.h |
10 | header-y += xt_LED.h | ||
10 | header-y += xt_MARK.h | 11 | header-y += xt_MARK.h |
11 | header-y += xt_NFLOG.h | 12 | header-y += xt_NFLOG.h |
12 | header-y += xt_NFQUEUE.h | 13 | header-y += xt_NFQUEUE.h |
diff --git a/include/linux/netfilter/xt_LED.h b/include/linux/netfilter/xt_LED.h new file mode 100644 index 000000000000..4c91a0d770d0 --- /dev/null +++ b/include/linux/netfilter/xt_LED.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef _XT_LED_H | ||
2 | #define _XT_LED_H | ||
3 | |||
4 | struct xt_led_info { | ||
5 | char id[27]; /* Unique ID for this trigger in the LED class */ | ||
6 | __u8 always_blink; /* Blink even if the LED is already on */ | ||
7 | __u32 delay; /* Delay until LED is switched off after trigger */ | ||
8 | |||
9 | /* Kernel data used in the module */ | ||
10 | void *internal_data __attribute__((aligned(8))); | ||
11 | }; | ||
12 | |||
13 | #endif /* _XT_LED_H */ | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 0eb98b4fbf44..cdbaaff6d0d6 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -372,6 +372,30 @@ config NETFILTER_XT_TARGET_HL | |||
372 | since you can easily create immortal packets that loop | 372 | since you can easily create immortal packets that loop |
373 | forever on the network. | 373 | forever on the network. |
374 | 374 | ||
375 | config NETFILTER_XT_TARGET_LED | ||
376 | tristate '"LED" target support' | ||
377 | depends on LEDS_CLASS | ||
378 | depends on NETFILTER_ADVANCED | ||
379 | help | ||
380 | This option adds a `LED' target, which allows you to blink LEDs in | ||
381 | response to particular packets passing through your machine. | ||
382 | |||
383 | This can be used to turn a spare LED into a network activity LED, | ||
384 | which only flashes in response to FTP transfers, for example. Or | ||
385 | you could have an LED which lights up for a minute or two every time | ||
386 | somebody connects to your machine via SSH. | ||
387 | |||
388 | You will need support for the "led" class to make this work. | ||
389 | |||
390 | To create an LED trigger for incoming SSH traffic: | ||
391 | iptables -A INPUT -p tcp --dport 22 -j LED --led-trigger-id ssh --led-delay 1000 | ||
392 | |||
393 | Then attach the new trigger to an LED on your system: | ||
394 | echo netfilter-ssh > /sys/class/leds/<ledname>/trigger | ||
395 | |||
396 | For more information on the LEDs available on your system, see | ||
397 | Documentation/leds-class.txt | ||
398 | |||
375 | config NETFILTER_XT_TARGET_MARK | 399 | config NETFILTER_XT_TARGET_MARK |
376 | tristate '"MARK" target support' | 400 | tristate '"MARK" target support' |
377 | default m if NETFILTER_ADVANCED=n | 401 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index da73ed25701c..7a9b8397573a 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -46,6 +46,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o | |||
46 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | 46 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o |
47 | obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o | 47 | obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o |
48 | obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o | 48 | obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o |
49 | obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o | ||
49 | obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o | 50 | obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o |
50 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o | 51 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o |
51 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | 52 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o |
diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c new file mode 100644 index 000000000000..8ff7843bb921 --- /dev/null +++ b/net/netfilter/xt_LED.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * xt_LED.c - netfilter target to make LEDs blink upon packet matches | ||
3 | * | ||
4 | * Copyright (C) 2008 Adam Nielsen <a.nielsen@shikadi.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/skbuff.h> | ||
24 | #include <linux/netfilter/x_tables.h> | ||
25 | #include <linux/leds.h> | ||
26 | #include <linux/mutex.h> | ||
27 | |||
28 | #include <linux/netfilter/xt_LED.h> | ||
29 | |||
30 | MODULE_LICENSE("GPL"); | ||
31 | MODULE_AUTHOR("Adam Nielsen <a.nielsen@shikadi.net>"); | ||
32 | MODULE_DESCRIPTION("Xtables: trigger LED devices on packet match"); | ||
33 | |||
34 | /* | ||
35 | * This is declared in here (the kernel module) only, to avoid having these | ||
36 | * dependencies in userspace code. This is what xt_led_info.internal_data | ||
37 | * points to. | ||
38 | */ | ||
39 | struct xt_led_info_internal { | ||
40 | struct led_trigger netfilter_led_trigger; | ||
41 | struct timer_list timer; | ||
42 | }; | ||
43 | |||
44 | static unsigned int | ||
45 | led_tg(struct sk_buff *skb, const struct xt_target_param *par) | ||
46 | { | ||
47 | const struct xt_led_info *ledinfo = par->targinfo; | ||
48 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; | ||
49 | |||
50 | /* | ||
51 | * If "always blink" is enabled, and there's still some time until the | ||
52 | * LED will switch off, briefly switch it off now. | ||
53 | */ | ||
54 | if ((ledinfo->delay > 0) && ledinfo->always_blink && | ||
55 | timer_pending(&ledinternal->timer)) | ||
56 | led_trigger_event(&ledinternal->netfilter_led_trigger,LED_OFF); | ||
57 | |||
58 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_FULL); | ||
59 | |||
60 | /* If there's a positive delay, start/update the timer */ | ||
61 | if (ledinfo->delay > 0) { | ||
62 | mod_timer(&ledinternal->timer, | ||
63 | jiffies + msecs_to_jiffies(ledinfo->delay)); | ||
64 | |||
65 | /* Otherwise if there was no delay given, blink as fast as possible */ | ||
66 | } else if (ledinfo->delay == 0) { | ||
67 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); | ||
68 | } | ||
69 | |||
70 | /* else the delay is negative, which means switch on and stay on */ | ||
71 | |||
72 | return XT_CONTINUE; | ||
73 | } | ||
74 | |||
75 | static void led_timeout_callback(unsigned long data) | ||
76 | { | ||
77 | struct xt_led_info *ledinfo = (struct xt_led_info *)data; | ||
78 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; | ||
79 | |||
80 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); | ||
81 | } | ||
82 | |||
83 | static bool led_tg_check(const struct xt_tgchk_param *par) | ||
84 | { | ||
85 | struct xt_led_info *ledinfo = par->targinfo; | ||
86 | struct xt_led_info_internal *ledinternal; | ||
87 | int err; | ||
88 | |||
89 | if (ledinfo->id[0] == '\0') { | ||
90 | printk(KERN_ERR KBUILD_MODNAME ": No 'id' parameter given.\n"); | ||
91 | return false; | ||
92 | } | ||
93 | |||
94 | ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL); | ||
95 | if (!ledinternal) { | ||
96 | printk(KERN_CRIT KBUILD_MODNAME ": out of memory\n"); | ||
97 | return false; | ||
98 | } | ||
99 | |||
100 | ledinternal->netfilter_led_trigger.name = ledinfo->id; | ||
101 | |||
102 | err = led_trigger_register(&ledinternal->netfilter_led_trigger); | ||
103 | if (err) { | ||
104 | printk(KERN_CRIT KBUILD_MODNAME | ||
105 | ": led_trigger_register() failed\n"); | ||
106 | if (err == -EEXIST) | ||
107 | printk(KERN_ERR KBUILD_MODNAME | ||
108 | ": Trigger name is already in use.\n"); | ||
109 | goto exit_alloc; | ||
110 | } | ||
111 | |||
112 | /* See if we need to set up a timer */ | ||
113 | if (ledinfo->delay > 0) | ||
114 | setup_timer(&ledinternal->timer, led_timeout_callback, | ||
115 | (unsigned long)ledinfo); | ||
116 | |||
117 | ledinfo->internal_data = ledinternal; | ||
118 | |||
119 | return true; | ||
120 | |||
121 | exit_alloc: | ||
122 | kfree(ledinternal); | ||
123 | |||
124 | return false; | ||
125 | } | ||
126 | |||
127 | static void led_tg_destroy(const struct xt_tgdtor_param *par) | ||
128 | { | ||
129 | const struct xt_led_info *ledinfo = par->targinfo; | ||
130 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; | ||
131 | |||
132 | if (ledinfo->delay > 0) | ||
133 | del_timer_sync(&ledinternal->timer); | ||
134 | |||
135 | led_trigger_unregister(&ledinternal->netfilter_led_trigger); | ||
136 | kfree(ledinternal); | ||
137 | } | ||
138 | |||
139 | static struct xt_target led_tg_reg __read_mostly = { | ||
140 | .name = "LED", | ||
141 | .revision = 0, | ||
142 | .family = NFPROTO_UNSPEC, | ||
143 | .target = led_tg, | ||
144 | .targetsize = XT_ALIGN(sizeof(struct xt_led_info)), | ||
145 | .checkentry = led_tg_check, | ||
146 | .destroy = led_tg_destroy, | ||
147 | .me = THIS_MODULE, | ||
148 | }; | ||
149 | |||
150 | static int __init led_tg_init(void) | ||
151 | { | ||
152 | return xt_register_target(&led_tg_reg); | ||
153 | } | ||
154 | |||
155 | static void __exit led_tg_exit(void) | ||
156 | { | ||
157 | xt_unregister_target(&led_tg_reg); | ||
158 | } | ||
159 | |||
160 | module_init(led_tg_init); | ||
161 | module_exit(led_tg_exit); | ||