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
);