summaryrefslogtreecommitdiffstats
path: root/extensions/libxt_CONNMARK.c
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@medozas.de>2008-01-29 13:36:27 +0000
committerPatrick McHardy <kaber@trash.net>2008-01-29 13:36:27 +0000
commitff068719055ae2327d94c79048381c09d3b744c4 (patch)
treebbb3ee304c3f8cc28f1513728019c3334a328283 /extensions/libxt_CONNMARK.c
parenta99cb4444ceff1b0029c7e25b0714dbee9021b12 (diff)
libxt_CONNMARK revision 1
Add support for xt_CONNMARK target revision 1. Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
Diffstat (limited to 'extensions/libxt_CONNMARK.c')
-rw-r--r--extensions/libxt_CONNMARK.c264
1 files changed, 256 insertions, 8 deletions
diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c
index f8c3caba..95d6b1cd 100644
--- a/extensions/libxt_CONNMARK.c
+++ b/extensions/libxt_CONNMARK.c
@@ -28,12 +28,10 @@
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_CONNMARK.h>
-#if 0
-struct markinfo {
- struct xt_entry_target t;
- struct ipt_connmark_target_info mark;
+enum {
+ F_MARK = 1 << 0,
+ F_SR_MARK = 1 << 1,
};
-#endif
/* Function which prints out usage message. */
static void CONNMARK_help(void)
@@ -55,6 +53,50 @@ static const struct option CONNMARK_opts[] = {
{ }
};
+static const struct option connmark_tg_opts[] = {
+ {.name = "set-xmark", .has_arg = true, .val = '='},
+ {.name = "set-mark", .has_arg = true, .val = '-'},
+ {.name = "and-mark", .has_arg = true, .val = '&'},
+ {.name = "or-mark", .has_arg = true, .val = '|'},
+ {.name = "xor-mark", .has_arg = true, .val = '^'},
+ {.name = "save-mark", .has_arg = false, .val = 'S'},
+ {.name = "restore-mark", .has_arg = false, .val = 'R'},
+ {.name = "ctmask", .has_arg = true, .val = 'c'},
+ {.name = "nfmask", .has_arg = true, .val = 'n'},
+ {.name = "mask", .has_arg = true, .val = 'm'},
+ {},
+};
+
+static void connmark_tg_help(void)
+{
+ printf(
+"CONNMARK target options:\n"
+" --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
+" --save-mark [--ctmask mask] [--nfmask mask]\n"
+" Copy ctmark to nfmark using masks\n"
+" --restore-mark [--ctmask mask] [--nfmask mask]\n"
+" Copy nfmark to ctmark using masks\n"
+" --set-mark value[/mask] Set conntrack mark value\n"
+" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
+" --restore-mark [--mask mask] Restore saved nfmark value\n"
+" --and-mark value Binary AND the ctmark with bits\n"
+" --or-mark value Binary OR the ctmark with bits\n"
+" --xor-mark value Binary XOR the ctmark with bits\n"
+);
+}
+
+static void connmark_tg_init(struct xt_entry_target *target)
+{
+ struct xt_connmark_tginfo1 *info = (void *)target->data;
+
+ /*
+ * Need these defaults for --save-mark/--restore-mark if no
+ * --ctmark or --nfmask is given.
+ */
+ info->ctmask = ~0U;
+ info->nfmask = ~0U;
+}
+
/* Function which parses command options; returns true if it
ate an option */
static int
@@ -110,7 +152,110 @@ CONNMARK_parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void CONNMARK_check(unsigned int flags)
+static int connmark_tg_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_connmark_tginfo1 *info = (void *)(*target)->data;
+ unsigned int value, mask = ~0U;
+ char *end;
+
+ switch (c) {
+ case '=': /* --set-xmark */
+ case '-': /* --set-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, &end, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ if (*end == '/')
+ if (!strtonum(end + 1, &end, &mask, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ if (*end != '\0')
+ param_act(P_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = mask;
+ if (c == '-')
+ info->ctmask |= value;
+ *flags |= F_MARK;
+ return true;
+
+ case '&': /* --and-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, NULL, &mask, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--and-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = 0;
+ info->ctmask = ~mask;
+ *flags |= F_MARK;
+ return true;
+
+ case '|': /* --or-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--or-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = value;
+ *flags |= F_MARK;
+ return true;
+
+ case '^': /* --xor-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--xor-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = 0;
+ *flags |= F_MARK;
+ return true;
+
+ case 'S': /* --save-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ info->mode = XT_CONNMARK_SAVE;
+ *flags |= F_MARK | F_SR_MARK;
+ return true;
+
+ case 'R': /* --restore-mark */
+ param_act(P_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ info->mode = XT_CONNMARK_RESTORE;
+ *flags |= F_MARK | F_SR_MARK;
+ return true;
+
+ case 'n': /* --nfmask */
+ if (!(*flags & F_SR_MARK))
+ exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--nfmask");
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--nfmask", optarg);
+ info->nfmask = value;
+ return true;
+
+ case 'c': /* --ctmask */
+ if (!(*flags & F_SR_MARK))
+ exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--ctmask");
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--ctmask", optarg);
+ info->ctmask = value;
+ return true;
+
+ case 'm': /* --mask */
+ if (!(*flags & F_SR_MARK))
+ exit_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--mask");
+ if (!strtonum(optarg, NULL, &value, 0, ~0U))
+ param_act(P_BAD_VALUE, "CONNMARK", "--mask", optarg);
+ info->nfmask = info->ctmask = value;
+ return true;
+ }
+
+ return false;
+}
+
+static void connmark_tg_check(unsigned int flags)
{
if (!flags)
exit_error(PARAMETER_PROBLEM,
@@ -159,6 +304,50 @@ static void CONNMARK_print(const void *ip,
}
}
+static void
+connmark_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_connmark_tginfo1 *info = (const void *)target->data;
+
+ switch (info->mode) {
+ case XT_CONNMARK_SET:
+ if (info->ctmark == 0)
+ printf("CONNMARK and 0x%x ",
+ (unsigned int)(u_int32_t)~info->ctmask);
+ else if (info->ctmark == info->ctmask)
+ printf("CONNMARK or 0x%x ", info->ctmark);
+ else if (info->ctmask == 0)
+ printf("CONNMARK xor 0x%x ", info->ctmark);
+ else
+ printf("CONNMARK xset 0x%x/0x%x ",
+ info->ctmark, info->ctmask);
+ break;
+ case XT_CONNMARK_SAVE:
+ if (info->nfmask == ~0U && info->ctmask == ~0U)
+ printf("CONNMARK save ");
+ else if (info->nfmask == info->ctmask)
+ printf("CONNMARK save mask 0x%x ", info->nfmask);
+ else
+ printf("CONNMARK save nfmask 0x%x ctmask ~0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ case XT_CONNMARK_RESTORE:
+ if (info->ctmask == ~0U && info->nfmask == ~0U)
+ printf("CONNMARK restore ");
+ else if (info->ctmask == info->nfmask)
+ printf("CONNMARK restore mask 0x%x ", info->ctmask);
+ else
+ printf("CONNMARK restore ctmask 0x%x nfmask ~0x%x ",
+ info->ctmask, info->nfmask);
+ break;
+
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE");
+ break;
+ }
+}
+
/* Saves the target into in parsable form to stdout. */
static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
{
@@ -194,16 +383,40 @@ static void CONNMARK_init(struct xt_entry_target *t)
markinfo->mask = 0xffffffffUL;
}
+static void
+connmark_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_connmark_tginfo1 *info = (const void *)target->data;
+
+ switch (info->mode) {
+ case XT_CONNMARK_SET:
+ printf("--set-xmark 0x%x/0x%x ", info->ctmark, info->ctmask);
+ break;
+ case XT_CONNMARK_SAVE:
+ printf("--save-mark --nfmask 0x%x --ctmask 0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ case XT_CONNMARK_RESTORE:
+ printf("--restore-mark --nfmask 0x%x --ctmask 0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE");
+ break;
+ }
+}
+
static struct xtables_target connmark_target = {
.family = AF_INET,
.name = "CONNMARK",
+ .revision = 0,
.version = IPTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.help = CONNMARK_help,
.init = CONNMARK_init,
.parse = CONNMARK_parse,
- .final_check = CONNMARK_check,
+ .final_check = connmark_tg_check,
.print = CONNMARK_print,
.save = CONNMARK_save,
.extra_opts = CONNMARK_opts,
@@ -212,20 +425,55 @@ static struct xtables_target connmark_target = {
static struct xtables_target connmark_target6 = {
.family = AF_INET6,
.name = "CONNMARK",
+ .revision = 0,
.version = IPTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
.help = CONNMARK_help,
.init = CONNMARK_init,
.parse = CONNMARK_parse,
- .final_check = CONNMARK_check,
+ .final_check = connmark_tg_check,
.print = CONNMARK_print,
.save = CONNMARK_save,
.extra_opts = CONNMARK_opts,
};
+static struct xtables_target connmark_tg_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "CONNMARK",
+ .revision = 1,
+ .family = AF_INET,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .help = connmark_tg_help,
+ .init = connmark_tg_init,
+ .parse = connmark_tg_parse,
+ .final_check = connmark_tg_check,
+ .print = connmark_tg_print,
+ .save = connmark_tg_save,
+ .extra_opts = connmark_tg_opts,
+};
+
+static struct xtables_target connmark_tg6_reg = {
+ .version = IPTABLES_VERSION,
+ .name = "CONNMARK",
+ .revision = 1,
+ .family = AF_INET6,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .help = connmark_tg_help,
+ .init = connmark_tg_init,
+ .parse = connmark_tg_parse,
+ .final_check = connmark_tg_check,
+ .print = connmark_tg_print,
+ .save = connmark_tg_save,
+ .extra_opts = connmark_tg_opts,
+};
+
void _init(void)
{
xtables_register_target(&connmark_target);
xtables_register_target(&connmark_target6);
+ xtables_register_target(&connmark_tg_reg);
+ xtables_register_target(&connmark_tg6_reg);
}