18#include <libmnl/libmnl.h>
20#include <linux/netfilter/nf_tables.h>
22#include <libnftnl/expr.h>
23#include <libnftnl/rule.h>
29 struct nftnl_expr *expr;
32static void nftnl_expr_inner_free(
const struct nftnl_expr *e)
37 nftnl_expr_free(inner->expr);
41nftnl_expr_inner_set(
struct nftnl_expr *e, uint16_t type,
42 const void *data, uint32_t data_len)
47 case NFTNL_EXPR_INNER_TYPE:
48 memcpy(&inner->type, data, data_len);
50 case NFTNL_EXPR_INNER_FLAGS:
51 memcpy(&inner->flags, data, data_len);
53 case NFTNL_EXPR_INNER_HDRSIZE:
54 memcpy(&inner->hdrsize, data, data_len);
56 case NFTNL_EXPR_INNER_EXPR:
58 nftnl_expr_free(inner->expr);
60 inner->expr = (
void *)data;
67nftnl_expr_inner_get(
const struct nftnl_expr *e, uint16_t type,
73 case NFTNL_EXPR_INNER_FLAGS:
74 *data_len =
sizeof(inner->flags);
76 case NFTNL_EXPR_INNER_TYPE:
77 *data_len =
sizeof(inner->type);
79 case NFTNL_EXPR_INNER_HDRSIZE:
80 *data_len =
sizeof(inner->hdrsize);
81 return &inner->hdrsize;
82 case NFTNL_EXPR_INNER_EXPR:
89nftnl_expr_inner_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
94 mnl_attr_put_u32(nlh, NFTA_INNER_NUM, htonl(0));
95 if (e->flags & (1 << NFTNL_EXPR_INNER_TYPE))
96 mnl_attr_put_u32(nlh, NFTA_INNER_TYPE, htonl(inner->type));
97 if (e->flags & (1 << NFTNL_EXPR_INNER_FLAGS))
98 mnl_attr_put_u32(nlh, NFTA_INNER_FLAGS, htonl(inner->flags));
99 if (e->flags & (1 << NFTNL_EXPR_INNER_HDRSIZE))
100 mnl_attr_put_u32(nlh, NFTA_INNER_HDRSIZE, htonl(inner->hdrsize));
101 if (e->flags & (1 << NFTNL_EXPR_INNER_EXPR)) {
102 nest = mnl_attr_nest_start(nlh, NFTA_INNER_EXPR);
103 nftnl_expr_build_payload(nlh, inner->expr);
104 mnl_attr_nest_end(nlh, nest);
108static int nftnl_inner_parse_cb(
const struct nlattr *attr,
void *data)
110 const struct nlattr **tb = data;
111 int type = mnl_attr_get_type(attr);
113 if (mnl_attr_type_valid(attr, NFTA_INNER_MAX) < 0)
118 case NFTA_INNER_TYPE:
119 case NFTA_INNER_HDRSIZE:
120 case NFTA_INNER_FLAGS:
121 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
124 case NFTA_INNER_EXPR:
125 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
136nftnl_expr_inner_parse(
struct nftnl_expr *e,
struct nlattr *attr)
139 struct nlattr *tb[NFTA_INNER_MAX + 1] = {};
140 struct nftnl_expr *expr;
143 err = mnl_attr_parse_nested(attr, nftnl_inner_parse_cb, tb);
147 if (tb[NFTA_INNER_HDRSIZE]) {
149 ntohl(mnl_attr_get_u32(tb[NFTA_INNER_HDRSIZE]));
150 e->flags |= (1 << NFTNL_EXPR_INNER_HDRSIZE);
152 if (tb[NFTA_INNER_FLAGS]) {
154 ntohl(mnl_attr_get_u32(tb[NFTA_INNER_FLAGS]));
155 e->flags |= (1 << NFTNL_EXPR_INNER_FLAGS);
157 if (tb[NFTA_INNER_TYPE]) {
159 ntohl(mnl_attr_get_u32(tb[NFTA_INNER_TYPE]));
160 e->flags |= (1 << NFTNL_EXPR_INNER_TYPE);
162 if (tb[NFTA_INNER_EXPR]) {
163 expr = nftnl_expr_parse(tb[NFTA_INNER_EXPR]);
168 nftnl_expr_free(inner->expr);
171 e->flags |= (1 << NFTNL_EXPR_INNER_EXPR);
178nftnl_expr_inner_snprintf(
char *buf,
size_t remain, uint32_t flags,
179 const struct nftnl_expr *e)
185 ret = snprintf(buf, remain,
"type %u hdrsize %u flags %x [",
186 inner->type, inner->hdrsize, inner->flags);
187 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
189 ret = snprintf(buf + offset, remain,
" %s ", inner->expr->ops->name);
190 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
192 ret = nftnl_expr_snprintf(buf + offset, remain, inner->expr,
193 NFTNL_OUTPUT_DEFAULT, 0);
194 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
196 ret = snprintf(buf + offset, remain,
"] ");
197 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
202static struct attr_policy inner_attr_policy[__NFTNL_EXPR_INNER_MAX] = {
203 [NFTNL_EXPR_INNER_TYPE] = { .maxlen =
sizeof(uint32_t) },
204 [NFTNL_EXPR_INNER_FLAGS] = { .maxlen =
sizeof(uint32_t) },
205 [NFTNL_EXPR_INNER_HDRSIZE] = { .maxlen =
sizeof(uint32_t) },
206 [NFTNL_EXPR_INNER_EXPR] = { .maxlen = 0 },
209struct expr_ops expr_ops_inner = {
212 .nftnl_max_attr = __NFTNL_EXPR_INNER_MAX - 1,
213 .attr_policy = inner_attr_policy,
214 .free = nftnl_expr_inner_free,
215 .set = nftnl_expr_inner_set,
216 .get = nftnl_expr_inner_get,
217 .parse = nftnl_expr_inner_parse,
218 .build = nftnl_expr_inner_build,
219 .output = nftnl_expr_inner_snprintf,