Adam, I wanted to apply this, but I get rejects for every single existing file. There appears to be some whitespace damage, please resend as attachment.
Hmm, that's odd - Thunderbird must not like sending tabs - sorry about that! I hope the attached files work better. Cheers, Adam.
Kernel module providing implementation of LED netfilter target. Each instance of the target appears as a led-trigger device, which can be associated with one or more LEDs in /sys/class/leds/ Acked-by: Richard Purdie <rpurdie@xxxxxxxxxxxxxxx> Signed-off-by: Adam Nielsen <a.nielsen@xxxxxxxxxxx> --- diff -urN linux-2.6.28.3-orig/drivers/leds/Kconfig linux-2.6.28.3/drivers/leds/Kconfig --- linux-2.6.28.3-orig/drivers/leds/Kconfig 2009-02-03 04:12:10.000000000 +1000 +++ linux-2.6.28.3/drivers/leds/Kconfig 2009-02-08 22:46:06.844626971 +1000 @@ -217,4 +217,7 @@ This allows LEDs to be initialised in the ON state. If unsure, say Y. +comment "iptables trigger is under Netfilter config (LED target)" + depends on LEDS_TRIGGERS + endif # NEW_LEDS diff -urN linux-2.6.28.3-orig/include/linux/netfilter/Kbuild linux-2.6.28.3/include/linux/netfilter/Kbuild --- linux-2.6.28.3-orig/include/linux/netfilter/Kbuild 2009-02-03 04:12:10.000000000 +1000 +++ linux-2.6.28.3/include/linux/netfilter/Kbuild 2009-02-08 22:46:06.911560913 +1000 @@ -7,6 +7,7 @@ header-y += xt_CONNMARK.h header-y += xt_CONNSECMARK.h header-y += xt_DSCP.h +header-y += xt_LED.h header-y += xt_MARK.h header-y += xt_NFLOG.h header-y += xt_NFQUEUE.h diff -urN linux-2.6.28.3-orig/include/linux/netfilter/xt_LED.h linux-2.6.28.3/include/linux/netfilter/xt_LED.h --- linux-2.6.28.3-orig/include/linux/netfilter/xt_LED.h 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.6.28.3/include/linux/netfilter/xt_LED.h 2009-02-12 07:29:19.033631735 +1000 @@ -0,0 +1,13 @@ +#ifndef _XT_LED_H +#define _XT_LED_H + +struct xt_led_info { + char id[27]; /* Unique ID for this trigger in the LED class */ + __u8 always_blink; /* Blink even if the LED is already on */ + __u32 delay; /* Delay until LED is switched off after trigger */ + + /* Kernel data used in the module */ + void *internal_data __attribute__((aligned(8))); +}; + +#endif /* _XT_LED_H */ diff -urN linux-2.6.28.3-orig/net/netfilter/Kconfig linux-2.6.28.3/net/netfilter/Kconfig --- linux-2.6.28.3-orig/net/netfilter/Kconfig 2009-02-03 04:12:10.000000000 +1000 +++ linux-2.6.28.3/net/netfilter/Kconfig 2009-02-08 22:46:06.982631079 +1000 @@ -357,6 +357,30 @@ To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_TARGET_LED + tristate '"LED" target support' + depends on LEDS_CLASS + depends on NETFILTER_ADVANCED + help + This option adds a `LED' target, which allows you to blink LEDs in + response to particular packets passing through your machine. + + This can be used to turn a spare LED into a network activity LED, + which only flashes in response to FTP transfers, for example. Or + you could have an LED which lights up for a minute or two every time + somebody connects to your machine via SSH. + + You will need support for the "led" class to make this work. + + To create an LED trigger for incoming SSH traffic: + iptables -A INPUT -p tcp --dport 22 -j LED --led-trigger-id ssh --led-delay 1000 + + Then attach the new trigger to an LED on your system: + echo netfilter-ssh > /sys/class/leds/<ledname>/trigger + + For more information on the LEDs available on your system, see + Documentation/leds-class.txt + config NETFILTER_XT_TARGET_MARK tristate '"MARK" target support' default m if NETFILTER_ADVANCED=n diff -urN linux-2.6.28.3-orig/net/netfilter/Makefile linux-2.6.28.3/net/netfilter/Makefile --- linux-2.6.28.3-orig/net/netfilter/Makefile 2009-02-03 04:12:10.000000000 +1000 +++ linux-2.6.28.3/net/netfilter/Makefile 2009-02-08 22:46:07.031632072 +1000 @@ -45,6 +45,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o +obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o diff -urN linux-2.6.28.3-orig/net/netfilter/xt_LED.c linux-2.6.28.3/net/netfilter/xt_LED.c --- linux-2.6.28.3-orig/net/netfilter/xt_LED.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.6.28.3/net/netfilter/xt_LED.c 2009-02-12 21:23:42.081990028 +1000 @@ -0,0 +1,162 @@ +/* + * xt_LED.c - netfilter target to make LEDs blink upon packet matches + * + * Copyright (C) 2008 Adam Nielsen <a.nielsen@xxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + * + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/netfilter/x_tables.h> +#include <linux/leds.h> +#include <linux/mutex.h> + +#include <linux/netfilter/xt_LED.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Adam Nielsen <a.nielsen@xxxxxxxxxxx>"); +MODULE_DESCRIPTION("Xtables: trigger LED devices on packet match"); + +/* + * This is declared in here (the kernel module) only, to avoid having these + * dependencies in userspace code. This is what xt_led_info.internal_data + * points to. + */ +struct xt_led_info_internal { + struct led_trigger netfilter_led_trigger; + struct timer_list timer; +}; + +static unsigned int +led_tg(struct sk_buff *skb, const struct xt_target_param *par) +{ + const struct xt_led_info *ledinfo = par->targinfo; + /*noconst*/struct xt_led_info_internal *ledinternal = ledinfo->internal_data; + + /* + * If "always blink" is enabled, and there's still some time until the + * LED will switch off, briefly switch it off now. + */ + if ((ledinfo->delay > 0) && ledinfo->always_blink + && timer_pending(&ledinternal->timer)) + led_trigger_event(&ledinternal->netfilter_led_trigger, + LED_OFF); + + led_trigger_event(&ledinternal->netfilter_led_trigger, LED_FULL); + + /* If there's a positive delay, start/update the timer */ + if (ledinfo->delay > 0) { + mod_timer(&ledinternal->timer, + jiffies + msecs_to_jiffies(ledinfo->delay)); + + /* Otherwise if there was no delay given, blink as fast as possible */ + } else if (ledinfo->delay == 0) { + led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); + } + + /* else the delay is negative, which means switch on and stay on */ + + return XT_CONTINUE; +} + +static void led_timeout_callback(unsigned long data) +{ + struct xt_led_info *ledinfo = (struct xt_led_info *)data; + struct xt_led_info_internal *ledinternal = ledinfo->internal_data; + + led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); +} + +static bool led_tg_check(const struct xt_tgchk_param *par) +{ + /*noconst*/ struct xt_led_info *ledinfo = par->targinfo; + struct xt_led_info_internal *ledinternal; + int err; + + if (ledinfo->id[0] == '\0') { + printk(KERN_ERR KBUILD_MODNAME ": No 'id' parameter given.\n"); + return false; + } + + ledinternal = kzalloc(sizeof(struct xt_led_info_internal), GFP_KERNEL); + if (!ledinternal) { + printk(KERN_CRIT KBUILD_MODNAME ": out of memory\n"); + return false; + } + + ledinternal->netfilter_led_trigger.name = ledinfo->id; + + err = led_trigger_register(&ledinternal->netfilter_led_trigger); + if (err) { + printk(KERN_CRIT KBUILD_MODNAME + ": led_trigger_register() failed\n"); + if (err == -EEXIST) + printk(KERN_ERR KBUILD_MODNAME + ": Trigger name is already in use.\n"); + goto exit_alloc; + } + + /* See if we need to set up a timer */ + if (ledinfo->delay > 0) + setup_timer(&ledinternal->timer, led_timeout_callback, + (unsigned long) ledinfo); + + ledinfo->internal_data = ledinternal; + + return true; + +exit_alloc: + kfree(ledinternal); + + return false; +} + +static void led_tg_destroy(const struct xt_tgdtor_param *par) +{ + const struct xt_led_info *ledinfo = par->targinfo; + /*noconst*/struct xt_led_info_internal *ledinternal = ledinfo->internal_data; + + if (ledinfo->delay > 0) + del_timer_sync(&ledinternal->timer); + + led_trigger_unregister(&ledinternal->netfilter_led_trigger); + kfree(ledinternal); +} + +static struct xt_target led_tg_reg __read_mostly = { + .name = "LED", + .revision = 0, + .family = NFPROTO_UNSPEC, + .target = led_tg, + .targetsize = XT_ALIGN(sizeof(struct xt_led_info)), + .checkentry = led_tg_check, + .destroy = led_tg_destroy, + .me = THIS_MODULE, +}; + +static int __init led_tg_init(void) +{ + return xt_register_target(&led_tg_reg); +} + +static void __exit led_tg_exit(void) +{ + xt_unregister_target(&led_tg_reg); +} + +module_init(led_tg_init); +module_exit(led_tg_exit);
Add a new "LED" target to iptables, which allows LEDs to blink in response to matching rules. Signed-off-by: Adam Nielsen <a.nielsen@xxxxxxxxxxx> --- diff --git a/extensions/libxt_LED.c b/extensions/libxt_LED.c new file mode 100644 index 0000000..c76a38a --- /dev/null +++ b/extensions/libxt_LED.c @@ -0,0 +1,158 @@ +/* + * libxt_LED.c - shared library add-on to iptables to add customized LED + * trigger support. + * + * (C) 2008 Adam Nielsen <a.nielsen@xxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <stddef.h> + +#include <xtables.h> + +#include <linux/netfilter/xt_LED.h> + +static const struct option LED_opts[] = { + { .name = "led-trigger-id", .has_arg = 1, .val = 'i' }, + { .name = "led-delay", .has_arg = 1, .val = 'd' }, + { .name = "led-always-blink", .has_arg = 0, .val = 'a' }, + { .name = NULL } +}; + +static void LED_help(void) +{ + printf( +"LED target options:\n" +"--led-trigger-id name suffix for led trigger name\n" +"--led-delay ms leave the LED on for this number of\n" +" milliseconds after triggering.\n" +"--led-always-blink blink on arriving packets, even if\n" +" the LED is already on.\n" + ); +} + +static int LED_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct xt_led_info *led = (struct xt_led_info *)(*target)->data; + + switch (c) { + case 'i': + param_act(P_NO_INVERT, "LED", "--led-trigger-id", invert); + + if (strlen("netfilter-") + strlen(optarg) > sizeof(led->id)) + exit_error(PARAMETER_PROBLEM, + "--led-trigger-id must be 16 chars or less"); + + if (optarg[0] == '\0') + exit_error(PARAMETER_PROBLEM, + "--led-trigger-id cannot be blank"); + + /* "netfilter-" + 16 char id == 26 == sizeof(led->id) */ + strcpy(led->id, "netfilter-"); + strcat(led->id, optarg); + *flags = 1; + return 1; + + case 'd': + param_act(P_NO_INVERT, "LED", "--led-delay", invert); + + if (strncasecmp(optarg, "inf", 3) == 0) + led->delay = -1; + else + led->delay = strtoul(optarg, NULL, 0); + + return 1; + + case 'a': + if (!invert) + led->always_blink = 1; + + return 1; + + } + return 0; +} + +static void LED_final_check(unsigned int flags) +{ + if (!flags) + exit_error(PARAMETER_PROBLEM, + "--led-trigger-id must be specified"); +} + +static void LED_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct xt_led_info *led = (const struct xt_led_info *)target->data; + const char *id = led->id + strlen("netfilter-"); /* trim off prefix */ + + printf("led-trigger-id:\""); + /* Escape double quotes and backslashes in the ID */ + while (*id) { + if ((*id == '"') || (*id == '\\')) + printf("\\"); + printf("%c", *id++); + } + printf("\" "); + + if (led->delay == -1) + printf("led-delay:inf "); + else + printf("led-delay:%dms ", led->delay); + + if (led->always_blink) + printf("led-always-blink "); +} + +static void LED_save(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_led_info *led = (const struct xt_led_info *)target->data; + const char *id = led->id + strlen("netfilter-"); /* trim off prefix */ + + printf("--led-trigger-id \""); + /* Escape double quotes and backslashes in the ID */ + while (*id) { + if ((*id == '"') || (*id == '\\')) + printf("\\"); + printf("%c", *id++); + } + printf("\" "); + + /* Only print the delay if it's not zero (the default) */ + if (led->delay > 0) + printf("--led-delay %d ", led->delay); + else if (led->delay == -1) + printf("--led-delay inf "); + + /* Only print always_blink if it's not set to the default */ + if (led->always_blink) + printf("--led-always-blink "); +} + +static struct xtables_target led_tg_reg = { + .family = PF_UNSPEC, + .name = "LED", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_led_info)), + .userspacesize = offsetof(struct xt_led_info, internal_data), + .help = LED_help, + .parse = LED_parse, + .final_check = LED_final_check, + .extra_opts = LED_opts, + .print = LED_print, + .save = LED_save, +}; + +void _init(void) +{ + xtables_register_target(&led_tg_reg); +} diff --git a/extensions/libxt_LED.man b/extensions/libxt_LED.man new file mode 100644 index 0000000..b65b3c2 --- /dev/null +++ b/extensions/libxt_LED.man @@ -0,0 +1,30 @@ +This creates an LED-trigger that can then be attached to system indicator +lights, to blink or illuminate them when certain packets pass through the +system. One example might be to light up an LED for a few minutes every time +an SSH connection is made to the local machine. The following options control +the trigger behaviour: +.TP +\fB--led-trigger-id\fP \fIname\fP +This is the name given to the LED trigger. The actual name of the trigger +will be prefixed with "netfilter-". +.TP +\fB--led-delay\fP \fIms\fP +This indicates how long (in milliseconds) the LED should be left illuminated +when a packet arrives before being switched off again. The default is 0 +(blink as fast as possible.) The special value \fIinf\fP can be given to +leave the LED on permanently once activated. (In this case the trigger will +need to be manually detached and reattached to the LED device to switch it +off again.) +.TP +\fB--led-always-blink\fP +Always make the LED blink on packet arrival, even if the LED is already on. +This allows notification of new packets even with long delay values (which +otherwise would result in a silent prolonging of the delay time.) +.TP +Example: +.TP +Create an LED trigger for incoming SSH traffic: +iptables -A INPUT -p tcp --dport 22 -j LED --led-trigger-id ssh +.TP +Then attach the new trigger to an LED: +echo netfilter-ssh > /sys/class/leds/<ledname>/trigger diff --git a/include/linux/netfilter/xt_LED.h b/include/linux/netfilter/xt_LED.h new file mode 100644 index 0000000..4c91a0d --- /dev/null +++ b/include/linux/netfilter/xt_LED.h @@ -0,0 +1,13 @@ +#ifndef _XT_LED_H +#define _XT_LED_H + +struct xt_led_info { + char id[27]; /* Unique ID for this trigger in the LED class */ + __u8 always_blink; /* Blink even if the LED is already on */ + __u32 delay; /* Delay until LED is switched off after trigger */ + + /* Kernel data used in the module */ + void *internal_data __attribute__((aligned(8))); +}; + +#endif /* _XT_LED_H */