2 Shared library add-on to iptables to add match support for every Nth packet
4 This file is distributed under the terms of the GNU General Public
5 License (GPL). Copies of the GPL can be obtained from:
6 ftp://prep.ai.mit.edu/pub/gnu/GPL
8 2001-07-17 Fabrice MARIE <fabrice@netfilter.org> : initial development.
9 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
10 * added support for multiple counters
11 * added support for matching on individual packets
21 #include <ip6tables.h>
22 #include <linux/netfilter_ipv6/ip6_tables.h>
23 #include <linux/netfilter_ipv6/ip6t_nth.h>
26 /* Function which prints out usage message. */
32 " --every Nth Match every Nth packet\n"
33 " [--counter] num Use counter 0-%u (default:0)\n"
34 " [--start] num Initialize the counter at the number 'num'\n"
35 " instead of 0. Must be between 0 and Nth-1\n"
36 " [--packet] num Match on 'num' packet. Must be between 0\n"
38 " If --packet is used for a counter than\n"
39 " there must be Nth number of --packet\n"
40 " rules, covering all values between 0 and\n"
41 " Nth-1 inclusively.\n",
42 IPTABLES_VERSION
, IP6T_NTH_NUM_COUNTERS
-1);
45 static struct option opts
[] = {
46 { "every", 1, 0, '1' },
47 { "start", 1, 0, '2' },
48 { "counter", 1, 0, '3' },
49 { "packet", 1, 0, '4' },
53 #define IP6T_NTH_OPT_EVERY 0x01
54 #define IP6T_NTH_OPT_NOT_EVERY 0x02
55 #define IP6T_NTH_OPT_START 0x04
56 #define IP6T_NTH_OPT_COUNTER 0x08
57 #define IP6T_NTH_OPT_PACKET 0x10
59 /* Function which parses command options; returns true if it
62 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
63 const struct ip6t_entry
*entry
,
64 unsigned int *nfcache
,
65 struct ip6t_entry_match
**match
)
67 struct ip6t_nth_info
*nthinfo
= (struct ip6t_nth_info
*)(*match
)->data
;
72 /* check for common mistakes... */
73 if ((!invert
) && (*flags
& IP6T_NTH_OPT_EVERY
))
74 exit_error(PARAMETER_PROBLEM
,
75 "Can't specify --every twice");
76 if (invert
&& (*flags
& IP6T_NTH_OPT_NOT_EVERY
))
77 exit_error(PARAMETER_PROBLEM
,
78 "Can't specify ! --every twice");
79 if ((!invert
) && (*flags
& IP6T_NTH_OPT_NOT_EVERY
))
80 exit_error(PARAMETER_PROBLEM
,
81 "Can't specify --every with ! --every");
82 if (invert
&& (*flags
& IP6T_NTH_OPT_EVERY
))
83 exit_error(PARAMETER_PROBLEM
,
84 "Can't specify ! --every with --every");
86 /* Remember, this function will interpret a leading 0 to be
87 Octal, a leading 0x to be hexdecimal... */
88 if (string_to_number(optarg
, 2, 100, &num
) == -1 || num
< 2)
89 exit_error(PARAMETER_PROBLEM
,
90 "bad --every `%s', must be between 2 and 100", optarg
);
92 /* assign the values */
93 nthinfo
->every
= num
-1;
95 nthinfo
->packet
= 0xFF;
96 if(!(*flags
& IP6T_NTH_OPT_EVERY
))
102 *flags
|= IP6T_NTH_OPT_NOT_EVERY
;
107 *flags
|= IP6T_NTH_OPT_EVERY
;
112 /* check for common mistakes... */
113 if (!((*flags
& IP6T_NTH_OPT_EVERY
) ||
114 (*flags
& IP6T_NTH_OPT_NOT_EVERY
)))
115 exit_error(PARAMETER_PROBLEM
,
116 "Can't specify --start before --every");
118 exit_error(PARAMETER_PROBLEM
,
119 "Can't specify with ! --start");
120 if (*flags
& IP6T_NTH_OPT_START
)
121 exit_error(PARAMETER_PROBLEM
,
122 "Can't specify --start twice");
123 if (string_to_number(optarg
, 0, nthinfo
->every
, &num
) == -1)
124 exit_error(PARAMETER_PROBLEM
,
125 "bad --start `%s', must between 0 and %u", optarg
, nthinfo
->every
);
126 *flags
|= IP6T_NTH_OPT_START
;
127 nthinfo
->startat
= num
;
130 /* check for common mistakes... */
132 exit_error(PARAMETER_PROBLEM
,
133 "Can't specify with ! --counter");
134 if (*flags
& IP6T_NTH_OPT_COUNTER
)
135 exit_error(PARAMETER_PROBLEM
,
136 "Can't specify --counter twice");
137 if (string_to_number(optarg
, 0, IP6T_NTH_NUM_COUNTERS
-1, &num
) == -1)
138 exit_error(PARAMETER_PROBLEM
,
139 "bad --counter `%s', must between 0 and %u", optarg
, IP6T_NTH_NUM_COUNTERS
-1);
140 /* assign the values */
141 *flags
|= IP6T_NTH_OPT_COUNTER
;
142 nthinfo
->counter
= num
;
145 /* check for common mistakes... */
146 if (!((*flags
& IP6T_NTH_OPT_EVERY
) ||
147 (*flags
& IP6T_NTH_OPT_NOT_EVERY
)))
148 exit_error(PARAMETER_PROBLEM
,
149 "Can't specify --packet before --every");
150 if ((*flags
& IP6T_NTH_OPT_NOT_EVERY
))
151 exit_error(PARAMETER_PROBLEM
,
152 "Can't specify --packet with ! --every");
154 exit_error(PARAMETER_PROBLEM
,
155 "Can't specify with ! --packet");
156 if (*flags
& IP6T_NTH_OPT_PACKET
)
157 exit_error(PARAMETER_PROBLEM
,
158 "Can't specify --packet twice");
159 if (string_to_number(optarg
, 0, nthinfo
->every
, &num
) == -1)
160 exit_error(PARAMETER_PROBLEM
,
161 "bad --packet `%s', must between 0 and %u", optarg
, nthinfo
->every
);
162 *flags
|= IP6T_NTH_OPT_PACKET
;
163 nthinfo
->packet
= num
;
171 /* Final check; nothing. */
172 static void final_check(unsigned int flags
)
176 /* Prints out the targinfo. */
178 print(const struct ip6t_ip6
*ip
,
179 const struct ip6t_entry_match
*match
,
182 const struct ip6t_nth_info
*nthinfo
183 = (const struct ip6t_nth_info
*)match
->data
;
185 if (nthinfo
->not == 1)
187 printf("every %uth ", (nthinfo
->every
+1));
188 if (nthinfo
->counter
!= 0)
189 printf("counter #%u ", (nthinfo
->counter
));
190 if (nthinfo
->packet
!= 0xFF)
191 printf("packet #%u ", nthinfo
->packet
);
192 if (nthinfo
->startat
!= 0)
193 printf("start at %u ", nthinfo
->startat
);
196 /* Saves the union ip6t_targinfo in parsable form to stdout. */
198 save(const struct ip6t_ip6
*ip
, const struct ip6t_entry_match
*match
)
200 const struct ip6t_nth_info
*nthinfo
201 = (const struct ip6t_nth_info
*)match
->data
;
203 if (nthinfo
->not == 1)
205 printf("--every %u ", (nthinfo
->every
+1));
206 printf("--counter %u ", (nthinfo
->counter
));
207 if (nthinfo
->startat
!= 0)
208 printf("--start %u ", nthinfo
->startat
);
209 if (nthinfo
->packet
!= 0xFF)
210 printf("--packet %u ", nthinfo
->packet
);
213 struct ip6tables_match nth
= {
215 .version
= IPTABLES_VERSION
,
216 .size
= IP6T_ALIGN(sizeof(struct ip6t_nth_info
)),
217 .userspacesize
= IP6T_ALIGN(sizeof(struct ip6t_nth_info
)),
220 .final_check
= &final_check
,
228 register_match6(&nth
);