DORMANTno replies

[PATCH 6/7] [IP] TUNNEL: Import ip6tunnel.c.

From: <hidden>
Date: 2006-11-24 03:31:49
Subsystem: the rest · Maintainer: Linus Torvalds

From: Masahide NAKAMURA <redacted>

This file (ip6tunnel.c) is renamed from ipv6tunnel.c which is imported
from usagi cvs tree. It is originally ported by MIPL to work on their
2.4 kernel patch (MIPL1).

Signed-off-by: Masahide NAKAMURA <redacted>
---
 ip/ip6tunnel.c |  402 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 402 insertions(+), 0 deletions(-)
diff --git a/ip/ip6tunnel.c b/ip/ip6tunnel.c
new file mode 100644
index 0000000..c8578e5
--- /dev/null
+++ b/ip/ip6tunnel.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ * 
+ * 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.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/*
+ * based on:
+ * $Id: s.ipv6tunnel.c 1.7 02/12/11 11:21:51+02:00 antti@traci.mipl.mediapoli.com $
+ *
+ */
+/*
+ * Author:
+ *	Masahide NAKAMURA @USAGI
+ */
+ 
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+#include <asm/types.h>
+#include <linux/sockios.h>
+#include <linux/ip.h>
+#include <linux/if_tunnel.h>
+
+#include "ipv6_tunnel.h"
+
+
+int tunnel_local_packets = 0;
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ipv6tunnel { add | change | del | show } [ NAME ]\n");
+	fprintf(stderr, "          [ --allow-local-packets ]\n");
+	fprintf(stderr, "          [ --use-original-traffic-class ]\n");
+	fprintf(stderr, "          [ remote ADDR local ADDR ]\n");
+	fprintf(stderr, "          [ dev PHYS_DEV ]\n");
+	fprintf(stderr, "          [ encaplimit TEL ]\n");
+	fprintf(stderr, "          [ hoplimit HOPLIMIT ]\n"); 
+	fprintf(stderr, "          [ flowlabel FL ]\n");
+	fprintf(stderr, "Where: NAME := STRING\n");
+	fprintf(stderr, "       ADDR := IPV6_ADDRESS\n");
+	fprintf(stderr, "       HOPLIMIT := 0..255\n");
+	fprintf(stderr, "       TEL := { none | 0..255 }\n");
+	fprintf(stderr, "       FL := 0x0..0xfffff\n");
+	fprintf(stderr, "       PHYS_DEV := STRING\n");
+	exit(-1);
+}
+
+static int do_ioctl_get_ifindex(char *dev)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+//	fprintf(stderr, "do_ioctl_get_ifindex\n");
+
+	strcpy(ifr.ifr_name, dev);
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err) {
+		perror("ioctl");
+		return 0;
+	}
+	close(fd);
+	return ifr.ifr_ifindex;
+}
+
+static char *do_ioctl_get_ifname(int idx)
+{
+	static struct ifreq ifr;
+	int fd;
+	int err;
+
+//	fprintf(stderr, "do_ioctl_get_ifname\n");
+
+	ifr.ifr_ifindex = idx;
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	err = ioctl(fd, SIOCGIFNAME, &ifr);
+	if (err) {
+		perror("ioctl");
+		return NULL;
+	}
+	close(fd);
+	return ifr.ifr_name;
+}
+
+static int do_get_ioctl(char *basedev, struct ipv6_tnl_parm *p)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+//	fprintf(stderr, "do_get_ioctl\n");
+
+	strcpy(ifr.ifr_name, basedev);
+	ifr.ifr_ifru.ifru_data = (void *)p;
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	err = ioctl(fd, SIOCGETTUNNEL, &ifr);
+	if (err)
+		perror("ioctl");
+	close(fd);
+	return err;
+}
+
+static int do_add_ioctl(int cmd, char *basedev, struct ipv6_tnl_parm *p)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+//	fprintf(stderr, "do_add_ioctl\n");
+
+	strcpy(ifr.ifr_name, basedev);
+	ifr.ifr_ifru.ifru_data = (void *)p;
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	err = ioctl(fd, cmd, &ifr);
+	if (err)
+		perror("ioctl");
+	close(fd);
+	return err;
+}
+
+
+static int do_del_ioctl(char *basedev, struct ipv6_tnl_parm *p)
+{
+	struct ifreq ifr;
+	int fd;
+	int err;
+
+//	fprintf(stderr, "do_del_ioctl\n");
+
+	strcpy(ifr.ifr_name, basedev);
+	ifr.ifr_ifru.ifru_data = (void *)p;
+	fd = socket(AF_INET6, SOCK_DGRAM, 0);
+	err = ioctl(fd, SIOCDELTUNNEL, &ifr);
+	if (err)
+		perror("ioctl");
+	close(fd);
+	return err;
+}
+
+void print_tunnel(struct ipv6_tnl_parm *p)
+{
+	char remote[64];
+	char local[64];
+	
+	inet_ntop(AF_INET6, &p->raddr, remote, sizeof(remote));
+	inet_ntop(AF_INET6, &p->laddr, local, sizeof(local));
+
+	printf("%s: %s/IPv6 remote %s local %s",
+	       p->name,
+	       (p->proto == IPPROTO_IPV6 ? "IPv6" : "unknown"),
+	       remote, local);
+	if (p->link) {
+		char *n = do_ioctl_get_ifname(p->link);
+		if (n)
+			printf(" dev %s", n);
+	}
+	if (p->encap_limit)
+		printf(" encaplimit %d", p->encap_limit);
+
+	printf(" hoplimit %d", p->hop_limit);
+
+	if (p->flow_lbl)
+		printf(" flowlabel 0x%x", p->flow_lbl);
+
+	if (p->flags) {
+		char flags[33];
+		char *fp = flags;
+		memset(flags, 0, 33);
+		if (p->flags & IPV6_TNL_F_IGN_ENCAP_LIMIT) {
+			*fp = 'E';
+			fp++;
+		}
+		if (p->flags & IPV6_TNL_F_USE_ORIG_TCLASS) {
+			*fp = 'T';
+			fp++;
+		}
+		if (p->flags & IPV6_TNL_F_ALLOW_LOCAL) {
+			*fp = 'L';
+			fp++;
+		}
+		if (p->flags & IPV6_TNL_F_KERNEL_DEV) {
+			*fp = 'K';
+			fp++;
+		}
+		if (p->flags & IPV6_TNL_F_MIPV6_DEV) {
+			*fp = 'M';
+			fp++;
+		}
+		if (p->flags & IPV6_TNL_F_RCV_ONLY) {
+			*fp = 'R';
+			fp++;
+		}
+		printf(" flags %s", flags);
+	}
+	printf("\n");
+}
+
+void resolve_name(char *name, struct in6_addr *ip6)
+{ 
+	struct addrinfo ai, *res; 
+	int err; 
+	memset(&ai, 0, sizeof(struct addrinfo)); 
+	ai.ai_family = AF_INET6; 
+	ai.ai_protocol = IPPROTO_IPV6; 
+	ai.ai_flags = AI_NUMERICHOST;
+	err = getaddrinfo(name, NULL, &ai, &res);
+	if (err)
+		exit(-1);
+
+	*ip6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr;
+	freeaddrinfo(res); 
+} 
+
+int get_u8(__u8 *val, char *arg)
+{
+	unsigned long res = 0;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtoul(arg, &ptr, 0);
+	if (!ptr || ptr == arg || *ptr || res > 0xFF)
+		return -1;
+	*val = (__u8) res;
+	return 0;
+}
+
+int get_u20(__u32 *val, char *arg)
+{
+	unsigned long res = 0;
+	char *ptr;
+
+	if (!arg || !*arg)
+		return -1;
+	res = strtoul(arg, &ptr, 0);
+	if (!ptr || ptr == arg || *ptr || res > 0xFFFFF)
+		return -1;
+	*val = res;
+	return 0;
+}
+
+static int parse_args(int argc, char **argv, struct ipv6_tnl_parm *p)
+{
+	char medium[IFNAMSIZ];
+
+//	fprintf(stderr, "parse_args\n");
+
+	memset(p, 0, sizeof(*p));
+	p->hop_limit = -1;
+	p->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
+	p->proto = IPPROTO_IPV6;
+	memset(&medium, 0, sizeof(medium));
+
+	while (argc > 0) {
+		if (!strcmp(*argv, "--help") || !strcmp(*argv, "-h")) {
+			usage();
+		} else if (!strcmp(*argv, "--allow-local-packets")) {
+			p->flags |= IPV6_TNL_F_ALLOW_LOCAL;
+		} else if (!strcmp(*argv, "--use-original-traffic-class")) {
+			p->flags |= IPV6_TNL_F_USE_ORIG_TCLASS;
+		} else if (!strcmp(*argv, "remote")) {
+			argv++; 
+			if (--argc <= 0) 
+				usage();
+			resolve_name(*argv, &p->raddr);
+		} else if (!strcmp(*argv, "local")) {
+			argv++; 
+			if (--argc <= 0) 
+				usage();
+			resolve_name(*argv, &p->laddr);
+		} else if (!strcmp(*argv, "dev")) {
+			argv++; 
+			if (--argc <= 0) 
+				usage();
+			strncpy(medium, *argv, IFNAMSIZ - 1);
+		} else if (!strcmp(*argv, "hoplimit")) {
+			__u8 uval;
+			argv++; 
+			if (--argc <= 0) 
+				usage();
+			if (get_u8(&uval, *argv) < -1)
+				usage();
+			p->hop_limit = uval;
+		} else if (!strcmp(*argv, "flowlabel")) {
+			__u32 uval;
+			argv++; 
+			if (--argc <= 0) 
+				usage();
+			if (get_u20(&uval, *argv) < -1)
+				usage();
+			p->flow_lbl = uval;
+		} else if (!strcmp(*argv, "encaplimit")) {
+			argv++; 
+			if (--argc <= 0) 
+				usage();
+			if (!strcmp(*argv, "none")) {
+				p->flags |= IPV6_TNL_F_IGN_ENCAP_LIMIT;
+			} else {
+				__u8 uval;
+				if (get_u8(&uval, *argv) < -1)
+					usage();
+				p->encap_limit = uval;
+			}
+		} else {
+			if (p->name[0])
+				usage();
+			strncpy(p->name, *argv, IFNAMSIZ - 1);
+		}
+		argc--; argv++;
+	}
+	if (medium[0]) {
+		p->link = do_ioctl_get_ifindex(medium);
+		if (p->link == 0)
+			return -1;
+	}
+	return 0;
+}
+
+static int do_show(int argc, char **argv)
+{
+        struct ipv6_tnl_parm p;
+
+        if (parse_args(argc, argv, &p) < 0)
+                return -1;
+
+	if (do_get_ioctl(p.name[0] ? p.name : "ip6tnl0", &p))
+                return -1;
+
+        print_tunnel(&p);
+        return 0;
+}
+
+
+
+
+static int do_add(int cmd, int argc, char **argv)
+{
+	struct ipv6_tnl_parm p;
+
+	if (parse_args(argc, argv, &p) < 0)
+		return -1;
+	
+	return do_add_ioctl(cmd, 
+			    cmd == SIOCCHGTUNNEL && p.name[0] ?
+			    p.name : "ip6tnl0", &p);
+}
+
+int do_del(int argc, char **argv)
+{
+	struct ipv6_tnl_parm p;
+
+	if (parse_args(argc, argv, &p) < 0)
+		return -1;
+
+	return do_del_ioctl(p.name[0] ? p.name : "ip6tnl0", &p);
+}
+
+
+int main(int argc, char **argv) 
+{ 
+	argc--;
+	argv++;
+	if (argc > 0) {
+		if (strcmp(*argv, "add") == 0)
+			return do_add(SIOCADDTUNNEL, argc - 1, argv + 1);
+		else if (strcmp(*argv, "change") == 0)
+			return do_add(SIOCCHGTUNNEL, argc - 1, argv + 1);
+		else if (strcmp(*argv, "del") == 0)
+			return do_del(argc - 1, argv + 1);
+		else if (strcmp(*argv, "show") == 0)
+			return do_show(argc - 1, argv + 1);
+		else
+			usage();
+
+	} else
+		return do_show(0, NULL);
+
+	return 0;
+}
-- 
1.4.2
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help