9 #include <linux/netfilter/xt_statistic.h>
11 static void statistic_help(void)
14 "statistic match options:\n"
15 " --mode mode Match mode (random, nth)\n"
17 " --probability p Probability\n"
19 " --every n Match every nth packet\n"
20 " --packet p Initial counter value (0 <= p <= n-1, default 0)\n");
23 static const struct option statistic_opts
[] = {
24 { "mode", 1, NULL
, '1' },
25 { "probability", 1, NULL
, '2' },
26 { "every", 1, NULL
, '3' },
27 { "packet", 1, NULL
, '4' },
31 static struct xt_statistic_info
*global_info
;
33 static void statistic_mt_init(struct xt_entry_match
*match
)
35 global_info
= (void *)match
->data
;
39 statistic_parse(int c
, char **argv
, int invert
, unsigned int *flags
,
40 const void *entry
, struct xt_entry_match
**match
)
42 struct xt_statistic_info
*info
= (void *)(*match
)->data
;
47 info
->flags
|= XT_STATISTIC_INVERT
;
52 xtables_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 xtables_error(PARAMETER_PROBLEM
, "Bad mode \"%s\"", optarg
);
63 xtables_error(PARAMETER_PROBLEM
, "double --probability");
65 if (prob
< 0 || prob
> 1)
66 xtables_error(PARAMETER_PROBLEM
,
67 "--probability must be between 0 and 1");
68 info
->u
.random
.probability
= 0x80000000 * prob
;
73 xtables_error(PARAMETER_PROBLEM
, "double --every");
74 if (!xtables_strtoui(optarg
, NULL
, &val
, 0, UINT32_MAX
))
75 xtables_error(PARAMETER_PROBLEM
,
76 "cannot parse --every `%s'", optarg
);
77 info
->u
.nth
.every
= val
;
78 if (info
->u
.nth
.every
== 0)
79 xtables_error(PARAMETER_PROBLEM
, "--every cannot be 0");
85 xtables_error(PARAMETER_PROBLEM
, "double --packet");
86 if (!xtables_strtoui(optarg
, NULL
, &val
, 0, UINT32_MAX
))
87 xtables_error(PARAMETER_PROBLEM
,
88 "cannot parse --packet `%s'", optarg
);
89 info
->u
.nth
.packet
= val
;
98 static void statistic_check(unsigned int flags
)
101 xtables_error(PARAMETER_PROBLEM
, "no mode specified");
102 if ((flags
& 0x2) && (flags
& (0x4 | 0x8)))
103 xtables_error(PARAMETER_PROBLEM
,
104 "both nth and random parameters given");
105 if (flags
& 0x2 && global_info
->mode
!= XT_STATISTIC_MODE_RANDOM
)
106 xtables_error(PARAMETER_PROBLEM
,
107 "--probability can only be used in random mode");
108 if (flags
& 0x4 && global_info
->mode
!= XT_STATISTIC_MODE_NTH
)
109 xtables_error(PARAMETER_PROBLEM
,
110 "--every can only be used in nth mode");
111 if (flags
& 0x8 && global_info
->mode
!= XT_STATISTIC_MODE_NTH
)
112 xtables_error(PARAMETER_PROBLEM
,
113 "--packet can only be used in nth mode");
114 if ((flags
& 0x8) && !(flags
& 0x4))
115 xtables_error(PARAMETER_PROBLEM
,
116 "--packet can only be used with --every");
117 /* at this point, info->u.nth.every have been decreased. */
118 if (global_info
->u
.nth
.packet
> global_info
->u
.nth
.every
)
119 xtables_error(PARAMETER_PROBLEM
,
120 "the --packet p must be 0 <= p <= n-1");
123 global_info
->u
.nth
.count
= global_info
->u
.nth
.every
-
124 global_info
->u
.nth
.packet
;
127 static void print_match(const struct xt_statistic_info
*info
, char *prefix
)
129 if (info
->flags
& XT_STATISTIC_INVERT
)
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);
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
);
147 statistic_print(const void *ip
, const struct xt_entry_match
*match
, int numeric
)
149 const struct xt_statistic_info
*info
= (const void *)match
->data
;
151 printf("statistic ");
152 print_match(info
, "");
155 static void statistic_save(const void *ip
, const struct xt_entry_match
*match
)
157 const struct xt_statistic_info
*info
= (const void *)match
->data
;
159 print_match(info
, "--");
162 static struct xtables_match statistic_match
= {
165 .version
= XTABLES_VERSION
,
166 .size
= XT_ALIGN(sizeof(struct xt_statistic_info
)),
167 .userspacesize
= offsetof(struct xt_statistic_info
, u
.nth
.count
),
168 .init
= statistic_mt_init
,
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
,
179 xtables_register_match(&statistic_match
);