[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/app/iptables/extensions/libxt_u32.c b/ap/app/iptables/extensions/libxt_u32.c
new file mode 100755
index 0000000..c2aeb27
--- /dev/null
+++ b/ap/app/iptables/extensions/libxt_u32.c
@@ -0,0 +1,284 @@
+/* Shared library add-on to iptables to add u32 matching,
+ * generalized matching on values found at packet offsets
+ *
+ * Detailed doc is in the kernel module source
+ * net/netfilter/xt_u32.c
+ *
+ * (C) 2002 by Don Cohen <don-netf@isis.cs3-inc.com>
+ * Released under the terms of GNU GPL v2
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: <jengelh@computergmbh.de>
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static const struct option u32_opts[] = {
+	{"u32", 1, NULL, 'u'},
+	{ .name = NULL }
+};
+
+static void u32_help(void)
+{
+	printf(
+		"u32 match options:\n"
+		"[!] --u32 tests\n"
+		"\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
+		"\t\t""value := range | value \",\" range\n"
+		"\t\t""range := number | number \":\" number\n"
+		"\t\t""location := number | location operator number\n"
+		"\t\t""operator := \"&\" | \"<<\" | \">>\" | \"@\"\n");
+}
+
+static void u32_dump(const struct xt_u32 *data)
+{
+	const struct xt_u32_test *ct;
+	unsigned int testind, i;
+
+	for (testind = 0; testind < data->ntests; ++testind) {
+		ct = &data->tests[testind];
+
+		if (testind > 0)
+			printf("&&");
+
+		printf("0x%x", ct->location[0].number);
+		for (i = 1; i < ct->nnums; ++i) {
+			switch (ct->location[i].nextop) {
+			case XT_U32_AND:
+				printf("&");
+				break;
+			case XT_U32_LEFTSH:
+				printf("<<");
+				break;
+			case XT_U32_RIGHTSH:
+				printf(">>");
+				break;
+			case XT_U32_AT:
+				printf("@");
+				break;
+			}
+			printf("0x%x", ct->location[i].number);
+		}
+
+		printf("=");
+		for (i = 0; i < ct->nvalues; ++i) {
+			if (i > 0)
+				printf(",");
+			if (ct->value[i].min == ct->value[i].max)
+				printf("0x%x", ct->value[i].min);
+			else
+				printf("0x%x:0x%x", ct->value[i].min,
+				       ct->value[i].max);
+		}
+	}
+	printf(" ");
+}
+
+/* string_to_number() is not quite what we need here ... */
+static u_int32_t parse_number(char **s, int pos)
+{
+	u_int32_t number;
+	char *end;
+
+	errno  = 0;
+	number = strtoul(*s, &end, 0);
+	if (end == *s)
+		xtables_error(PARAMETER_PROBLEM,
+			   "u32: at char %d: expected number", pos);
+	if (errno != 0)
+		xtables_error(PARAMETER_PROBLEM,
+			   "u32: at char %d: error reading number", pos);
+	*s = end;
+	return number;
+}
+
+static int u32_parse(int c, char **argv, int invert, unsigned int *flags,
+		     const void *entry, struct xt_entry_match **match)
+{
+	struct xt_u32 *data = (void *)(*match)->data;
+	unsigned int testind = 0, locind = 0, valind = 0;
+	struct xt_u32_test *ct = &data->tests[testind]; /* current test */
+	char *arg = argv[optind-1]; /* the argument string */
+	char *start = arg;
+	int state = 0;
+
+	if (c != 'u')
+		return 0;
+
+	data->invert = invert;
+
+	/*
+	 * states:
+	 * 0 = looking for numbers and operations,
+	 * 1 = looking for ranges
+	 */
+	while (1) {
+		/* read next operand/number or range */
+		while (isspace(*arg))
+			++arg;
+
+		if (*arg == '\0') {
+			/* end of argument found */
+			if (state == 0)
+				xtables_error(PARAMETER_PROBLEM,
+					   "u32: abrupt end of input after location specifier");
+			if (valind == 0)
+				xtables_error(PARAMETER_PROBLEM,
+					   "u32: test ended with no value specified");
+
+			ct->nnums    = locind;
+			ct->nvalues  = valind;
+			data->ntests = ++testind;
+
+			if (testind > XT_U32_MAXSIZE)
+				xtables_error(PARAMETER_PROBLEM,
+				           "u32: at char %u: too many \"&&\"s",
+				           (unsigned int)(arg - start));
+			return 1;
+		}
+
+		if (state == 0) {
+			/*
+			 * reading location: read a number if nothing read yet,
+			 * otherwise either op number or = to end location spec
+			 */
+			if (*arg == '=') {
+				if (locind == 0) {
+					xtables_error(PARAMETER_PROBLEM,
+					           "u32: at char %u: "
+					           "location spec missing",
+					           (unsigned int)(arg - start));
+				} else {
+					++arg;
+					state = 1;
+				}
+			} else {
+				if (locind != 0) {
+					/* need op before number */
+					if (*arg == '&') {
+						ct->location[locind].nextop = XT_U32_AND;
+					} else if (*arg == '<') {
+						if (*++arg != '<')
+							xtables_error(PARAMETER_PROBLEM,
+								   "u32: at char %u: a second '<' was expected", (unsigned int)(arg - start));
+						ct->location[locind].nextop = XT_U32_LEFTSH;
+					} else if (*arg == '>') {
+						if (*++arg != '>')
+							xtables_error(PARAMETER_PROBLEM,
+								   "u32: at char %u: a second '>' was expected", (unsigned int)(arg - start));
+						ct->location[locind].nextop = XT_U32_RIGHTSH;
+					} else if (*arg == '@') {
+						ct->location[locind].nextop = XT_U32_AT;
+					} else {
+						xtables_error(PARAMETER_PROBLEM,
+							"u32: at char %u: operator expected", (unsigned int)(arg - start));
+					}
+					++arg;
+				}
+				/* now a number; string_to_number skips white space? */
+				ct->location[locind].number =
+					parse_number(&arg, arg - start);
+				if (++locind > XT_U32_MAXSIZE)
+					xtables_error(PARAMETER_PROBLEM,
+						   "u32: at char %u: too many operators", (unsigned int)(arg - start));
+			}
+		} else {
+			/*
+			 * state 1 - reading values: read a range if nothing
+			 * read yet, otherwise either ,range or && to end
+			 * test spec
+			 */
+			if (*arg == '&') {
+				if (*++arg != '&')
+					xtables_error(PARAMETER_PROBLEM,
+						   "u32: at char %u: a second '&' was expected", (unsigned int)(arg - start));
+				if (valind == 0) {
+					xtables_error(PARAMETER_PROBLEM,
+						   "u32: at char %u: value spec missing", (unsigned int)(arg - start));
+				} else {
+					ct->nnums   = locind;
+					ct->nvalues = valind;
+					ct = &data->tests[++testind];
+					if (testind > XT_U32_MAXSIZE)
+						xtables_error(PARAMETER_PROBLEM,
+							   "u32: at char %u: too many \"&&\"s", (unsigned int)(arg - start));
+					++arg;
+					state  = 0;
+					locind = 0;
+					valind = 0;
+				}
+			} else { /* read value range */
+				if (valind > 0) { /* need , before number */
+					if (*arg != ',')
+						xtables_error(PARAMETER_PROBLEM,
+							   "u32: at char %u: expected \",\" or \"&&\"", (unsigned int)(arg - start));
+					++arg;
+				}
+				ct->value[valind].min =
+					parse_number(&arg, arg - start);
+
+				while (isspace(*arg))
+					++arg;
+
+				if (*arg == ':') {
+					++arg;
+					ct->value[valind].max =
+						parse_number(&arg, arg-start);
+				} else {
+					ct->value[valind].max =
+						ct->value[valind].min;
+				}
+
+				if (++valind > XT_U32_MAXSIZE)
+					xtables_error(PARAMETER_PROBLEM,
+						   "u32: at char %u: too many \",\"s", (unsigned int)(arg - start));
+			}
+		}
+	}
+}
+
+static void u32_print(const void *ip, const struct xt_entry_match *match,
+                      int numeric)
+{
+	const struct xt_u32 *data = (const void *)match->data;
+	printf("u32 ");
+	if (data->invert)
+		printf("! ");
+	u32_dump(data);
+}
+
+static void u32_save(const void *ip, const struct xt_entry_match *match)
+{
+	const struct xt_u32 *data = (const void *)match->data;
+	if (data->invert)
+		printf("! ");
+	printf("--u32 ");
+	u32_dump(data);
+}
+
+static struct xtables_match u32_match = {
+	.name          = "u32",
+	.family        = AF_UNSPEC,
+	.version       = XTABLES_VERSION,
+	.size          = XT_ALIGN(sizeof(struct xt_u32)),
+	.userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
+	.help          = u32_help,
+	.parse         = u32_parse,
+	.print         = u32_print,
+	.save          = u32_save,
+	.extra_opts    = u32_opts,
+};
+
+void _init(void)
+{
+	xtables_register_match(&u32_match);
+}