diff options
author | Kibum Kim <kb0929.kim@samsung.com> | 2012-01-07 00:47:33 +0900 |
---|---|---|
committer | Kibum Kim <kb0929.kim@samsung.com> | 2012-01-07 00:47:33 +0900 |
commit | 8df0096515fc2575560e13982f9edf76bf39555e (patch) | |
tree | 0d683bc1583f241ae5675f5fbdccb7260212b35b /extensions/libxt_CONNMARK.c | |
parent | dbc5ef4889caa206f4d47d83345357780ceef73e (diff) | |
download | iptables-8df0096515fc2575560e13982f9edf76bf39555e.tar.gz iptables-8df0096515fc2575560e13982f9edf76bf39555e.tar.bz2 iptables-8df0096515fc2575560e13982f9edf76bf39555e.zip |
Git init
Diffstat (limited to 'extensions/libxt_CONNMARK.c')
-rw-r--r-- | extensions/libxt_CONNMARK.c | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c new file mode 100644 index 0000000..6aba5f3 --- /dev/null +++ b/extensions/libxt_CONNMARK.c @@ -0,0 +1,445 @@ +/* Shared library add-on to iptables to add CONNMARK target support. + * + * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> + * by Henrik Nordstrom <hno@marasystems.com> + * + * Version 1.1 + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> + +#include <xtables.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_CONNMARK.h> + +struct xt_connmark_target_info { + unsigned long mark; + unsigned long mask; + u_int8_t mode; +}; + +enum { + F_MARK = 1 << 0, + F_SR_MARK = 1 << 1, +}; + +static void CONNMARK_help(void) +{ + printf( +"CONNMARK target options:\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"); +} + +static const struct option CONNMARK_opts[] = { + { "set-mark", 1, NULL, '1' }, + { "save-mark", 0, NULL, '2' }, + { "restore-mark", 0, NULL, '3' }, + { "mask", 1, NULL, '4' }, + { .name = NULL } +}; + +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'}, + {.name = NULL}, +}; + +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 = UINT32_MAX; + info->nfmask = UINT32_MAX; +} + +static int +CONNMARK_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_target **target) +{ + struct xt_connmark_target_info *markinfo + = (struct xt_connmark_target_info *)(*target)->data; + + switch (c) { + char *end; + case '1': + markinfo->mode = XT_CONNMARK_SET; + + markinfo->mark = strtoul(optarg, &end, 0); + if (*end == '/' && end[1] != '\0') + markinfo->mask = strtoul(end+1, &end, 0); + + if (*end != '\0' || end == optarg) + xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); + if (*flags) + xtables_error(PARAMETER_PROBLEM, + "CONNMARK target: Can't specify --set-mark twice"); + *flags = 1; + break; + case '2': + markinfo->mode = XT_CONNMARK_SAVE; + if (*flags) + xtables_error(PARAMETER_PROBLEM, + "CONNMARK target: Can't specify --save-mark twice"); + *flags = 1; + break; + case '3': + markinfo->mode = XT_CONNMARK_RESTORE; + if (*flags) + xtables_error(PARAMETER_PROBLEM, + "CONNMARK target: Can't specify --restore-mark twice"); + *flags = 1; + break; + case '4': + if (!*flags) + xtables_error(PARAMETER_PROBLEM, + "CONNMARK target: Can't specify --mask without a operation"); + markinfo->mask = strtoul(optarg, &end, 0); + + if (*end != '\0' || end == optarg) + xtables_error(PARAMETER_PROBLEM, "Bad MASK value \"%s\"", optarg); + break; + default: + return 0; + } + + return 1; +} + +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 = UINT32_MAX; + char *end; + + switch (c) { + case '=': /* --set-xmark */ + case '-': /* --set-mark */ + xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); + if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX)) + xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg); + if (*end == '/') + if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) + xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg); + if (*end != '\0') + xtables_param_act(XTF_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 */ + xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); + if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX)) + xtables_param_act(XTF_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 */ + xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); + if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) + xtables_param_act(XTF_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 */ + xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); + if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) + xtables_param_act(XTF_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 */ + xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); + info->mode = XT_CONNMARK_SAVE; + *flags |= F_MARK | F_SR_MARK; + return true; + + case 'R': /* --restore-mark */ + xtables_param_act(XTF_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)) + xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark " + "or --restore-mark is required for " + "--nfmask"); + if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) + xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--nfmask", optarg); + info->nfmask = value; + return true; + + case 'c': /* --ctmask */ + if (!(*flags & F_SR_MARK)) + xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark " + "or --restore-mark is required for " + "--ctmask"); + if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) + xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--ctmask", optarg); + info->ctmask = value; + return true; + + case 'm': /* --mask */ + if (!(*flags & F_SR_MARK)) + xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark " + "or --restore-mark is required for " + "--mask"); + if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) + xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--mask", optarg); + info->nfmask = info->ctmask = value; + return true; + } + + return false; +} + +static void connmark_tg_check(unsigned int flags) +{ + if (!flags) + xtables_error(PARAMETER_PROBLEM, + "CONNMARK target: No operation specified"); +} + +static void +print_mark(unsigned long mark) +{ + printf("0x%lx", mark); +} + +static void +print_mask(const char *text, unsigned long mask) +{ + if (mask != 0xffffffffUL) + printf("%s0x%lx", text, mask); +} + +static void CONNMARK_print(const void *ip, + const struct xt_entry_target *target, int numeric) +{ + const struct xt_connmark_target_info *markinfo = + (const struct xt_connmark_target_info *)target->data; + switch (markinfo->mode) { + case XT_CONNMARK_SET: + printf("CONNMARK set "); + print_mark(markinfo->mark); + print_mask("/", markinfo->mask); + printf(" "); + break; + case XT_CONNMARK_SAVE: + printf("CONNMARK save "); + print_mask("mask ", markinfo->mask); + printf(" "); + break; + case XT_CONNMARK_RESTORE: + printf("CONNMARK restore "); + print_mask("mask ", markinfo->mask); + break; + default: + printf("ERROR: UNKNOWN CONNMARK MODE "); + break; + } +} + +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 if (info->ctmask == 0xFFFFFFFFU) + printf("CONNMARK set 0x%x ", info->ctmark); + else + printf("CONNMARK xset 0x%x/0x%x ", + info->ctmark, info->ctmask); + break; + case XT_CONNMARK_SAVE: + if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX) + 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 == UINT32_MAX && info->nfmask == UINT32_MAX) + 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; + } +} + +static void CONNMARK_save(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_connmark_target_info *markinfo = + (const struct xt_connmark_target_info *)target->data; + + switch (markinfo->mode) { + case XT_CONNMARK_SET: + printf("--set-mark "); + print_mark(markinfo->mark); + print_mask("/", markinfo->mask); + printf(" "); + break; + case XT_CONNMARK_SAVE: + printf("--save-mark "); + print_mask("--mask ", markinfo->mask); + break; + case XT_CONNMARK_RESTORE: + printf("--restore-mark "); + print_mask("--mask ", markinfo->mask); + break; + default: + printf("ERROR: UNKNOWN CONNMARK MODE "); + break; + } +} + +static void CONNMARK_init(struct xt_entry_target *t) +{ + struct xt_connmark_target_info *markinfo + = (struct xt_connmark_target_info *)t->data; + + 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_tg_reg[] = { + { + .family = NFPROTO_UNSPEC, + .name = "CONNMARK", + .revision = 0, + .version = XTABLES_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_tg_check, + .print = CONNMARK_print, + .save = CONNMARK_save, + .extra_opts = CONNMARK_opts, + }, + { + .version = XTABLES_VERSION, + .name = "CONNMARK", + .revision = 1, + .family = NFPROTO_UNSPEC, + .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_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg)); +} |