[patch libnl] link: allow to add/get linkinfo of unknown type
Jiri Pirko
jpirko at redhat.com
Fri Nov 11 08:56:16 EST 2011
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 at redhat.com>
---
include/netlink-types.h | 1 +
lib/route/link.c | 76 +++++++++++++++++++++++++++++++++-------------
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/include/netlink-types.h b/include/netlink-types.h
index 750c897..82481b7 100644
--- a/include/netlink-types.h
+++ b/include/netlink-types.h
@@ -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;
diff --git a/lib/route/link.c b/lib/route/link.c
index e486b3f..ad5fcbe 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -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;
}
/** @} */
--
1.7.6
More information about the libnl
mailing list