blob: ead6de7053e7abbd49154b3fd7fdcb4587113cb6 [file] [log] [blame]
/* Shared library add-on to iptables to add LED support. */
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_LED.h>
#include <linux/ledman.h>
static struct option opts[] = {
{ .name = "led", .has_arg = 1, .flag = 0, .val = '1' },
{ .name = "save", .has_arg = 0, .flag = 0, .val = '2' },
{ .name = "restore", .has_arg = 0, .flag = 0, .val = '3' },
{ .name = NULL }
};
static void
init(struct xt_entry_target *t)
{
struct ipt_led_info *ledinfo = (struct ipt_led_info *)t->data;
ledinfo->led = LEDMAN_ALL;
ledinfo->mode = IPT_LED_SET;
}
struct ipt_led_names {
const char *name;
u_int32_t led;
};
static struct ipt_led_names ipt_led_names[] = {
#include "libipt_LED_def.c"
{ }
};
static u_int32_t
parse_led(const char *name)
{
unsigned int led = -1;
unsigned int set = 0;
if (!xtables_strtoui(name, NULL, &led, 0, 7)) {
unsigned int i = 0;
for (i = 0; ipt_led_names[i].name; i++) {
if (strcasecmp(name, ipt_led_names[i].name) == 0) {
set++;
led = ipt_led_names[i].led;
break;
}
if (strncasecmp(name, ipt_led_names[i].name,
strlen(name)) == 0) {
if (set++)
xtables_error(PARAMETER_PROBLEM,
"led `%s' ambiguous", name);
led = ipt_led_names[i].led;
}
}
if (!set)
xtables_error(PARAMETER_PROBLEM,
"led `%s' unknown", name);
}
return led;
}
#define IPT_LED_OPT_LED 0x01
#define IPT_LED_OPT_MODE 0x02
#define IPT_LED_OPT_NO_LED 0x04
static int
parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry,
struct xt_entry_target **target)
{
struct ipt_led_info *ledinfo = (struct ipt_led_info *)(*target)->data;
switch (c) {
case '1':
if (*flags & IPT_LED_OPT_LED)
xtables_error(PARAMETER_PROBLEM,
"Can't specify --led twice");
ledinfo->led = parse_led(optarg);
*flags |= IPT_LED_OPT_LED;
break;
case '2':
if (*flags & IPT_LED_OPT_MODE)
xtables_error(PARAMETER_PROBLEM,
"Can't specify --save twice");
ledinfo->mode = IPT_LED_SAVE;
*flags |= IPT_LED_OPT_MODE;
break;
case '3':
if (*flags & IPT_LED_OPT_MODE)
xtables_error(PARAMETER_PROBLEM,
"Can't specify --restore twice");
ledinfo->mode = IPT_LED_RESTORE;
*flags |= IPT_LED_OPT_MODE | IPT_LED_OPT_NO_LED;
break;
default:
return 0;
}
return 1;
}
static void
final_check(unsigned int flags)
{
if ((flags & IPT_LED_OPT_NO_LED) && (flags & IPT_LED_OPT_LED))
xtables_error(PARAMETER_PROBLEM,
"LED target: Can't specify --led with --restore");
if (!(flags & IPT_LED_OPT_NO_LED) && !(flags & IPT_LED_OPT_LED))
xtables_error(PARAMETER_PROBLEM,
"LED target: No --led specified");
}
static void
print(const void *ip,
const struct xt_entry_target *target,
int numeric)
{
const struct ipt_led_info *ledinfo
= (const struct ipt_led_info *)target->data;
unsigned int i;
printf("LED ");
switch (ledinfo->mode) {
case IPT_LED_SAVE:
printf("save ");
/* fallthrough */
case IPT_LED_SET:
for (i = 0; ipt_led_names[i].name; i++) {
if (ledinfo->led == ipt_led_names[i].led) {
printf("led %s ", ipt_led_names[i].name);
break;
}
}
if (!ipt_led_names[i].name)
printf("UNKNOWN led %u ", ledinfo->led);
break;
case IPT_LED_RESTORE:
printf("restore ");
break;
default:
printf("ERROR: UNKNOWN LED MODE ");
break;
}
}
static void
save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_led_info *ledinfo
= (const struct ipt_led_info *)target->data;
unsigned int i;
switch (ledinfo->mode) {
case IPT_LED_SAVE:
printf("--save ");
/* fallthrough */
case IPT_LED_SET:
printf("--led ");
for (i = 0; ipt_led_names[i].name; i++) {
if (ledinfo->led == ipt_led_names[i].led) {
printf("led %s ", ipt_led_names[i].name);
break;
}
}
if (!ipt_led_names[i].name)
printf("%u ", ledinfo->led);
break;
case IPT_LED_RESTORE:
printf("--restore ");
break;
default:
printf("ERROR: UNKNOWN LED MODE ");
break;
}
}
static void
help(void)
{
unsigned int i;
printf(
"LED target options:\n"
" --led LED LED to set\n"
" --save Save the LED value in the connection\n"
" --restore Use the saved LED value\n");
printf("LED names:\n");
for (i = 0; ipt_led_names[i].name; i++)
printf(" %s\n", ipt_led_names[i].name);
}
static
struct xtables_target led
= {
.name = "LED",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct ipt_led_info)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_led_info)),
.help = &help,
.init = &init,
.parse = &parse,
.final_check = &final_check,
.print = &print,
.save = &save,
.extra_opts = opts
};
void _init(void)
{
xtables_register_target(&led);
}