diff options
Diffstat (limited to 'extensions/libxt_statistic.c')
-rw-r--r-- | extensions/libxt_statistic.c | 171 |
1 files changed, 72 insertions, 99 deletions
diff --git a/extensions/libxt_statistic.c b/extensions/libxt_statistic.c index 913aa2c..b6ae5f5 100644 --- a/extensions/libxt_statistic.c +++ b/extensions/libxt_statistic.c @@ -1,144 +1,118 @@ +/* + * Copyright (c) 2006-2013 Patrick McHardy <kaber@trash.net> + */ + +#include <math.h> #include <stdio.h> -#include <netdb.h> #include <string.h> -#include <stdlib.h> -#include <stddef.h> -#include <getopt.h> - #include <xtables.h> #include <linux/netfilter/xt_statistic.h> +enum { + O_MODE = 0, + O_PROBABILITY, + O_EVERY, + O_PACKET, + F_PROBABILITY = 1 << O_PROBABILITY, + F_EVERY = 1 << O_EVERY, + F_PACKET = 1 << O_PACKET, +}; + static void statistic_help(void) { printf( "statistic match options:\n" " --mode mode Match mode (random, nth)\n" " random mode:\n" -" --probability p Probability\n" +"[!] --probability p Probability\n" " nth mode:\n" -" --every n Match every nth packet\n" +"[!] --every n Match every nth packet\n" " --packet p Initial counter value (0 <= p <= n-1, default 0)\n"); } -static const struct option statistic_opts[] = { - { "mode", 1, NULL, '1' }, - { "probability", 1, NULL, '2' }, - { "every", 1, NULL, '3' }, - { "packet", 1, NULL, '4' }, - { .name = NULL } +#define s struct xt_statistic_info +static const struct xt_option_entry statistic_opts[] = { + {.name = "mode", .id = O_MODE, .type = XTTYPE_STRING, + .flags = XTOPT_MAND}, + {.name = "probability", .id = O_PROBABILITY, .type = XTTYPE_DOUBLE, + .flags = XTOPT_INVERT, .min = 0, .max = 1, + .excl = F_EVERY | F_PACKET}, + {.name = "every", .id = O_EVERY, .type = XTTYPE_UINT32, .min = 1, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, u.nth.every), + .excl = F_PROBABILITY, .also = F_PACKET}, + {.name = "packet", .id = O_PACKET, .type = XTTYPE_UINT32, + .flags = XTOPT_PUT, XTOPT_POINTER(s, u.nth.packet), + .excl = F_PROBABILITY, .also = F_EVERY}, + XTOPT_TABLEEND, }; +#undef s -static struct xt_statistic_info *global_info; - -static void statistic_mt_init(struct xt_entry_match *match) -{ - global_info = (void *)match->data; -} - -static int -statistic_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) +static void statistic_parse(struct xt_option_call *cb) { - struct xt_statistic_info *info = (void *)(*match)->data; - unsigned int val; - double prob; + struct xt_statistic_info *info = cb->data; - if (invert) + if (cb->invert) info->flags |= XT_STATISTIC_INVERT; - switch (c) { - case '1': - if (*flags & 0x1) - xtables_error(PARAMETER_PROBLEM, "double --mode"); - if (!strcmp(optarg, "random")) + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_MODE: + if (strcmp(cb->arg, "random") == 0) info->mode = XT_STATISTIC_MODE_RANDOM; - else if (!strcmp(optarg, "nth")) + else if (strcmp(cb->arg, "nth") == 0) info->mode = XT_STATISTIC_MODE_NTH; else - xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", optarg); - *flags |= 0x1; + xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", + cb->arg); break; - case '2': - if (*flags & 0x2) - xtables_error(PARAMETER_PROBLEM, "double --probability"); - prob = atof(optarg); - if (prob < 0 || prob > 1) - xtables_error(PARAMETER_PROBLEM, - "--probability must be between 0 and 1"); - info->u.random.probability = 0x80000000 * prob; - *flags |= 0x2; + case O_PROBABILITY: + info->u.random.probability = lround(0x80000000 * cb->val.dbl); break; - case '3': - if (*flags & 0x4) - xtables_error(PARAMETER_PROBLEM, "double --every"); - if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "cannot parse --every `%s'", optarg); - info->u.nth.every = val; - if (info->u.nth.every == 0) - xtables_error(PARAMETER_PROBLEM, "--every cannot be 0"); - info->u.nth.every--; - *flags |= 0x4; + case O_EVERY: + --info->u.nth.every; break; - case '4': - if (*flags & 0x8) - xtables_error(PARAMETER_PROBLEM, "double --packet"); - if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) - xtables_error(PARAMETER_PROBLEM, - "cannot parse --packet `%s'", optarg); - info->u.nth.packet = val; - *flags |= 0x8; - break; - default: - return 0; } - return 1; } -static void statistic_check(unsigned int flags) +static void statistic_check(struct xt_fcheck_call *cb) { - if (!(flags & 0x1)) - xtables_error(PARAMETER_PROBLEM, "no mode specified"); - if ((flags & 0x2) && (flags & (0x4 | 0x8))) - xtables_error(PARAMETER_PROBLEM, - "both nth and random parameters given"); - if (flags & 0x2 && global_info->mode != XT_STATISTIC_MODE_RANDOM) - xtables_error(PARAMETER_PROBLEM, - "--probability can only be used in random mode"); - if (flags & 0x4 && global_info->mode != XT_STATISTIC_MODE_NTH) - xtables_error(PARAMETER_PROBLEM, - "--every can only be used in nth mode"); - if (flags & 0x8 && global_info->mode != XT_STATISTIC_MODE_NTH) + struct xt_statistic_info *info = cb->data; + + if (info->mode == XT_STATISTIC_MODE_RANDOM && + !(cb->xflags & F_PROBABILITY)) xtables_error(PARAMETER_PROBLEM, - "--packet can only be used in nth mode"); - if ((flags & 0x8) && !(flags & 0x4)) + "--probability must be specified when using " + "random mode"); + if (info->mode == XT_STATISTIC_MODE_NTH && + !(cb->xflags & (F_EVERY | F_PACKET))) xtables_error(PARAMETER_PROBLEM, - "--packet can only be used with --every"); + "--every and --packet must be specified when " + "using nth mode"); + /* at this point, info->u.nth.every have been decreased. */ - if (global_info->u.nth.packet > global_info->u.nth.every) + if (info->u.nth.packet > info->u.nth.every) xtables_error(PARAMETER_PROBLEM, "the --packet p must be 0 <= p <= n-1"); - - global_info->u.nth.count = global_info->u.nth.every - - global_info->u.nth.packet; + info->u.nth.count = info->u.nth.every - info->u.nth.packet; } static void print_match(const struct xt_statistic_info *info, char *prefix) { - if (info->flags & XT_STATISTIC_INVERT) - printf("! "); - switch (info->mode) { case XT_STATISTIC_MODE_RANDOM: - printf("%smode random %sprobability %f ", prefix, prefix, + printf(" %smode random%s %sprobability %.11f", prefix, + (info->flags & XT_STATISTIC_INVERT) ? " !" : "", + prefix, 1.0 * info->u.random.probability / 0x80000000); break; case XT_STATISTIC_MODE_NTH: - printf("%smode nth %severy %u ", prefix, prefix, + printf(" %smode nth%s %severy %u", prefix, + (info->flags & XT_STATISTIC_INVERT) ? " !" : "", + prefix, info->u.nth.every + 1); - if (info->u.nth.packet) - printf("%spacket %u ", prefix, info->u.nth.packet); + if (info->u.nth.packet || *prefix) + printf(" %spacket %u", prefix, info->u.nth.packet); break; } } @@ -148,7 +122,7 @@ statistic_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct xt_statistic_info *info = (const void *)match->data; - printf("statistic "); + printf(" statistic"); print_match(info, ""); } @@ -165,13 +139,12 @@ static struct xtables_match statistic_match = { .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct xt_statistic_info)), .userspacesize = offsetof(struct xt_statistic_info, u.nth.count), - .init = statistic_mt_init, .help = statistic_help, - .parse = statistic_parse, - .final_check = statistic_check, + .x6_parse = statistic_parse, + .x6_fcheck = statistic_check, .print = statistic_print, .save = statistic_save, - .extra_opts = statistic_opts, + .x6_options = statistic_opts, }; void _init(void) |