lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 12 Dec 2012 10:51:47 +0100
From:	Nicolas Dichtel <nicolas.dichtel@...nd.com>
To:	shemminger@...tta.com
Cc:	netdev@...r.kernel.org, Nicolas Dichtel <nicolas.dichtel@...nd.com>
Subject: [PATCH iproute2 3/3] ip: add support of 'ip link type [ipip|sit]'

This patch allows to manage ip tunnels via the interface ip link.
The syntax for parameters is the same that 'ip tunnel'.

It also allows to display tunnels parameters with 'ip -details link' or
'ip -details monitor link'.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@...nd.com>
---
 ip/Makefile     |   3 +-
 ip/iplink.c     |   2 +-
 ip/link_iptnl.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 343 insertions(+), 2 deletions(-)
 create mode 100644 ip/link_iptnl.c

diff --git a/ip/Makefile b/ip/Makefile
index abf54bf..2b606d4 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -4,7 +4,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
     iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
-    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o
+    iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
+    link_iptnl.o
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/iplink.c b/ip/iplink.c
index 8aac9fc..d73c705 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -84,7 +84,7 @@ void iplink_usage(void)
 	if (iplink_have_newlink()) {
 		fprintf(stderr, "\n");
 		fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n");
-		fprintf(stderr, "          bridge | ipoib | ip6tnl }\n");
+		fprintf(stderr, "          bridge | ipoib | ip6tnl | ipip | sit }\n");
 	}
 	exit(-1);
 }
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
new file mode 100644
index 0000000..238722d
--- /dev/null
+++ b/ip/link_iptnl.c
@@ -0,0 +1,340 @@
+/*
+ * link_iptnl.c	ipip and sit driver module
+ *
+ *		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:	Nicolas Dichtel <nicolas.dichtel@...nd.com>
+ *
+ */
+
+#include <string.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <linux/ip.h>
+#include <linux/if_tunnel.h>
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+#include "tunnel.h"
+
+static void usage(int sit) __attribute__((noreturn));
+static void usage(int sit)
+{
+	fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n");
+	fprintf(stderr, "          type { ipip | sit } [ remote ADDR ] [ local ADDR ]\n");
+	fprintf(stderr, "          [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
+	fprintf(stderr, "          [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n");
+	if (sit)
+		fprintf(stderr, "          [ isatap ]\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Where: NAME := STRING\n");
+	fprintf(stderr, "       ADDR := { IP_ADDRESS | any }\n");
+	fprintf(stderr, "       TOS  := { NUMBER | inherit }\n");
+	fprintf(stderr, "       TTL  := { 1..255 | inherit }\n");
+	exit(-1);
+}
+
+static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
+			      struct nlmsghdr *n)
+{
+	struct {
+		struct nlmsghdr n;
+		struct ifinfomsg i;
+		char buf[2048];
+	} req;
+	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
+	struct rtattr *tb[IFLA_MAX + 1];
+	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
+	struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
+	int len;
+	__u32 link = 0;
+	__u32 laddr = 0;
+	__u32 raddr = 0;
+	__u8 ttl = 0;
+	__u8 tos = 0;
+	__u8 pmtudisc = 1;
+	__u16 iflags = 0;
+	struct in6_addr ip6rdprefix;
+	__u16 ip6rdprefixlen = 0;
+	__u32 ip6rdrelayprefix = 0;
+	__u16 ip6rdrelayprefixlen = 0;
+
+	memset(&ip6rdprefix, 0, sizeof(ip6rdprefix));
+
+	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
+		memset(&req, 0, sizeof(req));
+
+		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
+		req.n.nlmsg_flags = NLM_F_REQUEST;
+		req.n.nlmsg_type = RTM_GETLINK;
+		req.i.ifi_family = preferred_family;
+		req.i.ifi_index = ifi->ifi_index;
+
+		if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) {
+get_failed:
+			fprintf(stderr,
+				"Failed to get existing tunnel info.\n");
+			return -1;
+		}
+
+		len = req.n.nlmsg_len;
+		len -= NLMSG_LENGTH(sizeof(*ifi));
+		if (len < 0)
+			goto get_failed;
+
+		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
+
+		if (!tb[IFLA_LINKINFO])
+			goto get_failed;
+
+		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
+
+		if (!linkinfo[IFLA_INFO_DATA])
+			goto get_failed;
+
+		parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
+				    linkinfo[IFLA_INFO_DATA]);
+
+		if (iptuninfo[IFLA_IPTUN_LOCAL])
+			laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
+
+		if (iptuninfo[IFLA_IPTUN_REMOTE])
+			raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
+
+		if (iptuninfo[IFLA_IPTUN_TTL])
+			ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
+
+		if (iptuninfo[IFLA_IPTUN_TOS])
+			tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
+
+		if (iptuninfo[IFLA_IPTUN_PMTUDISC])
+			pmtudisc =
+				rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
+
+		if (iptuninfo[IFLA_IPTUN_FLAGS])
+			iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
+
+		if (iptuninfo[IFLA_IPTUN_LINK])
+			link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
+
+		if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
+			memcpy(&ip6rdprefix,
+			       RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
+			       sizeof(laddr));
+
+		if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
+			ip6rdprefixlen =
+				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
+
+		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
+			ip6rdrelayprefix =
+				rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
+
+		if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
+			ip6rdrelayprefixlen =
+				rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
+	}
+
+	while (argc > 0) {
+		if (strcmp(*argv, "remote") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "any"))
+				raddr = get_addr32(*argv);
+			else
+				raddr = 0;
+		} else if (strcmp(*argv, "local") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "any"))
+				laddr = get_addr32(*argv);
+			else
+				laddr = 0;
+		} else if (matches(*argv, "dev") == 0) {
+			NEXT_ARG();
+			link = if_nametoindex(*argv);
+			if (link == 0)
+				invarg("\"dev\" is invalid", *argv);
+		} else if (strcmp(*argv, "ttl") == 0 ||
+			   strcmp(*argv, "hoplimit") == 0) {
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0) {
+				if (get_u8(&ttl, *argv, 0))
+					invarg("invalid TTL\n", *argv);
+			} else
+				ttl = 0;
+		} else if (strcmp(*argv, "tos") == 0 ||
+			   strcmp(*argv, "tclass") == 0 ||
+			   matches(*argv, "dsfield") == 0) {
+			__u32 uval;
+			NEXT_ARG();
+			if (strcmp(*argv, "inherit") != 0) {
+				if (rtnl_dsfield_a2n(&uval, *argv))
+					invarg("bad TOS value", *argv);
+				tos = uval;
+			} else
+				tos = 1;
+		} else if (strcmp(*argv, "nopmtudisc") == 0) {
+			pmtudisc = 0;
+		} else if (strcmp(*argv, "pmtudisc") == 0) {
+			pmtudisc = 1;
+		} else if (strcmp(lu->id, "sit") == 0 &&
+			   strcmp(*argv, "isatap") == 0) {
+			iflags |= SIT_ISATAP;
+		} else if (strcmp(*argv, "6rd-prefix") == 0) {
+			inet_prefix prefix;
+			NEXT_ARG();
+			if (get_prefix(&prefix, *argv, AF_INET6))
+				invarg("invalid 6rd_prefix\n", *argv);
+			memcpy(&ip6rdprefix, prefix.data, 16);
+			ip6rdprefixlen = prefix.bitlen;
+		} else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
+			inet_prefix prefix;
+			NEXT_ARG();
+			if (get_prefix(&prefix, *argv, AF_INET))
+				invarg("invalid 6rd-relay_prefix\n", *argv);
+			memcpy(&ip6rdrelayprefix, prefix.data, 4);
+			ip6rdrelayprefixlen = prefix.bitlen;
+		} else if (strcmp(*argv, "6rd-reset") == 0) {
+			inet_prefix prefix;
+			get_prefix(&prefix, "2002::", AF_INET6);
+			memcpy(&ip6rdprefix, prefix.data, 16);
+			ip6rdprefixlen = 16;
+			ip6rdrelayprefix = 0;
+			ip6rdrelayprefixlen = 0;
+		} else
+			usage(strcmp(lu->id, "sit") == 0);
+		argc--, argv++;
+	}
+
+	if (ttl && pmtudisc == 0) {
+		fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n");
+		exit(-1);
+	}
+
+	addattr32(n, 1024, IFLA_IPTUN_LINK, link);
+	addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
+	addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
+	addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
+	addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
+	addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
+	if (strcmp(lu->id, "sit") == 0) {
+		addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
+		if (ip6rdprefixlen) {
+			addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
+				  &ip6rdprefix, sizeof(ip6rdprefix));
+			addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
+				  ip6rdprefixlen);
+			addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
+				  ip6rdrelayprefix);
+			addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+				  ip6rdrelayprefixlen);
+		}
+	}
+
+	return 0;
+}
+
+static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
+{
+	char s1[1024];
+	char s2[64];
+	const char *local = "any";
+	const char *remote = "any";
+
+	if (!tb)
+		return;
+
+	if (tb[IFLA_IPTUN_REMOTE]) {
+		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
+
+		if (addr)
+			remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
+	}
+
+	fprintf(f, "remote %s ", remote);
+
+	if (tb[IFLA_IPTUN_LOCAL]) {
+		unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
+
+		if (addr)
+			local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
+	}
+
+	fprintf(f, "local %s ", local);
+
+	if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
+		unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
+		const char *n = if_indextoname(link, s2);
+
+		if (n)
+			fprintf(f, "dev %s ", n);
+		else
+			fprintf(f, "dev %u ", link);
+	}
+
+	if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
+		fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
+	else
+		fprintf(f, "ttl inherit ");
+
+	if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
+		int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
+
+		fputs("tos ", f);
+		if (tos == 1)
+			fputs("inherit ", f);
+		else
+			fprintf(f, "0x%x ", tos);
+	}
+
+	if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
+		fprintf(f, "pmtudisc ");
+	else
+		fprintf(f, "nopmtudisc ");
+
+	if (tb[IFLA_IPTUN_FLAGS]) {
+	       __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
+
+	      if (iflags & SIT_ISATAP)
+		      fprintf(f, "isatap ");
+	}
+
+	if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
+	    *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) {
+		__u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]);
+		__u16 relayprefixlen =
+			rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
+		__u32 relayprefix =
+			rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
+
+		printf("6rd-prefix %s/%u ",
+		       inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
+			         s1, sizeof(s1)),
+		       prefixlen);
+		if (relayprefix) {
+			printf("6rd-relay_prefix %s/%u ",
+			       format_host(AF_INET, 4, &relayprefix, s1,
+				           sizeof(s1)),
+			       relayprefixlen);
+		}
+	}
+}
+
+struct link_util ipip_link_util = {
+	.id = "ipip",
+	.maxattr = IFLA_IPTUN_MAX,
+	.parse_opt = iptunnel_parse_opt,
+	.print_opt = iptunnel_print_opt,
+};
+
+struct link_util sit_link_util = {
+	.id = "sit",
+	.maxattr = IFLA_IPTUN_MAX,
+	.parse_opt = iptunnel_parse_opt,
+	.print_opt = iptunnel_print_opt,
+};
-- 
1.8.0.1

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists