From c4b26bbcfeb6ca3deaa926c6f7921df83e9db06c Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Fri, 26 Sep 2014 23:19:43 +0200 Subject: [PATCH] link/inet6: add support for tokenized interface identifiers http://tools.ietf.org/html/draft-chown-6man-tokenised-ipv6-identifiers-02 [thaller@redhat.com: Add OOM handling, fix whitespace issues] https://github.com/thom311/libnl/pull/63 (cherry picked from b0d0d339cd69834bd05cb5c704fbf06677f754eb) Signed-off-by: Lubomir Rintel Signed-off-by: Thomas Haller --- include/Makefile.am | 1 + include/linux/if_link.h | 1 + include/netlink/route/link/inet6.h | 31 +++++++++++++++++ lib/route/link/inet6.c | 70 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 include/netlink/route/link/inet6.h diff --git a/include/Makefile.am b/include/Makefile.am index 765cf5a..40ed84f 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -48,6 +48,7 @@ nobase_libnlinclude_HEADERS = \ netlink/route/link/bridge.h \ netlink/route/link/can.h \ netlink/route/link/inet.h \ + netlink/route/link/inet6.h \ netlink/route/link/info-api.h \ netlink/route/link/macvlan.h \ netlink/route/link/vlan.h \ diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 8b84939..bbe6991 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -196,6 +196,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/include/netlink/route/link/inet6.h b/include/netlink/route/link/inet6.h new file mode 100644 index 0000000..71886d7 --- /dev/null +++ b/include/netlink/route/link/inet6.h @@ -0,0 +1,31 @@ +/* + * netlink/route/link/inet6.h INET6 Link Module + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2014 Dan Williams + */ + +#ifndef NETLINK_LINK_INET6_H_ +#define NETLINK_LINK_INET6_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_link_inet6_get_token(struct rtnl_link *, + struct nl_addr **); + +extern int rtnl_link_inet6_set_token(struct rtnl_link *, + struct nl_addr *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c index 6fa2741..eb4fa3f 100644 --- a/lib/route/link/inet6.c +++ b/lib/route/link/inet6.c @@ -20,6 +20,7 @@ struct inet6_data uint32_t i6_flags; struct ifla_cacheinfo i6_cacheinfo; uint32_t i6_conf[DEVCONF_MAX]; + struct in6_addr i6_token; }; static void *inet6_alloc(struct rtnl_link *link) @@ -48,6 +49,7 @@ static struct nla_policy inet6_policy[IFLA_INET6_MAX+1] = { [IFLA_INET6_CONF] = { .minlen = 4 }, [IFLA_INET6_STATS] = { .minlen = 8 }, [IFLA_INET6_ICMP6STATS] = { .minlen = 8 }, + [IFLA_INET6_TOKEN] = { .minlen = sizeof(struct in6_addr) }, }; static const uint8_t map_stat_id_from_IPSTATS_MIB_v1[__IPSTATS_MIB_MAX] = { @@ -155,6 +157,10 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr, if (tb[IFLA_INET6_CONF]) nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF], sizeof(i6->i6_conf)); + + if (tb[IFLA_INET6_TOKEN]) + nla_memcpy(&i6->i6_token, tb[IFLA_INET6_TOKEN], + sizeof(struct in6_addr)); /* * Due to 32bit data alignment, these addresses must be copied to an @@ -264,6 +270,7 @@ static void inet6_dump_details(struct rtnl_link *link, struct nl_dump_params *p, void *data) { struct inet6_data *i6 = data; + struct nl_addr *addr; char buf[64], buf2[64]; int i, n = 0; @@ -281,6 +288,11 @@ static void inet6_dump_details(struct rtnl_link *link, nl_dump(p, " retrans-time %s\n", nl_msec2str(i6->i6_cacheinfo.retrans_time, buf, sizeof(buf))); + addr = nl_addr_build(AF_INET6, &i6->i6_token, sizeof(i6->i6_token)); + nl_dump(p, " token %s\n", + nl_addr2str(addr, buf, sizeof(buf))); + nl_addr_put(addr); + nl_dump_line(p, " devconf:\n"); nl_dump_line(p, " "); @@ -473,6 +485,64 @@ static struct rtnl_link_af_ops inet6_ops = { .ao_protinfo_policy = &protinfo_policy, }; +/** + * Get IPv6 tokenized interface identifier + * @arg link Link object + * @arg token Tokenized interface identifier on success + * + * Returns the link's IPv6 tokenized interface identifier. + * + * @return 0 on success + * @return -NLE_NOMEM failure to allocate struct nl_addr result + * @return -NLE_NOATTR configuration setting not available + * @return -NLE_NOADDR tokenized interface identifier is not set + */ +int rtnl_link_inet6_get_token(struct rtnl_link *link, struct nl_addr **addr) +{ + struct inet6_data *id; + + if (!(id = rtnl_link_af_data(link, &inet6_ops))) + return -NLE_NOATTR; + + *addr = nl_addr_build(AF_INET6, &id->i6_token, sizeof(id->i6_token)); + if (!*addr) + return -NLE_NOMEM; + if (nl_addr_iszero(*addr)) { + nl_addr_put(*addr); + *addr = NULL; + return -NLE_NOADDR; + } + + return 0; +} + +/** + * Set IPv6 tokenized interface identifier + * @arg link Link object + * @arg token Tokenized interface identifier + * + * Sets the link's IPv6 tokenized interface identifier. + * + * @return 0 on success + * @return -NLE_NOMEM could not allocate inet6 data + * @return -NLE_INVAL addr is not a valid inet6 address + */ +int rtnl_link_inet6_set_token(struct rtnl_link *link, struct nl_addr *addr) +{ + struct inet6_data *id; + + if ((nl_addr_get_family(addr) != AF_INET6) || + (nl_addr_get_len(addr) != sizeof(id->i6_token))) + return -NLE_INVAL; + + if (!(id = rtnl_link_af_alloc(link, &inet6_ops))) + return -NLE_NOMEM; + + memcpy(&id->i6_token, nl_addr_get_binary_addr(addr), + sizeof(id->i6_token)); + return 0; +} + static void __init inet6_init(void) { rtnl_link_af_register(&inet6_ops); -- 1.9.3