NFTNL_UDATA_SET_MERGE_ELEMENTS,
NFTNL_UDATA_SET_KEY_TYPEOF,
NFTNL_UDATA_SET_DATA_TYPEOF,
+ NFTNL_UDATA_SET_EXPR,
__NFTNL_UDATA_SET_MAX
};
#define NFTNL_UDATA_SET_MAX (__NFTNL_UDATA_SET_MAX - 1)
* @NFTA_SET_USERDATA: user data (NLA_BINARY)
* @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
* @NFTA_SET_HANDLE: set handle (NLA_U64)
+ * @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes)
*/
enum nft_set_attributes {
NFTA_SET_UNSPEC,
NFTA_SET_PAD,
NFTA_SET_OBJ_TYPE,
NFTA_SET_HANDLE,
+ NFTA_SET_EXPR,
__NFTA_SET_MAX
};
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
xfree(s->name);
if (s->flags & (1 << NFTNL_SET_USERDATA))
xfree(s->user.data);
+ if (s->flags & (1 << NFTNL_SET_EXPR))
+ nftnl_expr_free(s->expr);
list_for_each_entry_safe(elem, tmp, &s->element_list, head) {
list_del(&elem->head);
case NFTNL_SET_USERDATA:
xfree(s->user.data);
break;
+ case NFTNL_SET_EXPR:
+ nftnl_expr_free(s->expr);
+ break;
default:
return;
}
memcpy(s->user.data, data, data_len);
s->user.len = data_len;
break;
+ case NFTNL_SET_EXPR:
+ if (s->flags & (1 << NFTNL_SET_EXPR))
+ nftnl_expr_free(s->expr);
+
+ s->expr = (void *)data;
+ break;
}
s->flags |= (1 << attr);
return 0;
case NFTNL_SET_USERDATA:
*data_len = s->user.len;
return s->user.data;
+ case NFTNL_SET_EXPR:
+ return s->expr;
}
return NULL;
}
mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
if (s->flags & (1 << NFTNL_SET_USERDATA))
mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
+ if (s->flags & (1 << NFTNL_SET_EXPR)) {
+ struct nlattr *nest1;
+
+ nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR);
+ nftnl_expr_build_payload(nlh, s->expr);
+ mnl_attr_nest_end(nlh, nest1);
+ }
}
if (ret < 0)
return ret;
}
+ if (tb[NFTA_SET_EXPR]) {
+ s->expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]);
+ if (!s->expr)
+ return -1;
+
+ s->flags |= (1 << NFTNL_SET_EXPR);
+ }
s->family = nfg->nfgen_family;
s->flags |= (1 << NFTNL_SET_FAMILY);