]> git.ipfire.org Git - thirdparty/libnl.git/commitdiff
link: allow to add/get linkinfo of unknown type
authorJiri Pirko <jpirko@redhat.com>
Fri, 11 Nov 2011 13:56:16 +0000 (14:56 +0100)
committerThomas Graf <tgraf@redhat.com>
Fri, 11 Nov 2011 14:37:03 +0000 (15:37 +0100)
store type kind in rtnl_link independently. That would allow to use this
value even if type_ops are not present. This allows for example to
create devices of type unknown to libnl.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
include/netlink-types.h
lib/route/link.c

index 750c897161841ec3cc1b9d7842c1ad8d1a8cc68d..82481b783406b0f2a3a3a44536861abe34488f9e 100644 (file)
@@ -167,6 +167,7 @@ struct rtnl_link
        uint8_t                         l_operstate;
        uint8_t                         l_linkmode;
        /* 2 byte hole */
+       char *                          l_info_kind;
        struct rtnl_link_info_ops *     l_info_ops;
        void *                          l_af_data[AF_MAX];
        void *                          l_info;
index e486b3f8ab4e4b36a5880c965a4525eabc6ce5d1..ad5fcbe90bbc1786ed95b0bec185dae553b59ba3 100644 (file)
@@ -195,6 +195,7 @@ static void link_free_data(struct nl_object *c)
                nl_addr_put(link->l_bcast);
 
                free(link->l_ifalias);
+               free(link->l_info_kind);
 
                do_foreach_af(link, af_free, NULL);
        }
@@ -218,6 +219,10 @@ static int link_clone(struct nl_object *_dst, struct nl_object *_src)
                if (!(dst->l_ifalias = strdup(src->l_ifalias)))
                        return -NLE_NOMEM;
 
+       if (src->l_info_kind)
+               if (!(dst->l_info_kind = strdup(src->l_info_kind)))
+                       return -NLE_NOMEM;
+
        if (src->l_info_ops && src->l_info_ops->io_clone) {
                err = src->l_info_ops->io_clone(dst, src);
                if (err < 0)
@@ -478,18 +483,27 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
                        struct rtnl_link_info_ops *ops;
                        char *kind;
 
-                       kind = nla_get_string(li[IFLA_INFO_KIND]);
+                       kind = nla_strdup(tb[IFLA_INFO_KIND]);
+                       if (kind == NULL) {
+                               err = -NLE_NOMEM;
+                               goto errout;
+                       }
+                       link->l_info_kind = kind;
+                       link->ce_mask |= LINK_ATTR_LINKINFO;
+
                        ops = rtnl_link_info_ops_lookup(kind);
                        link->l_info_ops = ops;
-                       
-                       if (ops && ops->io_parse &&
-                           (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
-                               err = ops->io_parse(link, li[IFLA_INFO_DATA],
-                                                   li[IFLA_INFO_XSTATS]);
-                               if (err < 0)
-                                       goto errout;
-                       } else {
-                               /* XXX: Warn about unparsed info? */
+
+                       if (ops) {
+                               if (ops->io_parse &&
+                                   (li[IFLA_INFO_DATA] || li[IFLA_INFO_XSTATS])) {
+                                       err = ops->io_parse(link, li[IFLA_INFO_DATA],
+                                                           li[IFLA_INFO_XSTATS]);
+                                       if (err < 0)
+                                               goto errout;
+                               } else {
+                                       /* XXX: Warn about unparsed info? */
+                               }
                        }
                }
        }
@@ -1115,17 +1129,19 @@ static int build_link_msg(int cmd, struct ifinfomsg *hdr,
        if (link->ce_mask & LINK_ATTR_MASTER)
                NLA_PUT_U32(msg, IFLA_MASTER, link->l_master);
 
-       if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops) {
+       if (link->ce_mask & LINK_ATTR_LINKINFO) {
                struct nlattr *info;
 
                if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
                        goto nla_put_failure;
 
-               NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_ops->io_name);
+               NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_kind);
 
-               if (link->l_info_ops->io_put_attrs &&
-                   link->l_info_ops->io_put_attrs(msg, link) < 0)
-                       goto nla_put_failure;
+               if (link->l_info_ops) {
+                       if (link->l_info_ops->io_put_attrs &&
+                           link->l_info_ops->io_put_attrs(msg, link) < 0)
+                               goto nla_put_failure;
+               }
 
                nla_nest_end(msg, info);
        }
@@ -1952,20 +1968,36 @@ int rtnl_link_set_type(struct rtnl_link *link, const char *type)
 {
        struct rtnl_link_info_ops *io;
        int err;
+       char *kind;
 
-       if ((io = rtnl_link_info_ops_lookup(type)) == NULL)
-               return -NLE_OPNOTSUPP;
-
+       free(link->l_info_kind);
+       link->ce_mask &= ~LINK_ATTR_LINKINFO;
        if (link->l_info_ops)
                release_link_info(link);
 
-       if (io->io_alloc && (err = io->io_alloc(link)) < 0)
-               return err;
+       if (!type)
+               return 0;
+
+       kind = strdup(type);
+       if (!kind)
+               return -NLE_NOMEM;
+
+       io = rtnl_link_info_ops_lookup(type);
+       if (io) {
+               if (io->io_alloc && (err = io->io_alloc(link)) < 0)
+                       goto errout;
 
+               link->l_info_ops = io;
+       }
+
+       link->l_info_kind = kind;
        link->ce_mask |= LINK_ATTR_LINKINFO;
-       link->l_info_ops = io;
 
        return 0;
+
+errout:
+       free(kind);
+       return err;
 }
 
 /**
@@ -1977,7 +2009,7 @@ int rtnl_link_set_type(struct rtnl_link *link, const char *type)
  */
 char *rtnl_link_get_type(struct rtnl_link *link)
 {
-       return link->l_info_ops ? link->l_info_ops->io_name : NULL;
+       return link->l_info_kind;
 }
 
 /** @} */