9
#include <linux/netfilter/xt_statistic.h>
15
"statistic match v%s options:\n"
16
" --mode mode Match mode (random, nth)\n"
18
" --probability p Probability\n"
20
" --every n Match every nth packet\n"
21
" --packet p Initial counter value (0 <= p <= n-1, default 0)\n"
26
static struct option opts[] = {
27
{ "mode", 1, 0, '1' },
28
{ "probability", 1, 0, '2' },
29
{ "every", 1, 0, '3' },
30
{ "packet", 1, 0, '4' },
34
static struct xt_statistic_info *info;
37
parse(int c, char **argv, int invert, unsigned int *flags,
38
const struct ipt_entry *entry,
39
unsigned int *nfcache,
40
struct ipt_entry_match **match)
44
info = (void *)(*match)->data;
47
info->flags |= XT_STATISTIC_INVERT;
52
exit_error(PARAMETER_PROBLEM, "double --mode");
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;
58
exit_error(PARAMETER_PROBLEM, "Bad mode `%s'", optarg);
63
exit_error(PARAMETER_PROBLEM, "double --probability");
65
if (prob < 0 || prob > 1)
66
exit_error(PARAMETER_PROBLEM,
67
"--probability must be between 0 and 1");
68
info->u.random.probability = 0x80000000 * prob;
73
exit_error(PARAMETER_PROBLEM, "double --every");
74
if (string_to_number(optarg, 0, 0xFFFFFFFF,
75
&info->u.nth.every) == -1)
76
exit_error(PARAMETER_PROBLEM,
77
"cannot parse --every `%s'", optarg);
78
if (info->u.nth.every == 0)
79
exit_error(PARAMETER_PROBLEM, "--every cannot be 0");
85
exit_error(PARAMETER_PROBLEM, "double --packet");
86
if (string_to_number(optarg, 0, 0xFFFFFFFF,
87
&info->u.nth.packet) == -1)
88
exit_error(PARAMETER_PROBLEM,
89
"cannot parse --packet `%s'", optarg);
98
/* Final check; must have specified --mark. */
100
final_check(unsigned int flags)
103
exit_error(PARAMETER_PROBLEM, "no mode specified");
104
if ((flags & 0x2) && (flags & (0x4 | 0x8)))
105
exit_error(PARAMETER_PROBLEM,
106
"both nth and random parameters given");
107
if (flags & 0x2 && info->mode != XT_STATISTIC_MODE_RANDOM)
108
exit_error(PARAMETER_PROBLEM,
109
"--probability can only be used in random mode");
110
if (flags & 0x4 && info->mode != XT_STATISTIC_MODE_NTH)
111
exit_error(PARAMETER_PROBLEM,
112
"--every can only be used in nth mode");
113
if (flags & 0x8 && info->mode != XT_STATISTIC_MODE_NTH)
114
exit_error(PARAMETER_PROBLEM,
115
"--packet can only be used in nth mode");
116
info->u.nth.count = info->u.nth.every - info->u.nth.packet;
119
/* Prints out the matchinfo. */
120
static void print_match(const struct xt_statistic_info *info, char *prefix)
122
if (info->flags & XT_STATISTIC_INVERT)
125
switch (info->mode) {
126
case XT_STATISTIC_MODE_RANDOM:
127
printf("%smode random %sprobability %f ", prefix, prefix,
128
1.0 * info->u.random.probability / 0x80000000);
130
case XT_STATISTIC_MODE_NTH:
131
printf("%smode nth %severy %u ", prefix, prefix,
132
info->u.nth.every + 1);
133
if (info->u.nth.packet)
134
printf("%spacket %u ", prefix, info->u.nth.packet);
140
print(const struct ipt_ip *ip,
141
const struct ipt_entry_match *match,
144
struct xt_statistic_info *info = (struct xt_statistic_info *)match->data;
146
printf("statistic ");
147
print_match(info, "");
150
/* Saves the union ipt_matchinfo in parsable form to stdout. */
152
save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
154
struct xt_statistic_info *info = (struct xt_statistic_info *)match->data;
156
print_match(info, "--");
159
static struct iptables_match statistic = {
161
.version = IPTABLES_VERSION,
162
.size = IPT_ALIGN(sizeof(struct xt_statistic_info)),
163
.userspacesize = offsetof(struct xt_statistic_info, u.nth.count),
166
.final_check = final_check,
174
register_match(&statistic);