Jan Engelhardt | 39d3aa3 | 2011-05-02 16:38:11 +0200 | [diff] [blame] | 1 | #include <math.h> |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 2 | #include <stdio.h> |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 3 | #include <string.h> |
Yasuyuki KOZAKAI | dfd78a8 | 2007-08-04 08:28:23 +0000 | [diff] [blame] | 4 | #include <xtables.h> |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 5 | #include <linux/netfilter/xt_statistic.h> |
| 6 | |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 7 | enum { |
| 8 | O_MODE = 0, |
| 9 | O_PROBABILITY, |
| 10 | O_EVERY, |
| 11 | O_PACKET, |
| 12 | F_PROBABILITY = 1 << O_PROBABILITY, |
| 13 | F_EVERY = 1 << O_EVERY, |
| 14 | F_PACKET = 1 << O_PACKET, |
| 15 | }; |
| 16 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 17 | static void statistic_help(void) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 18 | { |
| 19 | printf( |
Jan Engelhardt | 8b7c64d | 2008-04-15 11:48:25 +0200 | [diff] [blame] | 20 | "statistic match options:\n" |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 21 | " --mode mode Match mode (random, nth)\n" |
| 22 | " random mode:\n" |
Jan Engelhardt | d118d21 | 2011-05-02 16:29:18 +0200 | [diff] [blame] | 23 | "[!] --probability p Probability\n" |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 24 | " nth mode:\n" |
Jan Engelhardt | d118d21 | 2011-05-02 16:29:18 +0200 | [diff] [blame] | 25 | "[!] --every n Match every nth packet\n" |
Jan Engelhardt | 8b7c64d | 2008-04-15 11:48:25 +0200 | [diff] [blame] | 26 | " --packet p Initial counter value (0 <= p <= n-1, default 0)\n"); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 27 | } |
| 28 | |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 29 | #define s struct xt_statistic_info |
| 30 | static const struct xt_option_entry statistic_opts[] = { |
| 31 | {.name = "mode", .id = O_MODE, .type = XTTYPE_STRING, |
| 32 | .flags = XTOPT_MAND}, |
| 33 | {.name = "probability", .id = O_PROBABILITY, .type = XTTYPE_DOUBLE, |
| 34 | .flags = XTOPT_INVERT, .min = 0, .max = 1, |
| 35 | .excl = F_EVERY | F_PACKET}, |
| 36 | {.name = "every", .id = O_EVERY, .type = XTTYPE_UINT32, .min = 1, |
| 37 | .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, u.nth.every), |
| 38 | .excl = F_PROBABILITY, .also = F_PACKET}, |
| 39 | {.name = "packet", .id = O_PACKET, .type = XTTYPE_UINT32, |
| 40 | .flags = XTOPT_PUT, XTOPT_POINTER(s, u.nth.packet), |
| 41 | .excl = F_PROBABILITY, .also = F_EVERY}, |
| 42 | XTOPT_TABLEEND, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 43 | }; |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 44 | #undef s |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 45 | |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 46 | static void statistic_parse(struct xt_option_call *cb) |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 47 | { |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 48 | struct xt_statistic_info *info = cb->data; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 49 | |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 50 | if (cb->invert) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 51 | info->flags |= XT_STATISTIC_INVERT; |
| 52 | |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 53 | xtables_option_parse(cb); |
| 54 | switch (cb->entry->id) { |
| 55 | case O_MODE: |
| 56 | if (strcmp(cb->arg, "random") == 0) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 57 | info->mode = XT_STATISTIC_MODE_RANDOM; |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 58 | else if (strcmp(cb->arg, "nth") == 0) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 59 | info->mode = XT_STATISTIC_MODE_NTH; |
| 60 | else |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 61 | xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", |
| 62 | cb->arg); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 63 | break; |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 64 | case O_PROBABILITY: |
| 65 | info->u.random.probability = lround(0x80000000 * cb->val.dbl); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 66 | break; |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 67 | case O_EVERY: |
| 68 | --info->u.nth.every; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 69 | break; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 70 | } |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 71 | } |
| 72 | |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 73 | static void statistic_check(struct xt_fcheck_call *cb) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 74 | { |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 75 | struct xt_statistic_info *info = cb->data; |
| 76 | |
| 77 | if (info->mode == XT_STATISTIC_MODE_RANDOM && |
| 78 | !(cb->xflags & F_PROBABILITY)) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 79 | xtables_error(PARAMETER_PROBLEM, |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 80 | "--probability must be specified when using " |
| 81 | "random mode"); |
| 82 | if (info->mode == XT_STATISTIC_MODE_NTH && |
| 83 | !(cb->xflags & (F_EVERY | F_PACKET))) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 84 | xtables_error(PARAMETER_PROBLEM, |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 85 | "--every and --packet must be specified when " |
| 86 | "using nth mode"); |
| 87 | |
Nicolas Bouliane | 0c6bf10 | 2007-07-03 12:52:55 +0000 | [diff] [blame] | 88 | /* at this point, info->u.nth.every have been decreased. */ |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 89 | if (info->u.nth.packet > info->u.nth.every) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 90 | xtables_error(PARAMETER_PROBLEM, |
Nicolas Bouliane | 0c6bf10 | 2007-07-03 12:52:55 +0000 | [diff] [blame] | 91 | "the --packet p must be 0 <= p <= n-1"); |
| 92 | |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 93 | info->u.nth.count = info->u.nth.every - info->u.nth.packet; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 94 | } |
| 95 | |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 96 | static void print_match(const struct xt_statistic_info *info, char *prefix) |
| 97 | { |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 98 | switch (info->mode) { |
| 99 | case XT_STATISTIC_MODE_RANDOM: |
Jan Engelhardt | 39d3aa3 | 2011-05-02 16:38:11 +0200 | [diff] [blame] | 100 | printf(" %smode random%s %sprobability %.11f", prefix, |
Jan Engelhardt | d118d21 | 2011-05-02 16:29:18 +0200 | [diff] [blame] | 101 | (info->flags & XT_STATISTIC_INVERT) ? " !" : "", |
| 102 | prefix, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 103 | 1.0 * info->u.random.probability / 0x80000000); |
| 104 | break; |
| 105 | case XT_STATISTIC_MODE_NTH: |
Jan Engelhardt | d118d21 | 2011-05-02 16:29:18 +0200 | [diff] [blame] | 106 | printf(" %smode nth%s %severy %u", prefix, |
| 107 | (info->flags & XT_STATISTIC_INVERT) ? " !" : "", |
| 108 | prefix, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 109 | info->u.nth.every + 1); |
| 110 | if (info->u.nth.packet) |
Jan Engelhardt | 7386635 | 2010-12-18 02:04:59 +0100 | [diff] [blame] | 111 | printf(" %spacket %u", prefix, info->u.nth.packet); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 112 | break; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | static void |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 117 | statistic_print(const void *ip, const struct xt_entry_match *match, int numeric) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 118 | { |
Jan Engelhardt | 69f564e | 2009-05-26 13:14:06 +0200 | [diff] [blame] | 119 | const struct xt_statistic_info *info = (const void *)match->data; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 120 | |
Jan Engelhardt | 7386635 | 2010-12-18 02:04:59 +0100 | [diff] [blame] | 121 | printf(" statistic"); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 122 | print_match(info, ""); |
| 123 | } |
| 124 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 125 | static void statistic_save(const void *ip, const struct xt_entry_match *match) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 126 | { |
Jan Engelhardt | 69f564e | 2009-05-26 13:14:06 +0200 | [diff] [blame] | 127 | const struct xt_statistic_info *info = (const void *)match->data; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 128 | |
| 129 | print_match(info, "--"); |
| 130 | } |
| 131 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 132 | static struct xtables_match statistic_match = { |
Jan Engelhardt | 4297936 | 2009-06-01 11:56:23 +0200 | [diff] [blame] | 133 | .family = NFPROTO_UNSPEC, |
Yasuyuki KOZAKAI | dfd78a8 | 2007-08-04 08:28:23 +0000 | [diff] [blame] | 134 | .name = "statistic", |
Jan Engelhardt | 8b7c64d | 2008-04-15 11:48:25 +0200 | [diff] [blame] | 135 | .version = XTABLES_VERSION, |
Yasuyuki KOZAKAI | dfd78a8 | 2007-08-04 08:28:23 +0000 | [diff] [blame] | 136 | .size = XT_ALIGN(sizeof(struct xt_statistic_info)), |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 137 | .userspacesize = offsetof(struct xt_statistic_info, u.nth.count), |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 138 | .help = statistic_help, |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 139 | .x6_parse = statistic_parse, |
| 140 | .x6_fcheck = statistic_check, |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 141 | .print = statistic_print, |
| 142 | .save = statistic_save, |
Jan Engelhardt | 3c7f501 | 2011-05-02 18:26:31 +0200 | [diff] [blame] | 143 | .x6_options = statistic_opts, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 144 | }; |
| 145 | |
| 146 | void _init(void) |
| 147 | { |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 148 | xtables_register_match(&statistic_match); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 149 | } |