From e8b42fee7eaa1ba6df203fe0bc4496cae226cbd2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 2 May 2011 02:13:16 +0200 Subject: libxtables: support for XTTYPE_PLENMASK Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 4 +++- xtoptions.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index 47f797bd..a760755c 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -59,6 +59,7 @@ struct in_addr; * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian * %XTTYPE_PORTRC: colon-separated port range (names acceptable) * %XTTYPE_PORTRC_NE: same as %XTTYPE_PORTRC, stored in network-endian + * %XTTYPE_PLENMASK: prefix len stored as union nf_inet_addr */ enum xt_option_type { XTTYPE_NONE, @@ -80,6 +81,7 @@ enum xt_option_type { XTTYPE_PORT_NE, XTTYPE_PORTRC, XTTYPE_PORTRC_NE, + XTTYPE_PLENMASK, }; /** @@ -139,7 +141,7 @@ struct xt_option_call { uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; double dbl; - union nf_inet_addr inetaddr; + union nf_inet_addr inetaddr, inetmask; struct { uint8_t tos_value, tos_mask; }; diff --git a/xtoptions.c b/xtoptions.c index 86498a97..2bd66f96 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -561,6 +561,47 @@ static void xtopt_parse_mport(struct xt_option_call *cb) free(lo_arg); } +static void xtopt_parse_plenmask(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + uint32_t *mask = cb->val.inetmask.all; + unsigned int prefix_len = 128; + uint8_t max = 128; + + if (afinfo->family == NFPROTO_IPV6) + max = 128; + else if (afinfo->family == NFPROTO_IPV4) + max = 32; + + if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, max)) + xt_params->exit_err(PARAMETER_PROBLEM, + "%s: bad value for option \"--%s\", " + "or out of range (%u-%u).\n", + cb->ext_name, entry->name, 0, max); + + memset(mask, 0xFF, sizeof(union nf_inet_addr)); + if (prefix_len == 0) { + mask[0] = mask[1] = mask[2] = mask[3] = 0; + } else if (prefix_len <= 32) { + mask[0] <<= 32 - prefix_len; + mask[1] = mask[2] = mask[3] = 0; + } else if (prefix_len <= 64) { + mask[1] <<= 32 - (prefix_len - 32); + mask[2] = mask[3] = 0; + } else if (prefix_len <= 96) { + mask[2] <<= 32 - (prefix_len - 64); + mask[3] = 0; + } else if (prefix_len <= 128) { + mask[3] <<= 32 - (prefix_len - 96); + } + mask[0] = htonl(mask[0]); + mask[1] = htonl(mask[1]); + mask[2] = htonl(mask[2]); + mask[3] = htonl(mask[3]); + if (entry->flags & XTOPT_PUT) + memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr)); +} + static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT16] = xtopt_parse_int, @@ -580,6 +621,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_PORT_NE] = xtopt_parse_port, [XTTYPE_PORTRC] = xtopt_parse_mport, [XTTYPE_PORTRC_NE] = xtopt_parse_mport, + [XTTYPE_PLENMASK] = xtopt_parse_plenmask, }; static const size_t xtopt_psize[] = { @@ -599,6 +641,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_PORT_NE] = sizeof(uint16_t), [XTTYPE_PORTRC] = sizeof(uint16_t[2]), [XTTYPE_PORTRC_NE] = sizeof(uint16_t[2]), + [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr), }; /** -- cgit v1.2.3 From 27adf1ec123b949f1c7b48fbdef67d1d4ed18901 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 1 May 2011 21:52:25 +0200 Subject: libxt_connlimit: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_connlimit.c | 176 ++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 111 deletions(-) diff --git a/extensions/libxt_connlimit.c b/extensions/libxt_connlimit.c index badf68c0..a569f86a 100644 --- a/extensions/libxt_connlimit.c +++ b/extensions/libxt_connlimit.c @@ -1,18 +1,20 @@ -/* Shared library add-on to iptables to add connection limit support. */ -#include #include #include #include -#include -#include -#include #include #include enum { - FL_LIMIT = 1 << 0, - FL_MASK = 1 << 1, - FL_ADDR = 1 << 2, + O_UPTO = 0, + O_ABOVE, + O_MASK, + O_SADDR, + O_DADDR, + F_UPTO = 1 << O_UPTO, + F_ABOVE = 1 << O_ABOVE, + F_MASK = 1 << O_MASK, + F_SADDR = 1 << O_SADDR, + F_DADDR = 1 << O_DADDR, }; static void connlimit_help(void) @@ -26,14 +28,23 @@ static void connlimit_help(void) " --connlimit-daddr select destination addresses for grouping\n"); } -static const struct option connlimit_opts[] = { - {.name = "connlimit-upto", .has_arg = true, .val = 'U'}, - {.name = "connlimit-above", .has_arg = true, .val = 'A'}, - {.name = "connlimit-mask", .has_arg = true, .val = 'M'}, - {.name = "connlimit-saddr", .has_arg = false, .val = 's'}, - {.name = "connlimit-daddr", .has_arg = false, .val = 'd'}, - XT_GETOPT_TABLEEND, +#define s struct xt_connlimit_info +static const struct xt_option_entry connlimit_opts[] = { + {.name = "connlimit-upto", .id = O_UPTO, .excl = F_ABOVE, + .type = XTTYPE_UINT32, .flags = XTOPT_INVERT | XTOPT_PUT, + XTOPT_POINTER(s, limit)}, + {.name = "connlimit-above", .id = O_ABOVE, .excl = F_UPTO, + .type = XTTYPE_UINT32, .flags = XTOPT_INVERT | XTOPT_PUT, + XTOPT_POINTER(s, limit)}, + {.name = "connlimit-mask", .id = O_MASK, .type = XTTYPE_PLENMASK, + .flags = XTOPT_PUT, XTOPT_POINTER(s, mask)}, + {.name = "connlimit-saddr", .id = O_SADDR, .excl = F_DADDR, + .type = XTTYPE_NONE}, + {.name = "connlimit-daddr", .id = O_DADDR, .excl = F_SADDR, + .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; +#undef s static void connlimit_init(struct xt_entry_match *match) { @@ -43,111 +54,54 @@ static void connlimit_init(struct xt_entry_match *match) memset(info->v6_mask, 0xFF, sizeof(info->v6_mask)); } -static void prefix_to_netmask(uint32_t *mask, unsigned int prefix_len) +static void connlimit_parse(struct xt_option_call *cb, uint8_t family) { - if (prefix_len == 0) { - mask[0] = mask[1] = mask[2] = mask[3] = 0; - } else if (prefix_len <= 32) { - mask[0] <<= 32 - prefix_len; - mask[1] = mask[2] = mask[3] = 0; - } else if (prefix_len <= 64) { - mask[1] <<= 32 - (prefix_len - 32); - mask[2] = mask[3] = 0; - } else if (prefix_len <= 96) { - mask[2] <<= 32 - (prefix_len - 64); - mask[3] = 0; - } else if (prefix_len <= 128) { - mask[3] <<= 32 - (prefix_len - 96); - } - mask[0] = htonl(mask[0]); - mask[1] = htonl(mask[1]); - mask[2] = htonl(mask[2]); - mask[3] = htonl(mask[3]); -} - -static int -connlimit_parse(int c, char **argv, int invert, unsigned int *flags, - struct xt_entry_match **match, unsigned int family) -{ - struct xt_connlimit_info *info = (void *)(*match)->data; - const unsigned int revision = (*match)->u.user.revision; - char *err; - int i; + struct xt_connlimit_info *info = cb->data; + const unsigned int revision = (*cb->match)->u.user.revision; - switch (c) { - case 'A': /* --connlimit-above */ - xtables_param_act(XTF_ONLY_ONCE, "connlimit", - "--connlimit-{upto,above}", *flags & FL_LIMIT); - *flags |= FL_LIMIT; - if (invert) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_ABOVE: + if (cb->invert) info->flags |= XT_CONNLIMIT_INVERT; - info->limit = strtoul(optarg, NULL, 0); - return true; - case 'U': /* --connlimit-upto */ - xtables_param_act(XTF_ONLY_ONCE, "connlimit", - "--connlimit-{upto,above}", *flags & FL_LIMIT); - *flags |= FL_LIMIT; - if (!invert) + break; + case O_UPTO: + if (!cb->invert) info->flags |= XT_CONNLIMIT_INVERT; - info->limit = strtoul(optarg, NULL, 0); - return true; - case 'M': /* --connlimit-mask */ - xtables_param_act(XTF_NO_INVERT, "connlimit", - "--connlimit-mask", invert); - xtables_param_act(XTF_ONLY_ONCE, "connlimit", - "--connlimit-mask", *flags & FL_MASK); - *flags |= FL_MASK; - i = strtoul(optarg, &err, 0); - if (family == NFPROTO_IPV6) { - if (i > 128 || *err != '\0') - xtables_error(PARAMETER_PROBLEM, - "--connlimit-mask must be between " - "0 and 128"); - prefix_to_netmask(info->v6_mask, i); - } else { - if (i > 32 || *err != '\0') - xtables_error(PARAMETER_PROBLEM, - "--connlimit-mask must be between " - "0 and 32"); - if (i == 0) - info->v4_mask = 0; - else - info->v4_mask = htonl(0xFFFFFFFF << (32 - i)); - } - return true; - case 's': /* --connlimit-saddr */ + break; + case O_SADDR: + if (revision < 1) + xtables_error(PARAMETER_PROBLEM, + "xt_connlimit.0 does not support " + "--connlimit-daddr"); info->flags &= ~XT_CONNLIMIT_DADDR; - return true; - case 'd': /* --connlimit-daddr */ + break; + case O_DADDR: if (revision < 1) xtables_error(PARAMETER_PROBLEM, "xt_connlimit.0 does not support " "--connlimit-daddr"); info->flags |= XT_CONNLIMIT_DADDR; - return true; + break; } - return false; } -static int connlimit_parse4(int c, char **argv, int invert, - unsigned int *flags, const void *entry, - struct xt_entry_match **match) +static void connlimit_parse4(struct xt_option_call *cb) { - return connlimit_parse(c, argv, invert, flags, match, NFPROTO_IPV4); + return connlimit_parse(cb, NFPROTO_IPV4); } -static int connlimit_parse6(int c, char **argv, int invert, - unsigned int *flags, const void *entry, - struct xt_entry_match **match) +static void connlimit_parse6(struct xt_option_call *cb) { - return connlimit_parse(c, argv, invert, flags, match, NFPROTO_IPV6); + return connlimit_parse(cb, NFPROTO_IPV6); } -static void connlimit_check(unsigned int flags) +static void connlimit_check(struct xt_fcheck_call *cb) { - if (!(flags & 0x1)) + if ((cb->xflags & (F_UPTO | F_ABOVE)) == 0) xtables_error(PARAMETER_PROBLEM, - "You must specify \"--connlimit-above\""); + "You must specify \"--connlimit-above\" or " + "\"--connlimit-upto\"."); } static unsigned int count_bits4(uint32_t mask) @@ -239,11 +193,11 @@ static struct xtables_match connlimit_mt_reg[] = { .userspacesize = offsetof(struct xt_connlimit_info, data), .help = connlimit_help, .init = connlimit_init, - .parse = connlimit_parse4, - .final_check = connlimit_check, + .x6_parse = connlimit_parse4, + .x6_fcheck = connlimit_check, .print = connlimit_print4, .save = connlimit_save4, - .extra_opts = connlimit_opts, + .x6_options = connlimit_opts, }, { .name = "connlimit", @@ -254,11 +208,11 @@ static struct xtables_match connlimit_mt_reg[] = { .userspacesize = offsetof(struct xt_connlimit_info, data), .help = connlimit_help, .init = connlimit_init, - .parse = connlimit_parse6, - .final_check = connlimit_check, + .x6_parse = connlimit_parse6, + .x6_fcheck = connlimit_check, .print = connlimit_print6, .save = connlimit_save6, - .extra_opts = connlimit_opts, + .x6_options = connlimit_opts, }, { .name = "connlimit", @@ -269,11 +223,11 @@ static struct xtables_match connlimit_mt_reg[] = { .userspacesize = offsetof(struct xt_connlimit_info, data), .help = connlimit_help, .init = connlimit_init, - .parse = connlimit_parse4, - .final_check = connlimit_check, + .x6_parse = connlimit_parse4, + .x6_fcheck = connlimit_check, .print = connlimit_print4, .save = connlimit_save4, - .extra_opts = connlimit_opts, + .x6_options = connlimit_opts, }, { .name = "connlimit", @@ -284,11 +238,11 @@ static struct xtables_match connlimit_mt_reg[] = { .userspacesize = offsetof(struct xt_connlimit_info, data), .help = connlimit_help, .init = connlimit_init, - .parse = connlimit_parse6, - .final_check = connlimit_check, + .x6_parse = connlimit_parse6, + .x6_fcheck = connlimit_check, .print = connlimit_print6, .save = connlimit_save6, - .extra_opts = connlimit_opts, + .x6_options = connlimit_opts, }, }; -- cgit v1.2.3 From 51a746e6b1d66ca546fd2f8a1f7809868174e637 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 4 May 2011 12:30:15 +0200 Subject: libxt_recent: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_recent.c | 186 ++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 107 deletions(-) diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c index f8a5a18d..1e1a111f 100644 --- a/extensions/libxt_recent.c +++ b/extensions/libxt_recent.c @@ -1,27 +1,50 @@ -/* Shared library add-on to iptables to add recent matching support. */ #include #include -#include #include -#include -#include - #include #include -static const struct option recent_opts[] = { - {.name = "set", .has_arg = false, .val = 201}, - {.name = "rcheck", .has_arg = false, .val = 202}, - {.name = "update", .has_arg = false, .val = 203}, - {.name = "seconds", .has_arg = true, .val = 204}, - {.name = "hitcount", .has_arg = true, .val = 205}, - {.name = "remove", .has_arg = false, .val = 206}, - {.name = "rttl", .has_arg = false, .val = 207}, - {.name = "name", .has_arg = true, .val = 208}, - {.name = "rsource", .has_arg = false, .val = 209}, - {.name = "rdest", .has_arg = false, .val = 210}, - XT_GETOPT_TABLEEND, +enum { + O_SET = 0, + O_RCHECK, + O_UPDATE, + O_REMOVE, + O_SECONDS, + O_HITCOUNT, + O_RTTL, + O_NAME, + O_RSOURCE, + O_RDEST, + F_SET = 1 << O_SET, + F_RCHECK = 1 << O_RCHECK, + F_UPDATE = 1 << O_UPDATE, + F_REMOVE = 1 << O_REMOVE, + F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE, +}; + +#define s struct xt_recent_mtinfo +static const struct xt_option_entry recent_opts[] = { + {.name = "set", .id = O_SET, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE, + .excl = F_ANY_OP, .flags = XTOPT_INVERT}, + {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)}, + {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)}, + {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE, + .excl = F_SET | F_REMOVE}, + {.name = "name", .id = O_NAME, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, name)}, + {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE}, + {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; +#undef s static void recent_help(void) { @@ -59,101 +82,50 @@ static void recent_init(struct xt_entry_match *match) info->side = XT_RECENT_SOURCE; } -#define RECENT_CMDS \ - (XT_RECENT_SET | XT_RECENT_CHECK | \ - XT_RECENT_UPDATE | XT_RECENT_REMOVE) - -static int recent_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void recent_parse(struct xt_option_call *cb) { - struct xt_recent_mtinfo *info = (void *)(*match)->data; - - switch (c) { - case 201: - if (*flags & RECENT_CMDS) - xtables_error(PARAMETER_PROBLEM, - "recent: only one of `--set', `--rcheck' " - "`--update' or `--remove' may be set"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - info->check_set |= XT_RECENT_SET; - if (invert) info->invert = 1; - *flags |= XT_RECENT_SET; - break; - - case 202: - if (*flags & RECENT_CMDS) - xtables_error(PARAMETER_PROBLEM, - "recent: only one of `--set', `--rcheck' " - "`--update' or `--remove' may be set"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - info->check_set |= XT_RECENT_CHECK; - if(invert) info->invert = 1; - *flags |= XT_RECENT_CHECK; - break; - - case 203: - if (*flags & RECENT_CMDS) - xtables_error(PARAMETER_PROBLEM, - "recent: only one of `--set', `--rcheck' " - "`--update' or `--remove' may be set"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - info->check_set |= XT_RECENT_UPDATE; - if (invert) info->invert = 1; - *flags |= XT_RECENT_UPDATE; - break; - - case 204: - info->seconds = atoi(optarg); - break; - - case 205: - info->hit_count = atoi(optarg); - break; - - case 206: - if (*flags & RECENT_CMDS) - xtables_error(PARAMETER_PROBLEM, - "recent: only one of `--set', `--rcheck' " - "`--update' or `--remove' may be set"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - info->check_set |= XT_RECENT_REMOVE; - if (invert) info->invert = 1; - *flags |= XT_RECENT_REMOVE; - break; - - case 207: - info->check_set |= XT_RECENT_TTL; - *flags |= XT_RECENT_TTL; - break; - - case 208: - strncpy(info->name,optarg, XT_RECENT_NAME_LEN); - info->name[XT_RECENT_NAME_LEN-1] = '\0'; - break; - - case 209: - info->side = XT_RECENT_SOURCE; - break; - - case 210: - info->side = XT_RECENT_DEST; - break; + struct xt_recent_mtinfo *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SET: + info->check_set |= XT_RECENT_SET; + if (cb->invert) + info->invert = true; + break; + case O_RCHECK: + info->check_set |= XT_RECENT_CHECK; + if (cb->invert) + info->invert = true; + break; + case O_UPDATE: + info->check_set |= XT_RECENT_UPDATE; + if (cb->invert) + info->invert = true; + break; + case O_REMOVE: + info->check_set |= XT_RECENT_REMOVE; + if (cb->invert) + info->invert = true; + break; + case O_RTTL: + info->check_set |= XT_RECENT_TTL; + break; + case O_RSOURCE: + info->side = XT_RECENT_SOURCE; + break; + case O_RDEST: + info->side = XT_RECENT_DEST; + break; } - - return 1; } -static void recent_check(unsigned int flags) +static void recent_check(struct xt_fcheck_call *cb) { - if (!(flags & RECENT_CMDS)) + if (!(cb->xflags & F_ANY_OP)) xtables_error(PARAMETER_PROBLEM, "recent: you must specify one of `--set', `--rcheck' " "`--update' or `--remove'"); - if ((flags & XT_RECENT_TTL) && - (flags & (XT_RECENT_SET | XT_RECENT_REMOVE))) - xtables_error(PARAMETER_PROBLEM, - "recent: --rttl may only be used with --rcheck or " - "--update"); } static void recent_print(const void *ip, const struct xt_entry_match *match, @@ -218,11 +190,11 @@ static struct xtables_match recent_mt_reg = { .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)), .help = recent_help, .init = recent_init, - .parse = recent_parse, - .final_check = recent_check, + .x6_parse = recent_parse, + .x6_fcheck = recent_check, .print = recent_print, .save = recent_save, - .extra_opts = recent_opts, + .x6_options = recent_opts, }; void _init(void) -- cgit v1.2.3 From d7282413763b0ba85d512c1cd49174b762ff449c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 4 May 2011 16:41:13 +0200 Subject: libxtables: do not overlay addr and mask parts, and cleanup XTTYPE_HOSTMASK will require that what has now become haddr, hmask/hlen are not overlays of another. Thus relax the structure and always set all members of the {haddr, hmask, hlen} triplet now for all types that touch any of the members. Add some more comments and clean out ONEHOST. --- extensions/libxt_TEE.c | 2 +- extensions/libxt_TPROXY.c | 6 +++--- include/xtables.h.in | 17 ++++++++++++---- xtoptions.c | 50 +++++++++++++++++++++++++++++------------------ 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/extensions/libxt_TEE.c b/extensions/libxt_TEE.c index fd9a1b23..c89e5809 100644 --- a/extensions/libxt_TEE.c +++ b/extensions/libxt_TEE.c @@ -31,7 +31,7 @@ enum { #define s struct xt_tee_tginfo static const struct xt_option_entry tee_tg_opts[] = { - {.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_ONEHOST, + {.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_HOST, .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, gw)}, {.name = "oif", .id = O_OIF, .type = XTTYPE_STRING, .flags = XTOPT_PUT, XTOPT_POINTER(s, oif)}, diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c index 5264ea7d..61646c93 100644 --- a/extensions/libxt_TPROXY.c +++ b/extensions/libxt_TPROXY.c @@ -22,7 +22,7 @@ enum { 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 = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST}, {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32}, XTOPT_TABLEEND, }; @@ -31,7 +31,7 @@ static const struct xt_option_entry tproxy_tg0_opts[] = { 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, + {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST, .flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)}, {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32}, XTOPT_TABLEEND, @@ -129,7 +129,7 @@ static void tproxy_tg0_parse(struct xt_option_call *cb) info->mark_mask = cb->val.mask; break; case P_ADDR: - info->laddr = cb->val.inetaddr.ip; + info->laddr = cb->val.haddr.ip; break; } } diff --git a/include/xtables.h.in b/include/xtables.h.in index a760755c..c9ad5238 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -46,6 +46,12 @@ struct in_addr; #define XTOPT_TABLEEND {.name = NULL} /** + * Select the format the input has to conform to, as well as the target type + * (area pointed to with XTOPT_POINTER). Note that the storing is not always + * uniform. @cb->val will be populated with as much as there is space, i.e. + * exactly 2 items for ranges, but the target area can receive more values + * (e.g. in case of ranges), or less values (e.g. %XTTYPE_HOSTMASK). + * * %XTTYPE_NONE: option takes no argument * %XTTYPE_UINT*: standard integer * %XTTYPE_UINT*RC: colon-separated range of standard integers @@ -54,12 +60,12 @@ struct in_addr; * %XTTYPE_TOSMASK: 8-bit TOS value with optional mask * %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_HOST: one host or address (ptr: 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 * %XTTYPE_PORTRC: colon-separated port range (names acceptable) * %XTTYPE_PORTRC_NE: same as %XTTYPE_PORTRC, stored in network-endian - * %XTTYPE_PLENMASK: prefix len stored as union nf_inet_addr + * %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr) */ enum xt_option_type { XTTYPE_NONE, @@ -76,7 +82,7 @@ enum xt_option_type { XTTYPE_TOSMASK, XTTYPE_MARKMASK32, XTTYPE_SYSLOGLEVEL, - XTTYPE_ONEHOST, + XTTYPE_HOST, XTTYPE_PORT, XTTYPE_PORT_NE, XTTYPE_PORTRC, @@ -141,7 +147,10 @@ struct xt_option_call { uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; double dbl; - union nf_inet_addr inetaddr, inetmask; + struct { + union nf_inet_addr haddr, hmask; + uint8_t hlen; + }; struct { uint8_t tos_value, tos_mask; }; diff --git a/xtoptions.c b/xtoptions.c index 2bd66f96..f8031bbe 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -419,9 +419,11 @@ static socklen_t xtables_sa_hostlen(unsigned int afproto) } /** - * Accepts: a hostname (DNS), or a single inetaddr. + * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The + * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and + * @cb->val.hlen are set for completeness to the appropriate values. */ -static void xtopt_parse_onehost(struct xt_option_call *cb) +static void xtopt_parse_host(struct xt_option_call *cb) { struct addrinfo hints = {.ai_family = afinfo->family}; unsigned int adcount = 0; @@ -433,16 +435,19 @@ static void xtopt_parse_onehost(struct xt_option_call *cb) xt_params->exit_err(PARAMETER_PROBLEM, "getaddrinfo: %s\n", gai_strerror(ret)); + memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask)); + cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; + 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, + memset(&cb->val.haddr, 0, sizeof(cb->val.haddr)); + memcpy(&cb->val.haddr, xtables_sa_host(p->ai_addr, p->ai_family), xtables_sa_hostlen(p->ai_family)); ++adcount; continue; } - if (memcmp(&cb->val.inetaddr, + if (memcmp(&cb->val.haddr, xtables_sa_host(p->ai_addr, p->ai_family), xtables_sa_hostlen(p->ai_family)) != 0) xt_params->exit_err(PARAMETER_PROBLEM, @@ -453,8 +458,8 @@ static void xtopt_parse_onehost(struct xt_option_call *cb) freeaddrinfo(res); if (cb->entry->flags & XTOPT_PUT) /* Validation in xtables_option_metavalidate */ - memcpy(XTOPT_MKPTR(cb), &cb->val.inetaddr, - sizeof(cb->val.inetaddr)); + memcpy(XTOPT_MKPTR(cb), &cb->val.haddr, + sizeof(cb->val.haddr)); } /** @@ -488,7 +493,8 @@ static int xtables_getportbyname(const char *name) } /** - * Validate and parse a port specification and put the result into @cb. + * Validate and parse a port specification and put the result into + * @cb->val.port. */ static void xtopt_parse_port(struct xt_option_call *cb) { @@ -561,25 +567,27 @@ static void xtopt_parse_mport(struct xt_option_call *cb) free(lo_arg); } +/** + * Parse an integer and ensure it is within the address family's prefix length + * limits. The result is stored in @cb->val.hmask and @cb->val.hlen. If + * %XTOPT_PUT is used, hmask will be copied to the pointed-to area. + */ static void xtopt_parse_plenmask(struct xt_option_call *cb) { const struct xt_option_entry *entry = cb->entry; - uint32_t *mask = cb->val.inetmask.all; + uint32_t *mask = cb->val.hmask.all; unsigned int prefix_len = 128; - uint8_t max = 128; - if (afinfo->family == NFPROTO_IPV6) - max = 128; - else if (afinfo->family == NFPROTO_IPV4) - max = 32; - - if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, max)) + cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; + if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) xt_params->exit_err(PARAMETER_PROBLEM, "%s: bad value for option \"--%s\", " "or out of range (%u-%u).\n", - cb->ext_name, entry->name, 0, max); + cb->ext_name, entry->name, 0, cb->val.hlen); + cb->val.hlen = prefix_len; memset(mask, 0xFF, sizeof(union nf_inet_addr)); + /* This shifting is AF-independent. */ if (prefix_len == 0) { mask[0] = mask[1] = mask[2] = mask[3] = 0; } else if (prefix_len <= 32) { @@ -616,7 +624,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_TOSMASK] = xtopt_parse_tosmask, [XTTYPE_MARKMASK32] = xtopt_parse_markmask, [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, - [XTTYPE_ONEHOST] = xtopt_parse_onehost, + [XTTYPE_HOST] = xtopt_parse_host, [XTTYPE_PORT] = xtopt_parse_port, [XTTYPE_PORT_NE] = xtopt_parse_port, [XTTYPE_PORTRC] = xtopt_parse_mport, @@ -625,6 +633,10 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { }; static const size_t xtopt_psize[] = { + /* + * All types not listed here, and thus essentially being initialized to + * zero have zero on purpose. + */ [XTTYPE_UINT8] = sizeof(uint8_t), [XTTYPE_UINT16] = sizeof(uint16_t), [XTTYPE_UINT32] = sizeof(uint32_t), @@ -636,7 +648,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_DOUBLE] = sizeof(double), [XTTYPE_STRING] = -1, [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), - [XTTYPE_ONEHOST] = sizeof(union nf_inet_addr), + [XTTYPE_HOST] = sizeof(union nf_inet_addr), [XTTYPE_PORT] = sizeof(uint16_t), [XTTYPE_PORT_NE] = sizeof(uint16_t), [XTTYPE_PORTRC] = sizeof(uint16_t[2]), -- cgit v1.2.3 From 269cbfd30aac18c1fd251be83430dabc60abee0c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 5 May 2011 12:53:14 +0200 Subject: libxtables: flag invalid uses of XTOPT_PUT Signed-off-by: Jan Engelhardt --- xtoptions.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xtoptions.c b/xtoptions.c index f8031bbe..29d05d53 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -708,7 +708,8 @@ void xtables_option_metavalidate(const char *name, name, entry->id); if (!(entry->flags & XTOPT_PUT)) continue; - if (entry->type >= ARRAY_SIZE(xtopt_psize)) + if (entry->type >= ARRAY_SIZE(xtopt_psize) || + xtopt_psize[entry->type] == 0) xt_params->exit_err(OTHER_PROBLEM, "%s: entry type of option \"--%s\" cannot be " "combined with XTOPT_PUT\n", -- cgit v1.2.3 From fa9b759bacc0ad6a093892ef508811e7feb981b0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 4 May 2011 17:25:54 +0200 Subject: libxtables: XTTYPE_PLEN support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 2 ++ xtoptions.c | 41 +++++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index c9ad5238..9bb42351 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -65,6 +65,7 @@ struct in_addr; * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian * %XTTYPE_PORTRC: colon-separated port range (names acceptable) * %XTTYPE_PORTRC_NE: same as %XTTYPE_PORTRC, stored in network-endian + * %XTTYPE_PLEN: prefix length * %XTTYPE_PLENMASK: prefix length (ptr: union nf_inet_addr) */ enum xt_option_type { @@ -87,6 +88,7 @@ enum xt_option_type { XTTYPE_PORT_NE, XTTYPE_PORTRC, XTTYPE_PORTRC_NE, + XTTYPE_PLEN, XTTYPE_PLENMASK, }; diff --git a/xtoptions.c b/xtoptions.c index 29d05d53..3cc2e0cc 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -569,14 +569,12 @@ static void xtopt_parse_mport(struct xt_option_call *cb) /** * Parse an integer and ensure it is within the address family's prefix length - * limits. The result is stored in @cb->val.hmask and @cb->val.hlen. If - * %XTOPT_PUT is used, hmask will be copied to the pointed-to area. + * limits. The result is stored in @cb->val.hlen. */ -static void xtopt_parse_plenmask(struct xt_option_call *cb) +static void xtopt_parse_plen(struct xt_option_call *cb) { const struct xt_option_entry *entry = cb->entry; - uint32_t *mask = cb->val.hmask.all; - unsigned int prefix_len = 128; + unsigned int prefix_len = 128; /* happiness is a warm gcc */ cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128; if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) @@ -586,21 +584,35 @@ static void xtopt_parse_plenmask(struct xt_option_call *cb) cb->ext_name, entry->name, 0, cb->val.hlen); cb->val.hlen = prefix_len; +} + +/** + * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to + * a bitmask, and make it available through @cb->val.hmask (hlen remains + * valid). If %XTOPT_PUT is used, hmask will be copied to the target area. + */ +static void xtopt_parse_plenmask(struct xt_option_call *cb) +{ + const struct xt_option_entry *entry = cb->entry; + uint32_t *mask = cb->val.hmask.all; + + xtopt_parse_plen(cb); + memset(mask, 0xFF, sizeof(union nf_inet_addr)); /* This shifting is AF-independent. */ - if (prefix_len == 0) { + if (cb->val.hlen == 0) { mask[0] = mask[1] = mask[2] = mask[3] = 0; - } else if (prefix_len <= 32) { - mask[0] <<= 32 - prefix_len; + } else if (cb->val.hlen <= 32) { + mask[0] <<= 32 - cb->val.hlen; mask[1] = mask[2] = mask[3] = 0; - } else if (prefix_len <= 64) { - mask[1] <<= 32 - (prefix_len - 32); + } else if (cb->val.hlen <= 64) { + mask[1] <<= 32 - (cb->val.hlen - 32); mask[2] = mask[3] = 0; - } else if (prefix_len <= 96) { - mask[2] <<= 32 - (prefix_len - 64); + } else if (cb->val.hlen <= 96) { + mask[2] <<= 32 - (cb->val.hlen - 64); mask[3] = 0; - } else if (prefix_len <= 128) { - mask[3] <<= 32 - (prefix_len - 96); + } else if (cb->val.hlen <= 128) { + mask[3] <<= 32 - (cb->val.hlen - 96); } mask[0] = htonl(mask[0]); mask[1] = htonl(mask[1]); @@ -629,6 +641,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_PORT_NE] = xtopt_parse_port, [XTTYPE_PORTRC] = xtopt_parse_mport, [XTTYPE_PORTRC_NE] = xtopt_parse_mport, + [XTTYPE_PLEN] = xtopt_parse_plen, [XTTYPE_PLENMASK] = xtopt_parse_plenmask, }; -- cgit v1.2.3 From fe02f76e013941a7f65f57f297d3177bcfeb0623 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 4 May 2011 23:18:57 +0200 Subject: libxt_hashlimit: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_hashlimit.c | 419 +++++++++++++------------------------------ 1 file changed, 129 insertions(+), 290 deletions(-) diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c index cd057c5f..e683f9ad 100644 --- a/extensions/libxt_hashlimit.c +++ b/extensions/libxt_hashlimit.c @@ -15,9 +15,7 @@ #include #include #include -#include #include -#include #include #include @@ -45,6 +43,23 @@ static void hashlimit_help(void) XT_HASHLIMIT_BURST); } +enum { + O_UPTO = 0, + O_ABOVE, + O_LIMIT, + O_MODE, + O_SRCMASK, + O_DSTMASK, + O_NAME, + O_BURST, + O_HTABLE_SIZE, + O_HTABLE_MAX, + O_HTABLE_GCINT, + O_HTABLE_EXPIRE, + F_UPTO = 1 << O_UPTO, + F_ABOVE = 1 << O_ABOVE, +}; + static void hashlimit_mt_help(void) { printf( @@ -66,33 +81,64 @@ static void hashlimit_mt_help(void) "\n", XT_HASHLIMIT_BURST); } -static const struct option hashlimit_opts[] = { - {.name = "hashlimit", .has_arg = true, .val = '%'}, - {.name = "hashlimit-burst", .has_arg = true, .val = '$'}, - {.name = "hashlimit-htable-size", .has_arg = true, .val = '&'}, - {.name = "hashlimit-htable-max", .has_arg = true, .val = '*'}, - {.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('}, - {.name = "hashlimit-htable-expire", .has_arg = true, .val = ')'}, - {.name = "hashlimit-mode", .has_arg = true, .val = '_'}, - {.name = "hashlimit-name", .has_arg = true, .val = '"'}, - XT_GETOPT_TABLEEND, +#define s struct xt_hashlimit_info +static const struct xt_option_entry hashlimit_opts[] = { + {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE, + .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, + {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32, + .min = 1, .max = 10000, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.burst)}, + {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.size)}, + {.name = "hashlimit-htable-max", .id = O_HTABLE_MAX, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.max)}, + {.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.gc_interval)}, + {.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.expire)}, + {.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING, + .flags = XTOPT_MAND}, + {.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1}, + XTOPT_TABLEEND, }; - -static const struct option hashlimit_mt_opts[] = { - {.name = "hashlimit-upto", .has_arg = true, .val = '%'}, - {.name = "hashlimit-above", .has_arg = true, .val = '^'}, - {.name = "hashlimit", .has_arg = true, .val = '%'}, - {.name = "hashlimit-srcmask", .has_arg = true, .val = '<'}, - {.name = "hashlimit-dstmask", .has_arg = true, .val = '>'}, - {.name = "hashlimit-burst", .has_arg = true, .val = '$'}, - {.name = "hashlimit-htable-size", .has_arg = true, .val = '&'}, - {.name = "hashlimit-htable-max", .has_arg = true, .val = '*'}, - {.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('}, - {.name = "hashlimit-htable-expire", .has_arg = true, .val = ')'}, - {.name = "hashlimit-mode", .has_arg = true, .val = '_'}, - {.name = "hashlimit-name", .has_arg = true, .val = '"'}, - XT_GETOPT_TABLEEND, +#undef s + +#define s struct xt_hashlimit_mtinfo1 +static const struct xt_option_entry hashlimit_mt_opts[] = { + {.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE, + .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, + {.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO, + .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, + {.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE, + .type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */ + {.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN}, + {.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN}, + {.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32, + .min = 1, .max = 10000, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.burst)}, + {.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.size)}, + {.name = "hashlimit-htable-max", .id = O_HTABLE_MAX, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.max)}, + {.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.gc_interval)}, + {.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE, + .type = XTTYPE_UINT32, .flags = XTOPT_PUT, + XTOPT_POINTER(s, cfg.expire)}, + {.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING}, + {.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1}, + XTOPT_TABLEEND, }; +#undef s static int parse_rate(const char *rate, uint32_t *val) @@ -165,7 +211,7 @@ static void hashlimit_mt6_init(struct xt_entry_match *match) } /* Parse a 'mode' parameter into the required bitmask */ -static int parse_mode(uint32_t *mode, char *option_arg) +static int parse_mode(uint32_t *mode, const char *option_arg) { char *tok; char *arg = strdup(option_arg); @@ -193,280 +239,73 @@ static int parse_mode(uint32_t *mode, char *option_arg) return 0; } -enum { - PARAM_LIMIT = 1 << 0, - PARAM_BURST = 1 << 1, - PARAM_MODE = 1 << 2, - PARAM_NAME = 1 << 3, - PARAM_SIZE = 1 << 4, - PARAM_MAX = 1 << 5, - PARAM_GCINTERVAL = 1 << 6, - PARAM_EXPIRE = 1 << 7, - PARAM_SRCMASK = 1 << 8, - PARAM_DSTMASK = 1 << 9, -}; - -static int -hashlimit_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void hashlimit_parse(struct xt_option_call *cb) { - struct xt_hashlimit_info *r = - (struct xt_hashlimit_info *)(*match)->data; - unsigned int num; - - switch(c) { - case '%': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit", - *flags & PARAM_LIMIT); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!parse_rate(optarg, &r->cfg.avg)) - xtables_error(PARAMETER_PROBLEM, - "bad rate `%s'", optarg); - *flags |= PARAM_LIMIT; - break; + struct xt_hashlimit_info *info = cb->data; - case '$': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst", - *flags & PARAM_BURST); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!xtables_strtoui(optarg, NULL, &num, 0, 10000)) - xtables_error(PARAMETER_PROBLEM, - "bad --hashlimit-burst `%s'", optarg); - r->cfg.burst = num; - *flags |= PARAM_BURST; - break; - case '&': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size", - *flags & PARAM_SIZE); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "bad --hashlimit-htable-size: `%s'", optarg); - r->cfg.size = num; - *flags |= PARAM_SIZE; - break; - case '*': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max", - *flags & PARAM_MAX); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "bad --hashlimit-htable-max: `%s'", optarg); - r->cfg.max = num; - *flags |= PARAM_MAX; - break; - case '(': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", - "--hashlimit-htable-gcinterval", - *flags & PARAM_GCINTERVAL); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "bad --hashlimit-htable-gcinterval: `%s'", - optarg); - /* FIXME: not HZ dependent!! */ - r->cfg.gc_interval = num; - *flags |= PARAM_GCINTERVAL; - break; - case ')': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", - "--hashlimit-htable-expire", *flags & PARAM_EXPIRE); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "bad --hashlimit-htable-expire: `%s'", optarg); - /* FIXME: not HZ dependent */ - r->cfg.expire = num; - *flags |= PARAM_EXPIRE; + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_UPTO: + if (cb->invert) + info->cfg.mode |= XT_HASHLIMIT_INVERT; + if (!parse_rate(cb->arg, &info->cfg.avg)) + xtables_param_act(XTF_BAD_VALUE, "hashlimit", + "--hashlimit-upto", cb->arg); break; - case '_': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode", - *flags & PARAM_MODE); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (parse_mode(&r->cfg.mode, optarg) < 0) - xtables_error(PARAMETER_PROBLEM, - "bad --hashlimit-mode: `%s'\n", optarg); - *flags |= PARAM_MODE; + case O_ABOVE: + if (!cb->invert) + info->cfg.mode |= XT_HASHLIMIT_INVERT; + if (!parse_rate(cb->arg, &info->cfg.avg)) + xtables_param_act(XTF_BAD_VALUE, "hashlimit", + "--hashlimit-above", cb->arg); break; - case '"': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name", - *flags & PARAM_NAME); - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (strlen(optarg) == 0) - xtables_error(PARAMETER_PROBLEM, "Zero-length name?"); - strncpy(r->name, optarg, sizeof(r->name)); - *flags |= PARAM_NAME; + case O_MODE: + if (parse_mode(&info->cfg.mode, cb->arg) < 0) + xtables_param_act(XTF_BAD_VALUE, "hashlimit", + "--hashlimit-mode", cb->arg); break; } - - if (invert) - xtables_error(PARAMETER_PROBLEM, - "hashlimit does not support invert"); - - return 1; } -static int -hashlimit_mt_parse(struct xt_hashlimit_mtinfo1 *info, unsigned int *flags, - int c, int invert, unsigned int maxmask) +static void hashlimit_mt_parse(struct xt_option_call *cb) { - unsigned int num; + struct xt_hashlimit_mtinfo1 *info = cb->data; - switch(c) { - case '%': /* --hashlimit / --hashlimit-below */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-upto", - *flags & PARAM_LIMIT); - if (invert) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_UPTO: + if (cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(optarg, &info->cfg.avg)) + if (!parse_rate(cb->arg, &info->cfg.avg)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-upto", optarg); - *flags |= PARAM_LIMIT; - return true; - - case '^': /* --hashlimit-above == !--hashlimit-below */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-above", - *flags & PARAM_LIMIT); - if (!invert) + "--hashlimit-upto", cb->arg); + break; + case O_ABOVE: + if (!cb->invert) info->cfg.mode |= XT_HASHLIMIT_INVERT; - if (!parse_rate(optarg, &info->cfg.avg)) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-above", optarg); - *flags |= PARAM_LIMIT; - return true; - - case '$': /* --hashlimit-burst */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst", - *flags & PARAM_BURST); - if (!xtables_strtoui(optarg, NULL, &num, 0, 10000)) + if (!parse_rate(cb->arg, &info->cfg.avg)) xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-burst", optarg); - info->cfg.burst = num; - *flags |= PARAM_BURST; - return true; - - case '&': /* --hashlimit-htable-size */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size", - *flags & PARAM_SIZE); - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-htable-size", optarg); - info->cfg.size = num; - *flags |= PARAM_SIZE; - return true; - - case '*': /* --hashlimit-htable-max */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max", - *flags & PARAM_MAX); - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-htable-max", optarg); - info->cfg.max = num; - *flags |= PARAM_MAX; - return true; - - case '(': /* --hashlimit-htable-gcinterval */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", - "--hashlimit-htable-gcinterval", - *flags & PARAM_GCINTERVAL); - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-htable-gcinterval", optarg); - /* FIXME: not HZ dependent!! */ - info->cfg.gc_interval = num; - *flags |= PARAM_GCINTERVAL; - return true; - - case ')': /* --hashlimit-htable-expire */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", - "--hashlimit-htable-expire", *flags & PARAM_EXPIRE); - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-htable-expire", optarg); - /* FIXME: not HZ dependent */ - info->cfg.expire = num; - *flags |= PARAM_EXPIRE; - return true; - - case '_': - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode", - *flags & PARAM_MODE); - if (parse_mode(&info->cfg.mode, optarg) < 0) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-mode", optarg); - *flags |= PARAM_MODE; - return true; - - case '"': /* --hashlimit-name */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name", - *flags & PARAM_NAME); - if (strlen(optarg) == 0) - xtables_error(PARAMETER_PROBLEM, "Zero-length name?"); - strncpy(info->name, optarg, sizeof(info->name)); - info->name[sizeof(info->name)-1] = '\0'; - *flags |= PARAM_NAME; - return true; - - case '<': /* --hashlimit-srcmask */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-srcmask", - *flags & PARAM_SRCMASK); - if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask)) - xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-srcmask", optarg); - info->cfg.srcmask = num; - *flags |= PARAM_SRCMASK; - return true; - - case '>': /* --hashlimit-dstmask */ - xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-dstmask", - *flags & PARAM_DSTMASK); - if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask)) + "--hashlimit-above", cb->arg); + break; + case O_MODE: + if (parse_mode(&info->cfg.mode, cb->arg) < 0) xtables_param_act(XTF_BAD_VALUE, "hashlimit", - "--hashlimit-dstmask", optarg); - info->cfg.dstmask = num; - *flags |= PARAM_DSTMASK; - return true; + "--hashlimit-mode", cb->arg); + break; + case O_SRCMASK: + info->cfg.srcmask = cb->val.hlen; + break; + case O_DSTMASK: + info->cfg.dstmask = cb->val.hlen; + break; } - return false; -} - -static int -hashlimit_mt4_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - return hashlimit_mt_parse((void *)(*match)->data, - flags, c, invert, 32); -} - -static int -hashlimit_mt6_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - return hashlimit_mt_parse((void *)(*match)->data, - flags, c, invert, 128); } -static void hashlimit_check(unsigned int flags) +static void hashlimit_check(struct xt_fcheck_call *cb) { - if (!(flags & PARAM_LIMIT)) + if (!(cb->xflags & (F_UPTO | F_ABOVE))) xtables_error(PARAMETER_PROBLEM, "You have to specify --hashlimit"); - if (!(flags & PARAM_MODE)) - xtables_error(PARAMETER_PROBLEM, - "You have to specify --hashlimit-mode"); - if (!(flags & PARAM_NAME)) - xtables_error(PARAMETER_PROBLEM, - "You have to specify --hashlimit-name"); -} - -static void hashlimit_mt_check(unsigned int flags) -{ - if (!(flags & PARAM_LIMIT)) - xtables_error(PARAMETER_PROBLEM, "You have to specify " - "--hashlimit-upto or --hashlimit-above"); - if (!(flags & PARAM_NAME)) - xtables_error(PARAMETER_PROBLEM, - "You have to specify --hashlimit-name"); } static const struct rates @@ -664,11 +503,11 @@ static struct xtables_match hashlimit_mt_reg[] = { .userspacesize = offsetof(struct xt_hashlimit_info, hinfo), .help = hashlimit_help, .init = hashlimit_init, - .parse = hashlimit_parse, - .final_check = hashlimit_check, + .x6_parse = hashlimit_parse, + .x6_fcheck = hashlimit_check, .print = hashlimit_print, .save = hashlimit_save, - .extra_opts = hashlimit_opts, + .x6_options = hashlimit_mt_opts, }, { .version = XTABLES_VERSION, @@ -679,11 +518,11 @@ static struct xtables_match hashlimit_mt_reg[] = { .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo), .help = hashlimit_mt_help, .init = hashlimit_mt4_init, - .parse = hashlimit_mt4_parse, - .final_check = hashlimit_mt_check, + .x6_parse = hashlimit_mt_parse, + .x6_fcheck = hashlimit_check, .print = hashlimit_mt4_print, .save = hashlimit_mt4_save, - .extra_opts = hashlimit_mt_opts, + .x6_options = hashlimit_mt_opts, }, { .version = XTABLES_VERSION, @@ -694,11 +533,11 @@ static struct xtables_match hashlimit_mt_reg[] = { .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo), .help = hashlimit_mt_help, .init = hashlimit_mt6_init, - .parse = hashlimit_mt6_parse, - .final_check = hashlimit_mt_check, + .x6_parse = hashlimit_mt_parse, + .x6_fcheck = hashlimit_check, .print = hashlimit_mt6_print, .save = hashlimit_mt6_save, - .extra_opts = hashlimit_mt_opts, + .x6_options = hashlimit_mt_opts, }, }; -- cgit v1.2.3 From 66266abd17adc9631f3769ef0b82968c0bac6f38 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 5 May 2011 14:19:25 +0200 Subject: libxtables: XTTYPE_HOSTMASK support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 3 +++ xtoptions.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/xtables.h.in b/include/xtables.h.in index 9bb42351..caaec2fa 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -61,6 +61,8 @@ struct in_addr; * %XTTYPE_MARKMASK32: 32-bit mark with optional mask * %XTTYPE_SYSLOGLEVEL: syslog level by name or number * %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr) + * %XTTYPE_HOSTMASK: one host or address, with an optional prefix length + * (ptr: union nf_inet_addr; only host portion is stored) * %XTTYPE_PORT: 16-bit port name or number * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian * %XTTYPE_PORTRC: colon-separated port range (names acceptable) @@ -84,6 +86,7 @@ enum xt_option_type { XTTYPE_MARKMASK32, XTTYPE_SYSLOGLEVEL, XTTYPE_HOST, + XTTYPE_HOSTMASK, XTTYPE_PORT, XTTYPE_PORT_NE, XTTYPE_PORTRC, diff --git a/xtoptions.c b/xtoptions.c index 3cc2e0cc..36f90e47 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -622,6 +622,33 @@ static void xtopt_parse_plenmask(struct xt_option_call *cb) memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr)); } +static void xtopt_parse_hostmask(struct xt_option_call *cb) +{ + const char *orig_arg = cb->arg; + char *work, *p; + + if (strchr(cb->arg, '/') == NULL) { + xtopt_parse_host(cb); + return; + } + work = strdup(orig_arg); + if (work == NULL) + xt_params->exit_err(PARAMETER_PROBLEM, "strdup"); + p = strchr(work, '/'); /* by def this can't be NULL now */ + *p++ = '\0'; + /* + * Because xtopt_parse_host and xtopt_parse_plenmask would store + * different things in the same target area, XTTYPE_HOSTMASK must + * disallow XTOPT_PUT, which it does by forcing its absence, + * cf. not being listed in xtopt_psize. + */ + cb->arg = work; + xtopt_parse_host(cb); + cb->arg = p; + xtopt_parse_plenmask(cb); + cb->arg = orig_arg; +} + static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_UINT8] = xtopt_parse_int, [XTTYPE_UINT16] = xtopt_parse_int, @@ -637,6 +664,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_MARKMASK32] = xtopt_parse_markmask, [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, [XTTYPE_HOST] = xtopt_parse_host, + [XTTYPE_HOSTMASK] = xtopt_parse_hostmask, [XTTYPE_PORT] = xtopt_parse_port, [XTTYPE_PORT_NE] = xtopt_parse_port, [XTTYPE_PORTRC] = xtopt_parse_mport, @@ -662,6 +690,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_STRING] = -1, [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), [XTTYPE_HOST] = sizeof(union nf_inet_addr), + [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), [XTTYPE_PORT] = sizeof(uint16_t), [XTTYPE_PORT_NE] = sizeof(uint16_t), [XTTYPE_PORTRC] = sizeof(uint16_t[2]), -- cgit v1.2.3 From d441ad6a68c5d65344449962f4648d297d453b6c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 6 May 2011 17:45:12 +0200 Subject: libxt_policy: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_policy.c | 269 +++++++++++++--------------------------------- 1 file changed, 73 insertions(+), 196 deletions(-) diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c index 16e8c535..a514246c 100644 --- a/extensions/libxt_policy.c +++ b/extensions/libxt_policy.c @@ -1,25 +1,23 @@ -/* Shared library add-on to iptables to add policy support. */ #include +#include #include -#include #include -#include -#include -#include #include -#include -#include -#include -#include #include - #include -/* - * HACK: global pointer to current matchinfo for making - * final checks and adjustments in final_check. - */ -static struct xt_policy_info *policy_info; +enum { + O_DIRECTION = 0, + O_POLICY, + O_STRICT, + O_REQID, + O_SPI, + O_PROTO, + O_MODE, + O_TUNNELSRC, + O_TUNNELDST, + O_NEXT +}; static void policy_help(void) { @@ -39,62 +37,22 @@ static void policy_help(void) " --next begin next element in policy\n"); } -static const struct option policy_opts[] = -{ - { - .name = "dir", - .has_arg = true, - .val = '1', - }, - { - .name = "pol", - .has_arg = true, - .val = '2', - }, - { - .name = "strict", - .has_arg = false, - .val = '3' - }, - { - .name = "reqid", - .has_arg = true, - .val = '4', - }, - { - .name = "spi", - .has_arg = true, - .val = '5' - }, - { - .name = "tunnel-src", - .has_arg = true, - .val = '6' - }, - { - .name = "tunnel-dst", - .has_arg = true, - .val = '7' - }, - { - .name = "proto", - .has_arg = true, - .val = '8' - }, - { - .name = "mode", - .has_arg = true, - .val = '9' - }, - { - .name = "next", - .has_arg = false, - .val = 'a' - }, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry policy_opts[] = { + {.name = "dir", .id = O_DIRECTION, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "pol", .id = O_POLICY, .type = XTTYPE_STRING}, + {.name = "strict", .id = O_STRICT, .type = XTTYPE_NONE}, + {.name = "reqid", .id = O_REQID, .type = XTTYPE_UINT32}, + {.name = "spi", .id = O_SPI, .type = XTTYPE_UINT32}, + {.name = "tunnel-src", .id = O_TUNNELSRC, .type = XTTYPE_HOSTMASK}, + {.name = "tunnel-dst", .id = O_TUNNELDST, .type = XTTYPE_HOSTMASK}, + {.name = "proto", .id = O_PROTO, .type = XTTYPE_STRING}, + {.name = "mode", .id = O_MODE, .type = XTTYPE_STRING}, + {.name = "next", .id = O_NEXT, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; -static int parse_direction(char *s) +static int parse_direction(const char *s) { if (strcmp(s, "in") == 0) return XT_POLICY_MATCH_IN; @@ -103,7 +61,7 @@ static int parse_direction(char *s) xtables_error(PARAMETER_PROBLEM, "policy_match: invalid dir \"%s\"", s); } -static int parse_policy(char *s) +static int parse_policy(const char *s) { if (strcmp(s, "none") == 0) return XT_POLICY_MATCH_NONE; @@ -112,7 +70,7 @@ static int parse_policy(char *s) xtables_error(PARAMETER_PROBLEM, "policy match: invalid policy \"%s\"", s); } -static int parse_mode(char *s) +static int parse_mode(const char *s) { if (strcmp(s, "transport") == 0) return XT_POLICY_MODE_TRANSPORT; @@ -121,176 +79,95 @@ static int parse_mode(char *s) xtables_error(PARAMETER_PROBLEM, "policy match: invalid mode \"%s\"", s); } -static int policy_parse(int c, char **argv, int invert, unsigned int *flags, - struct xt_policy_info *info, uint8_t family) +static void policy_parse(struct xt_option_call *cb) { + struct xt_policy_info *info = cb->data; struct xt_policy_elem *e = &info->pol[info->len]; - struct in_addr *addr = NULL, mask; - struct in6_addr *addr6 = NULL, mask6; - unsigned int naddr = 0, num; - int mode; - - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - switch (c) { - case '1': - if (info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT)) - xtables_error(PARAMETER_PROBLEM, - "policy match: double --dir option"); - if (invert) - xtables_error(PARAMETER_PROBLEM, - "policy match: can't invert --dir option"); - - info->flags |= parse_direction(optarg); + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_DIRECTION: + info->flags |= parse_direction(cb->arg); break; - case '2': - if (invert) - xtables_error(PARAMETER_PROBLEM, - "policy match: can't invert --policy option"); - - info->flags |= parse_policy(optarg); + case O_POLICY: + info->flags |= parse_policy(cb->arg); break; - case '3': - if (info->flags & XT_POLICY_MATCH_STRICT) - xtables_error(PARAMETER_PROBLEM, - "policy match: double --strict option"); - - if (invert) - xtables_error(PARAMETER_PROBLEM, - "policy match: can't invert --strict option"); - + case O_STRICT: info->flags |= XT_POLICY_MATCH_STRICT; break; - case '4': + case O_REQID: if (e->match.reqid) xtables_error(PARAMETER_PROBLEM, "policy match: double --reqid option"); - e->match.reqid = 1; - e->invert.reqid = invert; - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg); - e->reqid = num; + e->invert.reqid = cb->invert; + e->reqid = cb->val.u32; break; - case '5': + case O_SPI: if (e->match.spi) xtables_error(PARAMETER_PROBLEM, "policy match: double --spi option"); - e->match.spi = 1; - e->invert.spi = invert; - if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) - xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg); - e->spi = num; + e->invert.spi = cb->invert; + e->spi = cb->val.u32; break; - case '6': + case O_TUNNELSRC: if (e->match.saddr) xtables_error(PARAMETER_PROBLEM, "policy match: double --tunnel-src option"); - if (family == NFPROTO_IPV6) - xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr); - else - xtables_ipparse_any(optarg, &addr, &mask, &naddr); - if (naddr > 1) - xtables_error(PARAMETER_PROBLEM, - "policy match: name resolves to multiple IPs"); - e->match.saddr = 1; - e->invert.saddr = invert; - if (family == NFPROTO_IPV6) { - memcpy(&e->saddr.a6, addr6, sizeof(*addr6)); - memcpy(&e->smask.a6, &mask6, sizeof(mask6)); - } else { - e->saddr.a4 = addr[0]; - e->smask.a4 = mask; - } + e->invert.saddr = cb->invert; + memcpy(&e->saddr, &cb->val.haddr, sizeof(cb->val.haddr)); + memcpy(&e->smask, &cb->val.hmask, sizeof(cb->val.hmask)); break; - case '7': + case O_TUNNELDST: if (e->match.daddr) xtables_error(PARAMETER_PROBLEM, "policy match: double --tunnel-dst option"); - - if (family == NFPROTO_IPV6) - xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr); - else - xtables_ipparse_any(optarg, &addr, &mask, &naddr); - if (naddr > 1) - xtables_error(PARAMETER_PROBLEM, - "policy match: name resolves to multiple IPs"); - e->match.daddr = 1; - e->invert.daddr = invert; - if (family == NFPROTO_IPV6) { - memcpy(&e->daddr.a6, addr6, sizeof(*addr6)); - memcpy(&e->dmask.a6, &mask6, sizeof(mask6)); - } else { - e->daddr.a4 = addr[0]; - e->dmask.a4 = mask; - } + e->invert.daddr = cb->invert; + memcpy(&e->daddr, &cb->val.haddr, sizeof(cb->val.haddr)); + memcpy(&e->dmask, &cb->val.hmask, sizeof(cb->val.hmask)); break; - case '8': + case O_PROTO: if (e->match.proto) xtables_error(PARAMETER_PROBLEM, "policy match: double --proto option"); - - e->proto = xtables_parse_protocol(optarg); + e->proto = xtables_parse_protocol(cb->arg); if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP && e->proto != IPPROTO_COMP) xtables_error(PARAMETER_PROBLEM, - "policy match: protocol must ah/esp/ipcomp"); + "policy match: protocol must be ah/esp/ipcomp"); e->match.proto = 1; - e->invert.proto = invert; + e->invert.proto = cb->invert; break; - case '9': + case O_MODE: if (e->match.mode) xtables_error(PARAMETER_PROBLEM, "policy match: double --mode option"); - - mode = parse_mode(optarg); e->match.mode = 1; - e->invert.mode = invert; - e->mode = mode; + e->invert.mode = cb->invert; + e->mode = parse_mode(cb->arg); break; - case 'a': - if (invert) - xtables_error(PARAMETER_PROBLEM, - "policy match: can't invert --next option"); - + case O_NEXT: if (++info->len == XT_POLICY_MAX_ELEM) xtables_error(PARAMETER_PROBLEM, "policy match: maximum policy depth reached"); break; } - - policy_info = info; - return 1; -} - -static int policy4_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - return policy_parse(c, argv, invert, flags, (void *)(*match)->data, - NFPROTO_IPV4); } -static int policy6_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void policy_check(struct xt_fcheck_call *cb) { - return policy_parse(c, argv, invert, flags, (void *)(*match)->data, - NFPROTO_IPV6); -} - -static void policy_check(unsigned int flags) -{ - struct xt_policy_info *info = policy_info; - struct xt_policy_elem *e; + struct xt_policy_info *info = cb->data; + const struct xt_policy_elem *e; int i; - if (info == NULL) - xtables_error(PARAMETER_PROBLEM, - "policy match: no parameters given"); - + /* + * The old "no parameters given" check is carried out + * by testing for --dir. + */ if (!(info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT))) xtables_error(PARAMETER_PROBLEM, "policy match: neither --dir in nor --dir out specified"); @@ -487,11 +364,11 @@ static struct xtables_match policy_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_policy_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)), .help = policy_help, - .parse = policy4_parse, - .final_check = policy_check, + .x6_parse = policy_parse, + .x6_fcheck = policy_check, .print = policy4_print, .save = policy4_save, - .extra_opts = policy_opts, + .x6_options = policy_opts, }, { .name = "policy", @@ -500,11 +377,11 @@ static struct xtables_match policy_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_policy_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)), .help = policy_help, - .parse = policy6_parse, - .final_check = policy_check, + .x6_parse = policy_parse, + .x6_fcheck = policy_check, .print = policy6_print, .save = policy6_save, - .extra_opts = policy_opts, + .x6_options = policy_opts, }, }; -- cgit v1.2.3 From 21d243c3152f0798683aacbf95acfc8c1378924e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 6 May 2011 22:49:43 +0200 Subject: libxt_owner: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_owner.c | 288 +++++++++++++++++++---------------------------- 1 file changed, 117 insertions(+), 171 deletions(-) diff --git a/extensions/libxt_owner.c b/extensions/libxt_owner.c index f930cf45..b60f9071 100644 --- a/extensions/libxt_owner.c +++ b/extensions/libxt_owner.c @@ -4,16 +4,11 @@ * Copyright © CC Computer Consultants GmbH, 2007 - 2008 * Jan Engelhardt */ -#include #include -#include #include #include #include -#include -#include #include - #include #include @@ -55,12 +50,12 @@ struct ip6t_owner_info { */ enum { - FLAG_UID_OWNER = 1 << 0, - FLAG_GID_OWNER = 1 << 1, - FLAG_SOCKET_EXISTS = 1 << 2, - FLAG_PID_OWNER = 1 << 3, - FLAG_SID_OWNER = 1 << 4, - FLAG_COMM = 1 << 5, + O_USER = 0, + O_GROUP, + O_SOCK_EXISTS, + O_PROCESS, + O_SESSION, + O_COMM, }; static void owner_mt_help_v0(void) @@ -95,170 +90,134 @@ static void owner_mt_help(void) "[!] --socket-exists Match if socket exists\n"); } -static const struct option owner_mt_opts_v0[] = { - {.name = "uid-owner", .has_arg = true, .val = 'u'}, - {.name = "gid-owner", .has_arg = true, .val = 'g'}, - {.name = "pid-owner", .has_arg = true, .val = 'p'}, - {.name = "sid-owner", .has_arg = true, .val = 's'}, - {.name = "cmd-owner", .has_arg = true, .val = 'c'}, - XT_GETOPT_TABLEEND, +#define s struct ipt_owner_info +static const struct xt_option_entry owner_mt_opts_v0[] = { + {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid), + .max = INT_MAX}, + {.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid), + .max = INT_MAX}, + {.name = "cmd-owner", .id = O_COMM, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, comm)}, + XTOPT_TABLEEND, }; - -static const struct option owner_mt6_opts_v0[] = { - {.name = "uid-owner", .has_arg = true, .val = 'u'}, - {.name = "gid-owner", .has_arg = true, .val = 'g'}, - {.name = "pid-owner", .has_arg = true, .val = 'p'}, - {.name = "sid-owner", .has_arg = true, .val = 's'}, - XT_GETOPT_TABLEEND, +#undef s + +#define s struct ip6t_owner_info +static const struct xt_option_entry owner_mt6_opts_v0[] = { + {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid), + .max = INT_MAX}, + {.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid), + .max = INT_MAX}, + XTOPT_TABLEEND, }; +#undef s -static const struct option owner_mt_opts[] = { - {.name = "uid-owner", .has_arg = true, .val = 'u'}, - {.name = "gid-owner", .has_arg = true, .val = 'g'}, - {.name = "socket-exists", .has_arg = false, .val = 'k'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry owner_mt_opts[] = { + {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING}, + {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING}, + {.name = "socket-exists", .id = O_SOCK_EXISTS, .type = XTTYPE_NONE}, + XTOPT_TABLEEND, }; -static int -owner_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void owner_mt_parse_v0(struct xt_option_call *cb) { - struct ipt_owner_info *info = (void *)(*match)->data; + struct ipt_owner_info *info = cb->data; struct passwd *pwd; struct group *grp; unsigned int id; - switch (c) { - case 'u': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner", *flags & FLAG_UID_OWNER); - if ((pwd = getpwnam(optarg)) != NULL) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_USER: + if ((pwd = getpwnam(cb->arg)) != NULL) id = pwd->pw_uid; - else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg); - if (invert) + else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1)) + xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg); + if (cb->invert) info->invert |= IPT_OWNER_UID; info->match |= IPT_OWNER_UID; info->uid = id; - *flags |= FLAG_UID_OWNER; - return true; - - case 'g': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner", *flags & FLAG_GID_OWNER); - if ((grp = getgrnam(optarg)) != NULL) + break; + case O_GROUP: + if ((grp = getgrnam(cb->arg)) != NULL) id = grp->gr_gid; - else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg); - if (invert) + else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1)) + xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg); + if (cb->invert) info->invert |= IPT_OWNER_GID; info->match |= IPT_OWNER_GID; info->gid = id; - *flags |= FLAG_GID_OWNER; - return true; - - case 'p': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner", *flags & FLAG_PID_OWNER); - if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg); - if (invert) + break; + case O_PROCESS: + if (cb->invert) info->invert |= IPT_OWNER_PID; info->match |= IPT_OWNER_PID; - info->pid = id; - *flags |= FLAG_PID_OWNER; - return true; - - case 's': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner", *flags & FLAG_SID_OWNER); - if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-value", optarg); - if (invert) + break; + case O_SESSION: + if (cb->invert) info->invert |= IPT_OWNER_SID; info->match |= IPT_OWNER_SID; - info->sid = id; - *flags |= FLAG_SID_OWNER; - return true; - - case 'c': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--cmd-owner", *flags & FLAG_COMM); - if (strlen(optarg) > sizeof(info->comm)) - xtables_error(PARAMETER_PROBLEM, "owner match: command " - "\"%s\" too long, max. %zu characters", - optarg, sizeof(info->comm)); - - info->comm[sizeof(info->comm)-1] = '\0'; - strncpy(info->comm, optarg, sizeof(info->comm)); - - if (invert) + break; + case O_COMM: + if (cb->invert) info->invert |= IPT_OWNER_COMM; info->match |= IPT_OWNER_COMM; - *flags |= FLAG_COMM; - return true; + break; } - return false; } -static int -owner_mt6_parse_v0(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void owner_mt6_parse_v0(struct xt_option_call *cb) { - struct ip6t_owner_info *info = (void *)(*match)->data; + struct ip6t_owner_info *info = cb->data; struct passwd *pwd; struct group *grp; unsigned int id; - switch (c) { - case 'u': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner", - *flags & FLAG_UID_OWNER); - if ((pwd = getpwnam(optarg)) != NULL) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_USER: + if ((pwd = getpwnam(cb->arg)) != NULL) id = pwd->pw_uid; - else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg); - if (invert) + else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1)) + xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg); + if (cb->invert) info->invert |= IP6T_OWNER_UID; info->match |= IP6T_OWNER_UID; info->uid = id; - *flags |= FLAG_UID_OWNER; - return true; - - case 'g': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner", - *flags & FLAG_GID_OWNER); - if ((grp = getgrnam(optarg)) != NULL) + break; + case O_GROUP: + if ((grp = getgrnam(cb->arg)) != NULL) id = grp->gr_gid; - else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg); - if (invert) + else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1)) + xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg); + if (cb->invert) info->invert |= IP6T_OWNER_GID; info->match |= IP6T_OWNER_GID; info->gid = id; - *flags |= FLAG_GID_OWNER; - return true; - - case 'p': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner", - *flags & FLAG_PID_OWNER); - if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg); - if (invert) + break; + case O_PROCESS: + if (cb->invert) info->invert |= IP6T_OWNER_PID; info->match |= IP6T_OWNER_PID; - info->pid = id; - *flags |= FLAG_PID_OWNER; - return true; - - case 's': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner", - *flags & FLAG_SID_OWNER); - if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX)) - xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-owner", optarg); - if (invert) + break; + case O_SESSION: + if (cb->invert) info->invert |= IP6T_OWNER_SID; info->match |= IP6T_OWNER_SID; - info->sid = id; - *flags |= FLAG_SID_OWNER; - return true; + break; } - return false; } static void owner_parse_range(const char *s, unsigned int *from, @@ -277,61 +236,48 @@ static void owner_parse_range(const char *s, unsigned int *from, xtables_param_act(XTF_BAD_VALUE, "owner", opt, s); } -static int owner_mt_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void owner_mt_parse(struct xt_option_call *cb) { - struct xt_owner_match_info *info = (void *)(*match)->data; + struct xt_owner_match_info *info = cb->data; struct passwd *pwd; struct group *grp; unsigned int from, to; - switch (c) { - case 'u': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner", - *flags & FLAG_UID_OWNER); - if ((pwd = getpwnam(optarg)) != NULL) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_USER: + if ((pwd = getpwnam(cb->arg)) != NULL) from = to = pwd->pw_uid; else - owner_parse_range(optarg, &from, &to, "--uid-owner"); - if (invert) + owner_parse_range(cb->arg, &from, &to, "--uid-owner"); + if (cb->invert) info->invert |= XT_OWNER_UID; info->match |= XT_OWNER_UID; info->uid_min = from; info->uid_max = to; - *flags |= FLAG_UID_OWNER; - return true; - - case 'g': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner", - *flags & FLAG_GID_OWNER); - if ((grp = getgrnam(optarg)) != NULL) + break; + case O_GROUP: + if ((grp = getgrnam(cb->arg)) != NULL) from = to = grp->gr_gid; else - owner_parse_range(optarg, &from, &to, "--gid-owner"); - if (invert) + owner_parse_range(cb->arg, &from, &to, "--gid-owner"); + if (cb->invert) info->invert |= XT_OWNER_GID; info->match |= XT_OWNER_GID; info->gid_min = from; info->gid_max = to; - *flags |= FLAG_GID_OWNER; - return true; - - case 'k': - xtables_param_act(XTF_ONLY_ONCE, "owner", "--socket-exists", - *flags & FLAG_SOCKET_EXISTS); - if (invert) + break; + case O_SOCK_EXISTS: + if (cb->invert) info->invert |= XT_OWNER_SOCKET; info->match |= XT_OWNER_SOCKET; - *flags |= FLAG_SOCKET_EXISTS; - return true; - + break; } - return false; } -static void owner_mt_check(unsigned int flags) +static void owner_mt_check(struct xt_fcheck_call *cb) { - if (flags == 0) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "owner: At least one of " "--uid-owner, --gid-owner or --socket-exists " "is required"); @@ -552,11 +498,11 @@ static struct xtables_match owner_mt_reg[] = { .size = XT_ALIGN(sizeof(struct ipt_owner_info)), .userspacesize = XT_ALIGN(sizeof(struct ipt_owner_info)), .help = owner_mt_help_v0, - .parse = owner_mt_parse_v0, - .final_check = owner_mt_check, + .x6_parse = owner_mt_parse_v0, + .x6_fcheck = owner_mt_check, .print = owner_mt_print_v0, .save = owner_mt_save_v0, - .extra_opts = owner_mt_opts_v0, + .x6_options = owner_mt_opts_v0, }, { .version = XTABLES_VERSION, @@ -566,11 +512,11 @@ static struct xtables_match owner_mt_reg[] = { .size = XT_ALIGN(sizeof(struct ip6t_owner_info)), .userspacesize = XT_ALIGN(sizeof(struct ip6t_owner_info)), .help = owner_mt6_help_v0, - .parse = owner_mt6_parse_v0, - .final_check = owner_mt_check, + .x6_parse = owner_mt6_parse_v0, + .x6_fcheck = owner_mt_check, .print = owner_mt6_print_v0, .save = owner_mt6_save_v0, - .extra_opts = owner_mt6_opts_v0, + .x6_options = owner_mt6_opts_v0, }, { .version = XTABLES_VERSION, @@ -580,11 +526,11 @@ static struct xtables_match owner_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_owner_match_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_owner_match_info)), .help = owner_mt_help, - .parse = owner_mt_parse, - .final_check = owner_mt_check, + .x6_parse = owner_mt_parse, + .x6_fcheck = owner_mt_check, .print = owner_mt_print, .save = owner_mt_save, - .extra_opts = owner_mt_opts, + .x6_options = owner_mt_opts, }, }; -- cgit v1.2.3 From 94cd683a969e024ec870df258fafd790b8a1abf1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 6 May 2011 22:59:07 +0200 Subject: libxt_osf: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_osf.c | 97 +++++++++++++++----------------------------------- 1 file changed, 29 insertions(+), 68 deletions(-) diff --git a/extensions/libxt_osf.c b/extensions/libxt_osf.c index 20acfeab..88274a0e 100644 --- a/extensions/libxt_osf.c +++ b/extensions/libxt_osf.c @@ -20,23 +20,19 @@ /* * xtables interface for OS fingerprint matching module. */ -#include #include -#include #include -#include -#include -#include - -#include - #include - #include #include - #include +enum { + O_GENRE = 0, + O_TTL, + O_LOGLEVEL, +}; + static void osf_help(void) { printf("OS fingerprint match options:\n" @@ -52,71 +48,37 @@ static void osf_help(void) ); } - -static const struct option osf_opts[] = { - {.name = "genre", .has_arg = true, .val = '1'}, - {.name = "ttl", .has_arg = true, .val = '2'}, - {.name = "log", .has_arg = true, .val = '3'}, - XT_GETOPT_TABLEEND, +#define s struct xt_osf_info +static const struct xt_option_entry osf_opts[] = { + {.name = "genre", .id = O_GENRE, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT, + XTOPT_POINTER(s, genre)}, + {.name = "ttl", .id = O_TTL, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl), .min = 0, .max = 2}, + {.name = "log", .id = O_LOGLEVEL, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, loglevel), .min = 0, .max = 2}, + XTOPT_TABLEEND, }; +#undef s - -static void osf_parse_string(const char *s, struct xt_osf_info *info) +static void osf_parse(struct xt_option_call *cb) { - if (strlen(s) < MAXGENRELEN) - strcpy(info->genre, s); - else - xtables_error(PARAMETER_PROBLEM, - "Genre string too long `%s' [%zd], max=%d", - s, strlen(s), MAXGENRELEN); -} - -static int osf_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, - struct xt_entry_match **match) -{ - struct xt_osf_info *info = (struct xt_osf_info *)(*match)->data; + struct xt_osf_info *info = cb->data; - switch(c) { - case '1': /* --genre */ - if (*flags & XT_OSF_GENRE) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple genre parameter"); - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - osf_parse_string(argv[optind-1], info); - if (invert) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_GENRE: + if (cb->invert) info->flags |= XT_OSF_INVERT; - info->len=strlen(info->genre); - *flags |= XT_OSF_GENRE; + info->len = strlen(info->genre); break; - case '2': /* --ttl */ - if (*flags & XT_OSF_TTL) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple ttl parameter"); - *flags |= XT_OSF_TTL; + case O_TTL: info->flags |= XT_OSF_TTL; - if (!xtables_strtoui(argv[optind-1], NULL, &info->ttl, 0, 2)) - xtables_error(PARAMETER_PROBLEM, "TTL parameter is too big"); break; - case '3': /* --log */ - if (*flags & XT_OSF_LOG) - xtables_error(PARAMETER_PROBLEM, - "Can't specify multiple log parameter"); - *flags |= XT_OSF_LOG; - if (!xtables_strtoui(argv[optind-1], NULL, &info->loglevel, 0, 2)) - xtables_error(PARAMETER_PROBLEM, "Log level parameter is too big"); + case O_LOGLEVEL: info->flags |= XT_OSF_LOG; break; } - - return 1; -} - -static void osf_final_check(unsigned int flags) -{ - if (!(flags & XT_OSF_GENRE)) - xtables_error(PARAMETER_PROBLEM, - "OS fingerprint match: You must specify `--genre'"); } static void osf_print(const void *ip, const struct xt_entry_match *match, int numeric) @@ -139,12 +101,11 @@ static struct xtables_match osf_match = { .size = XT_ALIGN(sizeof(struct xt_osf_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_osf_info)), .help = osf_help, - .parse = osf_parse, + .x6_parse = osf_parse, .print = osf_print, - .final_check = osf_final_check, .save = osf_save, - .extra_opts = osf_opts, - .family = NFPROTO_IPV4 + .x6_options = osf_opts, + .family = NFPROTO_IPV4, }; void _init(void) -- cgit v1.2.3 From 87a34d7aef2cba833f4f36536575dee304bbece5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 7 May 2011 00:15:49 +0200 Subject: libxt_multiport: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_multiport.c | 178 ++++++++++++++++++------------------------- include/xtables.h.in | 2 + xtoptions.c | 2 + 3 files changed, 77 insertions(+), 105 deletions(-) diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c index 7fa537e0..03af5a96 100644 --- a/extensions/libxt_multiport.c +++ b/extensions/libxt_multiport.c @@ -1,19 +1,23 @@ -/* Shared library add-on to iptables to add multiple TCP port support. */ -#include #include #include #include #include -#include - #include -#include -#include #include /* INT_MAX in ip_tables.h/ip6_tables.h */ #include #include #include +enum { + O_SOURCE_PORTS = 0, + O_DEST_PORTS, + O_SD_PORTS, + F_SOURCE_PORTS = 1 << O_SOURCE_PORTS, + F_DEST_PORTS = 1 << O_DEST_PORTS, + F_SD_PORTS = 1 << O_SD_PORTS, + F_ANY = F_SOURCE_PORTS | F_DEST_PORTS | F_SD_PORTS, +}; + /* Function which prints out usage message. */ static void multiport_help(void) { @@ -44,13 +48,18 @@ static void multiport_help_v1(void) " match both source and destination port(s)\n"); } -static const struct option multiport_opts[] = { - {.name = "source-ports", .has_arg = true, .val = '1'}, - {.name = "sports", .has_arg = true, .val = '1'}, /* synonym */ - {.name = "destination-ports", .has_arg = true, .val = '2'}, - {.name = "dports", .has_arg = true, .val = '2'}, /* synonym */ - {.name = "ports", .has_arg = true, .val = '3'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry multiport_opts[] = { + {.name = "source-ports", .id = O_SOURCE_PORTS, .type = XTTYPE_STRING, + .excl = F_ANY, .flags = XTOPT_INVERT}, + {.name = "sports", .id = O_SOURCE_PORTS, .type = XTTYPE_STRING, + .excl = F_ANY, .flags = XTOPT_INVERT}, + {.name = "destination-ports", .id = O_DEST_PORTS, + .type = XTTYPE_STRING, .excl = F_ANY, .flags = XTOPT_INVERT}, + {.name = "dports", .id = O_DEST_PORTS, .type = XTTYPE_STRING, + .excl = F_ANY, .flags = XTOPT_INVERT}, + {.name = "ports", .id = O_SD_PORTS, .type = XTTYPE_STRING, + .excl = F_ANY, .flags = XTOPT_INVERT}, + XTOPT_TABLEEND, }; static const char * @@ -152,136 +161,97 @@ check_proto(uint16_t pnum, uint8_t invflags) "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP"); } -/* Function which parses command options; returns true if it - ate an option */ -static int -__multiport_parse(int c, char **argv, int invert, unsigned int *flags, - struct xt_entry_match **match, uint16_t pnum, - uint8_t invflags) +static void __multiport_parse(struct xt_option_call *cb, uint16_t pnum, + uint8_t invflags) { const char *proto; - struct xt_multiport *multiinfo - = (struct xt_multiport *)(*match)->data; + struct xt_multiport *multiinfo = cb->data; - switch (c) { - case '1': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SOURCE_PORTS: proto = check_proto(pnum, invflags); - multiinfo->count = parse_multi_ports(optarg, + multiinfo->count = parse_multi_ports(cb->arg, multiinfo->ports, proto); multiinfo->flags = XT_MULTIPORT_SOURCE; break; - - case '2': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); + case O_DEST_PORTS: proto = check_proto(pnum, invflags); - multiinfo->count = parse_multi_ports(optarg, + multiinfo->count = parse_multi_ports(cb->arg, multiinfo->ports, proto); multiinfo->flags = XT_MULTIPORT_DESTINATION; break; - - case '3': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); + case O_SD_PORTS: proto = check_proto(pnum, invflags); - multiinfo->count = parse_multi_ports(optarg, + multiinfo->count = parse_multi_ports(cb->arg, multiinfo->ports, proto); multiinfo->flags = XT_MULTIPORT_EITHER; break; } - - if (invert) + if (cb->invert) xtables_error(PARAMETER_PROBLEM, - "multiport does not support invert"); - - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "multiport can only have one option"); - *flags = 1; - return 1; + "multiport.0 does not support invert"); } -static int -multiport_parse(int c, char **argv, int invert, unsigned int *flags, - const void *e, struct xt_entry_match **match) +static void multiport_parse(struct xt_option_call *cb) { - const struct ipt_entry *entry = e; - return __multiport_parse(c, argv, invert, flags, match, + const struct ipt_entry *entry = cb->xt_entry; + return __multiport_parse(cb, entry->ip.proto, entry->ip.invflags); } -static int -multiport_parse6(int c, char **argv, int invert, unsigned int *flags, - const void *e, struct xt_entry_match **match) +static void multiport_parse6(struct xt_option_call *cb) { - const struct ip6t_entry *entry = e; - return __multiport_parse(c, argv, invert, flags, match, + const struct ip6t_entry *entry = cb->xt_entry; + return __multiport_parse(cb, entry->ipv6.proto, entry->ipv6.invflags); } -static int -__multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags, - struct xt_entry_match **match, uint16_t pnum, - uint8_t invflags) +static void __multiport_parse_v1(struct xt_option_call *cb, uint16_t pnum, + uint8_t invflags) { const char *proto; - struct xt_multiport_v1 *multiinfo - = (struct xt_multiport_v1 *)(*match)->data; + struct xt_multiport_v1 *multiinfo = cb->data; - switch (c) { - case '1': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_SOURCE_PORTS: proto = check_proto(pnum, invflags); - parse_multi_ports_v1(optarg, multiinfo, proto); + parse_multi_ports_v1(cb->arg, multiinfo, proto); multiinfo->flags = XT_MULTIPORT_SOURCE; break; - - case '2': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); + case O_DEST_PORTS: proto = check_proto(pnum, invflags); - parse_multi_ports_v1(optarg, multiinfo, proto); + parse_multi_ports_v1(cb->arg, multiinfo, proto); multiinfo->flags = XT_MULTIPORT_DESTINATION; break; - - case '3': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); + case O_SD_PORTS: proto = check_proto(pnum, invflags); - parse_multi_ports_v1(optarg, multiinfo, proto); + parse_multi_ports_v1(cb->arg, multiinfo, proto); multiinfo->flags = XT_MULTIPORT_EITHER; break; } - - if (invert) + if (cb->invert) multiinfo->invert = 1; - - if (*flags) - xtables_error(PARAMETER_PROBLEM, - "multiport can only have one option"); - *flags = 1; - return 1; } -static int -multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags, - const void *e, struct xt_entry_match **match) +static void multiport_parse_v1(struct xt_option_call *cb) { - const struct ipt_entry *entry = e; - return __multiport_parse_v1(c, argv, invert, flags, match, + const struct ipt_entry *entry = cb->xt_entry; + return __multiport_parse_v1(cb, entry->ip.proto, entry->ip.invflags); } -static int -multiport_parse6_v1(int c, char **argv, int invert, unsigned int *flags, - const void *e, struct xt_entry_match **match) +static void multiport_parse6_v1(struct xt_option_call *cb) { - const struct ip6t_entry *entry = e; - return __multiport_parse_v1(c, argv, invert, flags, match, + const struct ip6t_entry *entry = cb->xt_entry; + return __multiport_parse_v1(cb, entry->ipv6.proto, entry->ipv6.invflags); } -/* Final check; must specify something. */ -static void multiport_check(unsigned int flags) +static void multiport_check(struct xt_fcheck_call *cb) { - if (!flags) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "multiport expection an option"); } @@ -307,7 +277,6 @@ print_port(uint16_t port, uint8_t protocol, int numeric) printf("%s", service); } -/* Prints out the matchinfo. */ static void __multiport_print(const struct xt_entry_match *match, int numeric, uint16_t proto) @@ -410,7 +379,6 @@ static void multiport_print6_v1(const void *ip_void, __multiport_print_v1(match, numeric, ip->proto); } -/* Saves the union ipt_matchinfo in parsable form to stdout. */ static void __multiport_save(const struct xt_entry_match *match, uint16_t proto) { @@ -509,11 +477,11 @@ static struct xtables_match multiport_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_multiport)), .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)), .help = multiport_help, - .parse = multiport_parse, - .final_check = multiport_check, + .x6_parse = multiport_parse, + .x6_fcheck = multiport_check, .print = multiport_print, .save = multiport_save, - .extra_opts = multiport_opts, + .x6_options = multiport_opts, }, { .family = NFPROTO_IPV6, @@ -523,11 +491,11 @@ static struct xtables_match multiport_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_multiport)), .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)), .help = multiport_help, - .parse = multiport_parse6, - .final_check = multiport_check, + .x6_parse = multiport_parse6, + .x6_fcheck = multiport_check, .print = multiport_print6, .save = multiport_save6, - .extra_opts = multiport_opts, + .x6_options = multiport_opts, }, { .family = NFPROTO_IPV4, @@ -537,11 +505,11 @@ static struct xtables_match multiport_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_multiport_v1)), .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)), .help = multiport_help_v1, - .parse = multiport_parse_v1, - .final_check = multiport_check, + .x6_parse = multiport_parse_v1, + .x6_fcheck = multiport_check, .print = multiport_print_v1, .save = multiport_save_v1, - .extra_opts = multiport_opts, + .x6_options = multiport_opts, }, { .family = NFPROTO_IPV6, @@ -551,11 +519,11 @@ static struct xtables_match multiport_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_multiport_v1)), .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)), .help = multiport_help_v1, - .parse = multiport_parse6_v1, - .final_check = multiport_check, + .x6_parse = multiport_parse6_v1, + .x6_fcheck = multiport_check, .print = multiport_print6_v1, .save = multiport_save6_v1, - .extra_opts = multiport_opts, + .x6_options = multiport_opts, }, }; diff --git a/include/xtables.h.in b/include/xtables.h.in index caaec2fa..50aa414c 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -163,10 +163,12 @@ struct xt_option_call { uint32_t mark, mask; }; } val; + /* Wished for a world where the ones below were gone: */ union { struct xt_entry_match **match; struct xt_entry_target **target; }; + void *xt_entry; }; /** diff --git a/xtoptions.c b/xtoptions.c index 36f90e47..413de1b8 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -808,6 +808,7 @@ void xtables_option_tpcall(unsigned int c, char **argv, bool invert, cb.data = t->t->data; cb.xflags = t->tflags; cb.target = &t->t; + cb.xt_entry = fw; t->x6_parse(&cb); t->tflags = cb.xflags; } @@ -842,6 +843,7 @@ void xtables_option_mpcall(unsigned int c, char **argv, bool invert, cb.data = m->m->data; cb.xflags = m->mflags; cb.match = &m->m; + cb.xt_entry = fw; m->x6_parse(&cb); m->mflags = cb.xflags; } -- cgit v1.2.3 From ef7d2e845f72fd3a01c9d89e73c90de5dcca73a7 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 8 May 2011 21:12:46 +0200 Subject: libipt_NETMAP: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libipt_NETMAP.c | 106 +++++++-------------------------------------- 1 file changed, 16 insertions(+), 90 deletions(-) diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c index 0e85dec1..5c4471a9 100644 --- a/extensions/libipt_NETMAP.c +++ b/extensions/libipt_NETMAP.c @@ -1,7 +1,6 @@ /* Shared library add-on to iptables to add static NAT support. Author: Svenning Soerensen */ -#include #include #include #include @@ -12,9 +11,14 @@ #define MODULENAME "NETMAP" -static const struct option NETMAP_opts[] = { - {.name = "to", .has_arg = true, .val = '1'}, - XT_GETOPT_TABLEEND, +enum { + O_TO = 0, +}; + +static const struct xt_option_entry NETMAP_opts[] = { + {.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_MAND}, + XTOPT_TABLEEND, }; static void NETMAP_help(void) @@ -25,18 +29,6 @@ static void NETMAP_help(void) NETMAP_opts[0].name); } -static uint32_t -bits2netmask(int bits) -{ - uint32_t netmask, bm; - - if (bits >= 32 || bits < 0) - return(~0); - for (netmask = 0, bm = 0x80000000; bits; bits--, bm >>= 1) - netmask |= bm; - return htonl(netmask); -} - static int netmask2bits(uint32_t netmask) { @@ -57,82 +49,17 @@ static void NETMAP_init(struct xt_entry_target *t) /* Actually, it's 0, but it's ignored at the moment. */ mr->rangesize = 1; - } -/* Parses network address */ -static void -parse_to(char *arg, struct nf_nat_range *range) +static void NETMAP_parse(struct xt_option_call *cb) { - char *slash; - const struct in_addr *ip; - uint32_t netmask; - unsigned int bits; + struct nf_nat_multi_range *mr = cb->data; + struct nf_nat_range *range = &mr->range[0]; + xtables_option_parse(cb); range->flags |= IP_NAT_RANGE_MAP_IPS; - slash = strchr(arg, '/'); - if (slash) - *slash = '\0'; - - ip = xtables_numeric_to_ipaddr(arg); - if (!ip) - xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n", - arg); - range->min_ip = ip->s_addr; - if (slash) { - if (strchr(slash+1, '.')) { - ip = xtables_numeric_to_ipmask(slash+1); - if (!ip) - xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n", - slash+1); - netmask = ip->s_addr; - } - else { - if (!xtables_strtoui(slash+1, NULL, &bits, 0, 32)) - xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n", - slash+1); - netmask = bits2netmask(bits); - } - /* Don't allow /0 (/1 is probably insane, too) */ - if (netmask == 0) - xtables_error(PARAMETER_PROBLEM, "Netmask needed\n"); - } - else - netmask = ~0; - - if (range->min_ip & ~netmask) { - if (slash) - *slash = '/'; - xtables_error(PARAMETER_PROBLEM, "Bad network address \"%s\"\n", - arg); - } - range->max_ip = range->min_ip | ~netmask; -} - -static int NETMAP_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_target **target) -{ - struct nf_nat_multi_range *mr - = (struct nf_nat_multi_range *)(*target)->data; - - switch (c) { - case '1': - if (xtables_check_inverse(optarg, &invert, NULL, 0, argv)) - xtables_error(PARAMETER_PROBLEM, - "Unexpected `!' after --%s", NETMAP_opts[0].name); - - parse_to(optarg, &mr->range[0]); - *flags = 1; - return 1; - } - return 0; -} - -static void NETMAP_check(unsigned int flags) -{ - if (!flags) - xtables_error(PARAMETER_PROBLEM, - MODULENAME" needs --%s", NETMAP_opts[0].name); + range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip; + range->max_ip = range->min_ip | ~cb->val.hmask.ip; } static void NETMAP_print(const void *ip, const struct xt_entry_target *target, @@ -167,11 +94,10 @@ static struct xtables_target netmap_tg_reg = { .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)), .help = NETMAP_help, .init = NETMAP_init, - .parse = NETMAP_parse, - .final_check = NETMAP_check, + .x6_parse = NETMAP_parse, .print = NETMAP_print, .save = NETMAP_save, - .extra_opts = NETMAP_opts, + .x6_options = NETMAP_opts, }; void _init(void) -- cgit v1.2.3 From 0f77e2e40a498688f3d8f8a65bf74ce13db893b2 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 7 May 2011 03:26:08 +0200 Subject: libxt_limit: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_limit.c | 53 +++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c index c4ba58bb..b15b02f2 100644 --- a/extensions/libxt_limit.c +++ b/extensions/libxt_limit.c @@ -3,20 +3,21 @@ * Jérôme de Vivie * Hervé Eychenne */ -#include #include #include #include -#include #include -#include #include -/* For 64bit kernel / 32bit userspace */ #include #define XT_LIMIT_AVG "3/hour" #define XT_LIMIT_BURST 5 +enum { + O_LIMIT = 0, + O_BURST, +}; + static void limit_help(void) { printf( @@ -28,10 +29,12 @@ static void limit_help(void) XT_LIMIT_BURST); } -static const struct option limit_opts[] = { - {.name = "limit", .has_arg = true, .val = '%'}, - {.name = "limit-burst", .has_arg = true, .val = '$'}, - XT_GETOPT_TABLEEND, +static const struct xt_option_entry limit_opts[] = { + {.name = "limit", .id = O_LIMIT, .type = XTTYPE_STRING}, + {.name = "limit-burst", .id = O_BURST, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_rateinfo, burst), + .min = 0, .max = 10000}, + XTOPT_TABLEEND, }; static @@ -85,35 +88,21 @@ static void limit_init(struct xt_entry_match *m) "Sorry: burst too large for that avg rate.\n"); */ -static int -limit_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void limit_parse(struct xt_option_call *cb) { - struct xt_rateinfo *r = (struct xt_rateinfo *)(*match)->data; - unsigned int num; - - switch(c) { - case '%': - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!parse_rate(optarg, &r->avg)) - xtables_error(PARAMETER_PROBLEM, - "bad rate `%s'", optarg); - break; + struct xt_rateinfo *r = cb->data; - case '$': - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break; - if (!xtables_strtoui(optarg, NULL, &num, 0, 10000)) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_LIMIT: + if (!parse_rate(cb->arg, &r->avg)) xtables_error(PARAMETER_PROBLEM, - "bad --limit-burst `%s'", optarg); - r->burst = num; + "bad rate \"%s\"'", cb->arg); break; } - - if (invert) + if (cb->invert) xtables_error(PARAMETER_PROBLEM, "limit does not support invert"); - - return 1; } static const struct rates @@ -162,10 +151,10 @@ static struct xtables_match limit_match = { .userspacesize = offsetof(struct xt_rateinfo, prev), .help = limit_help, .init = limit_init, - .parse = limit_parse, + .x6_parse = limit_parse, .print = limit_print, .save = limit_save, - .extra_opts = limit_opts, + .x6_options = limit_opts, }; void _init(void) -- cgit v1.2.3 From 170cf49a630fd0d237818b537c01794dde00b07a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 7 May 2011 12:56:39 +0200 Subject: libxtables: XTTYPE_PROTOCOL support Signed-off-by: Jan Engelhardt --- include/xtables.h.in | 4 +++- xtoptions.c | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/xtables.h.in b/include/xtables.h.in index 50aa414c..c3996a09 100644 --- a/include/xtables.h.in +++ b/include/xtables.h.in @@ -63,6 +63,7 @@ struct in_addr; * %XTTYPE_HOST: one host or address (ptr: union nf_inet_addr) * %XTTYPE_HOSTMASK: one host or address, with an optional prefix length * (ptr: union nf_inet_addr; only host portion is stored) + * %XTTYPE_PROTOCOL: protocol number/name from /etc/protocols (ptr: uint8_t) * %XTTYPE_PORT: 16-bit port name or number * %XTTYPE_PORT_NE: 16-bit port name or number, stored as network-endian * %XTTYPE_PORTRC: colon-separated port range (names acceptable) @@ -87,6 +88,7 @@ enum xt_option_type { XTTYPE_SYSLOGLEVEL, XTTYPE_HOST, XTTYPE_HOSTMASK, + XTTYPE_PROTOCOL, XTTYPE_PORT, XTTYPE_PORT_NE, XTTYPE_PORTRC, @@ -147,7 +149,7 @@ struct xt_option_call { bool invert; uint8_t nvals; union { - uint8_t u8, u8_range[2], syslog_level; + uint8_t u8, u8_range[2], syslog_level, protocol; uint16_t u16, u16_range[2], port, port_range[2]; uint32_t u32, u32_range[2]; uint64_t u64, u64_range[2]; diff --git a/xtoptions.c b/xtoptions.c index 413de1b8..70370edb 100644 --- a/xtoptions.c +++ b/xtoptions.c @@ -492,6 +492,29 @@ static int xtables_getportbyname(const char *name) return ntohs(ret); } +/** + * Validate and parse a protocol specification (number or name) by use of + * /etc/protocols and put the result into @cb->val.protocol. + */ +static void xtopt_parse_protocol(struct xt_option_call *cb) +{ + const struct protoent *entry; + unsigned int value = -1; + + if (xtables_strtoui(cb->arg, NULL, &value, 0, UINT8_MAX)) { + cb->val.protocol = value; + return; + } + entry = getprotobyname(cb->arg); + if (entry == NULL) + xt_params->exit_err(PARAMETER_PROBLEM, + "Protocol \"%s\" does not resolve to anything.\n", + cb->arg); + cb->val.protocol = entry->p_proto; + if (cb->entry->flags & XTOPT_PUT) + *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol; +} + /** * Validate and parse a port specification and put the result into * @cb->val.port. @@ -665,6 +688,7 @@ static void (*const xtopt_subparse[])(struct xt_option_call *) = { [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel, [XTTYPE_HOST] = xtopt_parse_host, [XTTYPE_HOSTMASK] = xtopt_parse_hostmask, + [XTTYPE_PROTOCOL] = xtopt_parse_protocol, [XTTYPE_PORT] = xtopt_parse_port, [XTTYPE_PORT_NE] = xtopt_parse_port, [XTTYPE_PORTRC] = xtopt_parse_mport, @@ -691,6 +715,7 @@ static const size_t xtopt_psize[] = { [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t), [XTTYPE_HOST] = sizeof(union nf_inet_addr), [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr), + [XTTYPE_PROTOCOL] = sizeof(uint8_t), [XTTYPE_PORT] = sizeof(uint16_t), [XTTYPE_PORT_NE] = sizeof(uint16_t), [XTTYPE_PORTRC] = sizeof(uint16_t[2]), -- cgit v1.2.3 From 372203af4c70fb20bc7ff3a49788b9bbf57d2eb1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 7 May 2011 13:03:06 +0200 Subject: libxt_ipvs: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_ipvs.c | 208 +++++++++++++++--------------------------------- 1 file changed, 65 insertions(+), 143 deletions(-) diff --git a/extensions/libxt_ipvs.c b/extensions/libxt_ipvs.c index 89303a11..88d235f6 100644 --- a/extensions/libxt_ipvs.c +++ b/extensions/libxt_ipvs.c @@ -5,31 +5,43 @@ * * Author: Hannes Eder */ -#include -#include -#include -#include -#include -#include #include -#include #include #include #include #include #include -static const struct option ipvs_mt_opts[] = { - { .name = "ipvs", .has_arg = false, .val = '0' }, - { .name = "vproto", .has_arg = true, .val = '1' }, - { .name = "vaddr", .has_arg = true, .val = '2' }, - { .name = "vport", .has_arg = true, .val = '3' }, - { .name = "vdir", .has_arg = true, .val = '4' }, - { .name = "vmethod", .has_arg = true, .val = '5' }, - { .name = "vportctl", .has_arg = true, .val = '6' }, - XT_GETOPT_TABLEEND, +enum { + /* For xt_ipvs: make sure this matches up with %XT_IPVS_*'s order */ + O_IPVS = 0, + O_VPROTO, + O_VADDR, + O_VPORT, + O_VDIR, + O_VMETHOD, + O_VPORTCTL, }; +#define s struct xt_ipvs_mtinfo +static const struct xt_option_entry ipvs_mt_opts[] = { + {.name = "ipvs", .id = O_IPVS, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, + {.name = "vproto", .id = O_VPROTO, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, l4proto)}, + {.name = "vaddr", .id = O_VADDR, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "vport", .id = O_VPORT, .type = XTTYPE_PORT, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vport)}, + {.name = "vdir", .id = O_VDIR, .type = XTTYPE_STRING}, + {.name = "vmethod", .id = O_VMETHOD, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "vportctl", .id = O_VPORTCTL, .type = XTTYPE_PORT, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vportctl)}, + XTOPT_TABLEEND, +}; +#undef s + static void ipvs_mt_help(void) { printf( @@ -49,152 +61,62 @@ static void ipvs_mt_help(void) ); } -static void ipvs_mt_parse_addr_and_mask(const char *arg, - union nf_inet_addr *address, - union nf_inet_addr *mask, - unsigned int family) -{ - struct in_addr *addr = NULL; - struct in6_addr *addr6 = NULL; - unsigned int naddrs = 0; - - if (family == NFPROTO_IPV4) { - xtables_ipparse_any(arg, &addr, &mask->in, &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&address->in, addr, sizeof(*addr)); - } else if (family == NFPROTO_IPV6) { - xtables_ip6parse_any(arg, &addr6, &mask->in6, &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&address->in6, addr6, sizeof(*addr6)); - } else { - /* Hu? */ - assert(false); - } -} - -/* Function which parses command options; returns true if it ate an option */ -static int ipvs_mt_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match, - unsigned int family) +static void ipvs_mt_parse(struct xt_option_call *cb) { - struct xt_ipvs_mtinfo *data = (void *)(*match)->data; - char *p = NULL; - uint8_t op = 0; - - if ('0' <= c && c <= '6') { - static const int ops[] = { - XT_IPVS_IPVS_PROPERTY, - XT_IPVS_PROTO, - XT_IPVS_VADDR, - XT_IPVS_VPORT, - XT_IPVS_DIR, - XT_IPVS_METHOD, - XT_IPVS_VPORTCTL - }; - op = ops[c - '0']; - } else - return 0; - - if (*flags & op & XT_IPVS_ONCE_MASK) - goto multiple_use; - - switch (c) { - case '0': /* --ipvs */ - /* Nothing to do here. */ - break; + struct xt_ipvs_mtinfo *data = cb->data; - case '1': /* --vproto */ - /* Canonicalize into lower case */ - for (p = optarg; *p != '\0'; ++p) - *p = tolower(*p); - - data->l4proto = xtables_parse_protocol(optarg); + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_VPROTO: + data->l4proto = cb->val.protocol; break; - - case '2': /* --vaddr */ - ipvs_mt_parse_addr_and_mask(optarg, &data->vaddr, - &data->vmask, family); + case O_VADDR: + memcpy(&data->vaddr, &cb->val.haddr, sizeof(cb->val.haddr)); + memcpy(&data->vmask, &cb->val.hmask, sizeof(cb->val.hmask)); break; - - case '3': /* --vport */ - data->vport = htons(xtables_parse_port(optarg, "tcp")); - break; - - case '4': /* --vdir */ - xtables_param_act(XTF_NO_INVERT, "ipvs", "--vdir", invert); - if (strcasecmp(optarg, "ORIGINAL") == 0) { + case O_VDIR: + if (strcasecmp(cb->arg, "ORIGINAL") == 0) { data->bitmask |= XT_IPVS_DIR; data->invert &= ~XT_IPVS_DIR; - } else if (strcasecmp(optarg, "REPLY") == 0) { + } else if (strcasecmp(cb->arg, "REPLY") == 0) { data->bitmask |= XT_IPVS_DIR; data->invert |= XT_IPVS_DIR; } else { xtables_param_act(XTF_BAD_VALUE, - "ipvs", "--vdir", optarg); + "ipvs", "--vdir", cb->arg); } break; - - case '5': /* --vmethod */ - if (strcasecmp(optarg, "GATE") == 0) + case O_VMETHOD: + if (strcasecmp(cb->arg, "GATE") == 0) data->fwd_method = IP_VS_CONN_F_DROUTE; - else if (strcasecmp(optarg, "IPIP") == 0) + else if (strcasecmp(cb->arg, "IPIP") == 0) data->fwd_method = IP_VS_CONN_F_TUNNEL; - else if (strcasecmp(optarg, "MASQ") == 0) + else if (strcasecmp(cb->arg, "MASQ") == 0) data->fwd_method = IP_VS_CONN_F_MASQ; else xtables_param_act(XTF_BAD_VALUE, - "ipvs", "--vmethod", optarg); - break; - - case '6': /* --vportctl */ - data->vportctl = htons(xtables_parse_port(optarg, "tcp")); + "ipvs", "--vmethod", cb->arg); break; } - - if (op & XT_IPVS_ONCE_MASK) { - if (data->invert & XT_IPVS_IPVS_PROPERTY) - xtables_error(PARAMETER_PROBLEM, - "! --ipvs cannot be together with" - " other options"); - data->bitmask |= XT_IPVS_IPVS_PROPERTY; - } - - data->bitmask |= op; - if (invert) - data->invert |= op; - *flags |= op; - return 1; - -multiple_use: - xtables_error(PARAMETER_PROBLEM, - "multiple use of the same IPVS option is not allowed"); + data->bitmask |= 1 << cb->entry->id; + if (cb->invert) + data->invert |= 1 << cb->entry->id; } -static int ipvs_mt4_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void ipvs_mt_check(struct xt_fcheck_call *cb) { - return ipvs_mt_parse(c, argv, invert, flags, entry, match, - NFPROTO_IPV4); -} - -static int ipvs_mt6_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - return ipvs_mt_parse(c, argv, invert, flags, entry, match, - NFPROTO_IPV6); -} + struct xt_ipvs_mtinfo *info = cb->data; -static void ipvs_mt_check(unsigned int flags) -{ - if (flags == 0) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "IPVS: At least one option is required"); + if (info->bitmask & XT_IPVS_ONCE_MASK) { + if (info->invert & XT_IPVS_IPVS_PROPERTY) + xtables_error(PARAMETER_PROBLEM, + "! --ipvs cannot be together with" + " other options"); + info->bitmask |= XT_IPVS_IPVS_PROPERTY; + } } /* Shamelessly copied from libxt_conntrack.c */ @@ -332,11 +254,11 @@ static struct xtables_match ipvs_matches_reg[] = { .size = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)), .userspacesize = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)), .help = ipvs_mt_help, - .parse = ipvs_mt4_parse, - .final_check = ipvs_mt_check, + .x6_parse = ipvs_mt_parse, + .x6_fcheck = ipvs_mt_check, .print = ipvs_mt4_print, .save = ipvs_mt4_save, - .extra_opts = ipvs_mt_opts, + .x6_options = ipvs_mt_opts, }, { .version = XTABLES_VERSION, @@ -346,11 +268,11 @@ static struct xtables_match ipvs_matches_reg[] = { .size = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)), .userspacesize = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)), .help = ipvs_mt_help, - .parse = ipvs_mt6_parse, - .final_check = ipvs_mt_check, + .x6_parse = ipvs_mt_parse, + .x6_fcheck = ipvs_mt_check, .print = ipvs_mt6_print, .save = ipvs_mt6_save, - .extra_opts = ipvs_mt_opts, + .x6_options = ipvs_mt_opts, }, }; -- cgit v1.2.3 From 73425492d4c57d34a616d948666ac75ecc612eed Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 8 May 2011 12:15:49 +0200 Subject: libxt_conntrack: use guided option parser Signed-off-by: Jan Engelhardt --- extensions/libxt_conntrack.c | 670 ++++++++++++++----------------------------- 1 file changed, 219 insertions(+), 451 deletions(-) diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index 8312d042..2fb3644d 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -6,21 +6,14 @@ * Copyright © CC Computer Consultants GmbH, 2007 - 2008 * Jan Engelhardt */ -#include -#include -#include -#include -#include #include -#include +#include #include #include #include #include -#include #include #include -#include struct ip_conntrack_old_tuple { struct { @@ -55,6 +48,22 @@ struct xt_conntrack_info { uint8_t invflags; }; +enum { + O_CTSTATE = 0, + O_CTPROTO, + O_CTORIGSRC, + O_CTORIGDST, + O_CTREPLSRC, + O_CTREPLDST, + O_CTORIGSRCPORT, + O_CTORIGDSTPORT, + O_CTREPLSRCPORT, + O_CTREPLDSTPORT, + O_CTSTATUS, + O_CTEXPIRE, + O_CTDIR, +}; + static void conntrack_mt_help(void) { printf( @@ -79,34 +88,59 @@ static void conntrack_mt_help(void) " --ctdir {ORIGINAL|REPLY} Flow direction of packet\n"); } -static const struct option conntrack_mt_opts_v0[] = { - {.name = "ctstate", .has_arg = true, .val = '1'}, - {.name = "ctproto", .has_arg = true, .val = '2'}, - {.name = "ctorigsrc", .has_arg = true, .val = '3'}, - {.name = "ctorigdst", .has_arg = true, .val = '4'}, - {.name = "ctreplsrc", .has_arg = true, .val = '5'}, - {.name = "ctrepldst", .has_arg = true, .val = '6'}, - {.name = "ctstatus", .has_arg = true, .val = '7'}, - {.name = "ctexpire", .has_arg = true, .val = '8'}, - XT_GETOPT_TABLEEND, +#define s struct xt_conntrack_info /* for v0 */ +static const struct xt_option_entry conntrack_mt_opts_v0[] = { + {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, + .flags = XTOPT_INVERT}, + {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOST, + .flags = XTOPT_INVERT}, + {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOST, + .flags = XTOPT_INVERT}, + {.name = "ctreplsrc", .id = O_CTREPLSRC, .type = XTTYPE_HOST, + .flags = XTOPT_INVERT}, + {.name = "ctrepldst", .id = O_CTREPLDST, .type = XTTYPE_HOST, + .flags = XTOPT_INVERT}, + {.name = "ctstatus", .id = O_CTSTATUS, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC, + .flags = XTOPT_INVERT}, + XTOPT_TABLEEND, }; - -static const struct option conntrack_mt_opts[] = { - {.name = "ctstate", .has_arg = true, .val = '1'}, - {.name = "ctproto", .has_arg = true, .val = '2'}, - {.name = "ctorigsrc", .has_arg = true, .val = '3'}, - {.name = "ctorigdst", .has_arg = true, .val = '4'}, - {.name = "ctreplsrc", .has_arg = true, .val = '5'}, - {.name = "ctrepldst", .has_arg = true, .val = '6'}, - {.name = "ctstatus", .has_arg = true, .val = '7'}, - {.name = "ctexpire", .has_arg = true, .val = '8'}, - {.name = "ctorigsrcport", .has_arg = true, .val = 'a'}, - {.name = "ctorigdstport", .has_arg = true, .val = 'b'}, - {.name = "ctreplsrcport", .has_arg = true, .val = 'c'}, - {.name = "ctrepldstport", .has_arg = true, .val = 'd'}, - {.name = "ctdir", .has_arg = true, .val = 'e'}, - {.name = NULL}, +#undef s + +#define s struct xt_conntrack_mtinfo3 /* for v1-v3 */ +/* We exploit the fact that v1-v3 share the same layout */ +static const struct xt_option_entry conntrack_mt_opts[] = { + {.name = "ctstate", .id = O_CTSTATE, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "ctproto", .id = O_CTPROTO, .type = XTTYPE_PROTOCOL, + .flags = XTOPT_INVERT}, + {.name = "ctorigsrc", .id = O_CTORIGSRC, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctorigdst", .id = O_CTORIGDST, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctreplsrc", .id = O_CTREPLSRC, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctrepldst", .id = O_CTREPLDST, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, + {.name = "ctstatus", .id = O_CTSTATUS, .type = XTTYPE_STRING, + .flags = XTOPT_INVERT}, + {.name = "ctexpire", .id = O_CTEXPIRE, .type = XTTYPE_UINT32RC, + .flags = XTOPT_INVERT}, + {.name = "ctorigsrcport", .id = O_CTORIGSRCPORT, .type = XTTYPE_PORTRC, + .flags = XTOPT_INVERT}, + {.name = "ctorigdstport", .id = O_CTORIGDSTPORT, .type = XTTYPE_PORTRC, + .flags = XTOPT_INVERT}, + {.name = "ctreplsrcport", .id = O_CTREPLSRCPORT, .type = XTTYPE_PORTRC, + .flags = XTOPT_INVERT}, + {.name = "ctrepldstport", .id = O_CTREPLDSTPORT, .type = XTTYPE_PORTRC, + .flags = XTOPT_INVERT}, + {.name = "ctdir", .id = O_CTDIR, .type = XTTYPE_STRING}, + XTOPT_TABLEEND, }; +#undef s static int parse_state(const char *state, size_t len, struct xt_conntrack_info *sinfo) @@ -320,39 +354,21 @@ conntrack_ps_expires(struct xt_conntrack_mtinfo3 *info, const char *s) info->expires_max = max; } -static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void conntrack_parse(struct xt_option_call *cb) { - struct xt_conntrack_info *sinfo = (void *)(*match)->data; - char *protocol = NULL; - unsigned int naddrs = 0; - struct in_addr *addrs = NULL; + struct xt_conntrack_info *sinfo = cb->data; - - switch (c) { - case '1': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - parse_states(optarg, sinfo); - if (invert) { + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_CTSTATE: + parse_states(cb->arg, sinfo); + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_STATE; - } - sinfo->flags |= XT_CONNTRACK_STATE; break; - - case '2': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - if(invert) + case O_CTPROTO: + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_PROTO; - - /* Canonicalize into lower case */ - for (protocol = optarg; *protocol; protocol++) - *protocol = tolower(*protocol); - - protocol = optarg; - sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = - xtables_parse_protocol(protocol); + sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = cb->val.protocol; if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0 && (sinfo->invflags & XT_INV_PROTO)) @@ -361,390 +377,151 @@ static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags, sinfo->flags |= XT_CONNTRACK_PROTO; break; - - case '3': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - if (invert) + case O_CTORIGSRC: + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_ORIGSRC; - - xtables_ipparse_any(optarg, &addrs, - &sinfo->sipmsk[IP_CT_DIR_ORIGINAL], - &naddrs); - if(naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - - if(naddrs == 1) { - sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr; - } - + sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = cb->val.haddr.ip; sinfo->flags |= XT_CONNTRACK_ORIGSRC; break; - - case '4': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - if (invert) + case O_CTORIGDST: + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_ORIGDST; - - xtables_ipparse_any(optarg, &addrs, - &sinfo->dipmsk[IP_CT_DIR_ORIGINAL], - &naddrs); - if(naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - - if(naddrs == 1) { - sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr; - } - + sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = cb->val.haddr.ip; sinfo->flags |= XT_CONNTRACK_ORIGDST; break; - - case '5': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - if (invert) + case O_CTREPLSRC: + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_REPLSRC; - - xtables_ipparse_any(optarg, &addrs, - &sinfo->sipmsk[IP_CT_DIR_REPLY], - &naddrs); - if(naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - - if(naddrs == 1) { - sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr; - } - + sinfo->tuple[IP_CT_DIR_REPLY].src.ip = cb->val.haddr.ip; sinfo->flags |= XT_CONNTRACK_REPLSRC; break; - - case '6': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - if (invert) + case O_CTREPLDST: + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_REPLDST; - - xtables_ipparse_any(optarg, &addrs, - &sinfo->dipmsk[IP_CT_DIR_REPLY], - &naddrs); - if(naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - - if(naddrs == 1) { - sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr; - } - + sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = cb->val.haddr.ip; sinfo->flags |= XT_CONNTRACK_REPLDST; break; - - case '7': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - parse_statuses(optarg, sinfo); - if (invert) { + case O_CTSTATUS: + parse_statuses(cb->arg, sinfo); + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_STATUS; - } sinfo->flags |= XT_CONNTRACK_STATUS; break; - - case '8': - xtables_check_inverse(optarg, &invert, &optind, 0, argv); - - parse_expires(optarg, sinfo); - if (invert) { + case O_CTEXPIRE: + parse_expires(cb->arg, sinfo); + if (cb->invert) sinfo->invflags |= XT_CONNTRACK_EXPIRES; - } sinfo->flags |= XT_CONNTRACK_EXPIRES; break; } - - *flags = sinfo->flags; - return 1; } -static void -ct_parse_ports(const char *param, const char *str, - u_int16_t *port_low, u_int16_t *port_high) +static void conntrack_mt_parse(struct xt_option_call *cb, uint8_t rev) { - unsigned int port; - char *buf, *cp; + struct xt_conntrack_mtinfo3 *info = cb->data; - buf = strdup(str); - cp = strchr(buf, ':'); - if (cp != NULL) - *cp = '\0'; - - if (!xtables_strtoui(buf, NULL, &port, 0, UINT16_MAX)) - xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf); - - if (port_high == NULL) { - /* revision 0-2 do not support ranges */ - if (cp != NULL) - xtables_error(PARAMETER_PROBLEM, "conntrack: " - "port ranges not supported"); - - *port_low = htons(port); - } else { - *port_low = port; - - if (cp != NULL) { - if (!xtables_strtoui(cp + 1, NULL, &port, 0, UINT16_MAX)) - xtables_param_act(XTF_BAD_VALUE, "conntrack", param, buf); - - *port_high = port; - if (*port_low > *port_high) - xtables_error(PARAMETER_PROBLEM, - "invalid portrange (min > max)"); - } else - *port_high = port; - } - - free(buf); -} - - -static int -conntrack_mt_parse(int c, bool invert, unsigned int *flags, - struct xt_conntrack_mtinfo3 *info, bool v3) -{ - char *p; - - switch (c) { - case '1': /* --ctstate */ - conntrack_ps_states(info, optarg); + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_CTSTATE: + conntrack_ps_states(info, cb->arg); info->match_flags |= XT_CONNTRACK_STATE; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_STATE; break; - - case '2': /* --ctproto */ - /* Canonicalize into lower case */ - for (p = optarg; *p != '\0'; ++p) - *p = tolower(*p); - info->l4proto = xtables_parse_protocol(optarg); - + case O_CTPROTO: + info->l4proto = cb->val.protocol; if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO)) xtables_error(PARAMETER_PROBLEM, "conntrack: rule would " "never match protocol"); info->match_flags |= XT_CONNTRACK_PROTO; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_PROTO; break; - - case '7': /* --ctstatus */ - conntrack_ps_statuses(info, optarg); + case O_CTORIGSRC: + info->origsrc_addr = cb->val.haddr; + info->origsrc_mask = cb->val.hmask; + info->match_flags |= XT_CONNTRACK_ORIGSRC; + if (cb->invert) + info->invert_flags |= XT_CONNTRACK_ORIGSRC; + break; + case O_CTORIGDST: + info->origdst_addr = cb->val.haddr; + info->origdst_mask = cb->val.hmask; + info->match_flags |= XT_CONNTRACK_ORIGDST; + if (cb->invert) + info->invert_flags |= XT_CONNTRACK_ORIGDST; + break; + case O_CTREPLSRC: + info->replsrc_addr = cb->val.haddr; + info->replsrc_mask = cb->val.hmask; + info->match_flags |= XT_CONNTRACK_REPLSRC; + if (cb->invert) + info->invert_flags |= XT_CONNTRACK_REPLSRC; + break; + case O_CTREPLDST: + info->repldst_addr = cb->val.haddr; + info->repldst_mask = cb->val.hmask; + info->match_flags |= XT_CONNTRACK_REPLDST; + if (cb->invert) + info->invert_flags |= XT_CONNTRACK_REPLDST; + break; + case O_CTSTATUS: + conntrack_ps_statuses(info, cb->arg); info->match_flags |= XT_CONNTRACK_STATUS; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_STATUS; break; - - case '8': /* --ctexpire */ - conntrack_ps_expires(info, optarg); + case O_CTEXPIRE: + conntrack_ps_expires(info, cb->arg); info->match_flags |= XT_CONNTRACK_EXPIRES; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_EXPIRES; break; - - case 'a': /* --ctorigsrcport */ - ct_parse_ports("--ctorigsrcport", optarg, - &info->origsrc_port, - v3 ? &info->origsrc_port_high : NULL); - + case O_CTORIGSRCPORT: + info->origsrc_port = cb->val.port_range[0]; + info->origsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] : + cb->val.port_range[0]; info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT; break; - - case 'b': /* --ctorigdstport */ - ct_parse_ports("--ctorigdstport", optarg, - &info->origdst_port, - v3 ? &info->origdst_port_high : NULL); - + case O_CTORIGDSTPORT: + info->origdst_port = cb->val.port_range[0]; + info->origdst_port = (cb->nvals == 2) ? cb->val.port_range[1] : + cb->val.port_range[0]; info->match_flags |= XT_CONNTRACK_ORIGDST_PORT; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT; break; - - case 'c': /* --ctreplsrcport */ - ct_parse_ports("--ctreplsrcport", optarg, - &info->replsrc_port, - v3 ? &info->replsrc_port_high : NULL); - + case O_CTREPLSRCPORT: + info->replsrc_port = cb->val.port_range[0]; + info->replsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] : + cb->val.port_range[0]; info->match_flags |= XT_CONNTRACK_REPLSRC_PORT; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT; break; - - case 'd': /* --ctrepldstport */ - ct_parse_ports("--ctrepldstport", optarg, - &info->repldst_port, - v3 ? &info->repldst_port_high : NULL); - + case O_CTREPLDSTPORT: + info->repldst_port = cb->val.port_range[0]; + info->repldst_port = (cb->nvals == 2) ? cb->val.port_range[1] : + cb->val.port_range[0]; info->match_flags |= XT_CONNTRACK_REPLDST_PORT; - if (invert) + if (cb->invert) info->invert_flags |= XT_CONNTRACK_REPLDST_PORT; break; - - case 'e': /* --ctdir */ - xtables_param_act(XTF_NO_INVERT, "conntrack", "--ctdir", invert); - if (strcasecmp(optarg, "ORIGINAL") == 0) { + case O_CTDIR: + if (strcasecmp(cb->arg, "ORIGINAL") == 0) { info->match_flags |= XT_CONNTRACK_DIRECTION; info->invert_flags &= ~XT_CONNTRACK_DIRECTION; - } else if (strcasecmp(optarg, "REPLY") == 0) { + } else if (strcasecmp(cb->arg, "REPLY") == 0) { info->match_flags |= XT_CONNTRACK_DIRECTION; info->invert_flags |= XT_CONNTRACK_DIRECTION; } else { - xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", optarg); + xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", cb->arg); } break; } - - *flags = info->match_flags; - return true; -} - -static int -conntrack_mt4_parse(int c, bool invert, unsigned int *flags, - struct xt_conntrack_mtinfo3 *info, bool v3) -{ - struct in_addr *addr = NULL; - unsigned int naddrs = 0; - - switch (c) { - case '3': /* --ctorigsrc */ - xtables_ipparse_any(optarg, &addr, &info->origsrc_mask.in, - &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->origsrc_addr.in, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_ORIGSRC; - if (invert) - info->invert_flags |= XT_CONNTRACK_ORIGSRC; - break; - - case '4': /* --ctorigdst */ - xtables_ipparse_any(optarg, &addr, &info->origdst_mask.in, - &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->origdst_addr.in, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_ORIGDST; - if (invert) - info->invert_flags |= XT_CONNTRACK_ORIGDST; - break; - - case '5': /* --ctreplsrc */ - xtables_ipparse_any(optarg, &addr, &info->replsrc_mask.in, - &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->replsrc_addr.in, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_REPLSRC; - if (invert) - info->invert_flags |= XT_CONNTRACK_REPLSRC; - break; - - case '6': /* --ctrepldst */ - xtables_ipparse_any(optarg, &addr, &info->repldst_mask.in, - &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->repldst_addr.in, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_REPLDST; - if (invert) - info->invert_flags |= XT_CONNTRACK_REPLDST; - break; - - - default: - return conntrack_mt_parse(c, invert, flags, info, v3); - } - - *flags = info->match_flags; - return true; -} - -static int -conntrack_mt6_parse(int c, bool invert, unsigned int *flags, - struct xt_conntrack_mtinfo3 *info, bool v3) -{ - struct in6_addr *addr = NULL; - unsigned int naddrs = 0; - - switch (c) { - case '3': /* --ctorigsrc */ - xtables_ip6parse_any(optarg, &addr, - &info->origsrc_mask.in6, &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_ORIGSRC; - if (invert) - info->invert_flags |= XT_CONNTRACK_ORIGSRC; - break; - - case '4': /* --ctorigdst */ - xtables_ip6parse_any(optarg, &addr, - &info->origdst_mask.in6, &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->origdst_addr.in, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_ORIGDST; - if (invert) - info->invert_flags |= XT_CONNTRACK_ORIGDST; - break; - - case '5': /* --ctreplsrc */ - xtables_ip6parse_any(optarg, &addr, - &info->replsrc_mask.in6, &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->replsrc_addr.in, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_REPLSRC; - if (invert) - info->invert_flags |= XT_CONNTRACK_REPLSRC; - break; - - case '6': /* --ctrepldst */ - xtables_ip6parse_any(optarg, &addr, - &info->repldst_mask.in6, &naddrs); - if (naddrs > 1) - xtables_error(PARAMETER_PROBLEM, - "multiple IP addresses not allowed"); - if (naddrs == 1) - memcpy(&info->repldst_addr.in, addr, sizeof(*addr)); - info->match_flags |= XT_CONNTRACK_REPLDST; - if (invert) - info->invert_flags |= XT_CONNTRACK_REPLDST; - break; - - - default: - return conntrack_mt_parse(c, invert, flags, info, v3); - } - - *flags = info->match_flags; - return true; } #define cinfo_transform(r, l) \ @@ -754,65 +531,56 @@ conntrack_mt6_parse(int c, bool invert, unsigned int *flags, (r)->status_mask = (l)->status_mask; \ } while (false); -static int -conntrack1_mt4_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void conntrack1_mt_parse(struct xt_option_call *cb) { - struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data; + struct xt_conntrack_mtinfo1 *info = cb->data; struct xt_conntrack_mtinfo3 up; + memset(&up, 0, sizeof(up)); cinfo_transform(&up, info); - if (!conntrack_mt4_parse(c, invert, flags, &up, false)) - return false; - cinfo_transform(info, &up); - return true; -} - -static int -conntrack1_mt6_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data; - struct xt_conntrack_mtinfo3 up; - - cinfo_transform(&up, info); - if (!conntrack_mt6_parse(c, invert, flags, &up, false)) - return false; + cb->data = &up; + conntrack_mt_parse(cb, 3); + if (up.origsrc_port != up.origsrc_port_high || + up.origdst_port != up.origdst_port_high || + up.replsrc_port != up.replsrc_port_high || + up.repldst_port != up.repldst_port_high) + xtables_error(PARAMETER_PROBLEM, + "connlimit rev 1 does not support port ranges"); cinfo_transform(info, &up); - return true; + cb->data = info; } -static int -conntrack2_mt4_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void conntrack2_mt_parse(struct xt_option_call *cb) { - return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, false); -} +#define cinfo2_transform(r, l) \ + memcpy((r), (l), offsetof(typeof(*(l)), sizeof(*info)); -static int -conntrack2_mt6_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, false); -} + struct xt_conntrack_mtinfo2 *info = cb->data; + struct xt_conntrack_mtinfo3 up; -static int -conntrack3_mt4_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data, true); + memset(&up, 0, sizeof(up)); + memcpy(&up, info, sizeof(*info)); + cb->data = &up; + conntrack_mt_parse(cb, 3); + if (up.origsrc_port != up.origsrc_port_high || + up.origdst_port != up.origdst_port_high || + up.replsrc_port != up.replsrc_port_high || + up.repldst_port != up.repldst_port_high) + xtables_error(PARAMETER_PROBLEM, + "connlimit rev 2 does not support port ranges"); + memcpy(info, &up, sizeof(*info)); + cb->data = info; +#undef cinfo2_transform } -static int -conntrack3_mt6_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void conntrack3_mt_parse(struct xt_option_call *cb) { - return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data, true); + conntrack_mt_parse(cb, 3); } -static void conntrack_mt_check(unsigned int flags) +static void conntrack_mt_check(struct xt_fcheck_call *cb) { - if (flags == 0) + if (cb->xflags == 0) xtables_error(PARAMETER_PROBLEM, "conntrack: At least one option " "is required"); } @@ -1259,11 +1027,11 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_info)), .help = conntrack_mt_help, - .parse = conntrack_parse, - .final_check = conntrack_mt_check, + .x6_parse = conntrack_parse, + .x6_fcheck = conntrack_mt_check, .print = conntrack_print, .save = conntrack_save, - .extra_opts = conntrack_mt_opts_v0, + .x6_options = conntrack_mt_opts_v0, }, { .version = XTABLES_VERSION, @@ -1273,11 +1041,11 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), .help = conntrack_mt_help, - .parse = conntrack1_mt4_parse, - .final_check = conntrack_mt_check, + .x6_parse = conntrack1_mt_parse, + .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt4_print, .save = conntrack1_mt4_save, - .extra_opts = conntrack_mt_opts, + .x6_options = conntrack_mt_opts, }, { .version = XTABLES_VERSION, @@ -1287,11 +1055,11 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), .help = conntrack_mt_help, - .parse = conntrack1_mt6_parse, - .final_check = conntrack_mt_check, + .x6_parse = conntrack1_mt_parse, + .x6_fcheck = conntrack_mt_check, .print = conntrack1_mt6_print, .save = conntrack1_mt6_save, - .extra_opts = conntrack_mt_opts, + .x6_options = conntrack_mt_opts, }, { .version = XTABLES_VERSION, @@ -1301,11 +1069,11 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), .help = conntrack_mt_help, - .parse = conntrack2_mt4_parse, - .final_check = conntrack_mt_check, + .x6_parse = conntrack2_mt_parse, + .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt_print, .save = conntrack2_mt_save, - .extra_opts = conntrack_mt_opts, + .x6_options = conntrack_mt_opts, }, { .version = XTABLES_VERSION, @@ -1315,11 +1083,11 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), .help = conntrack_mt_help, - .parse = conntrack2_mt6_parse, - .final_check = conntrack_mt_check, + .x6_parse = conntrack2_mt_parse, + .x6_fcheck = conntrack_mt_check, .print = conntrack2_mt6_print, .save = conntrack2_mt6_save, - .extra_opts = conntrack_mt_opts, + .x6_options = conntrack_mt_opts, }, { .version = XTABLES_VERSION, @@ -1329,11 +1097,11 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), .help = conntrack_mt_help, - .parse = conntrack3_mt4_parse, - .final_check = conntrack_mt_check, + .x6_parse = conntrack3_mt_parse, + .x6_fcheck = conntrack_mt_check, .print = conntrack3_mt_print, .save = conntrack3_mt_save, - .extra_opts = conntrack_mt_opts, + .x6_options = conntrack_mt_opts, }, { .version = XTABLES_VERSION, @@ -1343,11 +1111,11 @@ static struct xtables_match conntrack_mt_reg[] = { .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), .help = conntrack_mt_help, - .parse = conntrack3_mt6_parse, - .final_check = conntrack_mt_check, + .x6_parse = conntrack3_mt_parse, + .x6_fcheck = conntrack_mt_check, .print = conntrack3_mt6_print, .save = conntrack3_mt6_save, - .extra_opts = conntrack_mt_opts, + .x6_options = conntrack_mt_opts, }, }; -- cgit v1.2.3