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,
sizeof(inner->type));
50 case NFTNL_EXPR_INNER_FLAGS:
51 memcpy(&inner->flags, data,
sizeof(inner->flags));
53 case NFTNL_EXPR_INNER_HDRSIZE:
54 memcpy(&inner->hdrsize, data,
sizeof(inner->hdrsize));
56 case NFTNL_EXPR_INNER_EXPR:
58 nftnl_expr_free(inner->expr);
60 inner->expr = (
void *)data;
69nftnl_expr_inner_get(
const struct nftnl_expr *e, uint16_t type,
75 case NFTNL_EXPR_INNER_FLAGS:
76 *data_len =
sizeof(inner->flags);
78 case NFTNL_EXPR_INNER_TYPE:
79 *data_len =
sizeof(inner->type);
81 case NFTNL_EXPR_INNER_HDRSIZE:
82 *data_len =
sizeof(inner->hdrsize);
83 return &inner->hdrsize;
84 case NFTNL_EXPR_INNER_EXPR:
91nftnl_expr_inner_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
96 mnl_attr_put_u32(nlh, NFTA_INNER_NUM, htonl(0));
97 if (e->flags & (1 << NFTNL_EXPR_INNER_TYPE))
98 mnl_attr_put_u32(nlh, NFTA_INNER_TYPE, htonl(inner->type));
99 if (e->flags & (1 << NFTNL_EXPR_INNER_FLAGS))
100 mnl_attr_put_u32(nlh, NFTA_INNER_FLAGS, htonl(inner->flags));
101 if (e->flags & (1 << NFTNL_EXPR_INNER_HDRSIZE))
102 mnl_attr_put_u32(nlh, NFTA_INNER_HDRSIZE, htonl(inner->hdrsize));
103 if (e->flags & (1 << NFTNL_EXPR_INNER_EXPR)) {
104 nest = mnl_attr_nest_start(nlh, NFTA_INNER_EXPR);
105 nftnl_expr_build_payload(nlh, inner->expr);
106 mnl_attr_nest_end(nlh, nest);
110static int nftnl_inner_parse_cb(
const struct nlattr *attr,
void *data)
112 const struct nlattr **tb = data;
113 int type = mnl_attr_get_type(attr);
115 if (mnl_attr_type_valid(attr, NFTA_INNER_MAX) < 0)
120 case NFTA_INNER_TYPE:
121 case NFTA_INNER_HDRSIZE:
122 case NFTA_INNER_FLAGS:
123 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
126 case NFTA_INNER_EXPR:
127 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
138nftnl_expr_inner_parse(
struct nftnl_expr *e,
struct nlattr *attr)
141 struct nlattr *tb[NFTA_INNER_MAX + 1] = {};
142 struct nftnl_expr *expr;
145 err = mnl_attr_parse_nested(attr, nftnl_inner_parse_cb, tb);
149 if (tb[NFTA_INNER_HDRSIZE]) {
151 ntohl(mnl_attr_get_u32(tb[NFTA_INNER_HDRSIZE]));
152 e->flags |= (1 << NFTNL_EXPR_INNER_HDRSIZE);
154 if (tb[NFTA_INNER_FLAGS]) {
156 ntohl(mnl_attr_get_u32(tb[NFTA_INNER_FLAGS]));
157 e->flags |= (1 << NFTNL_EXPR_INNER_FLAGS);
159 if (tb[NFTA_INNER_TYPE]) {
161 ntohl(mnl_attr_get_u32(tb[NFTA_INNER_TYPE]));
162 e->flags |= (1 << NFTNL_EXPR_INNER_TYPE);
164 if (tb[NFTA_INNER_EXPR]) {
165 expr = nftnl_expr_parse(tb[NFTA_INNER_EXPR]);
170 nftnl_expr_free(inner->expr);
173 e->flags |= (1 << NFTNL_EXPR_INNER_EXPR);
180nftnl_expr_inner_snprintf(
char *buf,
size_t remain, uint32_t flags,
181 const struct nftnl_expr *e)
187 ret = snprintf(buf, remain,
"type %u hdrsize %u flags %x [",
188 inner->type, inner->hdrsize, inner->flags);
189 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
191 ret = snprintf(buf + offset, remain,
" %s ", inner->expr->ops->name);
192 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
194 ret = nftnl_expr_snprintf(buf + offset, remain, inner->expr,
195 NFTNL_OUTPUT_DEFAULT, 0);
196 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
198 ret = snprintf(buf + offset, remain,
"] ");
199 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
204struct expr_ops expr_ops_inner = {
207 .max_attr = NFTA_INNER_MAX,
208 .free = nftnl_expr_inner_free,
209 .set = nftnl_expr_inner_set,
210 .get = nftnl_expr_inner_get,
211 .parse = nftnl_expr_inner_parse,
212 .build = nftnl_expr_inner_build,
213 .output = nftnl_expr_inner_snprintf,