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

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
Lubomir Rintel 2014-09-26 23:19:43 +02:00 committed by Thomas Haller
parent e003951945
commit b0d0d339cd
2 changed files with 76 additions and 0 deletions

View File

@ -24,6 +24,12 @@ const char * rtnl_link_inet6_addrgenmode2str (uint8_t mode,
uint8_t rtnl_link_inet6_str2addrgenmode (const char *mode);
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 *);
extern int rtnl_link_inet6_get_addr_gen_mode(struct rtnl_link *,
uint8_t *);

View File

@ -22,6 +22,7 @@ struct inet6_data
uint32_t i6_flags;
struct ifla_cacheinfo i6_cacheinfo;
uint32_t i6_conf[DEVCONF_MAX];
struct in6_addr i6_token;
uint8_t i6_addr_gen_mode;
};
@ -57,6 +58,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) },
[IFLA_INET6_ADDR_GEN_MODE] = { .type = NLA_U8 },
};
@ -166,6 +168,10 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
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));
if (tb[IFLA_INET6_ADDR_GEN_MODE])
i6->i6_addr_gen_mode = nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE]);
@ -306,6 +312,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;
@ -323,6 +330,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(p, " link-local address mode %s\n",
rtnl_link_inet6_addrgenmode2str(i6->i6_addr_gen_mode,
buf, sizeof(buf)));
@ -520,6 +532,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;
}
/**
* Get IPv6 link-local address generation mode
* @arg link Link object