Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libip6t_nth.c
blob19b13f796d4ae539a87e3dcada64c1e3adc87253
1 /*
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
12 in the counter cycle
15 #include <stdio.h>
16 #include <netdb.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <syslog.h>
20 #include <getopt.h>
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. */
27 static void
28 help(void)
30 printf(
31 "nth v%s options:\n"
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"
37 " and Nth-1.\n\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' },
50 { 0 }
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
60 ate an option */
61 static int
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;
68 unsigned int num;
70 switch (c) {
71 case '1':
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;
94 nthinfo->startat = 0;
95 nthinfo->packet = 0xFF;
96 if(!(*flags & IP6T_NTH_OPT_EVERY))
98 nthinfo->counter = 0;
100 if (invert)
102 *flags |= IP6T_NTH_OPT_NOT_EVERY;
103 nthinfo->not = 1;
105 else
107 *flags |= IP6T_NTH_OPT_EVERY;
108 nthinfo->not = 0;
110 break;
111 case '2':
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");
117 if (invert)
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;
128 break;
129 case '3':
130 /* check for common mistakes... */
131 if (invert)
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;
143 break;
144 case '4':
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");
153 if (invert)
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;
164 break;
165 default:
166 return 0;
168 return 1;
171 /* Final check; nothing. */
172 static void final_check(unsigned int flags)
176 /* Prints out the targinfo. */
177 static void
178 print(const struct ip6t_ip6 *ip,
179 const struct ip6t_entry_match *match,
180 int numeric)
182 const struct ip6t_nth_info *nthinfo
183 = (const struct ip6t_nth_info *)match->data;
185 if (nthinfo->not == 1)
186 printf(" !");
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. */
197 static void
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)
204 printf("! ");
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 = {
214 .name = "nth",
215 .version = IPTABLES_VERSION,
216 .size = IP6T_ALIGN(sizeof(struct ip6t_nth_info)),
217 .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_nth_info)),
218 .help = &help,
219 .parse = &parse,
220 .final_check = &final_check,
221 .print = &print,
222 .save = &save,
223 .extra_opts = opts,
226 void _init(void)
228 register_match6(&nth);