summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/netlink/route/action.h1
-rw-r--r--include/netlink/utils.h7
-rw-r--r--lib/route/act.c5
-rw-r--r--lib/route/cls/basic.c8
-rw-r--r--lib/route/cls/u32.c8
-rw-r--r--lib/utils.c2
6 files changed, 28 insertions, 3 deletions
diff --git a/include/netlink/route/action.h b/include/netlink/route/action.h
index e904432..054bdd8 100644
--- a/include/netlink/route/action.h
+++ b/include/netlink/route/action.h
@@ -22,6 +22,7 @@ extern "C" {
#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 **);
diff --git a/include/netlink/utils.h b/include/netlink/utils.h
index 4c2aa19..8faf917 100644
--- a/include/netlink/utils.h
+++ b/include/netlink/utils.h
@@ -97,6 +97,13 @@ enum {
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)
};
diff --git a/lib/route/act.c b/lib/route/act.c
index 3141866..1e9673f 100644
--- a/lib/route/act.c
+++ b/lib/route/act.c
@@ -178,6 +178,11 @@ struct rtnl_act *rtnl_act_alloc(void)
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);
diff --git a/lib/route/cls/basic.c b/lib/route/cls/basic.c
index 5a67fae..6af3844 100644
--- a/lib/route/cls/basic.c
+++ b/lib/route/cls/basic.c
@@ -228,6 +228,8 @@ int rtnl_basic_add_action(struct rtnl_cls *cls, struct rtnl_act *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);
}
@@ -245,9 +247,13 @@ int rtnl_basic_del_action(struct rtnl_cls *cls, struct rtnl_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;
}
/** @} */
diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c
index 52ab263..e91c39a 100644
--- a/lib/route/cls/u32.c
+++ b/lib/route/cls/u32.c
@@ -470,6 +470,8 @@ int rtnl_u32_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
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);
}
@@ -488,9 +490,13 @@ int rtnl_u32_del_action(struct rtnl_cls *cls, struct rtnl_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;
}
/** @} */
diff --git a/lib/utils.c b/lib/utils.c
index ac36493..e2294e6 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -1146,7 +1146,7 @@ int nl_has_capability (int capability)
_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,