summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMagnus Öberg <magnus.oberg@westermo.se>2016-04-25 14:08:29 (GMT)
committerThomas Haller <thaller@redhat.com>2022-03-04 21:21:24 (GMT)
commit3bf0a9c211b5e22d805632541d1e5c07e6134922 (patch)
tree186f2492d8bbe765ace44e78e22b5f11451e0328 /lib
parent3147d865da73009c13500ae296441c54aa2e3551 (diff)
downloadlibnl-3bf0a9c211b5e22d805632541d1e5c07e6134922.zip
libnl-3bf0a9c211b5e22d805632541d1e5c07e6134922.tar.gz
libnl-3bf0a9c211b5e22d805632541d1e5c07e6134922.tar.bz2
cls:u32: fix u32_clone() function
Spit the function into 2 parts: - where first being responsible for memory allocation/cloning - and second for populating the destination object Make proper cloning of 'action' attribute. For now, only the first action in chain is included in the clone. Signed-off-by: Magnus Öberg <magnus.oberg@westermo.se> Signed-off-by: Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se> [thaller@redhat.com: fix using the correct cleanup macros] https://github.com/thom311/libnl/pull/245
Diffstat (limited to 'lib')
-rw-r--r--lib/route/cls/u32.c89
1 files changed, 77 insertions, 12 deletions
diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c
index 55163d1..e6c5172 100644
--- a/lib/route/cls/u32.c
+++ b/lib/route/cls/u32.c
@@ -22,6 +22,8 @@
#include <netlink/route/cls/u32.h>
#include <netlink/route/action.h>
+#include "netlink-private/utils.h"
+
/** @cond SKIP */
#define U32_ATTR_DIVISOR 0x001
#define U32_ATTR_HASH 0x002
@@ -177,6 +179,14 @@ static void u32_free_data(struct rtnl_tc *tc, void *data)
static int u32_clone(void *_dst, void *_src)
{
struct rtnl_u32 *dst = _dst, *src = _src;
+ _nl_auto_nl_data struct nl_data *selector = NULL;
+ _nl_auto_nl_data struct nl_data *mark = NULL;
+ _nl_auto_nl_data struct nl_data *police = NULL;
+ _nl_auto_nl_data struct nl_data *pcnt = NULL;
+ _nl_auto_nl_data struct nl_data *opts = NULL;
+ _nl_auto_nl_data struct nl_data *xstats = NULL;
+ _nl_auto_nl_data struct nl_data *subdata = NULL;
+ _nl_auto_rtnl_act struct rtnl_act *act = NULL;
dst->cu_pcnt = NULL;
dst->cu_selector = NULL;
@@ -184,26 +194,81 @@ static int u32_clone(void *_dst, void *_src)
dst->cu_act = NULL;
dst->cu_police = NULL;
- if (src->cu_selector &&
- !(dst->cu_selector = nl_data_clone(src->cu_selector)))
- return -NLE_NOMEM;
+ if (src->cu_selector) {
+ if (!(selector = nl_data_clone(src->cu_selector)))
+ return -NLE_NOMEM;
+ }
- if (src->cu_mark &&
- !(dst->cu_mark = nl_data_clone(src->cu_mark)))
- return -NLE_NOMEM;
+ if (src->cu_mark) {
+ if (!(mark = nl_data_clone(src->cu_mark)))
+ return -NLE_NOMEM;
+ }
if (src->cu_act) {
- if (!(dst->cu_act = rtnl_act_alloc()))
+ if (!(act = rtnl_act_alloc()))
return -NLE_NOMEM;
- memcpy(dst->cu_act, src->cu_act, sizeof(struct rtnl_act));
+ if (src->cu_act->c_opts) {
+ if (!(opts = nl_data_clone(src->cu_act->c_opts)))
+ return -NLE_NOMEM;
+ }
+
+ if (src->cu_act->c_xstats) {
+ if (!(xstats = nl_data_clone(src->cu_act->c_xstats)))
+ return -NLE_NOMEM;
+ }
+
+ if (src->cu_act->c_subdata) {
+ if (!(subdata = nl_data_clone(src->cu_act->c_subdata)))
+ return -NLE_NOMEM;
+ }
}
- if (src->cu_police && !(dst->cu_police = nl_data_clone(src->cu_police)))
- return -NLE_NOMEM;
+ if (src->cu_police) {
+ if (!(police = nl_data_clone(src->cu_police)))
+ return -NLE_NOMEM;
+ }
- if (src->cu_pcnt && !(dst->cu_pcnt = nl_data_clone(src->cu_pcnt)))
- return -NLE_NOMEM;
+ if (src->cu_pcnt) {
+ if (!(pcnt = nl_data_clone(src->cu_pcnt)))
+ return -NLE_NOMEM;
+ }
+
+ /* we've passed the critical point and its safe to proceed */
+
+ if (selector)
+ dst->cu_selector = _nl_steal_pointer(&selector);
+
+ if (mark)
+ dst->cu_mark = _nl_steal_pointer(&mark);
+
+ if (police)
+ dst->cu_police = _nl_steal_pointer(&police);
+
+ if (pcnt)
+ dst->cu_pcnt = _nl_steal_pointer(&pcnt);
+
+ if (act) {
+ dst->cu_act = _nl_steal_pointer(&act);
+
+ /* action nl list next and prev pointers must be updated */
+ nl_init_list_head(&dst->cu_act->ce_list);
+
+ if (opts)
+ dst->cu_act->c_opts = _nl_steal_pointer(&opts);
+
+ if (xstats)
+ dst->cu_act->c_xstats = _nl_steal_pointer(&xstats);
+
+ if (subdata)
+ dst->cu_act->c_subdata = _nl_steal_pointer(&subdata);
+
+ if (dst->cu_act->c_link) {
+ nl_object_get(OBJ_CAST(dst->cu_act->c_link));
+ }
+
+ dst->cu_act->a_next = NULL; /* Only clone first in chain */
+ }
return 0;
}