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

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/app/iproute2/iproute2-3.4.0/ip/iptuntap.c b/ap/app/iproute2/iproute2-3.4.0/ip/iptuntap.c
new file mode 100755
index 0000000..29f2777
--- /dev/null
+++ b/ap/app/iproute2/iproute2-3.4.0/ip/iptuntap.c
@@ -0,0 +1,324 @@
+/*
+ * iptunnel.c	       "ip tuntap"
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	David Woodhouse <David.Woodhouse@intel.com>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <pwd.h>
+#include <grp.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+#define TUNDEV "/dev/net/tun"
+
+static void usage(void) __attribute__((noreturn));
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ip tuntap { add | del } [ dev PHYS_DEV ] \n");
+	fprintf(stderr, "          [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n");
+	fprintf(stderr, "          [ one_queue ] [ pi ] [ vnet_hdr ]\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Where: USER  := { STRING | NUMBER }\n");
+	fprintf(stderr, "       GROUP := { STRING | NUMBER }\n");
+	exit(-1);
+}
+
+static int tap_add_ioctl(struct ifreq *ifr, uid_t uid, gid_t gid)
+{
+	int fd;
+	int ret = -1;
+
+#ifdef IFF_TUN_EXCL
+	ifr->ifr_flags |= IFF_TUN_EXCL;
+#endif
+
+	fd = open(TUNDEV, O_RDWR);
+	if (fd < 0) {
+		perror("open");
+		return -1;
+	}
+	if (ioctl(fd, TUNSETIFF, ifr)) {
+		perror("ioctl(TUNSETIFF)");
+		goto out;
+	}
+	if (uid != -1 && ioctl(fd, TUNSETOWNER, uid)) {
+		perror("ioctl(TUNSETOWNER)");
+		goto out;
+	}
+	if (gid != -1 && ioctl(fd, TUNSETGROUP, gid)) {
+		perror("ioctl(TUNSETGROUP)");
+		goto out;
+	}
+	if (ioctl(fd, TUNSETPERSIST, 1)) {
+		perror("ioctl(TUNSETPERSIST)");
+		goto out;
+	}
+	ret = 0;
+ out:
+	close(fd);
+	return ret;
+}
+
+static int tap_del_ioctl(struct ifreq *ifr)
+{
+	int fd = open(TUNDEV, O_RDWR);
+	int ret = -1;
+
+	if (fd < 0) {
+		perror("open");
+		return -1;
+	}
+	if (ioctl(fd, TUNSETIFF, ifr)) {
+		perror("ioctl(TUNSETIFF)");
+		goto out;
+	}
+	if (ioctl(fd, TUNSETPERSIST, 0)) {
+		perror("ioctl(TUNSETPERSIST)");
+		goto out;
+	}
+	ret = 0;
+ out:
+	close(fd);
+	return ret;
+
+}
+static int parse_args(int argc, char **argv, struct ifreq *ifr, uid_t *uid, gid_t *gid)
+{
+	int count = 0;
+
+	memset(ifr, 0, sizeof(*ifr));
+
+	ifr->ifr_flags |= IFF_NO_PI;
+
+	while (argc > 0) {
+		if (matches(*argv, "mode") == 0) {
+			NEXT_ARG();
+			if (matches(*argv, "tun") == 0) {
+				if (ifr->ifr_flags & IFF_TAP) {
+					fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
+					exit(-1);
+				}
+				ifr->ifr_flags |= IFF_TUN;
+			} else if (matches(*argv, "tap") == 0) {
+				if (ifr->ifr_flags & IFF_TUN) {
+					fprintf(stderr,"You managed to ask for more than one tunnel mode.\n");
+					exit(-1);
+				}
+				ifr->ifr_flags |= IFF_TAP;
+			} else {
+				fprintf(stderr,"Cannot guess tunnel mode.\n");
+				exit(-1);
+			}
+		} else if (uid && matches(*argv, "user") == 0) {
+			char *end;
+			unsigned long user;
+
+			NEXT_ARG();
+			if (**argv && ((user = strtol(*argv, &end, 10)), !*end))
+				*uid = user;
+			else {
+				struct passwd *pw = getpwnam(*argv);
+				if (!pw) {
+					fprintf(stderr, "invalid user \"%s\"\n", *argv);
+					exit(-1);
+				}
+				*uid = pw->pw_uid;
+			}
+		} else if (gid && matches(*argv, "group") == 0) {
+			char *end;
+			unsigned long group;
+
+			NEXT_ARG();
+
+			if (**argv && ((group = strtol(*argv, &end, 10)), !*end))
+				*gid = group;
+			else {
+				struct group *gr = getgrnam(*argv);
+				if (!gr) {
+					fprintf(stderr, "invalid group \"%s\"\n", *argv);
+					exit(-1);
+				}
+				*gid = gr->gr_gid;
+			}
+		} else if (matches(*argv, "pi") == 0) {
+			ifr->ifr_flags &= ~IFF_NO_PI;
+		} else if (matches(*argv, "one_queue") == 0) {
+			ifr->ifr_flags |= IFF_ONE_QUEUE;
+		} else if (matches(*argv, "vnet_hdr") == 0) {
+			ifr->ifr_flags |= IFF_VNET_HDR;
+		} else if (matches(*argv, "dev") == 0) {
+			NEXT_ARG();
+			strncpy(ifr->ifr_name, *argv, IFNAMSIZ-1);
+		} else {
+			if (matches(*argv, "name") == 0) {
+				NEXT_ARG();
+			} else if (matches(*argv, "help") == 0)
+				usage();
+			if (ifr->ifr_name[0])
+				duparg2("name", *argv);
+			strncpy(ifr->ifr_name, *argv, IFNAMSIZ);
+		}
+		count++;
+		argc--; argv++;
+	}
+
+	return 0;
+}
+
+
+static int do_add(int argc, char **argv)
+{
+	struct ifreq ifr;
+	uid_t uid = -1;
+	gid_t gid = -1;
+
+	if (parse_args(argc, argv, &ifr, &uid, &gid) < 0)
+		return -1;
+
+	if (!(ifr.ifr_flags & TUN_TYPE_MASK)) {
+		fprintf(stderr, "You failed to specify a tunnel mode\n");
+		return -1;
+	}
+	return tap_add_ioctl(&ifr, uid, gid);
+}
+
+static int do_del(int argc, char **argv)
+{
+	struct ifreq ifr;
+
+	if (parse_args(argc, argv, &ifr, NULL, NULL) < 0)
+		return -1;
+
+	return tap_del_ioctl(&ifr);
+}
+
+static int read_prop(char *dev, char *prop, long *value)
+{
+	char fname[IFNAMSIZ+25], buf[80], *endp;
+	ssize_t len;
+	int fd;
+	long result;
+
+	sprintf(fname, "/sys/class/net/%s/%s", dev, prop);
+	fd = open(fname, O_RDONLY);
+	if (fd < 0) {
+		if (strcmp(prop, "tun_flags"))
+			fprintf(stderr, "open %s: %s\n", fname,
+				strerror(errno));
+		return -1;
+	}
+	len = read(fd, buf, sizeof(buf)-1);
+	close(fd);
+	if (len < 0) {
+		fprintf(stderr, "read %s: %s", fname, strerror(errno));
+		return -1;
+	}
+
+	buf[len] = 0;
+	result = strtol(buf, &endp, 0);
+	if (*endp != '\n') {
+		fprintf(stderr, "Failed to parse %s\n", fname);
+		return -1;
+	}
+	*value = result;
+	return 0;
+}
+
+static void print_flags(long flags)
+{
+	if (flags & IFF_TUN)
+		printf(" tun");
+
+	if (flags & IFF_TAP)
+		printf(" tap");
+
+	if (!(flags & IFF_NO_PI))
+		printf(" pi");
+
+	if (flags & IFF_ONE_QUEUE)
+		printf(" one_queue");
+
+	if (flags & IFF_VNET_HDR)
+		printf(" vnet_hdr");
+
+	flags &= ~(IFF_TUN|IFF_TAP|IFF_NO_PI|IFF_ONE_QUEUE|IFF_VNET_HDR);
+	if (flags)
+		printf(" UNKNOWN_FLAGS:%lx", flags);
+}
+
+static int do_show(int argc, char **argv)
+{
+	DIR *dir;
+	struct dirent *d;
+	long flags, owner = -1, group = -1;
+
+	dir = opendir("/sys/class/net");
+	if (!dir) {
+		perror("opendir");
+		return -1;
+	}
+	while ((d = readdir(dir))) {
+		if (d->d_name[0] == '.' &&
+		    (d->d_name[1] == 0 || d->d_name[1] == '.'))
+			continue;
+
+		if (read_prop(d->d_name, "tun_flags", &flags))
+			continue;
+
+		read_prop(d->d_name, "owner", &owner);
+		read_prop(d->d_name, "group", &group);
+
+		printf("%s:", d->d_name);
+		print_flags(flags);
+		if (owner != -1)
+			printf(" user %ld", owner);
+		if (group != -1)
+			printf(" group %ld", group);
+		printf("\n");
+	}
+	closedir(dir);
+	return 0;
+}
+
+int do_iptuntap(int argc, char **argv)
+{
+	if (argc > 0) {
+		if (matches(*argv, "add") == 0)
+			return do_add(argc-1, argv+1);
+		if (matches(*argv, "del") == 0)
+			return do_del(argc-1, argv+1);
+		if (matches(*argv, "show") == 0 ||
+                    matches(*argv, "lst") == 0 ||
+                    matches(*argv, "list") == 0)
+                        return do_show(argc-1, argv+1);
+		if (matches(*argv, "help") == 0)
+			usage();
+	} else
+		return do_show(0, NULL);
+
+	fprintf(stderr, "Command \"%s\" is unknown, try \"ip tuntap help\".\n",
+		*argv);
+	exit(-1);
+}