]> granicus.if.org Git - libnl/commitdiff
link/inet6: add support for tokenized interface identifiers
authorLubomir Rintel <lkundrak@v3.sk>
Fri, 26 Sep 2014 21:19:43 +0000 (23:19 +0200)
committerThomas Haller <thaller@redhat.com>
Wed, 8 Oct 2014 14:47:43 +0000 (16:47 +0200)
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>
include/netlink/route/link/inet6.h
lib/route/link/inet6.c

index 8ffeab2c4e814bffde1a3d0b082666b3200b4f7a..7e81967947da94a089297c6de79bbb2f6255f0df 100644 (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 *);
 
index 0f096fcadff5f7e6ac73b1f4642338c06bdb9d79..f5b1802f9553aa6e131c1d9ec04872ab6b2f42d6 100644 (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