All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC 0/2] Add IPv6 tokenized interface identifier support
@ 2013-04-04 14:37 Daniel Borkmann
  2013-04-04 14:37 ` [PATCH net-next 1/2] net: ipv6: add " Daniel Borkmann
  2013-04-04 14:37 ` [PATCH iproute2 2/2] ip: " Daniel Borkmann
  0 siblings, 2 replies; 9+ messages in thread
From: Daniel Borkmann @ 2013-04-04 14:37 UTC (permalink / raw)
  To: davem; +Cc: netdev

This RFC patchset adds IPv6 tokenized interface identifier
support for the net-next kernel as well as for iproute2 in
order to configure a networking device for IPv6 Token IIDs.

For a more detailled description, have a look at the two
patches directly.

-- 
1.7.11.7

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net-next 1/2] net: ipv6: add tokenized interface identifier support
  2013-04-04 14:37 [PATCH RFC 0/2] Add IPv6 tokenized interface identifier support Daniel Borkmann
@ 2013-04-04 14:37 ` Daniel Borkmann
  2013-04-04 15:58   ` Hannes Frederic Sowa
  2013-04-04 16:29   ` YOSHIFUJI Hideaki
  2013-04-04 14:37 ` [PATCH iproute2 2/2] ip: " Daniel Borkmann
  1 sibling, 2 replies; 9+ messages in thread
From: Daniel Borkmann @ 2013-04-04 14:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, Hannes Frederic Sowa, YOSHIFUJI Hideaki

This patch adds support for tokenized IIDs, that allow for
administrators to assign well-known host-part addresses to
nodes whilst still obtaining global network prefix from
Router Advertisements. It is currently in IETF RFC draft
status [1]:

  The primary target for such support is server platforms
  where addresses are usually manually configured, rather
  than using DHCPv6 or SLAAC. By using tokenised identifiers,
  hosts can still determine their network prefix by use of
  SLAAC, but more readily be automatically renumbered should
  their network prefix change.

 [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02

The implementation is partially based on top of Mark K.
Thompson's proof of concept. Successfully tested by myself.

Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
 include/net/if_inet6.h       |    2 +
 include/net/ipv6.h           |    2 +
 include/uapi/linux/if_link.h |    1 +
 net/ipv6/addrconf.c          |   87 ++++++++++++++++++++++++++++++++++++++++-
 net/ipv6/addrconf_core.c     |    2 -
 5 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 9356322..f1063d6 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -187,6 +187,8 @@ struct inet6_dev {
 	struct list_head	tempaddr_list;
 #endif
 
+	struct in6_addr		token;
+
 	struct neigh_parms	*nd_parms;
 	struct inet6_dev	*next;
 	struct ipv6_devconf	cnf;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 0810aa5..da8c11e 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -88,6 +88,8 @@
 #define IPV6_ADDR_SCOPE_ORGLOCAL	0x08
 #define IPV6_ADDR_SCOPE_GLOBAL		0x0e
 
+#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
+
 /*
  *	Addr flags
  */
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index c4edfe1..6b35c42 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -201,6 +201,7 @@ enum {
 	IFLA_INET6_MCAST,	/* MC things. What of them?	*/
 	IFLA_INET6_CACHEINFO,	/* time values and max reasm size */
 	IFLA_INET6_ICMP6STATS,	/* statistics (icmpv6)		*/
+	IFLA_INET6_TOKEN,	/* device token			*/
 	__IFLA_INET6_MAX
 };
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a33b157..fb0e8a0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -422,6 +422,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 		ipv6_regen_rndid((unsigned long) ndev);
 	}
 #endif
+	memset(ndev->token.s6_addr, 0, sizeof(ndev->token.s6_addr));
 
 	if (netif_running(dev) && addrconf_qdisc_ok(dev))
 		ndev->if_flags |= IF_READY;
@@ -2136,8 +2137,14 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
 
 		if (pinfo->prefix_len == 64) {
 			memcpy(&addr, &pinfo->prefix, 8);
-			if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
-			    ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
+
+			if (!ipv6_addr_any(&in6_dev->token)) {
+				read_lock_bh(&in6_dev->lock);
+				memcpy(addr.s6_addr + 8,
+				       in6_dev->token.s6_addr + 8, 8);
+				read_unlock_bh(&in6_dev->lock);
+			} else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
+				   ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
 				in6_dev_put(in6_dev);
 				return;
 			}
@@ -4165,7 +4172,8 @@ static inline size_t inet6_ifla6_size(void)
 	     + nla_total_size(sizeof(struct ifla_cacheinfo))
 	     + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
 	     + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
-	     + nla_total_size(ICMP6_MIB_MAX * 8); /* IFLA_INET6_ICMP6STATS */
+	     + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
+	     + nla_total_size(sizeof(struct in6_addr)); /* IFLA_INET6_TOKEN */
 }
 
 static inline size_t inet6_if_nlmsg_size(void)
@@ -4252,6 +4260,13 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
 		goto nla_put_failure;
 	snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
 
+	nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr));
+	if (nla == NULL)
+		goto nla_put_failure;
+	read_lock_bh(&idev->lock);
+	memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla));
+	read_unlock_bh(&idev->lock);
+
 	return 0;
 
 nla_put_failure:
@@ -4279,6 +4294,71 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
 	return 0;
 }
 
+static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
+{
+	struct in6_addr ll_addr;
+	struct inet6_ifaddr *ifp;
+	struct net_device *dev = idev->dev;
+
+	if (token == NULL)
+		return -EINVAL;
+	if (ipv6_addr_any(token))
+		return -EINVAL;
+	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP))
+		return -EINVAL;
+	if (idev->dead || !(idev->if_flags & IF_READY))
+		return -EINVAL;
+	if (!ipv6_accept_ra(idev))
+		return -EINVAL;
+	if (idev->cnf.rtr_solicits <= 0)
+		return -EINVAL;
+
+	write_lock_bh(&idev->lock);
+
+	BUILD_BUG_ON(sizeof(token->s6_addr) != 16);
+	memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8);
+
+	write_unlock_bh(&idev->lock);
+
+	ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE | IFA_F_OPTIMISTIC);
+	ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters);
+
+	write_lock_bh(&idev->lock);
+	idev->if_flags |= IF_RS_SENT;
+
+	/* Well, that's kinda nasty ... */
+	list_for_each_entry(ifp, &idev->addr_list, if_list) {
+		spin_lock(&ifp->lock);
+		if (__ipv6_addr_type(&ifp->addr) &
+		    IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)) {
+			ifp->valid_lft = 0;
+			ifp->prefered_lft = 0;
+		}
+		spin_unlock(&ifp->lock);
+	}
+
+	write_unlock_bh(&idev->lock);
+	return 0;
+}
+
+static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
+{
+	int err = -EINVAL;
+	struct inet6_dev *idev = __in6_dev_get(dev);
+	struct nlattr *tb[IFLA_INET6_MAX + 1];
+
+	if (!idev)
+		return -EAFNOSUPPORT;
+
+	if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0)
+		BUG();
+
+	if (tb[IFLA_INET6_TOKEN])
+		err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN]));
+
+	return err;
+}
+
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
 			     u32 portid, u32 seq, int event, unsigned int flags)
 {
@@ -4981,6 +5061,7 @@ static struct rtnl_af_ops inet6_ops = {
 	.family		  = AF_INET6,
 	.fill_link_af	  = inet6_fill_link_af,
 	.get_link_af_size = inet6_get_link_af_size,
+	.set_link_af	  = inet6_set_link_af,
 };
 
 /*
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index d051e5f..8b723de 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -6,8 +6,6 @@
 #include <linux/export.h>
 #include <net/ipv6.h>
 
-#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
-
 static inline unsigned int ipv6_addr_scope2type(unsigned int scope)
 {
 	switch (scope) {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH iproute2 2/2] ip: ipv6: add tokenized interface identifier support
  2013-04-04 14:37 [PATCH RFC 0/2] Add IPv6 tokenized interface identifier support Daniel Borkmann
  2013-04-04 14:37 ` [PATCH net-next 1/2] net: ipv6: add " Daniel Borkmann
@ 2013-04-04 14:37 ` Daniel Borkmann
  2013-04-05 16:39   ` Stephen Hemminger
  1 sibling, 1 reply; 9+ messages in thread
From: Daniel Borkmann @ 2013-04-04 14:37 UTC (permalink / raw)
  To: davem; +Cc: netdev, Hannes Frederic Sowa, YOSHIFUJI Hideaki

This is experimental support for tokenized IIDs, that enable
administrators to assign well-known host-part addresses to nodes
whilst still obtaining global network prefix from Router
Advertisements. It is currently in IETF RFC draft status [1].

Example commands with iproute2:

Setting a device token:
  # ip token set ::1a:2b:3c:4d/64 dev eth1

Getting a device token:
  # ip token get dev eth1
  token ::1a:2b:3c:4d dev eth1

Listing all tokens:
  # ip token list  (or: ip token)
  token :: dev eth0
  token ::1a:2b:3c:4d dev eth1

 [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02

Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
---
 include/linux/if_link.h |   1 +
 ip/Makefile             |   2 +-
 ip/ip.c                 |   3 +-
 ip/ip_common.h          |   1 +
 ip/iptoken.c            | 208 ++++++++++++++++++++++++++++++++++++++++++++++++
 man/man8/Makefile       |   2 +-
 man/man8/ip-token.8     |  66 +++++++++++++++
 7 files changed, 280 insertions(+), 3 deletions(-)
 create mode 100644 ip/iptoken.c
 create mode 100644 man/man8/ip-token.8

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 40167af..f3a1b29 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -199,6 +199,7 @@ enum {
 	IFLA_INET6_MCAST,	/* MC things. What of them?	*/
 	IFLA_INET6_CACHEINFO,	/* time values and max reasm size */
 	IFLA_INET6_ICMP6STATS,	/* statistics (icmpv6)		*/
+	IFLA_INET6_TOKEN,	/* device token			*/
 	__IFLA_INET6_MAX
 };
 
diff --git a/ip/Makefile b/ip/Makefile
index 2b606d4..48bd4a1 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -1,6 +1,6 @@
 IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \
-    ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o \
+    ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.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 \
diff --git a/ip/ip.c b/ip/ip.c
index e10ddb2..69bd5ff 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -45,7 +45,7 @@ static void usage(void)
 "       ip [ -force ] -batch filename\n"
 "where  OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n"
 "                   tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\n"
-"                   netns | l2tp | tcp_metrics }\n"
+"                   netns | l2tp | tcp_metrics | token }\n"
 "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
 "                    -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
 "                    -4 | -6 | -I | -D | -B | -0 |\n"
@@ -80,6 +80,7 @@ static const struct cmd {
 	{ "tunl",	do_iptunnel },
 	{ "tuntap",	do_iptuntap },
 	{ "tap",	do_iptuntap },
+	{ "token",	do_iptoken },
 	{ "tcpmetrics",	do_tcp_metrics },
 	{ "tcp_metrics",do_tcp_metrics },
 	{ "monitor",	do_ipmonitor },
diff --git a/ip/ip_common.h b/ip/ip_common.h
index de56810..f9b4734 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -49,6 +49,7 @@ extern int do_xfrm(int argc, char **argv);
 extern int do_ipl2tp(int argc, char **argv);
 extern int do_tcp_metrics(int argc, char **argv);
 extern int do_ipnetconf(int argc, char **argv);
+extern int do_iptoken(int argc, char **argv);
 
 static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb)
 {
diff --git a/ip/iptoken.c b/ip/iptoken.c
new file mode 100644
index 0000000..1dd071d
--- /dev/null
+++ b/ip/iptoken.c
@@ -0,0 +1,208 @@
+/*
+ * iptoken.c    "ip token"
+ *
+ *              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:     Daniel Borkmann, <borkmann@redhat.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <linux/types.h>
+#include <linux/if.h>
+
+#include "rt_names.h"
+#include "utils.h"
+#include "ip_common.h"
+
+extern struct rtnl_handle rth;
+
+struct rtnl_dump_args {
+	FILE *fp;
+	int ifindex;
+};
+
+static void usage(void) __attribute__((noreturn));
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ip token [ list | set | get ] [ TOKEN ] [ dev DEV ]\n");
+	exit(-1);
+}
+
+static int print_token(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
+{
+	struct rtnl_dump_args *args = arg;
+	FILE *fp = args->fp;
+	int ifindex = args->ifindex;
+	struct ifinfomsg *ifi = NLMSG_DATA(n);
+	int len = n->nlmsg_len;
+	struct rtattr *tb[IFLA_MAX + 1];
+	struct rtattr *ltb[IFLA_INET6_MAX + 1];
+	char abuf[256];
+
+	if (n->nlmsg_type != RTM_NEWLINK)
+		return -1;
+
+	len -= NLMSG_LENGTH(sizeof(*ifi));
+	if (len < 0)
+		return -1;
+
+	if (ifi->ifi_family != AF_INET6)
+		return -1;
+	if (ifi->ifi_index == 0)
+		return -1;
+	if (ifindex > 0 && ifi->ifi_index != ifindex)
+		return 0;
+	if (ifi->ifi_flags & (IFF_LOOPBACK | IFF_NOARP))
+		return 0;
+
+	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
+	if (!tb[IFLA_PROTINFO])
+		return -1;
+
+	parse_rtattr_nested(ltb, IFLA_INET6_MAX, tb[IFLA_PROTINFO]);
+	if (!ltb[IFLA_INET6_TOKEN])
+		return -1;
+
+	fprintf(fp, "token %s ",
+		format_host(ifi->ifi_family,
+			    RTA_PAYLOAD(ltb[IFLA_INET6_TOKEN]),
+			    RTA_DATA(ltb[IFLA_INET6_TOKEN]),
+			    abuf, sizeof(abuf)));
+	fprintf(fp, "dev %s ", ll_index_to_name(ifi->ifi_index));
+	fprintf(fp, "\n");
+	fflush(fp);
+
+	return 0;
+}
+
+static int iptoken_list(int argc, char **argv)
+{
+	int af = AF_INET6;
+	struct rtnl_dump_args da;
+	const struct rtnl_dump_filter_arg a[2] = {
+		{ .filter = print_token, .arg1 = &da, },
+		{ .filter = NULL, .arg1 = NULL, },
+	};
+
+	memset(&da, 0, sizeof(da));
+	da.fp = stdout;
+
+	while (argc > 0) {
+		if (strcmp(*argv, "dev") == 0) {
+			NEXT_ARG();
+			if ((da.ifindex = ll_name_to_index(*argv)) == 0)
+				invarg("dev is invalid\n", *argv);
+			break;
+		}
+		argc--; argv++;
+	}
+
+	if (rtnl_wilddump_request(&rth, af, RTM_GETLINK) < 0) {
+		perror("Cannot send dump request");
+		return -1;
+	}
+
+	if (rtnl_dump_filter_l(&rth, a) < 0) {
+		fprintf(stderr, "Dump terminated\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int iptoken_set(int argc, char **argv)
+{
+	struct {
+		struct nlmsghdr n;
+		struct ifinfomsg ifi;
+		char buf[512];
+	} req;
+	struct rtattr *afs, *afs6;
+	bool have_token = false, have_dev = false;
+	inet_prefix addr;
+
+	memset(&addr, 0, sizeof(addr));
+	memset(&req, 0, sizeof(req));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = RTM_SETLINK;
+	req.ifi.ifi_family = AF_INET6;
+
+	while (argc > 0) {
+		if (strcmp(*argv, "dev") == 0) {
+			NEXT_ARG();
+			if (!have_dev) {
+				if ((req.ifi.ifi_index =
+				     ll_name_to_index(*argv)) == 0)
+					invarg("dev is invalid\n", *argv);
+				have_dev = true;
+			}
+		} else {
+			if (matches(*argv, "help") == 0)
+				usage();
+			if (!have_token) {
+				afs = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
+				afs6 = addattr_nest(&req.n, sizeof(req), AF_INET6);
+				get_prefix(&addr, *argv, req.ifi.ifi_family);
+				addattr_l(&req.n, sizeof(req), IFLA_INET6_TOKEN,
+					  &addr.data, addr.bytelen);
+				addattr_nest_end(&req.n, afs6);
+				addattr_nest_end(&req.n, afs);
+				have_token = true;
+			}
+		}
+		argc--; argv++;
+	}
+
+	if (!have_token) {
+		fprintf(stderr, "Not enough information: token "
+			"is required.\n");
+		return -1;
+	}
+	if (!have_dev) {
+		fprintf(stderr, "Not enough information: \"dev\" "
+			"argument is required.\n");
+		return -1;
+	}
+
+	if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
+		return -2;
+
+	return 0;
+}
+
+int do_iptoken(int argc, char **argv)
+{
+	ll_init_map(&rth);
+
+	if (argc < 1) {
+		return iptoken_list(0, NULL);
+	} else if (matches(argv[0], "list") == 0 ||
+		   matches(argv[0], "show") == 0) {
+		return iptoken_list(argc - 1, argv + 1);
+	} else if (matches(argv[0], "set") == 0 ||
+		   matches(argv[0], "add") == 0) {
+		return iptoken_set(argc - 1, argv + 1);
+	} else if (matches(argv[0], "get") == 0) {
+		return iptoken_list(argc - 1, argv + 1);
+	} else if (matches(argv[0], "help") == 0)
+		usage();
+
+	fprintf(stderr, "Command \"%s\" is unknown, try \"ip token help\".\n", *argv);
+	exit(-1);
+}
diff --git a/man/man8/Makefile b/man/man8/Makefile
index d208f3b..ff80c98 100644
--- a/man/man8/Makefile
+++ b/man/man8/Makefile
@@ -9,7 +9,7 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 ss.8 \
 	ip-addrlabel.8 ip-l2tp.8 \
 	ip-maddress.8 ip-monitor.8 ip-mroute.8 ip-neighbour.8 \
 	ip-netns.8 ip-ntable.8 ip-rule.8 ip-tunnel.8 ip-xfrm.8 \
-	ip-tcp_metrics.8 ip-netconf.8
+	ip-tcp_metrics.8 ip-netconf.8 ip-token.8
 
 all: $(TARGETS)
 
diff --git a/man/man8/ip-token.8 b/man/man8/ip-token.8
new file mode 100644
index 0000000..2085cb5
--- /dev/null
+++ b/man/man8/ip-token.8
@@ -0,0 +1,66 @@
+.TH IP\-TOKEN 8 "28 Mar 2013" "iproute2" "Linux"
+.SH "NAME"
+ip-token \- tokenized interface identifer support
+.SH "SYNOPSIS"
+.sp
+.ad l
+.in +8
+.ti -8
+.B ip token
+.RI " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.BR "ip token" " { " set " } "
+.IR TOKEN
+.B dev
+.IR DEV
+
+.ti -8
+.BR "ip token" " { " get " } "
+.B dev
+.IR DEV
+
+.ti -8
+.BR "ip token" " { " list " }"
+
+.SH "DESCRIPTION"
+IPv6 tokenized interface identifer support is used for assigning well-known
+host-part addresses to nodes whilst still obtaining a global network prefix
+from Router advertisements. The primary target for tokenized identifiers is
+server platforms where addresses are usually manually configured, rather than
+using DHCPv6 or SLAAC. By using tokenized identifiers, hosts can still
+determine their network prefix by use of SLAAC, but more readily be
+automatically renumbered should their network prefix change [1]. Tokenized
+IPv6 Identifiers are described in the RFC draft
+[1]: <draft-chown-6man-tokenised-ipv6-identifiers-02>.
+
+.SS ip token set - set an interface token
+set the interface token to the kernel. Once a token is set, it cannot be
+removed from the interface, only overwritten.
+.TP
+.I TOKEN
+the interface identifer token address.
+.TP
+.BI dev " DEV"
+the networking interface.
+
+.SS ip token get - get the interface token from the kernel
+show a tokenized interface identifer of a particular networking device.
+.B Arguments:
+coincide with the arguments of
+.B ip token set
+but the
+.I TOKEN
+must be left out.
+.SS ip token list - list all interface tokens
+list all tokenized interface identifers for the networking interfaces from
+the kernel.
+
+.SH SEE ALSO
+.br
+.BR ip (8)
+
+.SH AUTHOR
+Manpage by Daniel Borkmann
-- 
1.7.11.7

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 1/2] net: ipv6: add tokenized interface identifier support
  2013-04-04 14:37 ` [PATCH net-next 1/2] net: ipv6: add " Daniel Borkmann
@ 2013-04-04 15:58   ` Hannes Frederic Sowa
  2013-04-04 16:02     ` Daniel Borkmann
  2013-04-04 16:29   ` YOSHIFUJI Hideaki
  1 sibling, 1 reply; 9+ messages in thread
From: Hannes Frederic Sowa @ 2013-04-04 15:58 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev, YOSHIFUJI Hideaki

On Thu, Apr 04, 2013 at 04:37:37PM +0200, Daniel Borkmann wrote:
> This patch adds support for tokenized IIDs, that allow for
> administrators to assign well-known host-part addresses to
> nodes whilst still obtaining global network prefix from
> Router Advertisements. It is currently in IETF RFC draft
> status [1]:
> 
>   The primary target for such support is server platforms
>   where addresses are usually manually configured, rather
>   than using DHCPv6 or SLAAC. By using tokenised identifiers,
>   hosts can still determine their network prefix by use of
>   SLAAC, but more readily be automatically renumbered should
>   their network prefix change.
> 
>  [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02
> 
> The implementation is partially based on top of Mark K.
> Thompson's proof of concept. Successfully tested by myself.

Cool, this looks really useful.

One comment so far:

> +#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
> +

I think we should not export this macro but instead...

> +	/* Well, that's kinda nasty ... */
> +	list_for_each_entry(ifp, &idev->addr_list, if_list) {
> +		spin_lock(&ifp->lock);
> +		if (__ipv6_addr_type(&ifp->addr) &
> +		    IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)) {

...use

if (ipv6_addr_src_scope(&ifp->addr) == IPV6_ADDR_SCOPE_GLOBAL) {

here.

> diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
> index d051e5f..8b723de 100644
> --- a/net/ipv6/addrconf_core.c
> +++ b/net/ipv6/addrconf_core.c
> @@ -6,8 +6,6 @@
>  #include <linux/export.h>
>  #include <net/ipv6.h>
>  
> -#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
> -

This hunk can be dropped then.

Thanks,

  Hannes

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 1/2] net: ipv6: add tokenized interface identifier support
  2013-04-04 15:58   ` Hannes Frederic Sowa
@ 2013-04-04 16:02     ` Daniel Borkmann
  0 siblings, 0 replies; 9+ messages in thread
From: Daniel Borkmann @ 2013-04-04 16:02 UTC (permalink / raw)
  To: hannes; +Cc: davem, netdev, YOSHIFUJI Hideaki

On 04/04/2013 05:58 PM, Hannes Frederic Sowa wrote:
> On Thu, Apr 04, 2013 at 04:37:37PM +0200, Daniel Borkmann wrote:
>> This patch adds support for tokenized IIDs, that allow for
>> administrators to assign well-known host-part addresses to
>> nodes whilst still obtaining global network prefix from
>> Router Advertisements. It is currently in IETF RFC draft
>> status [1]:
>>
>>    The primary target for such support is server platforms
>>    where addresses are usually manually configured, rather
>>    than using DHCPv6 or SLAAC. By using tokenised identifiers,
>>    hosts can still determine their network prefix by use of
>>    SLAAC, but more readily be automatically renumbered should
>>    their network prefix change.
>>
>>   [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02
>>
>> The implementation is partially based on top of Mark K.
>> Thompson's proof of concept. Successfully tested by myself.
>
> Cool, this looks really useful.
>
> One comment so far:
>
>> +#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
>> +
>
> I think we should not export this macro but instead...
>
>> +	/* Well, that's kinda nasty ... */
>> +	list_for_each_entry(ifp, &idev->addr_list, if_list) {
>> +		spin_lock(&ifp->lock);
>> +		if (__ipv6_addr_type(&ifp->addr) &
>> +		    IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)) {
>
> ...use
>
> if (ipv6_addr_src_scope(&ifp->addr) == IPV6_ADDR_SCOPE_GLOBAL) {
>
> here.
>
>> diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
>> index d051e5f..8b723de 100644
>> --- a/net/ipv6/addrconf_core.c
>> +++ b/net/ipv6/addrconf_core.c
>> @@ -6,8 +6,6 @@
>>   #include <linux/export.h>
>>   #include <net/ipv6.h>
>>
>> -#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
>> -
>
> This hunk can be dropped then.

Thanks for the review Hannes, I'll do that in a version 2 of the set.

Thanks,

Daniel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 1/2] net: ipv6: add tokenized interface identifier support
  2013-04-04 14:37 ` [PATCH net-next 1/2] net: ipv6: add " Daniel Borkmann
  2013-04-04 15:58   ` Hannes Frederic Sowa
@ 2013-04-04 16:29   ` YOSHIFUJI Hideaki
  2013-04-04 16:48     ` Daniel Borkmann
  1 sibling, 1 reply; 9+ messages in thread
From: YOSHIFUJI Hideaki @ 2013-04-04 16:29 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev, Hannes Frederic Sowa, YOSHIFUJI Hideaki

Daniel Borkmann wrote:
> This patch adds support for tokenized IIDs, that allow for
> administrators to assign well-known host-part addresses to
> nodes whilst still obtaining global network prefix from
> Router Advertisements. It is currently in IETF RFC draft
> status [1]:
> 
>   The primary target for such support is server platforms
>   where addresses are usually manually configured, rather
>   than using DHCPv6 or SLAAC. By using tokenised identifiers,
>   hosts can still determine their network prefix by use of
>   SLAAC, but more readily be automatically renumbered should
>   their network prefix change.
> 
>  [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02
> 
> The implementation is partially based on top of Mark K.
> Thompson's proof of concept. Successfully tested by myself.
> 
> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
> ---
>  include/net/if_inet6.h       |    2 +
>  include/net/ipv6.h           |    2 +
>  include/uapi/linux/if_link.h |    1 +
>  net/ipv6/addrconf.c          |   87 ++++++++++++++++++++++++++++++++++++++++-
>  net/ipv6/addrconf_core.c     |    2 -
>  5 files changed, 89 insertions(+), 5 deletions(-)
> 
> diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
> index 9356322..f1063d6 100644
> --- a/include/net/if_inet6.h
> +++ b/include/net/if_inet6.h
> @@ -187,6 +187,8 @@ struct inet6_dev {
>  	struct list_head	tempaddr_list;
>  #endif
>  
> +	struct in6_addr		token;
> +
>  	struct neigh_parms	*nd_parms;
>  	struct inet6_dev	*next;
>  	struct ipv6_devconf	cnf;
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index 0810aa5..da8c11e 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -88,6 +88,8 @@
>  #define IPV6_ADDR_SCOPE_ORGLOCAL	0x08
>  #define IPV6_ADDR_SCOPE_GLOBAL		0x0e
>  
> +#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
> +
>  /*
>   *	Addr flags
>   */
> diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> index c4edfe1..6b35c42 100644
> --- a/include/uapi/linux/if_link.h
> +++ b/include/uapi/linux/if_link.h
> @@ -201,6 +201,7 @@ enum {
>  	IFLA_INET6_MCAST,	/* MC things. What of them?	*/
>  	IFLA_INET6_CACHEINFO,	/* time values and max reasm size */
>  	IFLA_INET6_ICMP6STATS,	/* statistics (icmpv6)		*/
> +	IFLA_INET6_TOKEN,	/* device token			*/
>  	__IFLA_INET6_MAX
>  };
>  
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index a33b157..fb0e8a0 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -422,6 +422,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
>  		ipv6_regen_rndid((unsigned long) ndev);
>  	}
>  #endif
> +	memset(ndev->token.s6_addr, 0, sizeof(ndev->token.s6_addr));
>  
>  	if (netif_running(dev) && addrconf_qdisc_ok(dev))
>  		ndev->if_flags |= IF_READY;
> @@ -2136,8 +2137,14 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
>  
>  		if (pinfo->prefix_len == 64) {
>  			memcpy(&addr, &pinfo->prefix, 8);
> -			if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
> -			    ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
> +
> +			if (!ipv6_addr_any(&in6_dev->token)) {
> +				read_lock_bh(&in6_dev->lock);
> +				memcpy(addr.s6_addr + 8,
> +				       in6_dev->token.s6_addr + 8, 8);
> +				read_unlock_bh(&in6_dev->lock);
> +			} else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
> +				   ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
>  				in6_dev_put(in6_dev);
>  				return;
>  			}

Why not initialize token by interface-identifier and then allow
users to "override"?

--yoshfuji

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net-next 1/2] net: ipv6: add tokenized interface identifier support
  2013-04-04 16:29   ` YOSHIFUJI Hideaki
@ 2013-04-04 16:48     ` Daniel Borkmann
  0 siblings, 0 replies; 9+ messages in thread
From: Daniel Borkmann @ 2013-04-04 16:48 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki; +Cc: davem, netdev, Hannes Frederic Sowa

On 04/04/2013 06:29 PM, YOSHIFUJI Hideaki wrote:
> Daniel Borkmann wrote:
>> This patch adds support for tokenized IIDs, that allow for
>> administrators to assign well-known host-part addresses to
>> nodes whilst still obtaining global network prefix from
>> Router Advertisements. It is currently in IETF RFC draft
>> status [1]:
>>
>>    The primary target for such support is server platforms
>>    where addresses are usually manually configured, rather
>>    than using DHCPv6 or SLAAC. By using tokenised identifiers,
>>    hosts can still determine their network prefix by use of
>>    SLAAC, but more readily be automatically renumbered should
>>    their network prefix change.
>>
>>   [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02
>>
>> The implementation is partially based on top of Mark K.
>> Thompson's proof of concept. Successfully tested by myself.
>>
>> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
>> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
>> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
>> ---
[...]
>>   		if (pinfo->prefix_len == 64) {
>>   			memcpy(&addr, &pinfo->prefix, 8);
>> -			if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
>> -			    ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
>> +
>> +			if (!ipv6_addr_any(&in6_dev->token)) {
>> +				read_lock_bh(&in6_dev->lock);
>> +				memcpy(addr.s6_addr + 8,
>> +				       in6_dev->token.s6_addr + 8, 8);
>> +				read_unlock_bh(&in6_dev->lock);
>> +			} else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
>> +				   ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
>>   				in6_dev_put(in6_dev);
>>   				return;
>>   			}
> 
> Why not initialize token by interface-identifier and then allow
> users to "override"?

Sure this would simplify this part above ...

... maybe I'm wrong, but then, probably, if someone changes the netdev's
hw address during runtime, we could not keep track of that anymore as
dynamically done in e.g. ipv6_generate_eui64(), since we've already done
the token init at an earlier point in time, no?

With the current patch, we would have a clear separation of both concepts
like ``either you use token iids, or you don't''.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2 2/2] ip: ipv6: add tokenized interface identifier support
  2013-04-04 14:37 ` [PATCH iproute2 2/2] ip: " Daniel Borkmann
@ 2013-04-05 16:39   ` Stephen Hemminger
  2013-04-07 11:58     ` Daniel Borkmann
  0 siblings, 1 reply; 9+ messages in thread
From: Stephen Hemminger @ 2013-04-05 16:39 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev, Hannes Frederic Sowa, YOSHIFUJI Hideaki

On Thu,  4 Apr 2013 16:37:38 +0200
Daniel Borkmann <dborkman@redhat.com> wrote:

> This is experimental support for tokenized IIDs, that enable
> administrators to assign well-known host-part addresses to nodes
> whilst still obtaining global network prefix from Router
> Advertisements. It is currently in IETF RFC draft status [1].
> 
> Example commands with iproute2:
> 
> Setting a device token:
>   # ip token set ::1a:2b:3c:4d/64 dev eth1
> 
> Getting a device token:
>   # ip token get dev eth1
>   token ::1a:2b:3c:4d dev eth1
> 
> Listing all tokens:
>   # ip token list  (or: ip token)
>   token :: dev eth0
>   token ::1a:2b:3c:4d dev eth1
> 
>  [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02
> 
> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>

Deferred.
Please resubmit during 3.10 merge window.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH iproute2 2/2] ip: ipv6: add tokenized interface identifier support
  2013-04-05 16:39   ` Stephen Hemminger
@ 2013-04-07 11:58     ` Daniel Borkmann
  0 siblings, 0 replies; 9+ messages in thread
From: Daniel Borkmann @ 2013-04-07 11:58 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: davem, netdev, Hannes Frederic Sowa, YOSHIFUJI Hideaki

On 04/05/2013 06:39 PM, Stephen Hemminger wrote:
> On Thu,  4 Apr 2013 16:37:38 +0200
> Daniel Borkmann <dborkman@redhat.com> wrote:
>
>> This is experimental support for tokenized IIDs, that enable
>> administrators to assign well-known host-part addresses to nodes
>> whilst still obtaining global network prefix from Router
>> Advertisements. It is currently in IETF RFC draft status [1].
>>
>> Example commands with iproute2:
>>
>> Setting a device token:
>>    # ip token set ::1a:2b:3c:4d/64 dev eth1
>>
>> Getting a device token:
>>    # ip token get dev eth1
>>    token ::1a:2b:3c:4d dev eth1
>>
>> Listing all tokens:
>>    # ip token list  (or: ip token)
>>    token :: dev eth0
>>    token ::1a:2b:3c:4d dev eth1
>>
>>   [1] http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02
>>
>> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
>> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
>> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
>
> Deferred.
> Please resubmit during 3.10 merge window.

Thanks, I'll do.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-04-07 11:59 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-04 14:37 [PATCH RFC 0/2] Add IPv6 tokenized interface identifier support Daniel Borkmann
2013-04-04 14:37 ` [PATCH net-next 1/2] net: ipv6: add " Daniel Borkmann
2013-04-04 15:58   ` Hannes Frederic Sowa
2013-04-04 16:02     ` Daniel Borkmann
2013-04-04 16:29   ` YOSHIFUJI Hideaki
2013-04-04 16:48     ` Daniel Borkmann
2013-04-04 14:37 ` [PATCH iproute2 2/2] ip: " Daniel Borkmann
2013-04-05 16:39   ` Stephen Hemminger
2013-04-07 11:58     ` Daniel Borkmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.