From 6d2998588de3d81129c98efd52040ea849cbf135 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 30 Jan 2008 13:54:57 +0100 Subject: [PATCH] Add xt_LOGMARK (nfmark, ctmark, secmark logger) xt_LOGMARK dumps the nfmark (packet mark), ctmark (connection mark) and/or secmark to syslog. Signed-off-by: Jan Engelhardt --- extensions/Kbuild | 1 + extensions/Makefile.am | 1 + extensions/libxt_LOGMARK.c | 168 ++++++++++++++++++++++++++++++++++ extensions/libxt_LOGMARK.man | 17 ++++ extensions/xt_LOGMARK.Kconfig | 6 ++ extensions/xt_LOGMARK.c | 99 ++++++++++++++++++++ extensions/xt_LOGMARK.h | 16 ++++ 7 files changed, 308 insertions(+) create mode 100644 extensions/libxt_LOGMARK.c create mode 100644 extensions/libxt_LOGMARK.man create mode 100644 extensions/xt_LOGMARK.Kconfig create mode 100644 extensions/xt_LOGMARK.c create mode 100644 extensions/xt_LOGMARK.h diff --git a/extensions/Kbuild b/extensions/Kbuild index 73c477f..8662717 100644 --- a/extensions/Kbuild +++ b/extensions/Kbuild @@ -1,5 +1,6 @@ # -*- Makefile -*- +obj-m += xt_LOGMARK.o obj-m += xt_TARPIT.o obj-m += xt_TEE.o obj-m += compat_xtables.o diff --git a/extensions/Makefile.am b/extensions/Makefile.am index 92403d1..d838aac 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -10,6 +10,7 @@ AM_CFLAGS = ${regular_CFLAGS} ${iptables_CFLAGS} ${kinclude_CFLAGS} \ -D_INIT=$*_init AM_LDFLAGS = -module -avoid-version ipt_LTLIBRARIES = \ + libxt_LOGMARK.la \ libxt_TARPIT.la \ libxt_TEE.la diff --git a/extensions/libxt_LOGMARK.c b/extensions/libxt_LOGMARK.c new file mode 100644 index 0000000..b074c59 --- /dev/null +++ b/extensions/libxt_LOGMARK.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include "xt_LOGMARK.h" + +enum { + F_LEVEL = 1 << 0, + F_PREFIX = 1 << 1, + F_NFMARK = 1 << 2, + F_CTMARK = 1 << 3, + F_SECMARK = 1 << 4, +}; + +static const struct option logmark_tg_opts[] = { + {.name = "log-level", .has_arg = true, .val = 'l'}, + {.name = "log-prefix", .has_arg = true, .val = 'p'}, + {.name = "log-nfmark", .has_arg = false, .val = 'n'}, + {.name = "log-ctmark", .has_arg = false, .val = 'c'}, + {.name = "log-secmark", .has_arg = false, .val = 's'}, + {}, +}; + +static void logmark_tg_help(void) +{ + printf( +"LOGMARK target options:\n" +" --log-level level Level of logging (numeric, 0-8)\n" +" --log-prefix prefix Prefix log messages with this string\n" +" --log-nfmark Log the packet mark\n" +" --log-ctmark Log the connection mark\n" +" --log-secmark Log the security mark of the packet\n" +); +} + +static void logmark_tg_init(struct xt_entry_target *target) +{ + struct xt_logmark_tginfo *info = (void *)target->data; + + info->level = 4; + *info->prefix = '\0'; +} + +static int +logmark_tg_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct xt_logmark_tginfo *info = (void *)(*target)->data; + unsigned int x; + + switch (c) { + case 'l': /* --log-level */ + param_act(P_ONLY_ONCE, "LOGMARK", "--log-level", *flags & F_LEVEL); + param_act(P_NO_INVERT, "LOGMARK", "--log-level", invert); + if (!strtonum(optarg, NULL, &x, 0, 8)) + param_act(P_BAD_VALUE, "LOGMARK", "--log-level", optarg); + info->level = x; + *flags |= F_LEVEL; + return true; + + case 'p': /* --log-prefix */ + param_act(P_ONLY_ONCE, "LOGMARK", "--log-prefix", *flags & F_PREFIX); + param_act(P_NO_INVERT, "LOGMARK", "--log-prefix", invert); + if (strlen(optarg) > sizeof(info->prefix)) + exit_error(PARAMETER_PROBLEM, "LOGMARK: Maximum " + "prefix length is %zu", + sizeof(info->prefix)); + if (strchr(optarg, '\n')) + exit_error(PARAMETER_PROBLEM, "LOGMARK: Newlines not " + "allowed in log prefix"); + strncpy(info->prefix, optarg, sizeof(info->prefix)); + *flags |= F_PREFIX; + return true; + + case 'n': /* --log-nfmark */ + param_act(P_ONLY_ONCE, "LOGMARK", "--log-nfmark", *flags & F_NFMARK); + param_act(P_NO_INVERT, "LOGMARK", "--log-nfmark", invert); + info->flags |= XT_LOGMARK_NFMARK; + *flags |= F_NFMARK; + return true; + + case 'c': /* --log-ctmark */ + param_act(P_ONLY_ONCE, "LOGMARK", "--log-ctmark", *flags & F_CTMARK); + param_act(P_NO_INVERT, "LOGMARK", "--log-ctmark", invert); + info->flags |= XT_LOGMARK_CTMARK; + *flags |= F_CTMARK; + return true; + + case 's': /* --log-secmark */ + param_act(P_ONLY_ONCE, "LOGMARK", "--log-secmark", *flags & F_SECMARK); + param_act(P_NO_INVERT, "LOGMARK", "--log-secmark", invert); + info->flags |= XT_LOGMARK_SECMARK; + *flags |= F_SECMARK; + return true; + } + return false; +} + +static void +logmark_tg_print(const void *ip, const struct xt_entry_target *target, + int numeric) +{ + const struct xt_logmark_tginfo *info = (void *)target->data; + + printf("LOGMARK level %u prefix \"%s\"", info->level, info->prefix); + if (info->flags & XT_LOGMARK_NFMARK) + printf(" nfmark"); + if (info->flags & XT_LOGMARK_CTMARK) + printf(" ctmark"); + if (info->flags & XT_LOGMARK_SECMARK) + printf(" secmark"); + printf("; "); +} + +static void +logmark_tg_save(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_logmark_tginfo *info = (void *)target->data; + + if (info->level != 4) + printf("--log-level %u ", info->level); + if (*info->prefix != '\0') + printf("--log-prefix \"%s\" ", info->prefix); + if (info->flags & XT_LOGMARK_NFMARK) + printf("--log-nfmark "); + if (info->flags & XT_LOGMARK_CTMARK) + printf("--log-ctmark "); + if (info->flags & XT_LOGMARK_SECMARK) + printf("--log-secmark "); +} + +static struct xtables_target logmark_tg_reg = { + .version = IPTABLES_VERSION, + .name = "LOGMARK", + .revision = 0, + .family = AF_INET, + .size = XT_ALIGN(sizeof(struct xt_logmark_tginfo)), + .userspacesize = XT_ALIGN(sizeof(struct xt_logmark_tginfo)), + .help = logmark_tg_help, + .init = logmark_tg_init, + .parse = logmark_tg_parse, + .print = logmark_tg_print, + .save = logmark_tg_save, + .extra_opts = logmark_tg_opts, +}; + +static struct xtables_target logmark_tg6_reg = { + .version = IPTABLES_VERSION, + .name = "LOGMARK", + .revision = 0, + .family = AF_INET6, + .size = XT_ALIGN(sizeof(struct xt_logmark_tginfo)), + .userspacesize = XT_ALIGN(sizeof(struct xt_logmark_tginfo)), + .help = logmark_tg_help, + .init = logmark_tg_init, + .parse = logmark_tg_parse, + .print = logmark_tg_print, + .save = logmark_tg_save, + .extra_opts = logmark_tg_opts, +}; + +void _init(void); +void _init(void) +{ + xtables_register_target(&logmark_tg_reg); + xtables_register_target(&logmark_tg6_reg); +} diff --git a/extensions/libxt_LOGMARK.man b/extensions/libxt_LOGMARK.man new file mode 100644 index 0000000..e954aa4 --- /dev/null +++ b/extensions/libxt_LOGMARK.man @@ -0,0 +1,17 @@ +The LOGMARK target will log packet and connection marks to syslog. +.TP +\fB--log-level\fR \fIlevel\fR +A logging level between 0 and 8 (inclusive). +.TP +\fB--log-prefix\fR \fIstring\fR +Prefix log messages with the specified prefix; up to 29 bytes long, and useful +for distinguishing messages in the logs. +.TP +\fB--log-nfmark\fR +Include the packet mark in the log. +.TP +\fB--log-ctmark\fR +Include the connection mark in the log. +.TP +\fB--log-secmark\fR +Include the packet secmark in the log. diff --git a/extensions/xt_LOGMARK.Kconfig b/extensions/xt_LOGMARK.Kconfig new file mode 100644 index 0000000..3743010 --- /dev/null +++ b/extensions/xt_LOGMARK.Kconfig @@ -0,0 +1,6 @@ +config NETFILTER_XT_TARGET_LOGMARK + tristate '"LOGMARK" target support' + depends on NETFILTER_XTABLES + ---help--- + This option adds a "LOGMARK" target which allows you to look at the + netfilter marks and secmark of the packet and connection. diff --git a/extensions/xt_LOGMARK.c b/extensions/xt_LOGMARK.c new file mode 100644 index 0000000..d6c05c7 --- /dev/null +++ b/extensions/xt_LOGMARK.c @@ -0,0 +1,99 @@ +/* + * xt_LOGMARK - netfilter mark logging + * useful for debugging + * + * Copyright © CC Computer Consultants, 2007 - 2008 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 or 3 as published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include "compat_xtables.h" +#include "xt_LOGMARK.h" + +static unsigned int +logmark_tg(struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, unsigned int hooknum, + const struct xt_target *target, const void *targinfo) +{ + const struct xt_logmark_tginfo *info = targinfo; + + printk("<%u>%.*s", info->level, sizeof(info->prefix), info->prefix); + + if (info->flags & XT_LOGMARK_NFMARK) + printk(" nfmark=0x%x", skb->mark); + if (info->flags & XT_LOGMARK_CTMARK) { + const struct nf_conn *ct; + enum ip_conntrack_info ctinfo; + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) + printk(" ctmark=X"); + else + printk(" ctmark=0x%x", ct->mark); + } + if (info->flags & XT_LOGMARK_SECMARK) + printk(" secmark=0x%x", skb->secmark); + printk("\n"); + + return XT_CONTINUE; +} + +static bool +logmark_tg_check(const char *tablename, const void *e, + const struct xt_target *target, void *targinfo, + unsigned int hook_mask) +{ + const struct xt_logmark_tginfo *info = targinfo; + + if (info->level >= 8) { + pr_debug("LOGMARK: level %u >= 8\n", info->level); + return false; + } + + return true; +} + +static struct xt_target logmark_tg_reg[] __read_mostly = { + { + .name = "LOGMARK", + .revision = 0, + .family = AF_INET, + .checkentry = logmark_tg_check, + .target = logmark_tg, + .targetsize = sizeof(struct xt_logmark_tginfo), + .me = THIS_MODULE, + }, + { + .name = "LOGMARK", + .revision = 0, + .family = AF_INET6, + .checkentry = logmark_tg_check, + .target = logmark_tg, + .targetsize = sizeof(struct xt_logmark_tginfo), + .me = THIS_MODULE, + }, +}; + +static int __init logmark_tg_init(void) +{ + return xt_register_targets(logmark_tg_reg, ARRAY_SIZE(logmark_tg_reg)); +} + +static void __exit logmark_tg_exit(void) +{ + xt_unregister_targets(logmark_tg_reg, ARRAY_SIZE(logmark_tg_reg)); +} + +module_init(logmark_tg_init); +module_exit(logmark_tg_exit); +MODULE_DESCRIPTION("Xtables: netfilter mark logging to syslog"); +MODULE_AUTHOR("Jan Engelhardt "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_LOGMARK"); +MODULE_ALIAS("ip6t_LOGMARK"); diff --git a/extensions/xt_LOGMARK.h b/extensions/xt_LOGMARK.h new file mode 100644 index 0000000..0f1ed52 --- /dev/null +++ b/extensions/xt_LOGMARK.h @@ -0,0 +1,16 @@ +#ifndef _LINUX_NETFILTER_XT_LOGMARK_TARGET_H +#define _LINUX_NETFILTER_XT_LOGMARK_TARGET_H 1 + +enum { + XT_LOGMARK_NFMARK = 1 << 0, + XT_LOGMARK_CTMARK = 1 << 1, + XT_LOGMARK_SECMARK = 1 << 2, +}; + +struct xt_logmark_tginfo { + char prefix[14]; + u_int8_t level; + u_int8_t flags; +}; + +#endif /* _LINUX_NETFILTER_XT_LOGMARK_TARGET_H */