Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 1 | #include <stdio.h> |
| 2 | #include <netdb.h> |
| 3 | #include <string.h> |
| 4 | #include <stdlib.h> |
| 5 | #include <stddef.h> |
| 6 | #include <getopt.h> |
| 7 | |
Yasuyuki KOZAKAI | dfd78a8 | 2007-08-04 08:28:23 +0000 | [diff] [blame] | 8 | #include <xtables.h> |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 9 | #include <linux/netfilter/xt_statistic.h> |
| 10 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 11 | static void statistic_help(void) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 12 | { |
| 13 | printf( |
Jan Engelhardt | 8b7c64d | 2008-04-15 11:48:25 +0200 | [diff] [blame] | 14 | "statistic match options:\n" |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 15 | " --mode mode Match mode (random, nth)\n" |
| 16 | " random mode:\n" |
| 17 | " --probability p Probability\n" |
| 18 | " nth mode:\n" |
| 19 | " --every n Match every nth packet\n" |
Jan Engelhardt | 8b7c64d | 2008-04-15 11:48:25 +0200 | [diff] [blame] | 20 | " --packet p Initial counter value (0 <= p <= n-1, default 0)\n"); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 21 | } |
| 22 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 23 | static const struct option statistic_opts[] = { |
Patrick McHardy | 500f483 | 2007-09-08 15:59:04 +0000 | [diff] [blame] | 24 | { "mode", 1, NULL, '1' }, |
| 25 | { "probability", 1, NULL, '2' }, |
| 26 | { "every", 1, NULL, '3' }, |
| 27 | { "packet", 1, NULL, '4' }, |
Max Kellermann | 9ee386a | 2008-01-29 13:48:05 +0000 | [diff] [blame] | 28 | { .name = NULL } |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 29 | }; |
| 30 | |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 31 | static struct xt_statistic_info *global_info; |
| 32 | |
| 33 | static void statistic_mt_init(struct xt_entry_match *match) |
| 34 | { |
| 35 | global_info = (void *)match->data; |
| 36 | } |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 37 | |
| 38 | static int |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 39 | statistic_parse(int c, char **argv, int invert, unsigned int *flags, |
| 40 | const void *entry, struct xt_entry_match **match) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 41 | { |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 42 | struct xt_statistic_info *info = (void *)(*match)->data; |
Jan Engelhardt | 5f2922c | 2009-01-27 18:43:01 +0100 | [diff] [blame] | 43 | unsigned int val; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 44 | double prob; |
| 45 | |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 46 | if (invert) |
| 47 | info->flags |= XT_STATISTIC_INVERT; |
| 48 | |
| 49 | switch (c) { |
| 50 | case '1': |
| 51 | if (*flags & 0x1) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 52 | xtables_error(PARAMETER_PROBLEM, "double --mode"); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 53 | if (!strcmp(optarg, "random")) |
| 54 | info->mode = XT_STATISTIC_MODE_RANDOM; |
| 55 | else if (!strcmp(optarg, "nth")) |
| 56 | info->mode = XT_STATISTIC_MODE_NTH; |
| 57 | else |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 58 | xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", optarg); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 59 | *flags |= 0x1; |
| 60 | break; |
| 61 | case '2': |
| 62 | if (*flags & 0x2) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 63 | xtables_error(PARAMETER_PROBLEM, "double --probability"); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 64 | prob = atof(optarg); |
| 65 | if (prob < 0 || prob > 1) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 66 | xtables_error(PARAMETER_PROBLEM, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 67 | "--probability must be between 0 and 1"); |
| 68 | info->u.random.probability = 0x80000000 * prob; |
| 69 | *flags |= 0x2; |
| 70 | break; |
| 71 | case '3': |
| 72 | if (*flags & 0x4) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 73 | xtables_error(PARAMETER_PROBLEM, "double --every"); |
Jan Engelhardt | 5f2922c | 2009-01-27 18:43:01 +0100 | [diff] [blame] | 74 | if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 75 | xtables_error(PARAMETER_PROBLEM, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 76 | "cannot parse --every `%s'", optarg); |
Jan Engelhardt | 5f2922c | 2009-01-27 18:43:01 +0100 | [diff] [blame] | 77 | info->u.nth.every = val; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 78 | if (info->u.nth.every == 0) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 79 | xtables_error(PARAMETER_PROBLEM, "--every cannot be 0"); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 80 | info->u.nth.every--; |
| 81 | *flags |= 0x4; |
| 82 | break; |
| 83 | case '4': |
| 84 | if (*flags & 0x8) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 85 | xtables_error(PARAMETER_PROBLEM, "double --packet"); |
Jan Engelhardt | 5f2922c | 2009-01-27 18:43:01 +0100 | [diff] [blame] | 86 | if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX)) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 87 | xtables_error(PARAMETER_PROBLEM, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 88 | "cannot parse --packet `%s'", optarg); |
Jan Engelhardt | 5f2922c | 2009-01-27 18:43:01 +0100 | [diff] [blame] | 89 | info->u.nth.packet = val; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 90 | *flags |= 0x8; |
| 91 | break; |
| 92 | default: |
| 93 | return 0; |
| 94 | } |
| 95 | return 1; |
| 96 | } |
| 97 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 98 | static void statistic_check(unsigned int flags) |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 99 | { |
| 100 | if (!(flags & 0x1)) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 101 | xtables_error(PARAMETER_PROBLEM, "no mode specified"); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 102 | if ((flags & 0x2) && (flags & (0x4 | 0x8))) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 103 | xtables_error(PARAMETER_PROBLEM, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 104 | "both nth and random parameters given"); |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 105 | if (flags & 0x2 && global_info->mode != XT_STATISTIC_MODE_RANDOM) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 106 | xtables_error(PARAMETER_PROBLEM, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 107 | "--probability can only be used in random mode"); |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 108 | if (flags & 0x4 && global_info->mode != XT_STATISTIC_MODE_NTH) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 109 | xtables_error(PARAMETER_PROBLEM, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 110 | "--every can only be used in nth mode"); |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 111 | if (flags & 0x8 && global_info->mode != XT_STATISTIC_MODE_NTH) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 112 | xtables_error(PARAMETER_PROBLEM, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 113 | "--packet can only be used in nth mode"); |
Nicolas Bouliane | 0c6bf10 | 2007-07-03 12:52:55 +0000 | [diff] [blame] | 114 | if ((flags & 0x8) && !(flags & 0x4)) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 115 | xtables_error(PARAMETER_PROBLEM, |
Nicolas Bouliane | 0c6bf10 | 2007-07-03 12:52:55 +0000 | [diff] [blame] | 116 | "--packet can only be used with --every"); |
| 117 | /* at this point, info->u.nth.every have been decreased. */ |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 118 | if (global_info->u.nth.packet > global_info->u.nth.every) |
Jan Engelhardt | 1829ed4 | 2009-02-21 03:29:44 +0100 | [diff] [blame] | 119 | xtables_error(PARAMETER_PROBLEM, |
Nicolas Bouliane | 0c6bf10 | 2007-07-03 12:52:55 +0000 | [diff] [blame] | 120 | "the --packet p must be 0 <= p <= n-1"); |
| 121 | |
| 122 | |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 123 | global_info->u.nth.count = global_info->u.nth.every - |
| 124 | global_info->u.nth.packet; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 125 | } |
| 126 | |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 127 | static void print_match(const struct xt_statistic_info *info, char *prefix) |
| 128 | { |
| 129 | if (info->flags & XT_STATISTIC_INVERT) |
| 130 | printf("! "); |
| 131 | |
| 132 | switch (info->mode) { |
| 133 | case XT_STATISTIC_MODE_RANDOM: |
| 134 | printf("%smode random %sprobability %f ", prefix, prefix, |
| 135 | 1.0 * info->u.random.probability / 0x80000000); |
| 136 | break; |
| 137 | case XT_STATISTIC_MODE_NTH: |
| 138 | printf("%smode nth %severy %u ", prefix, prefix, |
| 139 | info->u.nth.every + 1); |
| 140 | if (info->u.nth.packet) |
| 141 | printf("%spacket %u ", prefix, info->u.nth.packet); |
| 142 | break; |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | static void |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 147 | 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] | 148 | { |
Jan Engelhardt | 69f564e | 2009-05-26 13:14:06 +0200 | [diff] [blame] | 149 | const struct xt_statistic_info *info = (const void *)match->data; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 150 | |
| 151 | printf("statistic "); |
| 152 | print_match(info, ""); |
| 153 | } |
| 154 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 155 | 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] | 156 | { |
Jan Engelhardt | 69f564e | 2009-05-26 13:14:06 +0200 | [diff] [blame] | 157 | const struct xt_statistic_info *info = (const void *)match->data; |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 158 | |
| 159 | print_match(info, "--"); |
| 160 | } |
| 161 | |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 162 | static struct xtables_match statistic_match = { |
Jan Engelhardt | 4297936 | 2009-06-01 11:56:23 +0200 | [diff] [blame^] | 163 | .family = NFPROTO_UNSPEC, |
Yasuyuki KOZAKAI | dfd78a8 | 2007-08-04 08:28:23 +0000 | [diff] [blame] | 164 | .name = "statistic", |
Jan Engelhardt | 8b7c64d | 2008-04-15 11:48:25 +0200 | [diff] [blame] | 165 | .version = XTABLES_VERSION, |
Yasuyuki KOZAKAI | dfd78a8 | 2007-08-04 08:28:23 +0000 | [diff] [blame] | 166 | .size = XT_ALIGN(sizeof(struct xt_statistic_info)), |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 167 | .userspacesize = offsetof(struct xt_statistic_info, u.nth.count), |
Jan Engelhardt | dbb7754 | 2008-02-11 00:33:30 +0100 | [diff] [blame] | 168 | .init = statistic_mt_init, |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 169 | .help = statistic_help, |
| 170 | .parse = statistic_parse, |
| 171 | .final_check = statistic_check, |
| 172 | .print = statistic_print, |
| 173 | .save = statistic_save, |
| 174 | .extra_opts = statistic_opts, |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 175 | }; |
| 176 | |
| 177 | void _init(void) |
| 178 | { |
Jan Engelhardt | 181dead | 2007-10-04 16:27:07 +0000 | [diff] [blame] | 179 | xtables_register_match(&statistic_match); |
Patrick McHardy | 10e0fbb | 2006-08-31 14:01:35 +0000 | [diff] [blame] | 180 | } |