#endif
extern struct rtnl_act *rtnl_act_alloc(void);
+extern void rtnl_act_get(struct rtnl_act *);
extern void rtnl_act_put(struct rtnl_act *);
extern int rtnl_act_build_add_request(struct rtnl_act *, int,
struct nl_msg **);
NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE = 2,
#define NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE
+ /**
+ * rtnl_u32_add_action() and rtnl_basic_add_action() now grab a reference to act
+ * caller are free to release its own
+ */
+ NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE = 3,
+#define NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE
+
__NL_CAPABILITY_MAX
#define NL_CAPABILITY_MAX (__NL_CAPABILITY_MAX - 1)
};
return (struct rtnl_act *) tc;
}
+void rtnl_act_get(struct rtnl_act *act)
+{
+ nl_object_get(OBJ_CAST(act));
+}
+
void rtnl_act_put(struct rtnl_act *act)
{
nl_object_put((struct nl_object *) act);
return -NLE_NOMEM;
b->b_mask |= BASIC_ATTR_ACTION;
+ /* In case user frees it */
+ rtnl_act_get(act);
return rtnl_act_append(&b->b_act, act);
}
if (!(b->b_mask & BASIC_ATTR_ACTION))
return -NLE_INVAL;
ret = rtnl_act_remove(&b->b_act, act);
+ if (ret)
+ return ret;
+
if (!b->b_act)
b->b_mask &= ~BASIC_ATTR_ACTION;
- return ret;
+ rtnl_act_put(act);
+ return 0;
}
/** @} */
return -NLE_NOMEM;
u->cu_mask |= U32_ATTR_ACTION;
+ /* In case user frees it */
+ rtnl_act_get(act);
return rtnl_act_append(&u->cu_act, act);
}
return -NLE_INVAL;
ret = rtnl_act_remove(&u->cu_act, act);
+ if (ret)
+ return ret;
+
if (!u->cu_act)
u->cu_mask &= ~U32_ATTR_ACTION;
- return ret;
+ rtnl_act_put(act);
+ return 0;
}
/** @} */
_NL_SET(0,
NL_CAPABILITY_ROUTE_BUILD_MSG_SET_SCOPE,
NL_CAPABILITY_ROUTE_LINK_VETH_GET_PEER_OWN_REFERENCE,
- 0,
+ NL_CAPABILITY_ROUTE_LINK_CLS_ADD_ACT_OWN_REFERENCE,
0,
0,
0,