[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/libipt_SNAT.c b/ap/app/iptables/extensions/libipt_SNAT.c
new file mode 100755
index 0000000..944fe67
--- /dev/null
+++ b/ap/app/iptables/extensions/libipt_SNAT.c
@@ -0,0 +1,260 @@
+/* Shared library add-on to iptables to add source-NAT support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <iptables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <net/netfilter/nf_nat.h>
+
+#define IPT_SNAT_OPT_SOURCE 0x01
+#define IPT_SNAT_OPT_RANDOM 0x02
+
+/* Source NAT data consists of a multi-range, indicating where to map
+   to. */
+struct ipt_natinfo
+{
+	struct xt_entry_target t;
+	struct nf_nat_multi_range mr;
+};
+
+static void SNAT_help(void)
+{
+	printf(
+"SNAT target options:\n"
+" --to-source <ipaddr>[-<ipaddr>][:port-port]\n"
+"				Address to map source to.\n"
+"[--random]\n");
+}
+
+static const struct option SNAT_opts[] = {
+	{ "to-source", 1, NULL, '1' },
+	{ "random", 0, NULL, '2' },
+	{ .name = NULL }
+};
+
+static struct ipt_natinfo *
+append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
+{
+	unsigned int size;
+
+	/* One rangesize already in struct ipt_natinfo */
+	size = XT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
+
+	info = realloc(info, size);
+	if (!info)
+		xtables_error(OTHER_PROBLEM, "Out of memory\n");
+
+	info->t.u.target_size = size;
+	info->mr.range[info->mr.rangesize] = *range;
+	info->mr.rangesize++;
+
+	return info;
+}
+
+/* Ranges expected in network order. */
+static struct xt_entry_target *
+parse_to(char *arg, int portok, struct ipt_natinfo *info)
+{
+	struct nf_nat_range range;
+	char *colon, *dash, *error;
+	const struct in_addr *ip;
+
+	memset(&range, 0, sizeof(range));
+	colon = strchr(arg, ':');
+
+	if (colon) {
+		int port;
+
+		if (!portok)
+			xtables_error(PARAMETER_PROBLEM,
+				   "Need TCP, UDP, SCTP or DCCP with port specification");
+
+		range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
+
+		port = atoi(colon+1);
+		if (port <= 0 || port > 65535)
+			xtables_error(PARAMETER_PROBLEM,
+				   "Port `%s' not valid\n", colon+1);
+
+		error = strchr(colon+1, ':');
+		if (error)
+			xtables_error(PARAMETER_PROBLEM,
+				   "Invalid port:port syntax - use dash\n");
+
+		dash = strchr(colon, '-');
+		if (!dash) {
+			range.min.tcp.port
+				= range.max.tcp.port
+				= htons(port);
+		} else {
+			int maxport;
+
+			maxport = atoi(dash + 1);
+			if (maxport <= 0 || maxport > 65535)
+				xtables_error(PARAMETER_PROBLEM,
+					   "Port `%s' not valid\n", dash+1);
+			if (maxport < port)
+				/* People are stupid. */
+				xtables_error(PARAMETER_PROBLEM,
+					   "Port range `%s' funky\n", colon+1);
+			range.min.tcp.port = htons(port);
+			range.max.tcp.port = htons(maxport);
+		}
+		/* Starts with a colon? No IP info...*/
+		if (colon == arg)
+			return &(append_range(info, &range)->t);
+		*colon = '\0';
+	}
+
+	range.flags |= IP_NAT_RANGE_MAP_IPS;
+	dash = strchr(arg, '-');
+	if (colon && dash && dash > colon)
+		dash = NULL;
+
+	if (dash)
+		*dash = '\0';
+
+	ip = xtables_numeric_to_ipaddr(arg);
+	if (!ip)
+		xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+			   arg);
+	range.min_ip = ip->s_addr;
+	if (dash) {
+		ip = xtables_numeric_to_ipaddr(dash+1);
+		if (!ip)
+			xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
+				   dash+1);
+		range.max_ip = ip->s_addr;
+	} else
+		range.max_ip = range.min_ip;
+
+	return &(append_range(info, &range)->t);
+}
+
+static int SNAT_parse(int c, char **argv, int invert, unsigned int *flags,
+                      const void *e, struct xt_entry_target **target)
+{
+	const struct ipt_entry *entry = e;
+	struct ipt_natinfo *info = (void *)*target;
+	int portok;
+
+	if (entry->ip.proto == IPPROTO_TCP
+	    || entry->ip.proto == IPPROTO_UDP
+	    || entry->ip.proto == IPPROTO_SCTP
+	    || entry->ip.proto == IPPROTO_DCCP
+	    || entry->ip.proto == IPPROTO_ICMP)
+		portok = 1;
+	else
+		portok = 0;
+
+	switch (c) {
+	case '1':
+		if (xtables_check_inverse(optarg, &invert, NULL, 0))
+			xtables_error(PARAMETER_PROBLEM,
+				   "Unexpected `!' after --to-source");
+
+		if (*flags & IPT_SNAT_OPT_SOURCE) {
+			if (!kernel_version)
+				get_kernel_version();
+			if (kernel_version > LINUX_VERSION(2, 6, 10))
+				xtables_error(PARAMETER_PROBLEM,
+					   "Multiple --to-source not supported");
+		}
+		*target = parse_to(optarg, portok, info);
+		/* WTF do we need this for?? */
+		if (*flags & IPT_SNAT_OPT_RANDOM)
+			info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		*flags |= IPT_SNAT_OPT_SOURCE;
+		return 1;
+
+	case '2':
+		if (*flags & IPT_SNAT_OPT_SOURCE) {
+			info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+			*flags |= IPT_SNAT_OPT_RANDOM;
+		} else
+			*flags |= IPT_SNAT_OPT_RANDOM;
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
+static void SNAT_check(unsigned int flags)
+{
+	if (!(flags & IPT_SNAT_OPT_SOURCE))
+		xtables_error(PARAMETER_PROBLEM,
+			   "You must specify --to-source");
+}
+
+static void print_range(const struct nf_nat_range *r)
+{
+	if (r->flags & IP_NAT_RANGE_MAP_IPS) {
+		struct in_addr a;
+
+		a.s_addr = r->min_ip;
+		printf("%s", xtables_ipaddr_to_numeric(&a));
+		if (r->max_ip != r->min_ip) {
+			a.s_addr = r->max_ip;
+			printf("-%s", xtables_ipaddr_to_numeric(&a));
+		}
+	}
+	if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
+		printf(":");
+		printf("%hu", ntohs(r->min.tcp.port));
+		if (r->max.tcp.port != r->min.tcp.port)
+			printf("-%hu", ntohs(r->max.tcp.port));
+	}
+}
+
+static void SNAT_print(const void *ip, const struct xt_entry_target *target,
+                       int numeric)
+{
+	struct ipt_natinfo *info = (void *)target;
+	unsigned int i = 0;
+
+	printf("to:");
+	for (i = 0; i < info->mr.rangesize; i++) {
+		print_range(&info->mr.range[i]);
+		printf(" ");
+		if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf("random ");
+	}
+}
+
+static void SNAT_save(const void *ip, const struct xt_entry_target *target)
+{
+	struct ipt_natinfo *info = (void *)target;
+	unsigned int i = 0;
+
+	for (i = 0; i < info->mr.rangesize; i++) {
+		printf("--to-source ");
+		print_range(&info->mr.range[i]);
+		printf(" ");
+		if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+			printf("--random ");
+	}
+}
+
+static struct xtables_target snat_tg_reg = {
+	.name		= "SNAT",
+	.version	= XTABLES_VERSION,
+	.family		= NFPROTO_IPV4,
+	.size		= XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+	.help		= SNAT_help,
+	.parse		= SNAT_parse,
+	.final_check	= SNAT_check,
+	.print		= SNAT_print,
+	.save		= SNAT_save,
+	.extra_opts	= SNAT_opts,
+};
+
+void _init(void)
+{
+	xtables_register_target(&snat_tg_reg);
+}