19640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt/* Shared library add-on to iptables to add u32 matching,
29640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt * generalized matching on values found at packet offsets
39640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt *
49640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt * Detailed doc is in the kernel module source
59640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt * net/netfilter/xt_u32.c
69640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt *
79640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt * (C) 2002 by Don Cohen <don-netf@isis.cs3-inc.com>
89640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt * Released under the terms of GNU GPL v2
9032722b2d24138ee92e459c779ae4869f33b1f37Jan Engelhardt *
10032722b2d24138ee92e459c779ae4869f33b1f37Jan Engelhardt * Copyright © CC Computer Consultants GmbH, 2007
11032722b2d24138ee92e459c779ae4869f33b1f37Jan Engelhardt * Contact: <jengelh@computergmbh.de>
129640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt */
139640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt#include <ctype.h>
149640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt#include <errno.h>
154f7f187ffe1773487071b413491f062d141309ddJan Engelhardt#include <stdint.h>
169640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt#include <stdlib.h>
179640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt#include <stdio.h>
189640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt#include <xtables.h>
19a2a7f2b531cc582ab6cc3c2b73715ed1d58b9eabJan Engelhardt#include <linux/netfilter/xt_u32.h>
209640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
214f7f187ffe1773487071b413491f062d141309ddJan Engelhardtenum {
224f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	O_U32 = 0,
234f7f187ffe1773487071b413491f062d141309ddJan Engelhardt};
244f7f187ffe1773487071b413491f062d141309ddJan Engelhardt
254f7f187ffe1773487071b413491f062d141309ddJan Engelhardtstatic const struct xt_option_entry u32_opts[] = {
265a66f40d2f64e8792e1360906d3d6a1c829ba2b7Jan Engelhardt	{.name = "u32", .id = O_U32, .type = XTTYPE_STRING,
275a66f40d2f64e8792e1360906d3d6a1c829ba2b7Jan Engelhardt	 .flags = XTOPT_MAND},
284f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	XTOPT_TABLEEND,
299640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt};
309640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
319640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardtstatic void u32_help(void)
329640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt{
339640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	printf(
348b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt		"u32 match options:\n"
359640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		"[!] --u32 tests\n"
369640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		"\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
379640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		"\t\t""value := range | value \",\" range\n"
389640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		"\t\t""range := number | number \":\" number\n"
399640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		"\t\t""location := number | location operator number\n"
408b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt		"\t\t""operator := \"&\" | \"<<\" | \">>\" | \"@\"\n");
419640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt}
429640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
439640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardtstatic void u32_dump(const struct xt_u32 *data)
449640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt{
459640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	const struct xt_u32_test *ct;
469640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	unsigned int testind, i;
479640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
4873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" \"");
499640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	for (testind = 0; testind < data->ntests; ++testind) {
509640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		ct = &data->tests[testind];
519640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
529640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		if (testind > 0)
539640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			printf("&&");
549640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
559640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		printf("0x%x", ct->location[0].number);
569640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		for (i = 1; i < ct->nnums; ++i) {
579640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			switch (ct->location[i].nextop) {
589640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			case XT_U32_AND:
599640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				printf("&");
609640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				break;
619640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			case XT_U32_LEFTSH:
629640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				printf("<<");
639640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				break;
649640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			case XT_U32_RIGHTSH:
659640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				printf(">>");
669640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				break;
679640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			case XT_U32_AT:
689640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				printf("@");
699640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				break;
709640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			}
719640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			printf("0x%x", ct->location[i].number);
729640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		}
739640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
749640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		printf("=");
759640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		for (i = 0; i < ct->nvalues; ++i) {
769640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			if (i > 0)
779640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				printf(",");
789640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			if (ct->value[i].min == ct->value[i].max)
799640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				printf("0x%x", ct->value[i].min);
809640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			else
819640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				printf("0x%x:0x%x", ct->value[i].min,
829640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				       ct->value[i].max);
839640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		}
849640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	}
8573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	putchar('\"');
869640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt}
879640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
889640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt/* string_to_number() is not quite what we need here ... */
894f7f187ffe1773487071b413491f062d141309ddJan Engelhardtstatic uint32_t parse_number(const char **s, int pos)
909640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt{
917ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt	uint32_t number;
929640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	char *end;
939640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
949640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	errno  = 0;
959640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	number = strtoul(*s, &end, 0);
969640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	if (end == *s)
971829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
989640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			   "u32: at char %d: expected number", pos);
999640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	if (errno != 0)
1001829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt		xtables_error(PARAMETER_PROBLEM,
1019640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			   "u32: at char %d: error reading number", pos);
1029640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	*s = end;
1039640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	return number;
1049640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt}
1059640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
1064f7f187ffe1773487071b413491f062d141309ddJan Engelhardtstatic void u32_parse(struct xt_option_call *cb)
1079640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt{
1084f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	struct xt_u32 *data = cb->data;
1099640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	unsigned int testind = 0, locind = 0, valind = 0;
1109640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	struct xt_u32_test *ct = &data->tests[testind]; /* current test */
1114f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	const char *arg = cb->arg; /* the argument string */
1124f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	const char *start = cb->arg;
1139640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	int state = 0;
1149640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
115373e8513c4b9b0491e46ae89397ead03d093ee76Jan Engelhardt	xtables_option_parse(cb);
1164f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	data->invert = cb->invert;
1179640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
1189640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	/*
1199640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	 * states:
1209640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	 * 0 = looking for numbers and operations,
1219640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	 * 1 = looking for ranges
1229640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	 */
1239640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	while (1) {
1249640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		/* read next operand/number or range */
1259640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		while (isspace(*arg))
1269640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			++arg;
1279640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
1289640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		if (*arg == '\0') {
1299640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			/* end of argument found */
1309640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			if (state == 0)
1311829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt				xtables_error(PARAMETER_PROBLEM,
1329640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					   "u32: abrupt end of input after location specifier");
1339640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			if (valind == 0)
1341829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt				xtables_error(PARAMETER_PROBLEM,
1359640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					   "u32: test ended with no value specified");
1369640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
1379640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			ct->nnums    = locind;
1389640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			ct->nvalues  = valind;
1399640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			data->ntests = ++testind;
1409640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
1419640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			if (testind > XT_U32_MAXSIZE)
1421829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt				xtables_error(PARAMETER_PROBLEM,
14355951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt				           "u32: at char %u: too many \"&&\"s",
14455951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt				           (unsigned int)(arg - start));
1454f7f187ffe1773487071b413491f062d141309ddJan Engelhardt			return;
1469640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		}
1479640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
1489640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		if (state == 0) {
1499640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			/*
1509640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			 * reading location: read a number if nothing read yet,
1519640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			 * otherwise either op number or = to end location spec
1529640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			 */
1539640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			if (*arg == '=') {
1549640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (locind == 0) {
1551829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt					xtables_error(PARAMETER_PROBLEM,
15655951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt					           "u32: at char %u: "
1579640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					           "location spec missing",
15855951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt					           (unsigned int)(arg - start));
1599640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				} else {
1609640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					++arg;
1619640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					state = 1;
1629640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				}
1639640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			} else {
1649640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (locind != 0) {
1659640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					/* need op before number */
1669640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					if (*arg == '&') {
1679640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						ct->location[locind].nextop = XT_U32_AND;
1689640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					} else if (*arg == '<') {
1699640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						if (*++arg != '<')
1701829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt							xtables_error(PARAMETER_PROBLEM,
17155951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt								   "u32: at char %u: a second '<' was expected", (unsigned int)(arg - start));
1729640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						ct->location[locind].nextop = XT_U32_LEFTSH;
1739640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					} else if (*arg == '>') {
1749640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						if (*++arg != '>')
1751829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt							xtables_error(PARAMETER_PROBLEM,
17655951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt								   "u32: at char %u: a second '>' was expected", (unsigned int)(arg - start));
1779640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						ct->location[locind].nextop = XT_U32_RIGHTSH;
1789640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					} else if (*arg == '@') {
1799640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						ct->location[locind].nextop = XT_U32_AT;
1809640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					} else {
1811829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt						xtables_error(PARAMETER_PROBLEM,
18255951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt							"u32: at char %u: operator expected", (unsigned int)(arg - start));
1839640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					}
1849640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					++arg;
1859640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				}
1869640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				/* now a number; string_to_number skips white space? */
1879640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				ct->location[locind].number =
1889640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					parse_number(&arg, arg - start);
1899640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (++locind > XT_U32_MAXSIZE)
1901829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt					xtables_error(PARAMETER_PROBLEM,
19155951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt						   "u32: at char %u: too many operators", (unsigned int)(arg - start));
1929640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			}
1939640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		} else {
1949640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			/*
1959640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			 * state 1 - reading values: read a range if nothing
1969640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			 * read yet, otherwise either ,range or && to end
1979640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			 * test spec
1989640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			 */
1999640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			if (*arg == '&') {
2009640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (*++arg != '&')
2011829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt					xtables_error(PARAMETER_PROBLEM,
20255951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt						   "u32: at char %u: a second '&' was expected", (unsigned int)(arg - start));
2039640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (valind == 0) {
2041829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt					xtables_error(PARAMETER_PROBLEM,
20555951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt						   "u32: at char %u: value spec missing", (unsigned int)(arg - start));
2069640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				} else {
2079640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					ct->nnums   = locind;
2089640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					ct->nvalues = valind;
2099640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					ct = &data->tests[++testind];
2109640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					if (testind > XT_U32_MAXSIZE)
2111829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt						xtables_error(PARAMETER_PROBLEM,
21255951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt							   "u32: at char %u: too many \"&&\"s", (unsigned int)(arg - start));
2139640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					++arg;
2149640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					state  = 0;
2159640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					locind = 0;
2169640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					valind = 0;
2179640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				}
2189640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			} else { /* read value range */
2199640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (valind > 0) { /* need , before number */
2209640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					if (*arg != ',')
2211829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt						xtables_error(PARAMETER_PROBLEM,
22255951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt							   "u32: at char %u: expected \",\" or \"&&\"", (unsigned int)(arg - start));
2239640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					++arg;
2249640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				}
2259640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				ct->value[valind].min =
2269640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					parse_number(&arg, arg - start);
2279640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
2289640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				while (isspace(*arg))
2299640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					++arg;
2309640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
2319640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (*arg == ':') {
2329640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					++arg;
2339640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					ct->value[valind].max =
2349640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						parse_number(&arg, arg-start);
2359640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				} else {
2369640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt					ct->value[valind].max =
2379640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt						ct->value[valind].min;
2389640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				}
2399640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
2409640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt				if (++valind > XT_U32_MAXSIZE)
2411829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt					xtables_error(PARAMETER_PROBLEM,
24255951a0532e35cf73bd83b01014387616eb31431Jan Engelhardt						   "u32: at char %u: too many \",\"s", (unsigned int)(arg - start));
2439640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt			}
2449640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt		}
2459640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	}
2469640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt}
2479640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
2489640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardtstatic void u32_print(const void *ip, const struct xt_entry_match *match,
2499640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt                      int numeric)
2509640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt{
2519640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	const struct xt_u32 *data = (const void *)match->data;
25273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" u32");
2539640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	if (data->invert)
25473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" !");
2559640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	u32_dump(data);
2569640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt}
2579640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
2589640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardtstatic void u32_save(const void *ip, const struct xt_entry_match *match)
2599640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt{
2609640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	const struct xt_u32 *data = (const void *)match->data;
2619640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	if (data->invert)
26273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" !");
26373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" --u32");
2649640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	u32_dump(data);
2659640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt}
2669640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
267181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match u32_match = {
2689640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	.name          = "u32",
26942979363f3958b4436c6d2503753c182c58e55eaJan Engelhardt	.family        = NFPROTO_UNSPEC,
2708b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt	.version       = XTABLES_VERSION,
2719640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	.size          = XT_ALIGN(sizeof(struct xt_u32)),
2729640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	.userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
2739640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	.help          = u32_help,
2749640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	.print         = u32_print,
2759640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt	.save          = u32_save,
2764f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	.x6_parse      = u32_parse,
2774f7f187ffe1773487071b413491f062d141309ddJan Engelhardt	.x6_options    = u32_opts,
2789640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt};
2799640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt
2809640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardtvoid _init(void)
2819640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt{
282181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt	xtables_register_match(&u32_match);
2839640e529bd08c4c0458246fae0fd6b473c94ab46Jan Engelhardt}
284