1 /* Shared library add-on to iptables to add u32 matching,
2 * generalized matching on values found at packet offsets
4 * Detailed doc is in the kernel module source
5 * net/netfilter/xt_u32.c
7 * (C) 2002 by Don Cohen <don-netf@isis.cs3-inc.com>
8 * Released under the terms of GNU GPL v2
10 * Copyright © CC Computer Consultants GmbH, 2007
11 * Contact: <jengelh@computergmbh.de>
13 #include <sys/types.h>
23 #include <linux/netfilter/xt_u32.h>
25 static const struct option u32_opts[] = {
26 {"u32", 1, NULL, 'u'},
30 static void u32_help(void)
33 "u32 match options:\n"
35 "\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
36 "\t\t""value := range | value \",\" range\n"
37 "\t\t""range := number | number \":\" number\n"
38 "\t\t""location := number | location operator number\n"
39 "\t\t""operator := \"&\" | \"<<\" | \">>\" | \"@\"\n");
42 static void u32_dump(const struct xt_u32 *data)
44 const struct xt_u32_test *ct;
45 unsigned int testind, i;
47 for (testind = 0; testind < data->ntests; ++testind) {
48 ct = &data->tests[testind];
53 printf("0x%x", ct->location[0].number);
54 for (i = 1; i < ct->nnums; ++i) {
55 switch (ct->location[i].nextop) {
69 printf("0x%x", ct->location[i].number);
73 for (i = 0; i < ct->nvalues; ++i) {
76 if (ct->value[i].min == ct->value[i].max)
77 printf("0x%x", ct->value[i].min);
79 printf("0x%x:0x%x", ct->value[i].min,
86 /* string_to_number() is not quite what we need here ... */
87 static u_int32_t parse_number(char **s, int pos)
93 number = strtoul(*s, &end, 0);
95 xtables_error(PARAMETER_PROBLEM,
96 "u32: at char %d: expected number", pos);
98 xtables_error(PARAMETER_PROBLEM,
99 "u32: at char %d: error reading number", pos);
104 static int u32_parse(int c, char **argv, int invert, unsigned int *flags,
105 const void *entry, struct xt_entry_match **match)
107 struct xt_u32 *data = (void *)(*match)->data;
108 unsigned int testind = 0, locind = 0, valind = 0;
109 struct xt_u32_test *ct = &data->tests[testind]; /* current test */
110 char *arg = optarg; /* the argument string */
117 data->invert = invert;
121 * 0 = looking for numbers and operations,
122 * 1 = looking for ranges
125 /* read next operand/number or range */
126 while (isspace(*arg))
130 /* end of argument found */
132 xtables_error(PARAMETER_PROBLEM,
133 "u32: abrupt end of input after location specifier");
135 xtables_error(PARAMETER_PROBLEM,
136 "u32: test ended with no value specified");
139 ct->nvalues = valind;
140 data->ntests = ++testind;
142 if (testind > XT_U32_MAXSIZE)
143 xtables_error(PARAMETER_PROBLEM,
144 "u32: at char %u: too many \"&&\"s",
145 (unsigned int)(arg - start));
151 * reading location: read a number if nothing read yet,
152 * otherwise either op number or = to end location spec
156 xtables_error(PARAMETER_PROBLEM,
158 "location spec missing",
159 (unsigned int)(arg - start));
166 /* need op before number */
168 ct->location[locind].nextop = XT_U32_AND;
169 } else if (*arg == '<') {
171 xtables_error(PARAMETER_PROBLEM,
172 "u32: at char %u: a second '<' was expected", (unsigned int)(arg - start));
173 ct->location[locind].nextop = XT_U32_LEFTSH;
174 } else if (*arg == '>') {
176 xtables_error(PARAMETER_PROBLEM,
177 "u32: at char %u: a second '>' was expected", (unsigned int)(arg - start));
178 ct->location[locind].nextop = XT_U32_RIGHTSH;
179 } else if (*arg == '@') {
180 ct->location[locind].nextop = XT_U32_AT;
182 xtables_error(PARAMETER_PROBLEM,
183 "u32: at char %u: operator expected", (unsigned int)(arg - start));
187 /* now a number; string_to_number skips white space? */
188 ct->location[locind].number =
189 parse_number(&arg, arg - start);
190 if (++locind > XT_U32_MAXSIZE)
191 xtables_error(PARAMETER_PROBLEM,
192 "u32: at char %u: too many operators", (unsigned int)(arg - start));
196 * state 1 - reading values: read a range if nothing
197 * read yet, otherwise either ,range or && to end
202 xtables_error(PARAMETER_PROBLEM,
203 "u32: at char %u: a second '&' was expected", (unsigned int)(arg - start));
205 xtables_error(PARAMETER_PROBLEM,
206 "u32: at char %u: value spec missing", (unsigned int)(arg - start));
209 ct->nvalues = valind;
210 ct = &data->tests[++testind];
211 if (testind > XT_U32_MAXSIZE)
212 xtables_error(PARAMETER_PROBLEM,
213 "u32: at char %u: too many \"&&\"s", (unsigned int)(arg - start));
219 } else { /* read value range */
220 if (valind > 0) { /* need , before number */
222 xtables_error(PARAMETER_PROBLEM,
223 "u32: at char %u: expected \",\" or \"&&\"", (unsigned int)(arg - start));
226 ct->value[valind].min =
227 parse_number(&arg, arg - start);
229 while (isspace(*arg))
234 ct->value[valind].max =
235 parse_number(&arg, arg-start);
237 ct->value[valind].max =
238 ct->value[valind].min;
241 if (++valind > XT_U32_MAXSIZE)
242 xtables_error(PARAMETER_PROBLEM,
243 "u32: at char %u: too many \",\"s", (unsigned int)(arg - start));
249 static void u32_print(const void *ip, const struct xt_entry_match *match,
252 const struct xt_u32 *data = (const void *)match->data;
259 static void u32_save(const void *ip, const struct xt_entry_match *match)
261 const struct xt_u32 *data = (const void *)match->data;
268 static struct xtables_match u32_match = {
270 .family = NFPROTO_UNSPEC,
271 .version = XTABLES_VERSION,
272 .size = XT_ALIGN(sizeof(struct xt_u32)),
273 .userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
278 .extra_opts = u32_opts,
283 xtables_register_match(&u32_match);