From e5d9b828f6ec64fd77854578fbf1c33f214f3ac4 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Wed, 23 Apr 2014 17:28:29 -0700 Subject: act: grab a reference when adding an action to a filter When we add an action to a filter, its lifetime becomes same with the filter. So in case user frees it before us, we could just grab a reference here. Signed-off-by: Cong Wang Acked-by: Thomas Graf Signed-off-by: Thomas Haller --- include/netlink/route/action.h | 1 + include/netlink/utils.h | 7 +++++++ lib/route/act.c | 5 +++++ lib/route/cls/basic.c | 8 +++++++- lib/route/cls/u32.c | 8 +++++++- lib/utils.c | 2 +- 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, -- cgit v0.12