* [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