Commit 191b60bd authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Stephen Hemminger

ip: ipv6: add tokenized interface identifier support

This patch adds 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. This is the iproute2 part for
the kernel patch f53adae4eae5 (``net: ipv6: add tokenized
interface identifier support'').

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
Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
parent 79e9a1db
IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ 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 \ 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 \ ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \
iplink_vlan.o link_veth.o link_gre.o iplink_can.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_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
......
...@@ -45,7 +45,7 @@ static void usage(void) ...@@ -45,7 +45,7 @@ static void usage(void)
" ip [ -force ] -batch filename\n" " ip [ -force ] -batch filename\n"
"where OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n" "where OBJECT := { link | addr | addrlabel | route | rule | neigh | ntable |\n"
" tunnel | tuntap | maddr | mroute | mrule | monitor | xfrm |\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" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
" -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n" " -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n"
" -4 | -6 | -I | -D | -B | -0 |\n" " -4 | -6 | -I | -D | -B | -0 |\n"
...@@ -80,6 +80,7 @@ static const struct cmd { ...@@ -80,6 +80,7 @@ static const struct cmd {
{ "tunl", do_iptunnel }, { "tunl", do_iptunnel },
{ "tuntap", do_iptuntap }, { "tuntap", do_iptuntap },
{ "tap", do_iptuntap }, { "tap", do_iptuntap },
{ "token", do_iptoken },
{ "tcpmetrics", do_tcp_metrics }, { "tcpmetrics", do_tcp_metrics },
{ "tcp_metrics",do_tcp_metrics }, { "tcp_metrics",do_tcp_metrics },
{ "monitor", do_ipmonitor }, { "monitor", do_ipmonitor },
......
...@@ -49,6 +49,7 @@ extern int do_xfrm(int argc, char **argv); ...@@ -49,6 +49,7 @@ extern int do_xfrm(int argc, char **argv);
extern int do_ipl2tp(int argc, char **argv); extern int do_ipl2tp(int argc, char **argv);
extern int do_tcp_metrics(int argc, char **argv); extern int do_tcp_metrics(int argc, char **argv);
extern int do_ipnetconf(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) static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb)
{ {
......
/*
* 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]) {
fprintf(stderr, "Seems there's no support for IPv6 token!\n");
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);
}
...@@ -9,7 +9,7 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 ss.8 \ ...@@ -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-addrlabel.8 ip-l2tp.8 \
ip-maddress.8 ip-monitor.8 ip-mroute.8 ip-neighbour.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-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) all: $(TARGETS)
......
.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 are
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 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment