Blame bootstrap_ver/extensions/libxt_u32.c

Packit Service dd8e2b
/* Shared library add-on to iptables to add u32 matching,
Packit Service dd8e2b
 * generalized matching on values found at packet offsets
Packit Service dd8e2b
 *
Packit Service dd8e2b
 * Detailed doc is in the kernel module source
Packit Service dd8e2b
 * net/netfilter/xt_u32.c
Packit Service dd8e2b
 *
Packit Service dd8e2b
 * (C) 2002 by Don Cohen <don-netf@isis.cs3-inc.com>
Packit Service dd8e2b
 * Released under the terms of GNU GPL v2
Packit Service dd8e2b
 *
Packit Service dd8e2b
 * Copyright © CC Computer Consultants GmbH, 2007
Packit Service dd8e2b
 * Contact: <jengelh@computergmbh.de>
Packit Service dd8e2b
 */
Packit Service dd8e2b
#include <ctype.h>
Packit Service dd8e2b
#include <errno.h>
Packit Service dd8e2b
#include <stdint.h>
Packit Service dd8e2b
#include <stdlib.h>
Packit Service dd8e2b
#include <stdio.h>
Packit Service dd8e2b
#include <xtables.h>
Packit Service dd8e2b
#include <linux/netfilter/xt_u32.h>
Packit Service dd8e2b
Packit Service dd8e2b
enum {
Packit Service dd8e2b
	O_U32 = 0,
Packit Service dd8e2b
};
Packit Service dd8e2b
Packit Service dd8e2b
static const struct xt_option_entry u32_opts[] = {
Packit Service dd8e2b
	{.name = "u32", .id = O_U32, .type = XTTYPE_STRING,
Packit Service dd8e2b
	 .flags = XTOPT_MAND | XTOPT_INVERT},
Packit Service dd8e2b
	XTOPT_TABLEEND,
Packit Service dd8e2b
};
Packit Service dd8e2b
Packit Service dd8e2b
static void u32_help(void)
Packit Service dd8e2b
{
Packit Service dd8e2b
	printf(
Packit Service dd8e2b
		"u32 match options:\n"
Packit Service dd8e2b
		"[!] --u32 tests\n"
Packit Service dd8e2b
		"\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
Packit Service dd8e2b
		"\t\t""value := range | value \",\" range\n"
Packit Service dd8e2b
		"\t\t""range := number | number \":\" number\n"
Packit Service dd8e2b
		"\t\t""location := number | location operator number\n"
Packit Service dd8e2b
		"\t\t""operator := \"&\" | \"<<\" | \">>\" | \"@\"\n");
Packit Service dd8e2b
}
Packit Service dd8e2b
Packit Service dd8e2b
static void u32_dump(const struct xt_u32 *data)
Packit Service dd8e2b
{
Packit Service dd8e2b
	const struct xt_u32_test *ct;
Packit Service dd8e2b
	unsigned int testind, i;
Packit Service dd8e2b
Packit Service dd8e2b
	printf(" \"");
Packit Service dd8e2b
	for (testind = 0; testind < data->ntests; ++testind) {
Packit Service dd8e2b
		ct = &data->tests[testind];
Packit Service dd8e2b
Packit Service dd8e2b
		if (testind > 0)
Packit Service dd8e2b
			printf("&&";;
Packit Service dd8e2b
Packit Service dd8e2b
		printf("0x%x", ct->location[0].number);
Packit Service dd8e2b
		for (i = 1; i < ct->nnums; ++i) {
Packit Service dd8e2b
			switch (ct->location[i].nextop) {
Packit Service dd8e2b
			case XT_U32_AND:
Packit Service dd8e2b
				printf("&";;
Packit Service dd8e2b
				break;
Packit Service dd8e2b
			case XT_U32_LEFTSH:
Packit Service dd8e2b
				printf("<<");
Packit Service dd8e2b
				break;
Packit Service dd8e2b
			case XT_U32_RIGHTSH:
Packit Service dd8e2b
				printf(">>");
Packit Service dd8e2b
				break;
Packit Service dd8e2b
			case XT_U32_AT:
Packit Service dd8e2b
				printf("@");
Packit Service dd8e2b
				break;
Packit Service dd8e2b
			}
Packit Service dd8e2b
			printf("0x%x", ct->location[i].number);
Packit Service dd8e2b
		}
Packit Service dd8e2b
Packit Service dd8e2b
		printf("=");
Packit Service dd8e2b
		for (i = 0; i < ct->nvalues; ++i) {
Packit Service dd8e2b
			if (i > 0)
Packit Service dd8e2b
				printf(",");
Packit Service dd8e2b
			if (ct->value[i].min == ct->value[i].max)
Packit Service dd8e2b
				printf("0x%x", ct->value[i].min);
Packit Service dd8e2b
			else
Packit Service dd8e2b
				printf("0x%x:0x%x", ct->value[i].min,
Packit Service dd8e2b
				       ct->value[i].max);
Packit Service dd8e2b
		}
Packit Service dd8e2b
	}
Packit Service dd8e2b
	putchar('\"');
Packit Service dd8e2b
}
Packit Service dd8e2b
Packit Service dd8e2b
/* string_to_number() is not quite what we need here ... */
Packit Service dd8e2b
static uint32_t parse_number(const char **s, int pos)
Packit Service dd8e2b
{
Packit Service dd8e2b
	unsigned int number;
Packit Service dd8e2b
	char *end;
Packit Service dd8e2b
Packit Service dd8e2b
	if (!xtables_strtoui(*s, &end, &number, 0, UINT32_MAX) ||
Packit Service dd8e2b
	    end == *s)
Packit Service dd8e2b
		xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
			"u32: at char %d: not a number or out of range", pos);
Packit Service dd8e2b
	*s = end;
Packit Service dd8e2b
	return number;
Packit Service dd8e2b
}
Packit Service dd8e2b
Packit Service dd8e2b
static void u32_parse(struct xt_option_call *cb)
Packit Service dd8e2b
{
Packit Service dd8e2b
	struct xt_u32 *data = cb->data;
Packit Service dd8e2b
	unsigned int testind = 0, locind = 0, valind = 0;
Packit Service dd8e2b
	struct xt_u32_test *ct = &data->tests[testind]; /* current test */
Packit Service dd8e2b
	const char *arg = cb->arg; /* the argument string */
Packit Service dd8e2b
	const char *start = cb->arg;
Packit Service dd8e2b
	int state = 0;
Packit Service dd8e2b
Packit Service dd8e2b
	xtables_option_parse(cb);
Packit Service dd8e2b
	data->invert = cb->invert;
Packit Service dd8e2b
Packit Service dd8e2b
	/*
Packit Service dd8e2b
	 * states:
Packit Service dd8e2b
	 * 0 = looking for numbers and operations,
Packit Service dd8e2b
	 * 1 = looking for ranges
Packit Service dd8e2b
	 */
Packit Service dd8e2b
	while (1) {
Packit Service dd8e2b
		/* read next operand/number or range */
Packit Service dd8e2b
		while (isspace(*arg))
Packit Service dd8e2b
			++arg;
Packit Service dd8e2b
Packit Service dd8e2b
		if (*arg == '\0') {
Packit Service dd8e2b
			/* end of argument found */
Packit Service dd8e2b
			if (state == 0)
Packit Service dd8e2b
				xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
					   "u32: abrupt end of input after location specifier");
Packit Service dd8e2b
			if (valind == 0)
Packit Service dd8e2b
				xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
					   "u32: test ended with no value specified");
Packit Service dd8e2b
Packit Service dd8e2b
			ct->nnums    = locind;
Packit Service dd8e2b
			ct->nvalues  = valind;
Packit Service dd8e2b
			data->ntests = ++testind;
Packit Service dd8e2b
Packit Service dd8e2b
			if (testind > XT_U32_MAXSIZE)
Packit Service dd8e2b
				xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
				           "u32: at char %u: too many \"&&\"s",
Packit Service dd8e2b
				           (unsigned int)(arg - start));
Packit Service dd8e2b
			return;
Packit Service dd8e2b
		}
Packit Service dd8e2b
Packit Service dd8e2b
		if (state == 0) {
Packit Service dd8e2b
			/*
Packit Service dd8e2b
			 * reading location: read a number if nothing read yet,
Packit Service dd8e2b
			 * otherwise either op number or = to end location spec
Packit Service dd8e2b
			 */
Packit Service dd8e2b
			if (*arg == '=') {
Packit Service dd8e2b
				if (locind == 0) {
Packit Service dd8e2b
					xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
					           "u32: at char %u: "
Packit Service dd8e2b
					           "location spec missing",
Packit Service dd8e2b
					           (unsigned int)(arg - start));
Packit Service dd8e2b
				} else {
Packit Service dd8e2b
					++arg;
Packit Service dd8e2b
					state = 1;
Packit Service dd8e2b
				}
Packit Service dd8e2b
			} else {
Packit Service dd8e2b
				if (locind != 0) {
Packit Service dd8e2b
					/* need op before number */
Packit Service dd8e2b
					if (*arg == '&') {
Packit Service dd8e2b
						ct->location[locind].nextop = XT_U32_AND;
Packit Service dd8e2b
					} else if (*arg == '<') {
Packit Service dd8e2b
						if (*++arg != '<')
Packit Service dd8e2b
							xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
								   "u32: at char %u: a second '<' was expected", (unsigned int)(arg - start));
Packit Service dd8e2b
						ct->location[locind].nextop = XT_U32_LEFTSH;
Packit Service dd8e2b
					} else if (*arg == '>') {
Packit Service dd8e2b
						if (*++arg != '>')
Packit Service dd8e2b
							xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
								   "u32: at char %u: a second '>' was expected", (unsigned int)(arg - start));
Packit Service dd8e2b
						ct->location[locind].nextop = XT_U32_RIGHTSH;
Packit Service dd8e2b
					} else if (*arg == '@') {
Packit Service dd8e2b
						ct->location[locind].nextop = XT_U32_AT;
Packit Service dd8e2b
					} else {
Packit Service dd8e2b
						xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
							"u32: at char %u: operator expected", (unsigned int)(arg - start));
Packit Service dd8e2b
					}
Packit Service dd8e2b
					++arg;
Packit Service dd8e2b
				}
Packit Service dd8e2b
				/* now a number; string_to_number skips white space? */
Packit Service dd8e2b
				ct->location[locind].number =
Packit Service dd8e2b
					parse_number(&arg, arg - start);
Packit Service dd8e2b
				if (++locind > XT_U32_MAXSIZE)
Packit Service dd8e2b
					xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
						   "u32: at char %u: too many operators", (unsigned int)(arg - start));
Packit Service dd8e2b
			}
Packit Service dd8e2b
		} else {
Packit Service dd8e2b
			/*
Packit Service dd8e2b
			 * state 1 - reading values: read a range if nothing
Packit Service dd8e2b
			 * read yet, otherwise either ,range or && to end
Packit Service dd8e2b
			 * test spec
Packit Service dd8e2b
			 */
Packit Service dd8e2b
			if (*arg == '&') {
Packit Service dd8e2b
				if (*++arg != '&')
Packit Service dd8e2b
					xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
						   "u32: at char %u: a second '&' was expected", (unsigned int)(arg - start));
Packit Service dd8e2b
				if (valind == 0) {
Packit Service dd8e2b
					xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
						   "u32: at char %u: value spec missing", (unsigned int)(arg - start));
Packit Service dd8e2b
				} else {
Packit Service dd8e2b
					ct->nnums   = locind;
Packit Service dd8e2b
					ct->nvalues = valind;
Packit Service dd8e2b
					ct = &data->tests[++testind];
Packit Service dd8e2b
					if (testind > XT_U32_MAXSIZE)
Packit Service dd8e2b
						xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
							   "u32: at char %u: too many \"&&\"s", (unsigned int)(arg - start));
Packit Service dd8e2b
					++arg;
Packit Service dd8e2b
					state  = 0;
Packit Service dd8e2b
					locind = 0;
Packit Service dd8e2b
					valind = 0;
Packit Service dd8e2b
				}
Packit Service dd8e2b
			} else { /* read value range */
Packit Service dd8e2b
				if (valind > 0) { /* need , before number */
Packit Service dd8e2b
					if (*arg != ',')
Packit Service dd8e2b
						xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
							   "u32: at char %u: expected \",\" or \"&&\"", (unsigned int)(arg - start));
Packit Service dd8e2b
					++arg;
Packit Service dd8e2b
				}
Packit Service dd8e2b
				ct->value[valind].min =
Packit Service dd8e2b
					parse_number(&arg, arg - start);
Packit Service dd8e2b
Packit Service dd8e2b
				while (isspace(*arg))
Packit Service dd8e2b
					++arg;
Packit Service dd8e2b
Packit Service dd8e2b
				if (*arg == ':') {
Packit Service dd8e2b
					++arg;
Packit Service dd8e2b
					ct->value[valind].max =
Packit Service dd8e2b
						parse_number(&arg, arg-start);
Packit Service dd8e2b
				} else {
Packit Service dd8e2b
					ct->value[valind].max =
Packit Service dd8e2b
						ct->value[valind].min;
Packit Service dd8e2b
				}
Packit Service dd8e2b
Packit Service dd8e2b
				if (++valind > XT_U32_MAXSIZE)
Packit Service dd8e2b
					xtables_error(PARAMETER_PROBLEM,
Packit Service dd8e2b
						   "u32: at char %u: too many \",\"s", (unsigned int)(arg - start));
Packit Service dd8e2b
			}
Packit Service dd8e2b
		}
Packit Service dd8e2b
	}
Packit Service dd8e2b
}
Packit Service dd8e2b
Packit Service dd8e2b
static void u32_print(const void *ip, const struct xt_entry_match *match,
Packit Service dd8e2b
                      int numeric)
Packit Service dd8e2b
{
Packit Service dd8e2b
	const struct xt_u32 *data = (const void *)match->data;
Packit Service dd8e2b
	printf(" u32");
Packit Service dd8e2b
	if (data->invert)
Packit Service dd8e2b
		printf(" !");
Packit Service dd8e2b
	u32_dump(data);
Packit Service dd8e2b
}
Packit Service dd8e2b
Packit Service dd8e2b
static void u32_save(const void *ip, const struct xt_entry_match *match)
Packit Service dd8e2b
{
Packit Service dd8e2b
	const struct xt_u32 *data = (const void *)match->data;
Packit Service dd8e2b
	if (data->invert)
Packit Service dd8e2b
		printf(" !");
Packit Service dd8e2b
	printf(" --u32");
Packit Service dd8e2b
	u32_dump(data);
Packit Service dd8e2b
}
Packit Service dd8e2b
Packit Service dd8e2b
static struct xtables_match u32_match = {
Packit Service dd8e2b
	.name          = "u32",
Packit Service dd8e2b
	.family        = NFPROTO_UNSPEC,
Packit Service dd8e2b
	.version       = XTABLES_VERSION,
Packit Service dd8e2b
	.size          = XT_ALIGN(sizeof(struct xt_u32)),
Packit Service dd8e2b
	.userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
Packit Service dd8e2b
	.help          = u32_help,
Packit Service dd8e2b
	.print         = u32_print,
Packit Service dd8e2b
	.save          = u32_save,
Packit Service dd8e2b
	.x6_parse      = u32_parse,
Packit Service dd8e2b
	.x6_options    = u32_opts,
Packit Service dd8e2b
};
Packit Service dd8e2b
Packit Service dd8e2b
void _init(void)
Packit Service dd8e2b
{
Packit Service dd8e2b
	xtables_register_match(&u32_match);
Packit Service dd8e2b
}