From d25e217578492d17f7752bf77cfab5f2c2509795 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 14:57:44 +0100 Subject: libxtables: XTTYPE_MARKMASK32 support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 5 +++++ xtoptions.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/xtables.h.in b/include/xtables.h.in index c3c8da9c..2fa59771 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -50,6 +50,7 @@ struct in_addr; * %XTTYPE_UINT*: standard integer * %XTTYPE_UINT*RC: colon-separated range of standard integers * %XTTYPE_STRING: arbitrary string + * %XTTYPE_MARKMASK32: 32-bit mark with optional mask */ enum xt_option_type { XTTYPE_NONE, @@ -57,6 +58,7 @@ enum xt_option_type { XTTYPE_UINT32, XTTYPE_UINT32RC, XTTYPE_STRING, + XTTYPE_MARKMASK32, }; /** @@ -113,6 +115,9 @@ struct xt_option_call { union { uint8_t u8; uint32_t u32, u32_range[2]; + struct { + uint32_t mark, mask; + }; } val; }; diff --git a/xtoptions.c b/xtoptions.c index 631e7a3c..e9bcaa83 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -186,11 +186,40 @@ static void xtopt_parse_string(struct xt_option_call *cb) p[z] = '\0'; } +/** + * Validate the input for being conformant to "mark[/mask]". + */ +static void xtopt_parse_markmask(struct xt_option_call *cb) +{ + unsigned int mark = 0, mask = ~0U; + char *end; + + if (!xtables_strtoui(cb->arg, &end, &mark, 0, UINT32_MAX)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad mark value for option \"--%s\", " + "or out of range.\n", + cb->ext_name, cb->entry->name); + if (*end == '/' && + !xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad mask value for option \"--%s\", " + "or out of range.\n", + cb->ext_name, cb->entry->name); + if (*end != '\0') + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: trailing garbage after value " + "for option \"--%s\".\n", + cb->ext_name, cb->entry->name); + cb->val.mark = mark; + cb->val.mask = mask; +} + static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT32] = xtopt_parse_int, [XTTYPE_UINT32RC] = xtopt_parse_mint, [XTTYPE_STRING] = xtopt_parse_string, + [XTTYPE_MARKMASK32] = xtopt_parse_markmask, }; static const size_t xtopt_psize[] = { -- cgit v1.2.3 From 60756e7f8be9242b606f1b5fbcb38f45e4de29c5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 15:21:24 +0100 Subject: libxt_MARK: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_MARK.c | 202 +++++++++++++++++++----------------------------- extensions/libxt_mark.c | 95 ++++++----------------- 2 files changed, 104 insertions(+), 193 deletions(-) diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c index 885cf2f2..556dbde5 100644 --- a/extensions/libxt_MARK.c +++ b/extensions/libxt_MARK.c @@ -1,12 +1,6 @@ -/* Shared library add-on to iptables to add MARK target support. */ #include #include -#include -#include -#include - #include -#include #include /* Version 0 */ @@ -27,7 +21,18 @@ struct xt_mark_target_info_v1 { }; enum { - F_MARK = 1 << 0, + O_SET_MARK = 0, + O_AND_MARK, + O_OR_MARK, + O_XOR_MARK, + O_SET_XMARK, + F_SET_MARK = 1 << O_SET_MARK, + F_AND_MARK = 1 << O_AND_MARK, + F_OR_MARK = 1 << O_OR_MARK, + F_XOR_MARK = 1 << O_XOR_MARK, + F_SET_XMARK = 1 << O_SET_XMARK, + F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK | + F_XOR_MARK | F_SET_XMARK, }; static void MARK_help(void) @@ -39,20 +44,28 @@ static void MARK_help(void) " --or-mark value Binary OR the nfmark with value\n"); } -static const struct option MARK_opts[] = { - {.name = "set-mark", .has_arg = true, .val = '1'}, - {.name = "and-mark", .has_arg = true, .val = '2'}, - {.name = "or-mark", .has_arg = true, .val = '3'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry MARK_opts[] = { + {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32, + .excl = F_ANY}, + {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32, + .excl = F_ANY}, + {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32, + .excl = F_ANY}, + XTOPT_TABLEEND, }; -static const struct option mark_tg_opts[] = { - {.name = "set-xmark", .has_arg = true, .val = 'X'}, - {.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 = '^'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry mark_tg_opts[] = { + {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32, + .excl = F_ANY}, + {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32, + .excl = F_ANY}, + {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32, + .excl = F_ANY}, + {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32, + .excl = F_ANY}, + {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32, + .excl = F_ANY}, + XTOPT_TABLEEND, }; static void mark_tg_help(void) @@ -67,137 +80,80 @@ static void mark_tg_help(void) "\n"); } -/* Function which parses command options; returns true if it - ate an option */ -static int -MARK_parse_v0(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void MARK_parse_v0(struct xt_option_call *cb) { - struct xt_mark_target_info *markinfo - = (struct xt_mark_target_info *)(*target)->data; - unsigned int mark = 0; + struct xt_mark_target_info *markinfo = cb->data; - switch (c) { - case '1': - if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); - markinfo->mark = mark; - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "MARK target: Can't specify --set-mark twice"); - *flags = 1; + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SET_MARK: + markinfo->mark = cb->val.mark; break; - case '2': - xtables_error(PARAMETER_PROBLEM, - "MARK target: kernel too old for --and-mark"); - case '3': + default: xtables_error(PARAMETER_PROBLEM, - "MARK target: kernel too old for --or-mark"); + "MARK target: kernel too old for --%s", + cb->entry->name); } - - return 1; } -static void MARK_check(unsigned int flags) +static void MARK_check(struct xt_fcheck_call *cb) { - if (!flags) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "MARK target: Parameter --set/and/or-mark" " is required"); } -static int -MARK_parse_v1(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void MARK_parse_v1(struct xt_option_call *cb) { - struct xt_mark_target_info_v1 *markinfo - = (struct xt_mark_target_info_v1 *)(*target)->data; - unsigned int mark = 0; + struct xt_mark_target_info_v1 *markinfo = cb->data; - switch (c) { - case '1': + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SET_MARK: markinfo->mode = XT_MARK_SET; break; - case '2': + case O_AND_MARK: markinfo->mode = XT_MARK_AND; break; - case '3': + case O_OR_MARK: markinfo->mode = XT_MARK_OR; break; } - - if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); - markinfo->mark = mark; - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "MARK target: Can't specify --set-mark twice"); - - *flags = 1; - return 1; + markinfo->mark = cb->val.u32; } -static int mark_tg_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void mark_tg_parse(struct xt_option_call *cb) { - struct xt_mark_tginfo2 *info = (void *)(*target)->data; - unsigned int value, mask = UINT32_MAX; - char *end; + struct xt_mark_tginfo2 *info = cb->data; - switch (c) { - case 'X': /* --set-xmark */ - case '=': /* --set-mark */ - xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); - xtables_param_act(XTF_NO_INVERT, "MARK", "--set-xmark/--set-mark", invert); - if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg); - if (*end == '/') - if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg); - if (*end != '\0') - xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg); - info->mark = value; - info->mask = mask; - - if (c == '=') - info->mask = value | mask; + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SET_XMARK: + info->mark = cb->val.mark; + info->mask = cb->val.mask; break; - - case '&': /* --and-mark */ - xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); - xtables_param_act(XTF_NO_INVERT, "MARK", "--and-mark", invert); - if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "MARK", "--and-mark", optarg); + case O_SET_MARK: + info->mark = cb->val.mark; + info->mask = cb->val.mark | cb->val.mask; + break; + case O_AND_MARK: info->mark = 0; - info->mask = ~mask; + info->mask = ~cb->val.u32; break; - - case '|': /* --or-mark */ - xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); - xtables_param_act(XTF_NO_INVERT, "MARK", "--or-mark", invert); - if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "MARK", "--or-mark", optarg); - info->mark = value; - info->mask = value; + case O_OR_MARK: + info->mark = info->mask = cb->val.u32; break; - - case '^': /* --xor-mark */ - xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK); - xtables_param_act(XTF_NO_INVERT, "MARK", "--xor-mark", invert); - if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "MARK", "--xor-mark", optarg); - info->mark = value; + case O_XOR_MARK: + info->mark = cb->val.u32; info->mask = 0; break; } - - *flags |= F_MARK; - return true; } -static void mark_tg_check(unsigned int flags) +static void mark_tg_check(struct xt_fcheck_call *cb) { - if (flags == 0) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, " "--{and,or,xor,set}-mark options is required"); } @@ -298,11 +254,11 @@ static struct xtables_target mark_tg_reg[] = { .size = XT_ALIGN(sizeof(struct xt_mark_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)), .help = MARK_help, - .parse = MARK_parse_v0, - .final_check = MARK_check, .print = MARK_print_v0, .save = MARK_save_v0, - .extra_opts = MARK_opts, + .x6_parse = MARK_parse_v0, + .x6_fcheck = MARK_check, + .x6_options = MARK_opts, }, { .family = NFPROTO_IPV4, @@ -312,11 +268,11 @@ static struct xtables_target mark_tg_reg[] = { .size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)), .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)), .help = MARK_help, - .parse = MARK_parse_v1, - .final_check = MARK_check, .print = MARK_print_v1, .save = MARK_save_v1, - .extra_opts = MARK_opts, + .x6_parse = MARK_parse_v1, + .x6_fcheck = MARK_check, + .x6_options = MARK_opts, }, { .version = XTABLES_VERSION, @@ -326,11 +282,11 @@ static struct xtables_target mark_tg_reg[] = { .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)), .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)), .help = mark_tg_help, - .parse = mark_tg_parse, - .final_check = mark_tg_check, .print = mark_tg_print, .save = mark_tg_save, - .extra_opts = mark_tg_opts, + .x6_parse = mark_tg_parse, + .x6_fcheck = mark_tg_check, + .x6_options = mark_tg_opts, }, }; diff --git a/extensions/libxt_mark.c b/extensions/libxt_mark.c index d3c17277..7f8c995c 100644 --- a/extensions/libxt_mark.c +++ b/extensions/libxt_mark.c @@ -1,11 +1,5 @@ -/* Shared library add-on to iptables to add NFMARK matching support. */ #include #include -#include -#include -#include -#include - #include #include @@ -15,7 +9,7 @@ struct xt_mark_info { }; enum { - F_MARK = 1 << 0, + O_MARK = 0, }; static void mark_mt_help(void) @@ -25,62 +19,32 @@ static void mark_mt_help(void) "[!] --mark value[/mask] Match nfmark value with optional mask\n"); } -static const struct option mark_mt_opts[] = { - {.name = "mark", .has_arg = true, .val = '1'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry mark_mt_opts[] = { + {.name = "mark", .id = O_MARK, .type = XTTYPE_MARKMASK32, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, }; -static int mark_mt_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void mark_mt_parse(struct xt_option_call *cb) { - struct xt_mark_mtinfo1 *info = (void *)(*match)->data; - unsigned int mark, mask = UINT32_MAX; - char *end; - - switch (c) { - case '1': /* --mark */ - xtables_param_act(XTF_ONLY_ONCE, "mark", "--mark", *flags & F_MARK); - if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); - if (*end == '/') - if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); - if (*end != '\0') - xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg); - - if (invert) - info->invert = true; - info->mark = mark; - info->mask = mask; - *flags |= F_MARK; - return true; - } - return false; + struct xt_mark_mtinfo1 *info = cb->data; + + xtables_option_parse(cb); + if (cb->invert) + info->invert = true; + info->mark = cb->val.mark; + info->mask = cb->val.mask; } -static int -mark_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void mark_parse(struct xt_option_call *cb) { - struct xt_mark_info *markinfo = (struct xt_mark_info *)(*match)->data; - - switch (c) { - char *end; - case '1': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - markinfo->mark = strtoul(optarg, &end, 0); - if (*end == '/') { - markinfo->mask = strtoul(end+1, &end, 0); - } else - markinfo->mask = 0xffffffff; - if (*end != '\0' || end == optarg) - xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); - if (invert) - markinfo->invert = 1; - *flags = 1; - break; - } - return 1; + struct xt_mark_info *markinfo = cb->data; + + xtables_option_parse(cb); + if (cb->invert) + markinfo->invert = 1; + markinfo->mark = cb->val.mark; + markinfo->mask = cb->val.mask; } static void print_mark(unsigned int mark, unsigned int mask) @@ -91,13 +55,6 @@ static void print_mark(unsigned int mark, unsigned int mask) printf(" 0x%x", mark); } -static void mark_mt_check(unsigned int flags) -{ - if (flags == 0) - xtables_error(PARAMETER_PROBLEM, - "mark match: The --mark option is required"); -} - static void mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) { @@ -154,11 +111,10 @@ static struct xtables_match mark_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_mark_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)), .help = mark_mt_help, - .parse = mark_parse, - .final_check = mark_mt_check, .print = mark_print, .save = mark_save, - .extra_opts = mark_mt_opts, + .x6_parse = mark_parse, + .x6_options = mark_mt_opts, }, { .version = XTABLES_VERSION, @@ -168,11 +124,10 @@ static struct xtables_match mark_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), .userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)), .help = mark_mt_help, - .parse = mark_mt_parse, - .final_check = mark_mt_check, .print = mark_mt_print, .save = mark_mt_save, - .extra_opts = mark_mt_opts, + .x6_parse = mark_mt_parse, + .x6_options = mark_mt_opts, }, }; -- cgit v1.2.3 From 7299fa4b615d7f7ee12cde444266f6b31f667f9f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 15:54:58 +0100 Subject: libxt_CONNMARK: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_CONNMARK.c | 271 ++++++++++++++++++-------------------------- extensions/libxt_connmark.c | 98 +++++----------- 2 files changed, 134 insertions(+), 235 deletions(-) diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c index dbb9dc50..5d5351e3 100644 --- a/extensions/libxt_CONNMARK.c +++ b/extensions/libxt_CONNMARK.c @@ -20,13 +20,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include -#include -#include -#include - #include -#include #include struct xt_connmark_target_info { @@ -36,8 +32,28 @@ struct xt_connmark_target_info { }; enum { - F_MARK = 1 << 0, - F_SR_MARK = 1 << 1, + O_SET_MARK = 0, + O_SAVE_MARK, + O_RESTORE_MARK, + O_AND_MARK, + O_OR_MARK, + O_XOR_MARK, + O_SET_XMARK, + O_CTMASK, + O_NFMASK, + O_MASK, + F_SET_MARK = 1 << O_SET_MARK, + F_SAVE_MARK = 1 << O_SAVE_MARK, + F_RESTORE_MARK = 1 << O_RESTORE_MARK, + F_AND_MARK = 1 << O_AND_MARK, + F_OR_MARK = 1 << O_OR_MARK, + F_XOR_MARK = 1 << O_XOR_MARK, + F_SET_XMARK = 1 << O_SET_XMARK, + F_CTMASK = 1 << O_CTMASK, + F_NFMASK = 1 << O_NFMASK, + F_MASK = 1 << O_MASK, + F_OP_ANY = F_SET_MARK | F_SAVE_MARK | F_RESTORE_MARK | + F_AND_MARK | F_OR_MARK | F_XOR_MARK | F_SET_XMARK, }; static void CONNMARK_help(void) @@ -49,27 +65,44 @@ static void CONNMARK_help(void) " --restore-mark [--mask mask] Restore saved nfmark value\n"); } -static const struct option CONNMARK_opts[] = { - {.name = "set-mark", .has_arg = true, .val = '1'}, - {.name = "save-mark", .has_arg = false, .val = '2'}, - {.name = "restore-mark", .has_arg = false, .val = '3'}, - {.name = "mask", .has_arg = true, .val = '4'}, - XT_GETOPT_TABLEEND, +#define s struct xt_connmark_target_info +static const struct xt_option_entry CONNMARK_opts[] = { + {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32, + .excl = F_OP_ANY}, + {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE, + .excl = F_OP_ANY}, + {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE, + .excl = F_OP_ANY}, + {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32}, + XTOPT_TABLEEND, }; - -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'}, - XT_GETOPT_TABLEEND, +#undef s + +#define s struct xt_connmark_tginfo1 +static const struct xt_option_entry connmark_tg_opts[] = { + {.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32, + .excl = F_OP_ANY}, + {.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32, + .excl = F_OP_ANY}, + {.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32, + .excl = F_OP_ANY}, + {.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32, + .excl = F_OP_ANY}, + {.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32, + .excl = F_OP_ANY}, + {.name = "save-mark", .id = O_SAVE_MARK, .type = XTTYPE_NONE, + .excl = F_OP_ANY}, + {.name = "restore-mark", .id = O_RESTORE_MARK, .type = XTTYPE_NONE, + .excl = F_OP_ANY}, + {.name = "ctmask", .id = O_CTMASK, .type = XTTYPE_UINT32, + .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, ctmask)}, + {.name = "nfmask", .id = O_NFMASK, .type = XTTYPE_UINT32, + .excl = F_MASK, .flags = XTOPT_PUT, XTOPT_POINTER(s, nfmask)}, + {.name = "mask", .id = O_MASK, .type = XTTYPE_UINT32, + .excl = F_CTMASK | F_NFMASK}, + XTOPT_TABLEEND, }; +#undef s static void connmark_tg_help(void) { @@ -101,163 +134,75 @@ static void connmark_tg_init(struct xt_entry_target *target) 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) +static void CONNMARK_parse(struct xt_option_call *cb) { - struct xt_connmark_target_info *markinfo - = (struct xt_connmark_target_info *)(*target)->data; + struct xt_connmark_target_info *markinfo = cb->data; - switch (c) { - char *end; - case '1': + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SET_MARK: 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; + markinfo->mark = cb->val.mark; + markinfo->mask = cb->val.mask; break; - case '2': + case O_SAVE_MARK: markinfo->mode = XT_CONNMARK_SAVE; - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "CONNMARK target: Can't specify --save-mark twice"); - *flags = 1; break; - case '3': + case O_RESTORE_MARK: 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); + case O_MASK: + markinfo->mask = cb->val.u32; break; } - - return 1; } -static int connmark_tg_parse(int c, char **argv, int invert, - unsigned int *flags, const void *entry, - struct xt_entry_target **target) +static void connmark_tg_parse(struct xt_option_call *cb) { - struct xt_connmark_tginfo1 *info = (void *)(*target)->data; - unsigned int value, mask = UINT32_MAX; - char *end; + struct xt_connmark_tginfo1 *info = cb->data; - 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); + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SET_XMARK: 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->ctmark = cb->val.mark; + info->ctmask = cb->val.mask; + break; + case O_SET_MARK: + info->mode = XT_CONNMARK_SET; + info->ctmark = cb->val.mark; + info->ctmask = cb->val.mark | cb->val.mask; + break; + case O_AND_MARK: 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->ctmask = ~cb->val.u32; + break; + case O_OR_MARK: 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->ctmark = cb->val.u32; + info->ctmask = cb->val.u32; + break; + case O_XOR_MARK: info->mode = XT_CONNMARK_SET; - info->ctmark = value; + info->ctmark = cb->val.u32; info->ctmask = 0; - *flags |= F_MARK; - return true; - - case 'S': /* --save-mark */ - xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK); + break; + case O_SAVE_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); + break; + case O_RESTORE_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; + break; + case O_MASK: + info->nfmask = info->ctmask = cb->val.u32; + break; } - - return false; } -static void connmark_tg_check(unsigned int flags) +static void connmark_tg_check(struct xt_fcheck_call *cb) { - if (!flags) + if (!(cb->xflags & F_OP_ANY)) xtables_error(PARAMETER_PROBLEM, "CONNMARK target: No operation specified"); } @@ -412,11 +357,11 @@ static struct xtables_target connmark_tg_reg[] = { .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, + .x6_parse = CONNMARK_parse, + .x6_fcheck = connmark_tg_check, + .x6_options = CONNMARK_opts, }, { .version = XTABLES_VERSION, @@ -427,11 +372,11 @@ static struct xtables_target connmark_tg_reg[] = { .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, + .x6_parse = connmark_tg_parse, + .x6_fcheck = connmark_tg_check, + .x6_options = connmark_tg_opts, }, }; diff --git a/extensions/libxt_connmark.c b/extensions/libxt_connmark.c index a0e89fe7..6f1d5323 100644 --- a/extensions/libxt_connmark.c +++ b/extensions/libxt_connmark.c @@ -20,12 +20,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include -#include -#include -#include -#include - #include #include @@ -35,7 +31,7 @@ struct xt_connmark_info { }; enum { - F_MARK = 1 << 0, + O_MARK = 0, }; static void connmark_mt_help(void) @@ -45,65 +41,32 @@ static void connmark_mt_help(void) "[!] --mark value[/mask] Match ctmark value with optional mask\n"); } -static const struct option connmark_mt_opts[] = { - {.name = "mark", .has_arg = true, .val = '1'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry connmark_mt_opts[] = { + {.name = "mark", .id = O_MARK, .type = XTTYPE_MARKMASK32, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, }; -static int -connmark_mt_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void connmark_mt_parse(struct xt_option_call *cb) { - struct xt_connmark_mtinfo1 *info = (void *)(*match)->data; - unsigned int mark, mask = UINT32_MAX; - char *end; - - switch (c) { - case '1': /* --mark */ - xtables_param_act(XTF_ONLY_ONCE, "connmark", "--mark", *flags & F_MARK); - if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg); - if (*end == '/') - if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg); - if (*end != '\0') - xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg); - - if (invert) - info->invert = true; - info->mark = mark; - info->mask = mask; - *flags |= F_MARK; - return true; - } - return false; + struct xt_connmark_mtinfo1 *info = cb->data; + + xtables_option_parse(cb); + if (cb->invert) + info->invert = true; + info->mark = cb->val.mark; + info->mask = cb->val.mask; } -static int -connmark_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void connmark_parse(struct xt_option_call *cb) { - struct xt_connmark_info *markinfo = (struct xt_connmark_info *)(*match)->data; - - switch (c) { - char *end; - case '1': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - markinfo->mark = strtoul(optarg, &end, 0); - markinfo->mask = 0xffffffffUL; - - if (*end == '/') - markinfo->mask = strtoul(end+1, &end, 0); - - if (*end != '\0' || end == optarg) - xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg); - if (invert) - markinfo->invert = 1; - *flags = 1; - break; - } - return 1; + struct xt_connmark_info *markinfo = cb->data; + + xtables_option_parse(cb); + markinfo->mark = cb->val.mark; + markinfo->mask = cb->val.mask; + if (cb->invert) + markinfo->invert = 1; } static void print_mark(unsigned int mark, unsigned int mask) @@ -114,13 +77,6 @@ static void print_mark(unsigned int mark, unsigned int mask) printf(" 0x%x", mark); } -static void connmark_mt_check(unsigned int flags) -{ - if (flags == 0) - xtables_error(PARAMETER_PROBLEM, - "connmark: The --mark option is required"); -} - static void connmark_print(const void *ip, const struct xt_entry_match *match, int numeric) { @@ -175,11 +131,10 @@ static struct xtables_match connmark_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_connmark_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)), .help = connmark_mt_help, - .parse = connmark_parse, - .final_check = connmark_mt_check, .print = connmark_print, .save = connmark_save, - .extra_opts = connmark_mt_opts, + .x6_parse = connmark_parse, + .x6_options = connmark_mt_opts, }, { .version = XTABLES_VERSION, @@ -189,11 +144,10 @@ static struct xtables_match connmark_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)), .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)), .help = connmark_mt_help, - .parse = connmark_mt_parse, - .final_check = connmark_mt_check, .print = connmark_mt_print, .save = connmark_mt_save, - .extra_opts = connmark_mt_opts, + .x6_parse = connmark_mt_parse, + .x6_options = connmark_mt_opts, }, }; -- cgit v1.2.3 From 8b5bdea659f1fb86b3288a2568ab104a90b914e5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 16:56:53 +0100 Subject: libxtables: XTTYPE_UINT64 support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 2 ++ xtoptions.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index 2fa59771..c361bdbd 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -56,6 +56,7 @@ enum xt_option_type { XTTYPE_NONE, XTTYPE_UINT8, XTTYPE_UINT32, + XTTYPE_UINT64, XTTYPE_UINT32RC, XTTYPE_STRING, XTTYPE_MARKMASK32, @@ -115,6 +116,7 @@ struct xt_option_call { union { uint8_t u8; uint32_t u32, u32_range[2]; + uint64_t u64; struct { uint32_t mark, mask; }; diff --git a/xtoptions.c b/xtoptions.c index e9bcaa83..42063144 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -86,11 +86,13 @@ xtables_options_xfrm(struct option *orig_opts, struct option *oldopts, static void xtopt_parse_int(struct xt_option_call *cb) { const struct xt_option_entry *entry = cb->entry; - unsigned int lmin = 0, lmax = UINT32_MAX; + unsigned long long lmin = 0, lmax = UINT32_MAX; unsigned int value; if (entry->type == XTTYPE_UINT8) lmax = UINT8_MAX; + else if (entry->type == XTTYPE_UINT64) + lmax = UINT64_MAX; if (cb->entry->min != 0) lmin = cb->entry->min; if (cb->entry->max != 0) @@ -99,7 +101,7 @@ static void xtopt_parse_int(struct xt_option_call *cb) if (!xtables_strtoui(cb->arg, NULL, &value, lmin, lmax)) xt_params->exit_err(PARAMETER_PROBLEM, "%s: bad value for option \"--%s\", " - "or out of range (%u-%u).\n", + "or out of range (%llu-%llu).\n", cb->ext_name, entry->name, lmin, lmax); if (entry->type == XTTYPE_UINT8) { @@ -110,6 +112,10 @@ static void xtopt_parse_int(struct xt_option_call *cb) cb->val.u32 = value; if (entry->flags & XTOPT_PUT) *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32; + } else if (entry->type == XTTYPE_UINT64) { + cb->val.u64 = value; + if (entry->flags & XTOPT_PUT) + *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64; } } @@ -217,6 +223,7 @@ static void xtopt_parse_markmask(struct xt_option_call *cb) static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT32] = xtopt_parse_int, + [XTTYPE_UINT64] = xtopt_parse_int, [XTTYPE_UINT32RC] = xtopt_parse_mint, [XTTYPE_STRING] = xtopt_parse_string, [XTTYPE_MARKMASK32] = xtopt_parse_markmask, @@ -225,6 +232,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { static const size_t xtopt_psize[] = { [XTTYPE_UINT8] = sizeof(uint8_t), [XTTYPE_UINT32] = sizeof(uint32_t), + [XTTYPE_UINT64] = sizeof(uint64_t), [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), [XTTYPE_STRING] = -1, }; -- cgit v1.2.3 From 1e6c1ee1bf2822d5fdf61725148700a410fb8b86 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 16:58:24 +0100 Subject: libxt_quota: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_quota.c | 67 +++++++++++------------------------------------- 1 file changed, 15 insertions(+), 52 deletions(-) diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c index e3699ad7..988f404f 100644 --- a/extensions/libxt_quota.c +++ b/extensions/libxt_quota.c @@ -3,18 +3,18 @@ * * Sam Johnston */ -#include -#include #include -#include -#include #include - #include -static const struct option quota_opts[] = { - {.name = "quota", .has_arg = true, .val = '1'}, - XT_GETOPT_TABLEEND, +enum { + O_QUOTA = 0, +}; + +static const struct xt_option_entry quota_opts[] = { + {.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, }; static void quota_help(void) @@ -40,49 +40,13 @@ quota_save(const void *ip, const struct xt_entry_match *match) printf(" --quota %llu", (unsigned long long) q->quota); } -/* parse quota option */ -static int -parse_quota(const char *s, uint64_t * quota) -{ - *quota = strtoull(s, NULL, 10); - -#ifdef DEBUG_XT_QUOTA - printf("Quota: %llu\n", *quota); -#endif - - if (*quota == UINT64_MAX) - xtables_error(PARAMETER_PROBLEM, "quota invalid: '%s'\n", s); - else - return 1; -} - -static int -quota_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void quota_parse(struct xt_option_call *cb) { - struct xt_quota_info *info = (struct xt_quota_info *) (*match)->data; - - switch (c) { - case '1': - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, "quota: unexpected '!'"); - if (!parse_quota(optarg, &info->quota)) - xtables_error(PARAMETER_PROBLEM, - "bad quota: '%s'", optarg); + struct xt_quota_info *info = cb->data; - if (invert) - info->flags |= XT_QUOTA_INVERT; - *flags |= 1; - break; - } - return 1; -} - -static void quota_check(unsigned int flags) -{ - if (flags == 0) - xtables_error(PARAMETER_PROBLEM, - "quota: the --quota argument must be specified\n"); + xtables_option_parse(cb); + if (cb->invert) + info->flags |= XT_QUOTA_INVERT; } static struct xtables_match quota_match = { @@ -92,11 +56,10 @@ static struct xtables_match quota_match = { .size = XT_ALIGN(sizeof (struct xt_quota_info)), .userspacesize = offsetof(struct xt_quota_info, master), .help = quota_help, - .parse = quota_parse, - .final_check = quota_check, .print = quota_print, .save = quota_save, - .extra_opts = quota_opts, + .x6_parse = quota_parse, + .x6_options = quota_opts, }; void -- cgit v1.2.3 From 2e0ec4fa0fb5162c441cd666f55fe76777e40d5e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 16:24:43 +0100 Subject: libxtables: linked-list name<->id map This consolidates the maps from libxt_devgroup and libxt_realm. Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 15 ++++++++ xtoptions.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/include/xtables.h.in b/include/xtables.h.in index c361bdbd..30d9e73b 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -134,6 +134,16 @@ struct xt_fcheck_call { unsigned int xflags; }; +/** + * A "linear"/linked-list based name<->id map, for files similar to + * /etc/iproute2/. + */ +struct xtables_lmap { + char *name; + int id; + struct xtables_lmap *next; +}; + /* Include file for additions: new matches and targets. */ struct xtables_match { @@ -418,6 +428,11 @@ extern void xtables_option_mfcall(struct xtables_match *); extern void xtables_options_fcheck(const char *, unsigned int, const struct xt_option_entry *); +extern struct xtables_lmap *xtables_lmap_init(const char *); +extern void xtables_lmap_free(struct xtables_lmap *); +extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *); +extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int); + #ifdef XTABLES_INTERNAL /* Shipped modules rely on this... */ diff --git a/xtoptions.c b/xtoptions.c index 42063144..f48c011c 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -7,6 +7,7 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. */ +#include #include #include #include @@ -487,3 +488,101 @@ void xtables_option_mfcall(struct xtables_match *m) if (m->x6_options != NULL) xtables_options_fcheck(m->name, m->mflags, m->x6_options); } + +struct xtables_lmap *xtables_lmap_init(const char *file) +{ + struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this; + char buf[512]; + FILE *fp; + char *cur, *nxt; + int id; + + fp = fopen(file, "re"); + if (fp == NULL) + return NULL; + + while (fgets(buf, sizeof(buf), fp) != NULL) { + cur = buf; + while (isspace(*cur)) + ++cur; + if (*cur == '#' || *cur == '\n' || *cur == '\0') + continue; + + /* iproute2 allows hex and dec format */ + errno = 0; + id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10); + if (nxt == cur || errno != 0) + continue; + + /* same boundaries as in iproute2 */ + if (id < 0 || id > 255) + continue; + cur = nxt; + + if (!isspace(*cur)) + continue; + while (isspace(*cur)) + ++cur; + if (*cur == '#' || *cur == '\n' || *cur == '\0') + continue; + nxt = cur; + while (*nxt != '\0' && !isspace(*nxt)) + ++nxt; + if (nxt == cur) + continue; + *nxt = '\0'; + + /* found valid data */ + lmap_this = malloc(sizeof(*lmap_this)); + if (lmap_this == NULL) { + perror("malloc"); + goto out; + } + lmap_this->id = id; + lmap_this->name = strdup(cur); + if (lmap_this->name == NULL) { + free(lmap_this); + goto out; + } + lmap_this->next = NULL; + + if (lmap_prev != NULL) + lmap_prev->next = lmap_this; + else + lmap_head = lmap_this; + lmap_prev = lmap_this; + } + + fclose(fp); + return lmap_head; + out: + xtables_lmap_free(lmap_head); + return NULL; +} + +void xtables_lmap_free(struct xtables_lmap *head) +{ + struct xtables_lmap *next; + + for (; head != NULL; head = next) { + next = head->next; + free(head->name); + free(head); + } +} + +int xtables_lmap_name2id(const struct xtables_lmap *head, const char *name) +{ + for (; head != NULL; head = head->next) + if (strcmp(head->name, name) == 0) + return head->id; + return -1; +} + +const char *xtables_lmap_id2name(const struct xtables_lmap *head, int id) +{ + for (; head != NULL; head = head->next) + if (head->id == id) + return head->name; + return NULL; +} -- cgit v1.2.3 From 5d8e61ef4636383ca47cd748cd7457a238de37a6 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 16:02:03 +0100 Subject: libxt_devgroup: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_devgroup.c | 201 +++++++++----------------------------------- 1 file changed, 41 insertions(+), 160 deletions(-) diff --git a/extensions/libxt_devgroup.c b/extensions/libxt_devgroup.c index 26248687..a925dd08 100644 --- a/extensions/libxt_devgroup.c +++ b/extensions/libxt_devgroup.c @@ -2,14 +2,10 @@ * * Copyright (c) 2011 Patrick McHardy */ -#include #include -#include #include #include #include -#include -#include #include #include @@ -23,200 +19,84 @@ static void devgroup_help(void) } enum { - XT_DEVGROUP_OPT_SRCGROUP = 1, - XT_DEVGROUP_OPT_DSTGROUP, + O_SRC_GROUP = 0, + O_DST_GROUP, }; -static const struct option devgroup_opts[] = { - { .name = "src-group", .has_arg = true, .val = XT_DEVGROUP_OPT_SRCGROUP }, - { .name = "dst-group", .has_arg = true, .val = XT_DEVGROUP_OPT_DSTGROUP }, - XT_GETOPT_TABLEEND, -}; - -struct devgroupname { - unsigned int id; - char *name; - int len; - struct devgroupname *next; +static const struct xt_option_entry devgroup_opts[] = { + {.name = "src-group", .id = O_SRC_GROUP, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "dst-group", .id = O_DST_GROUP, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + XTOPT_TABLEEND, }; /* array of devgroups from /etc/iproute2/group_map */ -static struct devgroupname *devgroups; -/* 1 if loading failed */ -static int rdberr; +static struct xtables_lmap *devgroups; -static void load_devgroups(void) +static void devgroup_init(struct xt_entry_match *match) { - const char* rfnm = "/etc/iproute2/group_map"; - char buf[512]; - FILE *fil; - char *cur, *nxt; - int id; - struct devgroupname *oldnm = NULL, *newnm = NULL; - - fil = fopen(rfnm, "r"); - if (!fil) { - rdberr = 1; - return; - } - - while (fgets(buf, sizeof(buf), fil)) { - cur = buf; - while ((*cur == ' ') || (*cur == '\t')) - cur++; - if ((*cur == '#') || (*cur == '\n') || (*cur == 0)) - continue; - - /* iproute2 allows hex and dec format */ - errno = 0; - id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16); - if ((nxt == cur) || errno) - continue; - - /* same boundaries as in iproute2 */ - if (id < 0 || id > 255) - continue; - cur = nxt; - - if (!isspace(*cur)) - continue; - while ((*cur == ' ') || (*cur == '\t')) - cur++; - if ((*cur == '#') || (*cur == '\n') || (*cur == 0)) - continue; - nxt = cur; - while ((*nxt != 0) && !isspace(*nxt)) - nxt++; - if (nxt == cur) - continue; - - /* found valid data */ - newnm = malloc(sizeof(struct devgroupname)); - if (newnm == NULL) { - perror("libxt_devgroup: malloc failed"); - exit(1); - } - newnm->id = id; - newnm->len = nxt - cur; - newnm->name = malloc(newnm->len + 1); - if (newnm->name == NULL) { - perror("libxt_devgroup: malloc failed"); - exit(1); - } - strncpy(newnm->name, cur, newnm->len); - newnm->name[newnm->len] = 0; - newnm->next = NULL; - - if (oldnm) - oldnm->next = newnm; - else - devgroups = newnm; - oldnm = newnm; - } - - fclose(fil); -} - -/* get devgroup id for name, -1 if error/not found */ -static int devgroup_name2id(const char* name) -{ - struct devgroupname* cur; - - if ((devgroups == NULL) && (rdberr == 0)) - load_devgroups(); - cur = devgroups; - if (cur == NULL) - return -1; - while (cur) { - if (!strncmp(name, cur->name, cur->len + 1)) - return cur->id; - cur = cur->next; - } - return -1; -} - -/* get devgroup name for id, NULL if error/not found */ -static const char *devgroup_id2name(int id) -{ - struct devgroupname* cur; - - if ((devgroups == NULL) && (rdberr == 0)) - load_devgroups(); - cur = devgroups; - if (cur == NULL) - return NULL; - while (cur) { - if (id == cur->id) - return cur->name; - cur = cur->next; - } - return NULL; + const char file[] = "/etc/iproute2/group_map"; + devgroups = xtables_lmap_init(file); + if (devgroups == NULL && errno != ENOENT) + fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno)); } -static int devgroup_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void devgroup_parse(struct xt_option_call *cb) { - struct xt_devgroup_info *info = (struct xt_devgroup_info *)(*match)->data; + struct xt_devgroup_info *info = cb->data; unsigned int id; char *end; - switch (c) { - case XT_DEVGROUP_OPT_SRCGROUP: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - end = optarg; - info->src_group = strtoul(optarg, &end, 0); - if (end != optarg && (*end == '/' || *end == '\0')) { + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SRC_GROUP: + info->src_group = strtoul(cb->arg, &end, 0); + if (end != cb->arg && (*end == '/' || *end == '\0')) { if (*end == '/') info->src_mask = strtoul(end+1, &end, 0); else info->src_mask = 0xffffffff; - if (*end != '\0' || end == optarg) + if (*end != '\0' || end == cb->arg) xtables_error(PARAMETER_PROBLEM, "Bad src-group value `%s'", - optarg); + cb->arg); } else { - id = devgroup_name2id(optarg); + id = xtables_lmap_name2id(devgroups, cb->arg); if (id == -1) xtables_error(PARAMETER_PROBLEM, "Device group `%s' not found", - optarg); + cb->arg); info->src_group = id; info->src_mask = 0xffffffff; } - info->flags |= XT_DEVGROUP_MATCH_SRC; - if (invert) + if (cb->invert) info->flags |= XT_DEVGROUP_INVERT_SRC; - *flags |= c; break; - case XT_DEVGROUP_OPT_DSTGROUP: - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - end = optarg; - info->dst_group = strtoul(optarg, &end, 0); - if (end != optarg && (*end == '/' || *end == '\0')) { + case O_DST_GROUP: + info->dst_group = strtoul(cb->arg, &end, 0); + if (end != cb->arg && (*end == '/' || *end == '\0')) { if (*end == '/') info->dst_mask = strtoul(end+1, &end, 0); else info->dst_mask = 0xffffffff; - if (*end != '\0' || end == optarg) + if (*end != '\0' || end == cb->arg) xtables_error(PARAMETER_PROBLEM, "Bad dst-group value `%s'", - optarg); + cb->arg); } else { - id = devgroup_name2id(optarg); + id = xtables_lmap_name2id(devgroups, cb->arg); if (id == -1) xtables_error(PARAMETER_PROBLEM, "Device group `%s' not found", - optarg); + cb->arg); info->dst_group = id; info->dst_mask = 0xffffffff; } - info->flags |= XT_DEVGROUP_MATCH_DST; - if (invert) + if (cb->invert) info->flags |= XT_DEVGROUP_INVERT_DST; - *flags |= c; break; } - return 1; } static void @@ -228,7 +108,7 @@ print_devgroup(unsigned int id, unsigned int mask, int numeric) printf("0x%x/0x%x", id, mask); else { if (numeric == 0) - name = devgroup_id2name(id); + name = xtables_lmap_id2name(devgroups, id); if (name) printf("%s", name); else @@ -269,9 +149,9 @@ static void devgroup_save(const void *ip, const struct xt_entry_match *match) devgroup_show("--", info, 0); } -static void devgroup_check(unsigned int flags) +static void devgroup_check(struct xt_fcheck_call *cb) { - if (!flags) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "devgroup match: You must specify either " "'--src-group' or '--dst-group'"); @@ -283,12 +163,13 @@ static struct xtables_match devgroup_mt_reg = { .family = NFPROTO_UNSPEC, .size = XT_ALIGN(sizeof(struct xt_devgroup_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_devgroup_info)), + .init = devgroup_init, .help = devgroup_help, - .parse = devgroup_parse, - .final_check = devgroup_check, .print = devgroup_print, .save = devgroup_save, - .extra_opts = devgroup_opts, + .x6_parse = devgroup_parse, + .x6_fcheck = devgroup_check, + .x6_options = devgroup_opts, }; void _init(void) -- cgit v1.2.3 From f04d48879fea70451148d7867d5a388efe63b48f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 16:38:51 +0100 Subject: libipt_realm: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libipt_realm.c | 202 +++++++++------------------------------------- 1 file changed, 39 insertions(+), 163 deletions(-) diff --git a/extensions/libipt_realm.c b/extensions/libipt_realm.c index 17b1754e..b60c57ee 100644 --- a/extensions/libipt_realm.c +++ b/extensions/libipt_realm.c @@ -1,12 +1,7 @@ -/* Shared library add-on to iptables to add realm matching support. */ -#include #include -#include #include #include #include -#include -#include #if defined(__GLIBC__) && __GLIBC__ == 2 #include #else @@ -15,6 +10,10 @@ #include #include +enum { + O_REALM = 0, +}; + static void realm_help(void) { printf( @@ -23,165 +22,49 @@ static void realm_help(void) " Match realm\n"); } -static const struct option realm_opts[] = { - {.name = "realm", .has_arg = true, .val = '1'}, - XT_GETOPT_TABLEEND, -}; - -struct realmname { - int id; - char* name; - int len; - struct realmname* next; +static const struct xt_option_entry realm_opts[] = { + {.name = "realm", .id = O_REALM, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, }; /* array of realms from /etc/iproute2/rt_realms */ -static struct realmname *realms; -/* 1 if loading failed */ -static int rdberr; +static struct xtables_lmap *realms; -static void load_realms(void) +static void realm_init(struct xt_entry_match *m) { - const char* rfnm = "/etc/iproute2/rt_realms"; - char buf[512]; - FILE *fil; - char *cur, *nxt; - int id; - struct realmname *oldnm = NULL, *newnm = NULL; - - fil = fopen(rfnm, "re"); - if (!fil) { - rdberr = 1; - return; - } - - while (fgets(buf, sizeof(buf), fil)) { - cur = buf; - while ((*cur == ' ') || (*cur == '\t')) - cur++; - if ((*cur == '#') || (*cur == '\n') || (*cur == 0)) - continue; - - /* iproute2 allows hex and dec format */ - errno = 0; - id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16); - if ((nxt == cur) || errno) - continue; - - /* same boundaries as in iproute2 */ - if (id < 0 || id > 255) - continue; - cur = nxt; - - if (!isspace(*cur)) - continue; - while ((*cur == ' ') || (*cur == '\t')) - cur++; - if ((*cur == '#') || (*cur == '\n') || (*cur == 0)) - continue; - nxt = cur; - while ((*nxt != 0) && !isspace(*nxt)) - nxt++; - if (nxt == cur) - continue; - - /* found valid data */ - newnm = malloc(sizeof(struct realmname)); - if (newnm == NULL) { - perror("libipt_realm: malloc failed"); - exit(1); - } - newnm->id = id; - newnm->len = nxt - cur; - newnm->name = malloc(newnm->len + 1); - if (newnm->name == NULL) { - perror("libipt_realm: malloc failed"); - exit(1); - } - strncpy(newnm->name, cur, newnm->len); - newnm->name[newnm->len] = 0; - newnm->next = NULL; - - if (oldnm) - oldnm->next = newnm; - else - realms = newnm; - oldnm = newnm; - } - - fclose(fil); + const char file[] = "/etc/iproute2/rt_realms"; + realms = xtables_lmap_init(file); + if (realms == NULL && errno != ENOENT) + fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno)); } -/* get realm id for name, -1 if error/not found */ -static int realm_name2id(const char* name) +static void realm_parse(struct xt_option_call *cb) { - struct realmname* cur; - - if ((realms == NULL) && (rdberr == 0)) - load_realms(); - cur = realms; - if (cur == NULL) - return -1; - while (cur) { - if (!strncmp(name, cur->name, cur->len + 1)) - return cur->id; - cur = cur->next; - } - return -1; -} - -/* get realm name for id, NULL if error/not found */ -static const char *realm_id2name(int id) -{ - struct realmname* cur; - - if ((realms == NULL) && (rdberr == 0)) - load_realms(); - cur = realms; - if (cur == NULL) - return NULL; - while (cur) { - if (id == cur->id) - return cur->name; - cur = cur->next; - } - return NULL; -} - -static int realm_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct ipt_realm_info *realminfo = (struct ipt_realm_info *)(*match)->data; + struct ipt_realm_info *realminfo = cb->data; int id; + char *end; - switch (c) { - char *end; - case '1': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - end = optarg = optarg; - realminfo->id = strtoul(optarg, &end, 0); - if (end != optarg && (*end == '/' || *end == '\0')) { - if (*end == '/') - realminfo->mask = strtoul(end+1, &end, 0); - else - realminfo->mask = 0xffffffff; - if (*end != '\0' || end == optarg) - xtables_error(PARAMETER_PROBLEM, - "Bad realm value `%s'", optarg); - } else { - id = realm_name2id(optarg); - if (id == -1) - xtables_error(PARAMETER_PROBLEM, - "Realm `%s' not found", optarg); - realminfo->id = id; + xtables_option_parse(cb); + realminfo->id = strtoul(cb->arg, &end, 0); + if (end != cb->arg && (*end == '/' || *end == '\0')) { + if (*end == '/') + realminfo->mask = strtoul(end+1, &end, 0); + else realminfo->mask = 0xffffffff; - } - if (invert) - realminfo->invert = 1; - *flags = 1; - break; + if (*end != '\0' || end == cb->arg) + xtables_error(PARAMETER_PROBLEM, + "Bad realm value \"%s\"", cb->arg); + } else { + id = xtables_lmap_name2id(realms, cb->arg); + if (id == -1) + xtables_error(PARAMETER_PROBLEM, + "Realm \"%s\" not found", cb->arg); + realminfo->id = id; + realminfo->mask = 0xffffffff; } - return 1; + if (cb->invert) + realminfo->invert = 1; } static void @@ -193,7 +76,7 @@ print_realm(unsigned long id, unsigned long mask, int numeric) printf(" 0x%lx/0x%lx", id, mask); else { if (numeric == 0) - name = realm_id2name(id); + name = xtables_lmap_id2name(realms, id); if (name) printf(" %s", name); else @@ -224,13 +107,6 @@ static void realm_save(const void *ip, const struct xt_entry_match *match) print_realm(ri->id, ri->mask, 0); } -static void realm_check(unsigned int flags) -{ - if (!flags) - xtables_error(PARAMETER_PROBLEM, - "realm match: You must specify `--realm'"); -} - static struct xtables_match realm_mt_reg = { .name = "realm", .version = XTABLES_VERSION, @@ -238,11 +114,11 @@ static struct xtables_match realm_mt_reg = { .size = XT_ALIGN(sizeof(struct ipt_realm_info)), .userspacesize = XT_ALIGN(sizeof(struct ipt_realm_info)), .help = realm_help, - .parse = realm_parse, - .final_check = realm_check, + .init = realm_init, .print = realm_print, .save = realm_save, - .extra_opts = realm_opts, + .x6_parse = realm_parse, + .x6_options = realm_opts, }; void _init(void) -- cgit v1.2.3 From 564eaf48e14411803a353206eefbb89d525c63ff Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 16:59:23 +0100 Subject: libxtables: XTTYPE_UINT16RC support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 2 ++ xtoptions.c | 28 +++++++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index 30d9e73b..ae76bb6b 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -57,6 +57,7 @@ enum xt_option_type { XTTYPE_UINT8, XTTYPE_UINT32, XTTYPE_UINT64, + XTTYPE_UINT16RC, XTTYPE_UINT32RC, XTTYPE_STRING, XTTYPE_MARKMASK32, @@ -115,6 +116,7 @@ struct xt_option_call { uint8_t nvals; union { uint8_t u8; + uint16_t u16_range[2]; uint32_t u32, u32_range[2]; uint64_t u64; struct { diff --git a/xtoptions.c b/xtoptions.c index f48c011c..ca5bffab 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -133,15 +133,18 @@ static void xtopt_parse_mint(struct xt_option_call *cb) { const struct xt_option_entry *entry = cb->entry; const char *arg = cb->arg; - uint32_t *put = XTOPT_MKPTR(cb); + size_t esize = sizeof(uint32_t); + char *put = XTOPT_MKPTR(cb); unsigned int maxiter, value; char *end = ""; char sep = ':'; - maxiter = entry->size / sizeof(uint32_t); + if (entry->type == XTTYPE_UINT16RC) + esize = sizeof(uint16_t); + maxiter = entry->size / esize; if (maxiter == 0) maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */ - if (entry->size % sizeof(uint32_t) != 0) + if (entry->size % esize != 0) xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does " "not have proper size\n", __func__); @@ -161,10 +164,19 @@ static void xtopt_parse_mint(struct xt_option_call *cb) "%s: Argument to \"--%s\" has unexpected " "characters.\n", cb->ext_name, entry->name); ++cb->nvals; - if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) - cb->val.u32_range[cb->nvals] = value; - if (entry->flags & XTOPT_PUT) - *put++ = value; + if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) { + if (entry->type == XTTYPE_UINT16RC) + cb->val.u16_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT32RC) + cb->val.u32_range[cb->nvals] = value; + } + if (entry->flags & XTOPT_PUT) { + if (entry->type == XTTYPE_UINT16RC) + *(uint16_t *)put = value; + else if (entry->type == XTTYPE_UINT32RC) + *(uint32_t *)put = value; + put += esize; + } if (*end == '\0') break; } @@ -225,6 +237,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT32] = xtopt_parse_int, [XTTYPE_UINT64] = xtopt_parse_int, + [XTTYPE_UINT16RC] = xtopt_parse_mint, [XTTYPE_UINT32RC] = xtopt_parse_mint, [XTTYPE_STRING] = xtopt_parse_string, [XTTYPE_MARKMASK32] = xtopt_parse_markmask, @@ -234,6 +247,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_UINT8] = sizeof(uint8_t), [XTTYPE_UINT32] = sizeof(uint32_t), [XTTYPE_UINT64] = sizeof(uint64_t), + [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), [XTTYPE_STRING] = -1, }; -- cgit v1.2.3 From c15f9e3f6d8552cddfc858b115d996c7cf5b47e9 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:00:49 +0100 Subject: libxt_length: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_length.c | 92 +++++++++-------------------------------------- 1 file changed, 17 insertions(+), 75 deletions(-) diff --git a/extensions/libxt_length.c b/extensions/libxt_length.c index a12aefef..4f3a3318 100644 --- a/extensions/libxt_length.c +++ b/extensions/libxt_length.c @@ -1,14 +1,11 @@ -/* Shared library add-on to iptables to add packet length matching support. */ -#include #include -#include -#include -#include -#include - #include #include +enum { + O_LENGTH = 0, +}; + static void length_help(void) { printf( @@ -17,75 +14,21 @@ static void length_help(void) " of values (inclusive)\n"); } -static const struct option length_opts[] = { - {.name = "length", .has_arg = true, .val = '1'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry length_opts[] = { + {.name = "length", .id = O_LENGTH, .type = XTTYPE_UINT16RC, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, }; -static uint16_t -parse_length(const char *s) -{ - unsigned int len; - - if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, "length invalid: \"%s\"\n", s); - else - return len; -} - -/* If a single value is provided, min and max are both set to the value */ -static void -parse_lengths(const char *s, struct xt_length_info *info) -{ - char *buffer; - char *cp; - - buffer = strdup(s); - if ((cp = strchr(buffer, ':')) == NULL) - info->min = info->max = parse_length(buffer); - else { - *cp = '\0'; - cp++; - - info->min = buffer[0] ? parse_length(buffer) : 0; - info->max = cp[0] ? parse_length(cp) : 0xFFFF; - } - free(buffer); - - if (info->min > info->max) - xtables_error(PARAMETER_PROBLEM, - "length min. range value `%u' greater than max. " - "range value `%u'", info->min, info->max); - -} - -static int -length_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void length_parse(struct xt_option_call *cb) { - struct xt_length_info *info = (struct xt_length_info *)(*match)->data; - - switch (c) { - case '1': - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "length: `--length' may only be " - "specified once"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - parse_lengths(optarg, info); - if (invert) - info->invert = 1; - *flags = 1; - break; - } - return 1; -} + struct xt_length_info *info = cb->data; -static void length_check(unsigned int flags) -{ - if (!flags) - xtables_error(PARAMETER_PROBLEM, - "length: You must specify `--length'"); + xtables_option_parse(cb); + info->min = cb->val.u16_range[0]; + info->max = (cb->nvals == 2) ? cb->val.u16_range[1] : UINT16_MAX; + if (cb->invert) + info->invert = 1; } static void @@ -118,11 +61,10 @@ static struct xtables_match length_match = { .size = XT_ALIGN(sizeof(struct xt_length_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)), .help = length_help, - .parse = length_parse, - .final_check = length_check, .print = length_print, .save = length_save, - .extra_opts = length_opts, + .x6_parse = length_parse, + .x6_options = length_opts, }; void _init(void) -- cgit v1.2.3 From ba77b9b142b55c856b0a2950eddece7ad7e6bfbc Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:04:35 +0100 Subject: libxt_tcpmss: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_tcpmss.c | 92 +++++++++++------------------------------------ 1 file changed, 20 insertions(+), 72 deletions(-) diff --git a/extensions/libxt_tcpmss.c b/extensions/libxt_tcpmss.c index 3dc35286..c7c59717 100644 --- a/extensions/libxt_tcpmss.c +++ b/extensions/libxt_tcpmss.c @@ -1,14 +1,11 @@ -/* Shared library add-on to iptables to add tcp MSS matching support. */ -#include #include -#include -#include -#include -#include - #include #include +enum { + O_TCPMSS = 0, +}; + static void tcpmss_help(void) { printf( @@ -17,71 +14,23 @@ static void tcpmss_help(void) " (only valid for TCP SYN or SYN/ACK packets)\n"); } -static const struct option tcpmss_opts[] = { - {.name = "mss", .has_arg = true, .val = '1'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry tcpmss_opts[] = { + {.name = "mss", .id = O_TCPMSS, .type = XTTYPE_UINT16RC, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, }; -static uint16_t -parse_tcp_mssvalue(const char *mssvalue) -{ - unsigned int mssvaluenum; - - if (xtables_strtoui(mssvalue, NULL, &mssvaluenum, 0, UINT16_MAX)) - return mssvaluenum; - - xtables_error(PARAMETER_PROBLEM, - "Invalid mss `%s' specified", mssvalue); -} - -static void -parse_tcp_mssvalues(const char *mssvaluestring, - uint16_t *mss_min, uint16_t *mss_max) -{ - char *buffer; - char *cp; - - buffer = strdup(mssvaluestring); - if ((cp = strchr(buffer, ':')) == NULL) - *mss_min = *mss_max = parse_tcp_mssvalue(buffer); - else { - *cp = '\0'; - cp++; - - *mss_min = buffer[0] ? parse_tcp_mssvalue(buffer) : 0; - *mss_max = cp[0] ? parse_tcp_mssvalue(cp) : 0xFFFF; - } - free(buffer); -} - -static int -tcpmss_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct xt_tcpmss_match_info *mssinfo = - (struct xt_tcpmss_match_info *)(*match)->data; - - switch (c) { - case '1': - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "Only one `--mss' allowed"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - parse_tcp_mssvalues(optarg, - &mssinfo->mss_min, &mssinfo->mss_max); - if (invert) - mssinfo->invert = 1; - *flags = 1; - break; - } - return 1; -} - -static void tcpmss_check(unsigned int flags) +static void tcpmss_parse(struct xt_option_call *cb) { - if (!flags) - xtables_error(PARAMETER_PROBLEM, - "tcpmss match: You must specify `--mss'"); + struct xt_tcpmss_match_info *mssinfo = cb->data; + + xtables_option_parse(cb); + mssinfo->mss_min = cb->val.u16_range[0]; + mssinfo->mss_max = mssinfo->mss_min; + if (cb->nvals == 2) + mssinfo->mss_max = cb->val.u16_range[1]; + if (cb->invert) + mssinfo->invert = 1; } static void @@ -114,11 +63,10 @@ static struct xtables_match tcpmss_match = { .size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)), .help = tcpmss_help, - .parse = tcpmss_parse, - .final_check = tcpmss_check, .print = tcpmss_print, .save = tcpmss_save, - .extra_opts = tcpmss_opts, + .x6_parse = tcpmss_parse, + .x6_options = tcpmss_opts, }; void _init(void) -- cgit v1.2.3 From 8bf513ada0aae0e4b1ac5160113fc532c2f525d0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:09:19 +0100 Subject: libxtables: XTTYPE_UINT8RC support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 3 ++- xtoptions.c | 14 +++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index ae76bb6b..8f65b053 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -57,6 +57,7 @@ enum xt_option_type { XTTYPE_UINT8, XTTYPE_UINT32, XTTYPE_UINT64, + XTTYPE_UINT8RC, XTTYPE_UINT16RC, XTTYPE_UINT32RC, XTTYPE_STRING, @@ -115,7 +116,7 @@ struct xt_option_call { bool invert; uint8_t nvals; union { - uint8_t u8; + uint8_t u8, u8_range[2]; uint16_t u16_range[2]; uint32_t u32, u32_range[2]; uint64_t u64; diff --git a/xtoptions.c b/xtoptions.c index ca5bffab..babc8276 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -139,7 +139,9 @@ static void xtopt_parse_mint(struct xt_option_call *cb) char *end = ""; char sep = ':'; - if (entry->type == XTTYPE_UINT16RC) + if (entry->type == XTTYPE_UINT8RC) + esize = sizeof(uint8_t); + else if (entry->type == XTTYPE_UINT16RC) esize = sizeof(uint16_t); maxiter = entry->size / esize; if (maxiter == 0) @@ -165,13 +167,17 @@ static void xtopt_parse_mint(struct xt_option_call *cb) "characters.\n", cb->ext_name, entry->name); ++cb->nvals; if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) { - if (entry->type == XTTYPE_UINT16RC) + if (entry->type == XTTYPE_UINT8RC) + cb->val.u8_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT16RC) cb->val.u16_range[cb->nvals] = value; else if (entry->type == XTTYPE_UINT32RC) cb->val.u32_range[cb->nvals] = value; } if (entry->flags & XTOPT_PUT) { - if (entry->type == XTTYPE_UINT16RC) + if (entry->type == XTTYPE_UINT8RC) + *(uint8_t *)put = value; + else if (entry->type == XTTYPE_UINT16RC) *(uint16_t *)put = value; else if (entry->type == XTTYPE_UINT32RC) *(uint32_t *)put = value; @@ -237,6 +243,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT32] = xtopt_parse_int, [XTTYPE_UINT64] = xtopt_parse_int, + [XTTYPE_UINT8RC] = xtopt_parse_mint, [XTTYPE_UINT16RC] = xtopt_parse_mint, [XTTYPE_UINT32RC] = xtopt_parse_mint, [XTTYPE_STRING] = xtopt_parse_string, @@ -247,6 +254,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_UINT8] = sizeof(uint8_t), [XTTYPE_UINT32] = sizeof(uint32_t), [XTTYPE_UINT64] = sizeof(uint64_t), + [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), [XTTYPE_STRING] = -1, -- cgit v1.2.3 From bc438c4cbdab09fafbbceecddd54e44e4234a4a1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:13:54 +0100 Subject: libxtables: XTTYPE_UINT64RC support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 3 ++- xtoptions.c | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index 8f65b053..325c04c4 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -60,6 +60,7 @@ enum xt_option_type { XTTYPE_UINT8RC, XTTYPE_UINT16RC, XTTYPE_UINT32RC, + XTTYPE_UINT64RC, XTTYPE_STRING, XTTYPE_MARKMASK32, }; @@ -119,7 +120,7 @@ struct xt_option_call { uint8_t u8, u8_range[2]; uint16_t u16_range[2]; uint32_t u32, u32_range[2]; - uint64_t u64; + uint64_t u64, u64_range[2]; struct { uint32_t mark, mask; }; diff --git a/xtoptions.c b/xtoptions.c index babc8276..a74938fa 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -143,6 +143,8 @@ static void xtopt_parse_mint(struct xt_option_call *cb) esize = sizeof(uint8_t); else if (entry->type == XTTYPE_UINT16RC) esize = sizeof(uint16_t); + else if (entry->type == XTTYPE_UINT64RC) + esize = sizeof(uint64_t); maxiter = entry->size / esize; if (maxiter == 0) maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */ @@ -173,6 +175,8 @@ static void xtopt_parse_mint(struct xt_option_call *cb) cb->val.u16_range[cb->nvals] = value; else if (entry->type == XTTYPE_UINT32RC) cb->val.u32_range[cb->nvals] = value; + else if (entry->type == XTTYPE_UINT64RC) + cb->val.u64_range[cb->nvals] = value; } if (entry->flags & XTOPT_PUT) { if (entry->type == XTTYPE_UINT8RC) @@ -181,6 +185,8 @@ static void xtopt_parse_mint(struct xt_option_call *cb) *(uint16_t *)put = value; else if (entry->type == XTTYPE_UINT32RC) *(uint32_t *)put = value; + else if (entry->type == XTTYPE_UINT64RC) + *(uint64_t *)put = value; put += esize; } if (*end == '\0') @@ -246,6 +252,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8RC] = xtopt_parse_mint, [XTTYPE_UINT16RC] = xtopt_parse_mint, [XTTYPE_UINT32RC] = xtopt_parse_mint, + [XTTYPE_UINT64RC] = xtopt_parse_mint, [XTTYPE_STRING] = xtopt_parse_string, [XTTYPE_MARKMASK32] = xtopt_parse_markmask, }; @@ -257,6 +264,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), [XTTYPE_UINT16RC] = sizeof(uint16_t[2]), [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), + [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), [XTTYPE_STRING] = -1, }; -- cgit v1.2.3 From 09631dc60ce41bc484a42fcf4d4ddf7036820bd1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:19:10 +0100 Subject: libxt_connbytes: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_connbytes.c | 107 +++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 69 deletions(-) diff --git a/extensions/libxt_connbytes.c b/extensions/libxt_connbytes.c index 1d3391ae..46a7e4b9 100644 --- a/extensions/libxt_connbytes.c +++ b/extensions/libxt_connbytes.c @@ -1,14 +1,14 @@ -/* Shared library add-on to iptables to add byte tracking support. */ -#include #include -#include #include -#include -#include #include -#include #include +enum { + O_CONNBYTES = 0, + O_CONNBYTES_DIR, + O_CONNBYTES_MODE, +}; + static void connbytes_help(void) { printf( @@ -18,87 +18,57 @@ static void connbytes_help(void) " --connbytes-mode [packets, bytes, avgpkt]\n"); } -static const struct option connbytes_opts[] = { - {.name = "connbytes", .has_arg = true, .val = '1'}, - {.name = "connbytes-dir", .has_arg = true, .val = '2'}, - {.name = "connbytes-mode", .has_arg = true, .val = '3'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry connbytes_opts[] = { + {.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC, + .flags = XTOPT_MAND | XTOPT_INVERT}, + {.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING, + .flags = XTOPT_MAND}, + {.name = "connbytes-mode", .id = O_CONNBYTES_MODE, + .type = XTTYPE_STRING, .flags = XTOPT_MAND}, + XTOPT_TABLEEND, }; -static void -parse_range(const char *arg, struct xt_connbytes_info *si) -{ - char *colon,*p; - - si->count.from = strtoul(arg,&colon,10); - if (*colon != ':') - xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", arg); - si->count.to = strtoul(colon+1,&p,10); - if (p == colon+1) { - /* second number omited */ - si->count.to = 0xffffffff; - } - if (si->count.from > si->count.to) - xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu", - (unsigned long long)si->count.from, - (unsigned long long)si->count.to); -} - -static int -connbytes_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void connbytes_parse(struct xt_option_call *cb) { - struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data; - unsigned long i; - - switch (c) { - case '1': - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) - optind++; - - parse_range(optarg, sinfo); - if (invert) { + struct xt_connbytes_info *sinfo = cb->data; + unsigned long long i; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_CONNBYTES: + sinfo->count.from = cb->val.u64_range[0]; + sinfo->count.to = cb->val.u64_range[0]; + if (cb->nvals == 2) + sinfo->count.to = cb->val.u64_range[1]; + if (cb->invert) { i = sinfo->count.from; sinfo->count.from = sinfo->count.to; sinfo->count.to = i; } - *flags |= 1; break; - case '2': - if (!strcmp(optarg, "original")) + case O_CONNBYTES_DIR: + if (strcmp(cb->arg, "original") == 0) sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL; - else if (!strcmp(optarg, "reply")) + else if (strcmp(cb->arg, "reply") == 0) sinfo->direction = XT_CONNBYTES_DIR_REPLY; - else if (!strcmp(optarg, "both")) + else if (strcmp(cb->arg, "both") == 0) sinfo->direction = XT_CONNBYTES_DIR_BOTH; else xtables_error(PARAMETER_PROBLEM, - "Unknown --connbytes-dir `%s'", optarg); - - *flags |= 2; + "Unknown --connbytes-dir `%s'", cb->arg); break; - case '3': - if (!strcmp(optarg, "packets")) + case O_CONNBYTES_MODE: + if (strcmp(cb->arg, "packets") == 0) sinfo->what = XT_CONNBYTES_PKTS; - else if (!strcmp(optarg, "bytes")) + else if (strcmp(cb->arg, "bytes") == 0) sinfo->what = XT_CONNBYTES_BYTES; - else if (!strcmp(optarg, "avgpkt")) + else if (strcmp(cb->arg, "avgpkt") == 0) sinfo->what = XT_CONNBYTES_AVGPKT; else xtables_error(PARAMETER_PROBLEM, - "Unknown --connbytes-mode `%s'", optarg); - *flags |= 4; + "Unknown --connbytes-mode `%s'", cb->arg); break; } - - return 1; -} - -static void connbytes_check(unsigned int flags) -{ - if (flags != 7) - xtables_error(PARAMETER_PROBLEM, "You must specify `--connbytes'" - "`--connbytes-dir' and `--connbytes-mode'"); } static void print_mode(const struct xt_connbytes_info *sinfo) @@ -185,11 +155,10 @@ static struct xtables_match connbytes_match = { .size = XT_ALIGN(sizeof(struct xt_connbytes_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)), .help = connbytes_help, - .parse = connbytes_parse, - .final_check = connbytes_check, .print = connbytes_print, .save = connbytes_save, - .extra_opts = connbytes_opts, + .x6_parse = connbytes_parse, + .x6_options = connbytes_opts, }; void _init(void) -- cgit v1.2.3 From 0eff54bd407aae6b99c3b189d356929e399b5a38 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:42:51 +0100 Subject: libxtables: XTTYPE_UINT16 support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 3 ++- xtoptions.c | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index 325c04c4..6167f4da 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -55,6 +55,7 @@ struct in_addr; enum xt_option_type { XTTYPE_NONE, XTTYPE_UINT8, + XTTYPE_UINT16, XTTYPE_UINT32, XTTYPE_UINT64, XTTYPE_UINT8RC, @@ -118,7 +119,7 @@ struct xt_option_call { uint8_t nvals; union { uint8_t u8, u8_range[2]; - uint16_t u16_range[2]; + uint16_t u16, u16_range[2]; uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; struct { diff --git a/xtoptions.c b/xtoptions.c index a74938fa..939e6860 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -92,6 +92,8 @@ static void xtopt_parse_int(struct xt_option_call *cb) if (entry->type == XTTYPE_UINT8) lmax = UINT8_MAX; + else if (entry->type == XTTYPE_UINT16) + lmax = UINT16_MAX; else if (entry->type == XTTYPE_UINT64) lmax = UINT64_MAX; if (cb->entry->min != 0) @@ -109,6 +111,10 @@ static void xtopt_parse_int(struct xt_option_call *cb) cb->val.u8 = value; if (entry->flags & XTOPT_PUT) *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8; + } else if (entry->type == XTTYPE_UINT16) { + cb->val.u16 = value; + if (entry->flags & XTOPT_PUT) + *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16; } else if (entry->type == XTTYPE_UINT32) { cb->val.u32 = value; if (entry->flags & XTOPT_PUT) @@ -247,6 +253,7 @@ static void xtopt_parse_markmask(struct xt_option_call *cb) static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, + [XTTYPE_UINT16] = xtopt_parse_int, [XTTYPE_UINT32] = xtopt_parse_int, [XTTYPE_UINT64] = xtopt_parse_int, [XTTYPE_UINT8RC] = xtopt_parse_mint, @@ -259,6 +266,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { static const size_t xtopt_psize[] = { [XTTYPE_UINT8] = sizeof(uint8_t), + [XTTYPE_UINT16] = sizeof(uint16_t), [XTTYPE_UINT32] = sizeof(uint32_t), [XTTYPE_UINT64] = sizeof(uint64_t), [XTTYPE_UINT8RC] = sizeof(uint8_t[2]), -- cgit v1.2.3 From a05562e1e2fb2e18f34d29ec57c4217a3014d1f2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:47:03 +0100 Subject: libxt_CT: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_CT.c | 74 +++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index 38ee17b1..7b93bfaf 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -1,9 +1,5 @@ -#include #include #include -#include -#include -#include #include #include #include @@ -20,22 +16,26 @@ static void ct_help(void) ); } -enum ct_options { - CT_OPT_NOTRACK = 0x1, - CT_OPT_HELPER = 0x2, - CT_OPT_CTEVENTS = 0x4, - CT_OPT_EXPEVENTS = 0x8, - CT_OPT_ZONE = 0x10, +enum { + O_NOTRACK = 0, + O_HELPER, + O_CTEVENTS, + O_EXPEVENTS, + O_ZONE, }; -static const struct option ct_opts[] = { - {.name = "notrack", .has_arg = false, .val = CT_OPT_NOTRACK}, - {.name = "helper", .has_arg = true, .val = CT_OPT_HELPER}, - {.name = "ctevents", .has_arg = true, .val = CT_OPT_CTEVENTS}, - {.name = "expevents", .has_arg = true, .val = CT_OPT_EXPEVENTS}, - {.name = "zone", .has_arg = true, .val = CT_OPT_ZONE}, - XT_GETOPT_TABLEEND, +#define s struct xt_ct_target_info +static const struct xt_option_entry ct_opts[] = { + {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE}, + {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)}, + {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING}, + {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING}, + {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)}, + XTOPT_TABLEEND, }; +#undef s struct event_tbl { const char *name; @@ -96,40 +96,22 @@ static void ct_print_events(const char *pfx, const struct event_tbl *tbl, } } -static int ct_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void ct_parse(struct xt_option_call *cb) { - struct xt_ct_target_info *info = (struct xt_ct_target_info *)(*target)->data; - unsigned int zone; + struct xt_ct_target_info *info = cb->data; - switch (c) { - case CT_OPT_NOTRACK: - xtables_param_act(XTF_ONLY_ONCE, "CT", "--notrack", *flags & CT_OPT_NOTRACK); + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_NOTRACK: info->flags |= XT_CT_NOTRACK; break; - case CT_OPT_HELPER: - xtables_param_act(XTF_ONLY_ONCE, "CT", "--helper", *flags & CT_OPT_HELPER); - strncpy(info->helper, optarg, sizeof(info->helper)); - info->helper[sizeof(info->helper) - 1] = '\0'; + case O_CTEVENTS: + info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg); break; - case CT_OPT_CTEVENTS: - xtables_param_act(XTF_ONLY_ONCE, "CT", "--ctevents", *flags & CT_OPT_CTEVENTS); - info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), optarg); - break; - case CT_OPT_EXPEVENTS: - xtables_param_act(XTF_ONLY_ONCE, "CT", "--expevents", *flags & CT_OPT_EXPEVENTS); - info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), optarg); - break; - case CT_OPT_ZONE: - xtables_param_act(XTF_ONLY_ONCE, "CT", "--zone", *flags & CT_OPT_ZONE); - if (!xtables_strtoui(optarg, NULL, &zone, 0, UINT16_MAX)) - xtables_error(PARAMETER_PROBLEM, "Bad zone value \"%s\"", optarg); - info->zone = zone; + case O_EXPEVENTS: + info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg); break; } - - *flags |= c; - return 1; } static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric) @@ -178,10 +160,10 @@ static struct xtables_target ct_target = { .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), .userspacesize = offsetof(struct xt_ct_target_info, ct), .help = ct_help, - .parse = ct_parse, .print = ct_print, .save = ct_save, - .extra_opts = ct_opts, + .x6_parse = ct_parse, + .x6_options = ct_opts, }; void _init(void) -- cgit v1.2.3 From 478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 17:54:50 +0100 Subject: libxt_NFQUEUE: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_NFQUEUE.c | 139 +++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 92 deletions(-) diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c index 7f2aab16..a86c88a3 100644 --- a/extensions/libxt_NFQUEUE.c +++ b/extensions/libxt_NFQUEUE.c @@ -5,16 +5,16 @@ * This program is distributed under the terms of GNU GPL v2, 1991 * */ -#include #include -#include -#include -#include - #include -#include #include +enum { + O_QUEUE_NUM = 0, + O_QUEUE_BALANCE, + O_QUEUE_BYPASS, +}; + static void NFQUEUE_help(void) { printf( @@ -38,103 +38,58 @@ static void NFQUEUE_help_v2(void) " --queue-bypass Bypass Queueing if no queue instance exists.\n"); } -static const struct option NFQUEUE_opts[] = { - {.name = "queue-num", .has_arg = true, .val = 'F'}, - {.name = "queue-balance", .has_arg = true, .val = 'B'}, - {.name = "queue-bypass", .has_arg = false,.val = 'P'}, - XT_GETOPT_TABLEEND, +#define s struct xt_NFQ_info +static const struct xt_option_entry NFQUEUE_opts[] = { + {.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum)}, + {.name = "queue-balance", .id = O_QUEUE_BALANCE, + .type = XTTYPE_UINT16RC}, + {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; +#undef s -static void exit_badqueue(const char *s) -{ - xtables_error(PARAMETER_PROBLEM, "Invalid queue number `%s'\n", s); -} - -static void -parse_num(const char *s, struct xt_NFQ_info *tinfo) +static void NFQUEUE_parse(struct xt_option_call *cb) { - unsigned int num; - - if (!xtables_strtoui(s, NULL, &num, 0, UINT16_MAX)) - exit_badqueue(s); - - tinfo->queuenum = num; -} - -static int -NFQUEUE_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - struct xt_NFQ_info *tinfo - = (struct xt_NFQ_info *)(*target)->data; - - switch (c) { - case 'F': - if (*flags) - xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " - "Only use --queue-num ONCE!"); - parse_num(optarg, tinfo); - break; - case 'B': + xtables_option_parse(cb); + if (cb->entry->id == O_QUEUE_BALANCE) xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " "--queue-balance not supported (kernel too old?)"); - } - - return 1; } -static int -NFQUEUE_parse_v1(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void NFQUEUE_parse_v1(struct xt_option_call *cb) { - struct xt_NFQ_info_v1 *info = (void *)(*target)->data; - char *colon; - unsigned int firstqueue, lastqueue; - - switch (c) { - case 'F': /* fallthrough */ - case 'B': - if (*flags) - xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " - "Only use --queue-num ONCE!"); - - if (!xtables_strtoui(optarg, &colon, &firstqueue, 0, UINT16_MAX)) - exit_badqueue(optarg); - - info->queuenum = firstqueue; - - if (c == 'F') { - if (*colon) - exit_badqueue(optarg); - break; - } + struct xt_NFQ_info_v1 *info = cb->data; + const uint16_t *r = cb->val.u16_range; - if (*colon != ':') - xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", optarg); - - if (!xtables_strtoui(colon + 1, NULL, &lastqueue, 1, UINT16_MAX)) - exit_badqueue(optarg); - - if (firstqueue >= lastqueue) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_QUEUE_BALANCE: + if (cb->nvals != 2) + xtables_error(PARAMETER_PROBLEM, + "Bad range \"%s\"", cb->arg); + if (r[0] >= r[1]) xtables_error(PARAMETER_PROBLEM, "%u should be less than %u", - firstqueue, lastqueue); - info->queues_total = lastqueue - firstqueue + 1; + r[0], r[1]); + info->queuenum = r[0]; + info->queues_total = r[1] - r[0] + 1; break; } - - return 1; } -static int -NFQUEUE_parse_v2(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void NFQUEUE_parse_v2(struct xt_option_call *cb) { - if (c == 'P') { - struct xt_NFQ_info_v2 *info = (void *)(*target)->data; + struct xt_NFQ_info_v2 *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_QUEUE_BYPASS: info->bypass = 1; - return 1; + break; + default: + NFQUEUE_parse_v1(cb); + break; } - return NFQUEUE_parse_v1(c, argv, invert, flags, entry, target); } static void NFQUEUE_print(const void *ip, @@ -214,10 +169,10 @@ static struct xtables_target nfqueue_targets[] = { .size = XT_ALIGN(sizeof(struct xt_NFQ_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)), .help = NFQUEUE_help, - .parse = NFQUEUE_parse, .print = NFQUEUE_print, .save = NFQUEUE_save, - .extra_opts = NFQUEUE_opts + .x6_parse = NFQUEUE_parse, + .x6_options = NFQUEUE_opts },{ .family = NFPROTO_UNSPEC, .revision = 1, @@ -227,10 +182,10 @@ static struct xtables_target nfqueue_targets[] = { .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)), .help = NFQUEUE_help_v1, .init = NFQUEUE_init_v1, - .parse = NFQUEUE_parse_v1, .print = NFQUEUE_print_v1, .save = NFQUEUE_save_v1, - .extra_opts = NFQUEUE_opts, + .x6_parse = NFQUEUE_parse_v1, + .x6_options = NFQUEUE_opts, },{ .family = NFPROTO_UNSPEC, .revision = 2, @@ -240,10 +195,10 @@ static struct xtables_target nfqueue_targets[] = { .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)), .help = NFQUEUE_help_v2, .init = NFQUEUE_init_v1, - .parse = NFQUEUE_parse_v2, .print = NFQUEUE_print_v2, .save = NFQUEUE_save_v2, - .extra_opts = NFQUEUE_opts, + .x6_parse = NFQUEUE_parse_v2, + .x6_options = NFQUEUE_opts, } }; -- cgit v1.2.3 From ea2a02f7e961011b2e226c25a5e8ff49e1f84278 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 18:00:05 +0100 Subject: libxt_TCPMSS: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_TCPMSS.c | 96 +++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 61 deletions(-) diff --git a/extensions/libxt_TCPMSS.c b/extensions/libxt_TCPMSS.c index e15e87a8..2266326d 100644 --- a/extensions/libxt_TCPMSS.c +++ b/extensions/libxt_TCPMSS.c @@ -2,16 +2,17 @@ * * Copyright (c) 2000 Marc Boucher */ -#include #include -#include -#include -#include - #include -#include +#include +#include #include +enum { + O_SET_MSS = 0, + O_CLAMP_MSS, +}; + struct mssinfo { struct xt_entry_target t; struct xt_tcpmss_info mss; @@ -28,69 +29,42 @@ hdrsize); static void TCPMSS_help(void) { - __TCPMSS_help(40); + __TCPMSS_help(sizeof(struct iphdr)); } static void TCPMSS_help6(void) { - __TCPMSS_help(60); + __TCPMSS_help(sizeof(struct ip6_hdr)); } -static const struct option TCPMSS_opts[] = { - {.name = "set-mss", .has_arg = true, .val = '1'}, - {.name = "clamp-mss-to-pmtu", .has_arg = false, .val = '2'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry TCPMSS4_opts[] = { + {.name = "set-mss", .id = O_SET_MSS, .type = XTTYPE_UINT16, + .min = 0, .max = UINT16_MAX - sizeof(struct iphdr), + .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_tcpmss_info, mss)}, + {.name = "clamp-mss-to-pmtu", .id = O_CLAMP_MSS, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; -static int __TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target, - int hdrsize) -{ - struct xt_tcpmss_info *mssinfo - = (struct xt_tcpmss_info *)(*target)->data; - - switch (c) { - unsigned int mssval; - - case '1': - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "TCPMSS target: Only one option may be specified"); - if (!xtables_strtoui(optarg, NULL, &mssval, - 0, UINT16_MAX - hdrsize)) - xtables_error(PARAMETER_PROBLEM, "Bad TCPMSS value \"%s\"", optarg); - - mssinfo->mss = mssval; - *flags = 1; - break; - - case '2': - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "TCPMSS target: Only one option may be specified"); - mssinfo->mss = XT_TCPMSS_CLAMP_PMTU; - *flags = 1; - break; - } - - return 1; -} +static const struct xt_option_entry TCPMSS6_opts[] = { + {.name = "set-mss", .id = O_SET_MSS, .type = XTTYPE_UINT16, + .min = 0, .max = UINT16_MAX - sizeof(struct ip6_hdr), + .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_tcpmss_info, mss)}, + {.name = "clamp-mss-to-pmtu", .id = O_CLAMP_MSS, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, +}; -static int TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void TCPMSS_parse(struct xt_option_call *cb) { - return __TCPMSS_parse(c, argv, invert, flags, entry, target, 40); -} + struct xt_tcpmss_info *mssinfo = cb->data; -static int TCPMSS_parse6(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - return __TCPMSS_parse(c, argv, invert, flags, entry, target, 60); + xtables_option_parse(cb); + if (cb->entry->id == O_CLAMP_MSS) + mssinfo->mss = XT_TCPMSS_CLAMP_PMTU; } -static void TCPMSS_check(unsigned int flags) +static void TCPMSS_check(struct xt_fcheck_call *cb) { - if (!flags) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "TCPMSS target: At least one parameter is required"); } @@ -124,11 +98,11 @@ static struct xtables_target tcpmss_target = { .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), .help = TCPMSS_help, - .parse = TCPMSS_parse, - .final_check = TCPMSS_check, .print = TCPMSS_print, .save = TCPMSS_save, - .extra_opts = TCPMSS_opts, + .x6_parse = TCPMSS_parse, + .x6_fcheck = TCPMSS_check, + .x6_options = TCPMSS4_opts, }; static struct xtables_target tcpmss_target6 = { @@ -138,11 +112,11 @@ static struct xtables_target tcpmss_target6 = { .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)), .help = TCPMSS_help6, - .parse = TCPMSS_parse6, - .final_check = TCPMSS_check, .print = TCPMSS_print, .save = TCPMSS_save, - .extra_opts = TCPMSS_opts, + .x6_parse = TCPMSS_parse, + .x6_fcheck = TCPMSS_check, + .x6_options = TCPMSS6_opts, }; void _init(void) -- cgit v1.2.3 From 33d180871bea281a448efd0c1a49517318162382 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 18:11:58 +0100 Subject: libxtables: pass struct xt_entry_{match,target} to x6 parser Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 4 ++++ xtoptions.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/include/xtables.h.in b/include/xtables.h.in index 6167f4da..afade14b 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -126,6 +126,10 @@ struct xt_option_call { uint32_t mark, mask; }; } val; + union { + struct xt_entry_match **match; + struct xt_entry_target **target; + }; }; /** diff --git a/xtoptions.c b/xtoptions.c index 939e6860..b3acff9e 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -384,6 +384,7 @@ void xtables_option_tpcall(unsigned int c, char **argv, bool invert, cb.ext_name = t->name; cb.data = t->t->data; cb.xflags = t->tflags; + cb.target = &t->t; t->x6_parse(&cb); t->tflags = cb.xflags; } @@ -417,6 +418,7 @@ void xtables_option_mpcall(unsigned int c, char **argv, bool invert, cb.ext_name = m->name; cb.data = m->m->data; cb.xflags = m->mflags; + cb.match = &m->m; m->x6_parse(&cb); m->mflags = cb.xflags; } -- cgit v1.2.3 From c618a0b1d3696c30f7791a427da9ba60186dfe05 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 6 Mar 2011 18:12:04 +0100 Subject: libxt_string: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_string.c | 138 ++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 91 deletions(-) diff --git a/extensions/libxt_string.c b/extensions/libxt_string.c index 1030d2e3..eef0b081 100644 --- a/extensions/libxt_string.c +++ b/extensions/libxt_string.c @@ -20,18 +20,25 @@ * updated to work with slightly modified * ipt_string_info. */ -#define _GNU_SOURCE 1 -#include #include -#include #include #include -#include #include #include -#include #include +enum { + O_FROM = 0, + O_TO, + O_ALGO, + O_ICASE, + O_STRING, + O_HEX_STRING, + F_STRING = 1 << O_STRING, + F_HEX_STRING = 1 << O_HEX_STRING, + F_OP_ANY = F_STRING | F_HEX_STRING, +}; + static void string_help(void) { printf( @@ -44,15 +51,22 @@ static void string_help(void) "[!] --hex-string string Match a hex string in a packet\n"); } -static const struct option string_opts[] = { - {.name = "from", .has_arg = true, .val = '1'}, - {.name = "to", .has_arg = true, .val = '2'}, - {.name = "algo", .has_arg = true, .val = '3'}, - {.name = "string", .has_arg = true, .val = '4'}, - {.name = "hex-string", .has_arg = true, .val = '5'}, - {.name = "icase", .has_arg = false, .val = '6'}, - XT_GETOPT_TABLEEND, +#define s struct xt_string_info +static const struct xt_option_entry string_opts[] = { + {.name = "from", .id = O_FROM, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, from_offset)}, + {.name = "to", .id = O_TO, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, to_offset)}, + {.name = "algo", .id = O_ALGO, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, algo)}, + {.name = "string", .id = O_STRING, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT, .excl = F_HEX_STRING}, + {.name = "hex-string", .id = O_HEX_STRING, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT, .excl = F_STRING}, + {.name = "icase", .id = O_ICASE, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; +#undef s static void string_init(struct xt_entry_match *m) { @@ -73,17 +87,6 @@ parse_string(const char *s, struct xt_string_info *info) xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s); } -static void -parse_algo(const char *s, struct xt_string_info *info) -{ - /* xt_string needs \0 for algo name */ - if (strlen(s) < XT_STRING_MAX_ALGO_NAME_SIZE) { - strncpy(info->algo, s, XT_STRING_MAX_ALGO_NAME_SIZE); - return; - } - xtables_error(PARAMETER_PROBLEM, "ALGO too long \"%s\"", s); -} - static void parse_hex_string(const char *s, struct xt_string_info *info) { @@ -162,94 +165,47 @@ parse_hex_string(const char *s, struct xt_string_info *info) info->patlen = sindex; } -#define STRING 0x1 -#define ALGO 0x2 -#define FROM 0x4 -#define TO 0x8 -#define ICASE 0x10 - -static int -string_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void string_parse(struct xt_option_call *cb) { - struct xt_string_info *stringinfo = - (struct xt_string_info *)(*match)->data; - const int revision = (*match)->u.user.revision; + struct xt_string_info *stringinfo = cb->data; + const unsigned int revision = (*cb->match)->u.user.revision; - switch (c) { - case '1': - if (*flags & FROM) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple --from"); - stringinfo->from_offset = atoi(optarg); - *flags |= FROM; - break; - case '2': - if (*flags & TO) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple --to"); - stringinfo->to_offset = atoi(optarg); - *flags |= TO; - break; - case '3': - if (*flags & ALGO) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple --algo"); - parse_algo(optarg, stringinfo); - *flags |= ALGO; - break; - case '4': - if (*flags & STRING) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple --string"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - parse_string(optarg, stringinfo); - if (invert) { + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_STRING: + parse_string(cb->arg, stringinfo); + if (cb->invert) { if (revision == 0) stringinfo->u.v0.invert = 1; else stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; } - *flags |= STRING; break; - - case '5': - if (*flags & STRING) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple --hex-string"); - - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - parse_hex_string(optarg, stringinfo); /* sets length */ - if (invert) { + case O_HEX_STRING: + parse_hex_string(cb->arg, stringinfo); /* sets length */ + if (cb->invert) { if (revision == 0) stringinfo->u.v0.invert = 1; else stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; } - *flags |= STRING; break; - - case '6': + case O_ICASE: if (revision == 0) xtables_error(VERSION_PROBLEM, "Kernel doesn't support --icase"); stringinfo->u.v1.flags |= XT_STRING_FLAG_IGNORECASE; - *flags |= ICASE; break; } - return 1; } -static void string_check(unsigned int flags) +static void string_check(struct xt_fcheck_call *cb) { - if (!(flags & STRING)) + if (!(cb->xflags & F_OP_ANY)) xtables_error(PARAMETER_PROBLEM, "STRING match: You must specify `--string' or " "`--hex-string'"); - if (!(flags & ALGO)) - xtables_error(PARAMETER_PROBLEM, - "STRING match: You must specify `--algo'"); } /* Test to see if the string contains non-printable chars or quotes */ @@ -357,11 +313,11 @@ static struct xtables_match string_mt_reg[] = { .userspacesize = offsetof(struct xt_string_info, config), .help = string_help, .init = string_init, - .parse = string_parse, - .final_check = string_check, .print = string_print, .save = string_save, - .extra_opts = string_opts, + .x6_parse = string_parse, + .x6_fcheck = string_check, + .x6_options = string_opts, }, { .name = "string", @@ -372,11 +328,11 @@ static struct xtables_match string_mt_reg[] = { .userspacesize = offsetof(struct xt_string_info, config), .help = string_help, .init = string_init, - .parse = string_parse, - .final_check = string_check, .print = string_print, .save = string_save, - .extra_opts = string_opts, + .x6_parse = string_parse, + .x6_fcheck = string_check, + .x6_options = string_opts, }, }; -- cgit v1.2.3 From 41a4cea0f4109fb76762dca073c3c1217658ee06 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 15 Feb 2011 22:10:48 +0100 Subject: libxtables: XTTYPE_SYSLOGLEVEL support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 4 +++- xtoptions.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index afade14b..afdac36a 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -51,6 +51,7 @@ struct in_addr; * %XTTYPE_UINT*RC: colon-separated range of standard integers * %XTTYPE_STRING: arbitrary string * %XTTYPE_MARKMASK32: 32-bit mark with optional mask + * %XTTYPE_SYSLOGLEVEL: syslog level by name or number */ enum xt_option_type { XTTYPE_NONE, @@ -64,6 +65,7 @@ enum xt_option_type { XTTYPE_UINT64RC, XTTYPE_STRING, XTTYPE_MARKMASK32, + XTTYPE_SYSLOGLEVEL, }; /** @@ -118,7 +120,7 @@ struct xt_option_call { bool invert; uint8_t nvals; union { - uint8_t u8, u8_range[2]; + uint8_t u8, u8_range[2], syslog_level; uint16_t u16, u16_range[2]; uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; diff --git a/xtoptions.c b/xtoptions.c index b3acff9e..a6738c11 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "xtables.h" #include "xshared.h" @@ -24,6 +25,14 @@ #define XTOPT_MKPTR(cb) \ ((void *)((char *)(cb)->data + (cb)->entry->ptroff)) +/** + * Simple key-value pairs for syslog levels + */ +struct syslog_level { + char name[8]; + uint8_t level; +}; + /** * Creates getopt options from the x6-style option map, and assigns each a * getopt id. @@ -251,6 +260,43 @@ static void xtopt_parse_markmask(struct xt_option_call *cb) cb->val.mask = mask; } +static int xtopt_sysloglvl_compare(const void *a, const void *b) +{ + const char *name = a; + const struct syslog_level *entry = b; + + return strcmp(name, entry->name); +} + +static void xtopt_parse_sysloglevel(struct xt_option_call *cb) +{ + static const struct syslog_level log_names[] = { /* must be sorted */ + {"alert", LOG_ALERT}, + {"crit", LOG_CRIT}, + {"debug", LOG_DEBUG}, + {"emerg", LOG_EMERG}, + {"error", LOG_ERR}, /* deprecated */ + {"info", LOG_INFO}, + {"notice", LOG_NOTICE}, + {"panic", LOG_EMERG}, /* deprecated */ + {"warning", LOG_WARNING}, + }; + const struct syslog_level *e; + unsigned int num = 0; + + if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) { + e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names), + sizeof(*log_names), xtopt_sysloglvl_compare); + if (e == NULL) + xt_params->exit_err(PARAMETER_PROBLEM, + "log level \"%s\" unknown\n", cb->arg); + num = e->level; + } + cb->val.syslog_level = num; + if (cb->entry->flags & XTOPT_PUT) + *(uint8_t *)XTOPT_MKPTR(cb) = num; +} + static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT16] = xtopt_parse_int, @@ -262,6 +308,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT64RC] = xtopt_parse_mint, [XTTYPE_STRING] = xtopt_parse_string, [XTTYPE_MARKMASK32] = xtopt_parse_markmask, + [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, }; static const size_t xtopt_psize[] = { @@ -274,6 +321,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_UINT32RC] = sizeof(uint32_t[2]), [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), [XTTYPE_STRING] = -1, + [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), }; /** -- cgit v1.2.3 From 0dd344a9bedc24feb6ad99d4620bdc7da171c72d Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 15 Feb 2011 12:05:12 +0100 Subject: libip[6]t_LOG: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libip6t_LOG.c | 174 +++++++++++------------------------------------ extensions/libipt_LOG.c | 174 +++++++++++------------------------------------ 2 files changed, 82 insertions(+), 266 deletions(-) diff --git a/extensions/libip6t_LOG.c b/extensions/libip6t_LOG.c index e9c738f1..a419ec91 100644 --- a/extensions/libip6t_LOG.c +++ b/extensions/libip6t_LOG.c @@ -1,11 +1,6 @@ -/* Shared library add-on to ip6tables to add LOG support. */ -#include #include -#include #include -#include #include -#include #include #include @@ -17,6 +12,16 @@ #define LOG_DEFAULT_LEVEL LOG_WARNING +enum { + O_LOG_LEVEL = 0, + O_LOG_PREFIX, + O_LOG_TCPSEQ, + O_LOG_TCPOPTS, + O_LOG_IPOPTS, + O_LOG_UID, + O_LOG_MAC, +}; + static void LOG_help(void) { printf( @@ -30,16 +35,20 @@ static void LOG_help(void) " --log-macdecode Decode MAC addresses and protocol.\n"); } -static const struct option LOG_opts[] = { - {.name = "log-level", .has_arg = true, .val = '!'}, - {.name = "log-prefix", .has_arg = true, .val = '#'}, - {.name = "log-tcp-sequence", .has_arg = false, .val = '1'}, - {.name = "log-tcp-options", .has_arg = false, .val = '2'}, - {.name = "log-ip-options", .has_arg = false, .val = '3'}, - {.name = "log-uid", .has_arg = false, .val = '4'}, - {.name = "log-macdecode", .has_arg = false, .val = '5'}, - XT_GETOPT_TABLEEND, +#define s struct ip6t_log_info +static const struct xt_option_entry LOG_opts[] = { + {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL, + .flags = XTOPT_PUT, XTOPT_POINTER(s, level)}, + {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1}, + {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE}, + {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE}, + {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE}, + {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE}, + {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; +#undef s static void LOG_init(struct xt_entry_target *t) { @@ -66,134 +75,33 @@ static const struct ip6t_log_names ip6t_log_names[] { .name = "warning", .level = LOG_WARNING } }; -static uint8_t -parse_level(const char *level) +static void LOG_parse(struct xt_option_call *cb) { - unsigned int lev = -1; - unsigned int set = 0; - - if (!xtables_strtoui(level, NULL, &lev, 0, 7)) { - unsigned int i = 0; - - for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i) - if (strncasecmp(level, ip6t_log_names[i].name, - strlen(level)) == 0) { - if (set++) - xtables_error(PARAMETER_PROBLEM, - "log-level `%s' ambiguous", - level); - lev = ip6t_log_names[i].level; - } + struct ip6t_log_info *info = cb->data; - if (!set) - xtables_error(PARAMETER_PROBLEM, - "log-level `%s' unknown", level); - } - - return lev; -} - -#define IP6T_LOG_OPT_LEVEL 0x01 -#define IP6T_LOG_OPT_PREFIX 0x02 -#define IP6T_LOG_OPT_TCPSEQ 0x04 -#define IP6T_LOG_OPT_TCPOPT 0x08 -#define IP6T_LOG_OPT_IPOPT 0x10 -#define IP6T_LOG_OPT_UID 0x20 -#define IP6T_LOG_OPT_MACDECODE 0x40 - -static int LOG_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data; - - switch (c) { - case '!': - if (*flags & IP6T_LOG_OPT_LEVEL) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-level twice"); - - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --log-level"); - - loginfo->level = parse_level(optarg); - *flags |= IP6T_LOG_OPT_LEVEL; - break; - - case '#': - if (*flags & IP6T_LOG_OPT_PREFIX) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-prefix twice"); - - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --log-prefix"); - - if (strlen(optarg) > sizeof(loginfo->prefix) - 1) - xtables_error(PARAMETER_PROBLEM, - "Maximum prefix length %u for --log-prefix", - (unsigned int)sizeof(loginfo->prefix) - 1); - - if (strlen(optarg) == 0) - xtables_error(PARAMETER_PROBLEM, - "No prefix specified for --log-prefix"); - - if (strlen(optarg) != strlen(strtok(optarg, "\n"))) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_LOG_PREFIX: + if (strchr(cb->arg, '\n') != NULL) xtables_error(PARAMETER_PROBLEM, "Newlines not allowed in --log-prefix"); - - strcpy(loginfo->prefix, optarg); - *flags |= IP6T_LOG_OPT_PREFIX; break; - - case '1': - if (*flags & IP6T_LOG_OPT_TCPSEQ) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-tcp-sequence " - "twice"); - - loginfo->logflags |= IP6T_LOG_TCPSEQ; - *flags |= IP6T_LOG_OPT_TCPSEQ; + case O_LOG_TCPSEQ: + info->logflags = IP6T_LOG_TCPSEQ; break; - - case '2': - if (*flags & IP6T_LOG_OPT_TCPOPT) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-tcp-options twice"); - - loginfo->logflags |= IP6T_LOG_TCPOPT; - *flags |= IP6T_LOG_OPT_TCPOPT; + case O_LOG_TCPOPTS: + info->logflags = IP6T_LOG_TCPOPT; break; - - case '3': - if (*flags & IP6T_LOG_OPT_IPOPT) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-ip-options twice"); - - loginfo->logflags |= IP6T_LOG_IPOPT; - *flags |= IP6T_LOG_OPT_IPOPT; + case O_LOG_IPOPTS: + info->logflags = IP6T_LOG_IPOPT; break; - - case '4': - if (*flags & IP6T_LOG_OPT_UID) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-uid twice"); - - loginfo->logflags |= IP6T_LOG_UID; - *flags |= IP6T_LOG_OPT_UID; + case O_LOG_UID: + info->logflags = IP6T_LOG_UID; break; - - case '5': - if (*flags & IP6T_LOG_OPT_MACDECODE) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-macdecode twice"); - - loginfo->logflags |= IP6T_LOG_MACDECODE; - *flags |= IP6T_LOG_OPT_MACDECODE; + case O_LOG_MAC: + info->logflags = IP6T_LOG_MACDECODE; break; } - - return 1; } static void LOG_print(const void *ip, const struct xt_entry_target *target, @@ -264,10 +172,10 @@ static struct xtables_target log_tg6_reg = { .userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)), .help = LOG_help, .init = LOG_init, - .parse = LOG_parse, .print = LOG_print, .save = LOG_save, - .extra_opts = LOG_opts, + .x6_parse = LOG_parse, + .x6_options = LOG_opts, }; void _init(void) diff --git a/extensions/libipt_LOG.c b/extensions/libipt_LOG.c index ba6af044..b270bcf6 100644 --- a/extensions/libipt_LOG.c +++ b/extensions/libipt_LOG.c @@ -1,11 +1,6 @@ -/* Shared library add-on to iptables to add LOG support. */ -#include #include -#include #include -#include #include -#include #include #include @@ -17,6 +12,16 @@ #define IPT_LOG_MASK 0x0f #endif +enum { + O_LOG_LEVEL = 0, + O_LOG_PREFIX, + O_LOG_TCPSEQ, + O_LOG_TCPOPTS, + O_LOG_IPOPTS, + O_LOG_UID, + O_LOG_MAC, +}; + static void LOG_help(void) { printf( @@ -30,16 +35,20 @@ static void LOG_help(void) " --log-macdecode Decode MAC addresses and protocol.\n\n"); } -static const struct option LOG_opts[] = { - {.name = "log-level", .has_arg = true, .val = '!'}, - {.name = "log-prefix", .has_arg = true, .val = '#'}, - {.name = "log-tcp-sequence", .has_arg = false, .val = '1'}, - {.name = "log-tcp-options", .has_arg = false, .val = '2'}, - {.name = "log-ip-options", .has_arg = false, .val = '3'}, - {.name = "log-uid", .has_arg = false, .val = '4'}, - {.name = "log-macdecode", .has_arg = false, .val = '5'}, - XT_GETOPT_TABLEEND, +#define s struct ipt_log_info +static const struct xt_option_entry LOG_opts[] = { + {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL, + .flags = XTOPT_PUT, XTOPT_POINTER(s, level)}, + {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1}, + {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE}, + {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE}, + {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE}, + {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE}, + {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; +#undef s static void LOG_init(struct xt_entry_target *t) { @@ -66,134 +75,33 @@ static const struct ipt_log_names ipt_log_names[] { .name = "warning", .level = LOG_WARNING } }; -static uint8_t -parse_level(const char *level) +static void LOG_parse(struct xt_option_call *cb) { - unsigned int lev = -1; - unsigned int set = 0; - - if (!xtables_strtoui(level, NULL, &lev, 0, 7)) { - unsigned int i = 0; - - for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i) - if (strncasecmp(level, ipt_log_names[i].name, - strlen(level)) == 0) { - if (set++) - xtables_error(PARAMETER_PROBLEM, - "log-level `%s' ambiguous", - level); - lev = ipt_log_names[i].level; - } + struct ipt_log_info *info = cb->data; - if (!set) - xtables_error(PARAMETER_PROBLEM, - "log-level `%s' unknown", level); - } - - return lev; -} - -#define IPT_LOG_OPT_LEVEL 0x01 -#define IPT_LOG_OPT_PREFIX 0x02 -#define IPT_LOG_OPT_TCPSEQ 0x04 -#define IPT_LOG_OPT_TCPOPT 0x08 -#define IPT_LOG_OPT_IPOPT 0x10 -#define IPT_LOG_OPT_UID 0x20 -#define IPT_LOG_OPT_MACDECODE 0x40 - -static int LOG_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - struct ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data; - - switch (c) { - case '!': - if (*flags & IPT_LOG_OPT_LEVEL) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-level twice"); - - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --log-level"); - - loginfo->level = parse_level(optarg); - *flags |= IPT_LOG_OPT_LEVEL; - break; - - case '#': - if (*flags & IPT_LOG_OPT_PREFIX) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-prefix twice"); - - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --log-prefix"); - - if (strlen(optarg) > sizeof(loginfo->prefix) - 1) - xtables_error(PARAMETER_PROBLEM, - "Maximum prefix length %u for --log-prefix", - (unsigned int)sizeof(loginfo->prefix) - 1); - - if (strlen(optarg) == 0) - xtables_error(PARAMETER_PROBLEM, - "No prefix specified for --log-prefix"); - - if (strlen(optarg) != strlen(strtok(optarg, "\n"))) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_LOG_PREFIX: + if (strchr(cb->arg, '\n') != NULL) xtables_error(PARAMETER_PROBLEM, "Newlines not allowed in --log-prefix"); - - strcpy(loginfo->prefix, optarg); - *flags |= IPT_LOG_OPT_PREFIX; break; - - case '1': - if (*flags & IPT_LOG_OPT_TCPSEQ) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-tcp-sequence " - "twice"); - - loginfo->logflags |= IPT_LOG_TCPSEQ; - *flags |= IPT_LOG_OPT_TCPSEQ; + case O_LOG_TCPSEQ: + info->logflags = IPT_LOG_TCPSEQ; break; - - case '2': - if (*flags & IPT_LOG_OPT_TCPOPT) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-tcp-options twice"); - - loginfo->logflags |= IPT_LOG_TCPOPT; - *flags |= IPT_LOG_OPT_TCPOPT; + case O_LOG_TCPOPTS: + info->logflags = IPT_LOG_TCPOPT; break; - - case '3': - if (*flags & IPT_LOG_OPT_IPOPT) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-ip-options twice"); - - loginfo->logflags |= IPT_LOG_IPOPT; - *flags |= IPT_LOG_OPT_IPOPT; + case O_LOG_IPOPTS: + info->logflags = IPT_LOG_IPOPT; break; - - case '4': - if (*flags & IPT_LOG_OPT_UID) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --log-uid twice"); - - loginfo->logflags |= IPT_LOG_UID; - *flags |= IPT_LOG_OPT_UID; + case O_LOG_UID: + info->logflags = IPT_LOG_UID; break; - - case '5': - if (*flags & IPT_LOG_OPT_MACDECODE) - xtables_error(PARAMETER_PROBLEM, - "Can't specifiy --log-macdecode twice"); - - loginfo->logflags |= IPT_LOG_MACDECODE; - *flags |= IPT_LOG_OPT_MACDECODE; + case O_LOG_MAC: + info->logflags = IPT_LOG_MACDECODE; break; } - - return 1; } static void LOG_print(const void *ip, const struct xt_entry_target *target, @@ -266,10 +174,10 @@ static struct xtables_target log_tg_reg = { .userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)), .help = LOG_help, .init = LOG_init, - .parse = LOG_parse, .print = LOG_print, .save = LOG_save, - .extra_opts = LOG_opts, + .x6_parse = LOG_parse, + .x6_options = LOG_opts, }; void _init(void) -- cgit v1.2.3 From 2b01f706e7ba48d72e57f8e47457a86d9ed44992 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 14 Feb 2011 15:10:15 +0100 Subject: libxtables: XTTYPE_ONEHOST support The bonus of the POSIX socket API is that it is almost protocol-agnostic and that there are ready-made functions to take over the gist of address parsing and packing. Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 3 +++ xtoptions.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/include/xtables.h.in b/include/xtables.h.in index afdac36a..d8a31245 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -52,6 +52,7 @@ struct in_addr; * %XTTYPE_STRING: arbitrary string * %XTTYPE_MARKMASK32: 32-bit mark with optional mask * %XTTYPE_SYSLOGLEVEL: syslog level by name or number + * %XTTYPE_ONEHOST: one host or address (union nf_inet_addr) */ enum xt_option_type { XTTYPE_NONE, @@ -66,6 +67,7 @@ enum xt_option_type { XTTYPE_STRING, XTTYPE_MARKMASK32, XTTYPE_SYSLOGLEVEL, + XTTYPE_ONEHOST, }; /** @@ -124,6 +126,7 @@ struct xt_option_call { uint16_t u16, u16_range[2]; uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; + union nf_inet_addr inetaddr; struct { uint32_t mark, mask; }; diff --git a/xtoptions.c b/xtoptions.c index a6738c11..e0c3213f 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -297,6 +297,63 @@ static void xtopt_parse_sysloglevel(struct xt_option_call *cb) *(uint8_t *)XTOPT_MKPTR(cb) = num; } +static void *xtables_sa_host(const void *sa, unsigned int afproto) +{ + if (afproto == AF_INET6) + return &((struct sockaddr_in6 *)sa)->sin6_addr; + else if (afproto == AF_INET) + return &((struct sockaddr_in *)sa)->sin_addr; + return (void *)sa; +} + +static socklen_t xtables_sa_hostlen(unsigned int afproto) +{ + if (afproto == AF_INET6) + return sizeof(struct in6_addr); + else if (afproto == AF_INET) + return sizeof(struct in_addr); + return 0; +} + +/** + * Accepts: a hostname (DNS), or a single inetaddr. + */ +static void xtopt_parse_onehost(struct xt_option_call *cb) +{ + struct addrinfo hints = {.ai_family = afinfo->family}; + unsigned int adcount = 0; + struct addrinfo *res, *p; + int ret; + + ret = getaddrinfo(cb->arg, NULL, &hints, &res); + if (ret < 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "getaddrinfo: %s\n", gai_strerror(ret)); + + for (p = res; p != NULL; p = p->ai_next) { + if (adcount == 0) { + memset(&cb->val.inetaddr, 0, sizeof(cb->val.inetaddr)); + memcpy(&cb->val.inetaddr, + xtables_sa_host(p->ai_addr, p->ai_family), + xtables_sa_hostlen(p->ai_family)); + ++adcount; + continue; + } + if (memcmp(&cb->val.inetaddr, + xtables_sa_host(p->ai_addr, p->ai_family), + xtables_sa_hostlen(p->ai_family)) != 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s resolves to more than one address\n", + cb->arg); + } + + freeaddrinfo(res); + if (cb->entry->flags & XTOPT_PUT) + /* Validation in xtables_option_metavalidate */ + memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr, + sizeof(cb->val.inetaddr)); +} + static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT16] = xtopt_parse_int, @@ -309,6 +366,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_STRING] = xtopt_parse_string, [XTTYPE_MARKMASK32] = xtopt_parse_markmask, [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, + [XTTYPE_ONEHOST] = xtopt_parse_onehost, }; static const size_t xtopt_psize[] = { @@ -322,6 +380,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_UINT64RC] = sizeof(uint64_t[2]), [XTTYPE_STRING] = -1, [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), + [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr), }; /** -- cgit v1.2.3 From b8592fa3352018646b0befaa48f930f75c5b7d92 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 14 Feb 2011 15:12:50 +0100 Subject: libxtables: XTTYPE_PORT support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 6 +++++- xtoptions.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index d8a31245..a9a9ffad 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -53,6 +53,8 @@ struct in_addr; * %XTTYPE_MARKMASK32: 32-bit mark with optional mask * %XTTYPE_SYSLOGLEVEL: syslog level by name or number * %XTTYPE_ONEHOST: one host or address (union nf_inet_addr) + * %XTTYPE_PORT: 16-bit port name or number + * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian */ enum xt_option_type { XTTYPE_NONE, @@ -68,6 +70,8 @@ enum xt_option_type { XTTYPE_MARKMASK32, XTTYPE_SYSLOGLEVEL, XTTYPE_ONEHOST, + XTTYPE_PORT, + XTTYPE_PORT_NE, }; /** @@ -123,7 +127,7 @@ struct xt_option_call { uint8_t nvals; union { uint8_t u8, u8_range[2], syslog_level; - uint16_t u16, u16_range[2]; + uint16_t u16, u16_range[2], port; uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; union nf_inet_addr inetaddr; diff --git a/xtoptions.c b/xtoptions.c index e0c3213f..c3cc40e6 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -354,6 +354,53 @@ static void xtopt_parse_onehost(struct xt_option_call *cb) sizeof(cb->val.inetaddr)); } +/** + * @name: port name, or number as a string (e.g. "http" or "80") + * + * Resolve a port name to a number. Returns the port number in integral + * form on success, or <0 on error. (errno will not be set.) + */ +static int xtables_getportbyname(const char *name) +{ + struct addrinfo *res = NULL, *p; + int ret; + + ret = getaddrinfo(NULL, name, NULL, &res); + if (ret < 0) + return -1; + ret = -1; + for (p = res; p != NULL; p = p->ai_next) { + if (p->ai_family == AF_INET6) { + ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port; + break; + } else if (p->ai_family == AF_INET) { + ret = ((struct sockaddr_in *)p->ai_addr)->sin_port; + break; + } + } + freeaddrinfo(res); + return ntohs(ret); +} + +/** + * Validate and parse a port specification and put the result into @cb. + */ +static void xtopt_parse_port(struct xt_option_call *cb) +{ + int ret; + + ret = xtables_getportbyname(cb->arg); + if (ret < 0) + xt_params->exit_err(PARAMETER_PROBLEM, + "Port \"%s\" does not resolve to anything.\n", + cb->arg); + cb->val.port = ret; + if (cb->entry->type == XTTYPE_PORT_NE) + cb->val.port = htons(cb->val.port); + if (cb->entry->flags & XTOPT_PUT) + *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port; +} + static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT16] = xtopt_parse_int, @@ -367,6 +414,8 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_MARKMASK32] = xtopt_parse_markmask, [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, [XTTYPE_ONEHOST] = xtopt_parse_onehost, + [XTTYPE_PORT] = xtopt_parse_port, + [XTTYPE_PORT_NE] = xtopt_parse_port, }; static const size_t xtopt_psize[] = { @@ -381,6 +430,8 @@ static const size_t xtopt_psize[] = { [XTTYPE_STRING] = -1, [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr), + [XTTYPE_PORT] = sizeof(uint16_t), + [XTTYPE_PORT_NE] = sizeof(uint16_t), }; /** -- cgit v1.2.3 From 64cb56e3e894f6b8b523ecb45f91abe43b07cf0c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 9 Feb 2011 02:15:22 +0100 Subject: libxt_TPROXY: use guided option parser I am starting with a simple module here that does not require a final_check function. Signed-off-by: Jan Engelhardt --- extensions/libxt_TPROXY.c | 216 +++++++++++++--------------------------------- 1 file changed, 62 insertions(+), 154 deletions(-) diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c index 890dd866..5264ea7d 100644 --- a/extensions/libxt_TPROXY.c +++ b/extensions/libxt_TPROXY.c @@ -1,32 +1,42 @@ /* - * Shared library add-on to iptables to add TPROXY target support. + * shared library add-on to iptables to add TPROXY target support. * * Copyright (C) 2002-2008 BalaBit IT Ltd. */ -#include -#include -#include #include -#include -#include #include - #include -#include #include +#include -static const struct option tproxy_tg_opts[] = { - {.name = "on-port", .has_arg = true, .val = '1'}, - {.name = "on-ip", .has_arg = true, .val = '2'}, - {.name = "tproxy-mark", .has_arg = true, .val = '3'}, - XT_GETOPT_TABLEEND, +enum { + P_PORT = 0, + P_ADDR, + P_MARK, + F_PORT = 1 << P_PORT, + F_ADDR = 1 << P_ADDR, + F_MARK = 1 << P_MARK, }; -enum { - PARAM_ONPORT = 1 << 0, - PARAM_ONIP = 1 << 1, - PARAM_MARK = 1 << 2, +#define s struct xt_tproxy_target_info +static const struct xt_option_entry tproxy_tg0_opts[] = { + {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)}, + {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_ONEHOST}, + {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32}, + XTOPT_TABLEEND, }; +#undef s +#define s struct xt_tproxy_target_info_v1 +static const struct xt_option_entry tproxy_tg1_opts[] = { + {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)}, + {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_ONEHOST, + .flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)}, + {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32}, + XTOPT_TABLEEND, +}; +#undef s static void tproxy_tg_help(void) { @@ -37,134 +47,6 @@ static void tproxy_tg_help(void) " --tproxy-mark value[/mask] Mark packets with the given value/mask\n\n"); } -static void parse_tproxy_lport(const char *s, uint16_t *portp) -{ - unsigned int lport; - - if (xtables_strtoui(s, NULL, &lport, 0, UINT16_MAX)) - *portp = htons(lport); - else - xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-port", s); -} - -static void parse_tproxy_laddr(const char *s, union nf_inet_addr *addrp, - unsigned int nfproto) -{ - struct in6_addr *laddr6 = NULL; - struct in_addr *laddr4 = NULL; - - if (nfproto == NFPROTO_IPV6) { - laddr6 = xtables_numeric_to_ip6addr(s); - if (laddr6 == NULL) - goto out; - addrp->in6 = *laddr6; - } else if (nfproto == NFPROTO_IPV4) { - laddr4 = xtables_numeric_to_ipaddr(s); - if (laddr4 == NULL) - goto out; - addrp->in = *laddr4; - } - return; - out: - xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-ip", s); -} - -static void parse_tproxy_mark(char *s, uint32_t *markp, uint32_t *maskp) -{ - unsigned int value, mask = UINT32_MAX; - char *end; - - if (!xtables_strtoui(s, &end, &value, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); - if (*end == '/') - if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); - if (*end != '\0') - xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); - - *markp = value; - *maskp = mask; -} - -static int tproxy_tg_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - struct xt_tproxy_target_info *info = (void *)(*target)->data; - - switch (c) { - case '1': - xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT); - xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert); - parse_tproxy_lport(optarg, &info->lport); - *flags |= PARAM_ONPORT; - return 1; - case '2': - xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP); - xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert); - parse_tproxy_laddr(optarg, (void *)&info->laddr, NFPROTO_IPV4); - *flags |= PARAM_ONIP; - return 1; - case '3': - xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK); - xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert); - parse_tproxy_mark(optarg, &info->mark_value, &info->mark_mask); - *flags |= PARAM_MARK; - return 1; - } - - return 0; -} - -static int -tproxy_tg_parse1(int c, char **argv, int invert, unsigned int *flags, - struct xt_tproxy_target_info_v1 *info, unsigned int nfproto) -{ - switch (c) { - case '1': - xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT); - xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert); - parse_tproxy_lport(optarg, &info->lport); - *flags |= PARAM_ONPORT; - return true; - case '2': - xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP); - xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert); - parse_tproxy_laddr(optarg, (void *)&info->laddr, nfproto); - *flags |= PARAM_ONIP; - return true; - case '3': - xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK); - xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert); - parse_tproxy_mark(optarg, &info->mark_value, &info->mark_mask); - *flags |= PARAM_MARK; - return true; - } - return false; -} - -static int -tproxy_tg_parse4(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - struct xt_tproxy_target_info_v1 *info = (void *)(*target)->data; - return tproxy_tg_parse1(c, argv, invert, flags, info, NFPROTO_IPV4); -} - -static int -tproxy_tg_parse6(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - struct xt_tproxy_target_info_v1 *info = (void *)(*target)->data; - return tproxy_tg_parse1(c, argv, invert, flags, info, NFPROTO_IPV6); -} - -static void tproxy_tg_check(unsigned int flags) -{ - if (!(flags & PARAM_ONPORT)) - xtables_error(PARAMETER_PROBLEM, - "TPROXY target: Parameter --on-port is required"); -} - static void tproxy_tg_print(const void *ip, const struct xt_entry_target *target, int numeric) { @@ -236,6 +118,35 @@ tproxy_tg_save6(const void *ip, const struct xt_entry_target *target) (unsigned int)info->mark_value, (unsigned int)info->mark_mask); } +static void tproxy_tg0_parse(struct xt_option_call *cb) +{ + struct xt_tproxy_target_info *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case P_MARK: + info->mark_value = cb->val.mark; + info->mark_mask = cb->val.mask; + break; + case P_ADDR: + info->laddr = cb->val.inetaddr.ip; + break; + } +} + +static void tproxy_tg1_parse(struct xt_option_call *cb) +{ + struct xt_tproxy_target_info_v1 *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case P_MARK: + info->mark_value = cb->val.mark; + info->mark_mask = cb->val.mask; + break; + } +} + static struct xtables_target tproxy_tg_reg[] = { { .name = "TPROXY", @@ -245,11 +156,10 @@ static struct xtables_target tproxy_tg_reg[] = { .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info)), .help = tproxy_tg_help, - .parse = tproxy_tg_parse, - .final_check = tproxy_tg_check, .print = tproxy_tg_print, .save = tproxy_tg_save, - .extra_opts = tproxy_tg_opts, + .x6_options = tproxy_tg0_opts, + .x6_parse = tproxy_tg0_parse, }, { .name = "TPROXY", @@ -259,11 +169,10 @@ static struct xtables_target tproxy_tg_reg[] = { .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)), .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)), .help = tproxy_tg_help, - .parse = tproxy_tg_parse4, - .final_check = tproxy_tg_check, .print = tproxy_tg_print4, .save = tproxy_tg_save4, - .extra_opts = tproxy_tg_opts, + .x6_options = tproxy_tg1_opts, + .x6_parse = tproxy_tg1_parse, }, { .name = "TPROXY", @@ -273,11 +182,10 @@ static struct xtables_target tproxy_tg_reg[] = { .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)), .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)), .help = tproxy_tg_help, - .parse = tproxy_tg_parse6, - .final_check = tproxy_tg_check, .print = tproxy_tg_print6, .save = tproxy_tg_save6, - .extra_opts = tproxy_tg_opts, + .x6_options = tproxy_tg1_opts, + .x6_parse = tproxy_tg1_parse, }, }; -- cgit v1.2.3 From 1f2474ae5276e49005c8e234dec091b007e3fce2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 8 Mar 2011 01:24:26 +0100 Subject: libipt_ULOG: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libipt_ULOG.c | 137 ++++++++++++----------------------------------- 1 file changed, 34 insertions(+), 103 deletions(-) diff --git a/extensions/libipt_ULOG.c b/extensions/libipt_ULOG.c index 8eeccf00..e08ae056 100644 --- a/extensions/libipt_ULOG.c +++ b/extensions/libipt_ULOG.c @@ -9,29 +9,18 @@ * * libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp */ -#include #include -#include #include -#include -#include -#include #include /* For 64bit kernel / 32bit userspace */ #include - -static void print_groups(unsigned int gmask) -{ - int b; - unsigned int test; - - for (b = 31; b >= 0; b--) { - test = (1 << b); - if (gmask & test) - printf(" %d", b + 1); - } -} +enum { + O_ULOG_NLGROUP = 0, + O_ULOG_PREFIX, + O_ULOG_CPRANGE, + O_ULOG_QTHR, +}; static void ULOG_help(void) { @@ -42,12 +31,16 @@ static void ULOG_help(void) " --ulog-prefix prefix Prefix log messages with this prefix.\n"); } -static const struct option ULOG_opts[] = { - {.name = "ulog-nlgroup", .has_arg = true, .val = '!'}, - {.name = "ulog-prefix", .has_arg = true, .val = '#'}, - {.name = "ulog-cprange", .has_arg = true, .val = 'A'}, - {.name = "ulog-qthreshold", .has_arg = true, .val = 'B'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry ULOG_opts[] = { + {.name = "ulog-nlgroup", .id = O_ULOG_NLGROUP, .type = XTTYPE_UINT8, + .min = 1, .max = 32}, + {.name = "ulog-prefix", .id = O_ULOG_PREFIX, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(struct ipt_ulog_info, prefix), + .min = 1}, + {.name = "ulog-cprange", .id = O_ULOG_CPRANGE, .type = XTTYPE_UINT64, + .min = 1, .max = ULOG_MAX_QLEN}, + {.name = "ulog-qthreshold", .id = O_ULOG_QTHR, .type = XTTYPE_UINT64}, + XTOPT_TABLEEND, }; static void ULOG_init(struct xt_entry_target *t) @@ -59,87 +52,27 @@ static void ULOG_init(struct xt_entry_target *t) } -#define IPT_LOG_OPT_NLGROUP 0x01 -#define IPT_LOG_OPT_PREFIX 0x02 -#define IPT_LOG_OPT_CPRANGE 0x04 -#define IPT_LOG_OPT_QTHRESHOLD 0x08 - -static int ULOG_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) +static void ULOG_parse(struct xt_option_call *cb) { - struct ipt_ulog_info *loginfo = - (struct ipt_ulog_info *) (*target)->data; - int group_d; + struct ipt_ulog_info *loginfo = cb->data; - switch (c) { - case '!': - if (*flags & IPT_LOG_OPT_NLGROUP) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --ulog-nlgroup twice"); - - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --ulog-nlgroup"); - group_d = atoi(optarg); - if (group_d > 32 || group_d < 1) - xtables_error(PARAMETER_PROBLEM, - "--ulog-nlgroup has to be between 1 and 32"); - - loginfo->nl_group = (1 << (group_d - 1)); - - *flags |= IPT_LOG_OPT_NLGROUP; + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_ULOG_NLGROUP: + loginfo->nl_group = 1 << (cb->val.u8 - 1); break; - - case '#': - if (*flags & IPT_LOG_OPT_PREFIX) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --ulog-prefix twice"); - - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --ulog-prefix"); - - if (strlen(optarg) > sizeof(loginfo->prefix) - 1) - xtables_error(PARAMETER_PROBLEM, - "Maximum prefix length %u for --ulog-prefix", - (unsigned int)sizeof(loginfo->prefix) - 1); - - if (strlen(optarg) == 0) - xtables_error(PARAMETER_PROBLEM, - "No prefix specified for --ulog-prefix"); - - if (strlen(optarg) != strlen(strtok(optarg, "\n"))) + case O_ULOG_PREFIX: + if (strchr(cb->arg, '\n') != NULL) xtables_error(PARAMETER_PROBLEM, "Newlines not allowed in --ulog-prefix"); - - strcpy(loginfo->prefix, optarg); - *flags |= IPT_LOG_OPT_PREFIX; break; - case 'A': - if (*flags & IPT_LOG_OPT_CPRANGE) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --ulog-cprange twice"); - if (atoi(optarg) < 0) - xtables_error(PARAMETER_PROBLEM, - "Negative copy range?"); - loginfo->copy_range = atoi(optarg); - *flags |= IPT_LOG_OPT_CPRANGE; + case O_ULOG_CPRANGE: + loginfo->copy_range = cb->val.u64; break; - case 'B': - if (*flags & IPT_LOG_OPT_QTHRESHOLD) - xtables_error(PARAMETER_PROBLEM, - "Can't specify --ulog-qthreshold twice"); - if (atoi(optarg) < 1) - xtables_error(PARAMETER_PROBLEM, - "Negative or zero queue threshold ?"); - if (atoi(optarg) > ULOG_MAX_QLEN) - xtables_error(PARAMETER_PROBLEM, - "Maximum queue length exceeded"); - loginfo->qthreshold = atoi(optarg); - *flags |= IPT_LOG_OPT_QTHRESHOLD; + case O_ULOG_QTHR: + loginfo->qthreshold = cb->val.u64; break; } - return 1; } static void ULOG_save(const void *ip, const struct xt_entry_target *target) @@ -152,10 +85,8 @@ static void ULOG_save(const void *ip, const struct xt_entry_target *target) xtables_save_string(loginfo->prefix); } - if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) { - printf(" --ulog-nlgroup"); - print_groups(loginfo->nl_group); - } + if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) + printf(" --ulog-nlgroup %d", ffs(loginfo->nl_group)); if (loginfo->copy_range) printf(" --ulog-cprange %u", (unsigned int)loginfo->copy_range); @@ -170,8 +101,8 @@ static void ULOG_print(const void *ip, const struct xt_entry_target *target, = (const struct ipt_ulog_info *) target->data; printf(" ULOG "); - printf("copy_range %u nlgroup", (unsigned int)loginfo->copy_range); - print_groups(loginfo->nl_group); + printf("copy_range %u nlgroup %d", (unsigned int)loginfo->copy_range, + ffs(loginfo->nl_group)); if (strcmp(loginfo->prefix, "") != 0) printf(" prefix \"%s\"", loginfo->prefix); printf(" queue_threshold %u", (unsigned int)loginfo->qthreshold); @@ -185,10 +116,10 @@ static struct xtables_target ulog_tg_reg = { .userspacesize = XT_ALIGN(sizeof(struct ipt_ulog_info)), .help = ULOG_help, .init = ULOG_init, - .parse = ULOG_parse, .print = ULOG_print, .save = ULOG_save, - .extra_opts = ULOG_opts, + .x6_parse = ULOG_parse, + .x6_options = ULOG_opts, }; void _init(void) -- cgit v1.2.3