struct rtnl_link_info_ops *io = link->l_info_ops;
if (io != NULL) {
- io->io_free(link);
+ if (io->io_free)
+ io->io_free(link);
rtnl_link_info_ops_put(io);
link->l_info_ops = NULL;
}
kind = nla_get_string(li[IFLA_INFO_KIND]);
ops = rtnl_link_info_ops_lookup(kind);
- if (ops != NULL) {
+ if (ops && ops->io_parse) {
link->l_info_ops = ops;
err = ops->io_parse(link, li[IFLA_INFO_DATA],
li[IFLA_INFO_XSTATS]);
if (link->ce_mask & LINK_ATTR_IFALIAS)
NLA_PUT_STRING(msg, IFLA_IFALIAS, link->l_ifalias);
- if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops &&
- link->l_info_ops->io_put_attrs) {
+ if ((link->ce_mask & LINK_ATTR_LINKINFO) && link->l_info_ops) {
struct nlattr *info;
if (!(info = nla_nest_start(msg, IFLA_LINKINFO)))
NLA_PUT_STRING(msg, IFLA_INFO_KIND, link->l_info_ops->io_name);
- if (link->l_info_ops->io_put_attrs(msg, link) < 0)
+ 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);
return -NLE_MSGSIZE;
}
+/**
+ * Build a netlink message requesting the addition of a new virtual link
+ * @arg link new link to add
+ * @arg flags additional netlink message flags
+ * @arg result pointer to store resulting netlink message
+ *
+ * The behaviour of this function is identical to rtnl_link_add() with
+ * the exception that it will not send the message but return it in the
+ * provided return pointer instead.
+ *
+ * @see rtnl_link_add()
+ *
+ * @note This operation is not supported on all kernel versions.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_link_build_add_request(struct rtnl_link *link, int flags,
+ struct nl_msg **result)
+{
+ struct ifinfomsg ifi = {
+ .ifi_family = link->l_family,
+ .ifi_index = link->l_index,
+ .ifi_flags = link->l_flags,
+ };
+
+ return build_link_msg(RTM_NEWLINK, &ifi, link, flags, result);
+}
+
+/**
+ * Add virtual link
+ * @arg sk netlink socket.
+ * @arg link new link to add
+ * @arg flags additional netlink message flags
+ *
+ * Builds a \c RTM_NEWLINK netlink message requesting the addition of
+ * a new virtual link.
+ *
+ * After sending, the function will wait for the ACK or an eventual
+ * error message to be received and will therefore block until the
+ * operation has been completed.
+ *
+ * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause
+ * this function to return immediately after sending. In this case,
+ * it is the responsibility of the caller to handle any error
+ * messages returned.
+ *
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ err = rtnl_link_build_add_request(link, flags, &msg);
+ if (err < 0)
+ return err;
+
+ err = nl_send_auto_complete(sk, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return wait_for_ack(sk);
+}
+
/**
* Build a netlink message requesting the modification of a link
* @arg orig original link to change
if (link->l_info_ops)
release_link_info(link);
- if ((err = io->io_alloc(link)) < 0)
+ if (io->io_alloc && (err = io->io_alloc(link)) < 0)
return err;
+ link->ce_mask |= LINK_ATTR_LINKINFO;
link->l_info_ops = io;
return 0;