15 #include <arpa/inet.h>
18 #include <libmnl/libmnl.h>
19 #include <linux/netfilter/nf_tables.h>
20 #include <libnftnl/expr.h>
21 #include <libnftnl/rule.h>
26 union nft_data_reg data;
27 enum nft_registers dreg;
31 nft_rule_expr_immediate_set(
struct nft_rule_expr *e, uint16_t type,
32 const void *data, uint32_t data_len)
37 case NFT_EXPR_IMM_DREG:
38 imm->dreg = *((uint32_t *)data);
40 case NFT_EXPR_IMM_DATA:
41 memcpy(&imm->data.val, data, data_len);
42 imm->data.len = data_len;
44 case NFT_EXPR_IMM_VERDICT:
45 imm->data.verdict = *((uint32_t *)data);
47 case NFT_EXPR_IMM_CHAIN:
49 xfree(imm->data.chain);
51 imm->data.chain = strdup(data);
60 nft_rule_expr_immediate_get(
const struct nft_rule_expr *e, uint16_t type,
66 case NFT_EXPR_IMM_DREG:
67 *data_len =
sizeof(imm->dreg);
69 case NFT_EXPR_IMM_DATA:
70 *data_len = imm->data.len;
71 return &imm->data.val;
72 case NFT_EXPR_IMM_VERDICT:
73 *data_len =
sizeof(imm->data.verdict);
74 return &imm->data.verdict;
75 case NFT_EXPR_IMM_CHAIN:
76 *data_len = strlen(imm->data.chain)+1;
77 return imm->data.chain;
82 static int nft_rule_expr_immediate_cb(
const struct nlattr *attr,
void *data)
84 const struct nlattr **tb = data;
85 int type = mnl_attr_get_type(attr);
87 if (mnl_attr_type_valid(attr, NFTA_IMMEDIATE_MAX) < 0)
91 case NFTA_IMMEDIATE_DREG:
92 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
93 perror(
"mnl_attr_validate");
97 case NFTA_IMMEDIATE_DATA:
98 if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) {
99 perror(
"mnl_attr_validate");
110 nft_rule_expr_immediate_build(
struct nlmsghdr *nlh,
struct nft_rule_expr *e)
114 if (e->flags & (1 << NFT_EXPR_IMM_DREG))
115 mnl_attr_put_u32(nlh, NFTA_IMMEDIATE_DREG, htonl(imm->dreg));
118 if (e->flags & (1 << NFT_EXPR_IMM_DATA)) {
121 nest = mnl_attr_nest_start(nlh, NFTA_IMMEDIATE_DATA);
122 mnl_attr_put(nlh, NFTA_DATA_VALUE, imm->data.len, imm->data.val);
123 mnl_attr_nest_end(nlh, nest);
125 }
else if (e->flags & (1 << NFT_EXPR_IMM_VERDICT)) {
126 struct nlattr *nest1, *nest2;
128 nest1 = mnl_attr_nest_start(nlh, NFTA_IMMEDIATE_DATA);
129 nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
130 mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(imm->data.verdict));
131 if (e->flags & (1 << NFT_EXPR_IMM_CHAIN))
132 mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, imm->data.chain);
134 mnl_attr_nest_end(nlh, nest1);
135 mnl_attr_nest_end(nlh, nest2);
140 nft_rule_expr_immediate_parse(
struct nft_rule_expr *e,
struct nlattr *attr)
143 struct nlattr *tb[NFTA_IMMEDIATE_MAX+1] = {};
146 if (mnl_attr_parse_nested(attr, nft_rule_expr_immediate_cb, tb) < 0)
149 if (tb[NFTA_IMMEDIATE_DREG]) {
150 imm->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_IMMEDIATE_DREG]));
151 e->flags |= (1 << NFT_EXPR_IMM_DREG);
153 if (tb[NFTA_IMMEDIATE_DATA]) {
156 ret = nft_parse_data(&imm->data, tb[NFTA_IMMEDIATE_DATA], &type);
163 e->flags |= (1 << NFT_EXPR_IMM_DATA);
167 e->flags |= (1 << NFT_EXPR_IMM_VERDICT);
171 e->flags |= (1 << NFT_EXPR_IMM_VERDICT) |
172 (1 << NFT_EXPR_IMM_CHAIN);
181 nft_rule_expr_immediate_json_parse(
struct nft_rule_expr *e, json_t *root,
182 struct nft_parse_err *err)
189 if (nft_jansson_parse_reg(root,
"dreg", NFT_TYPE_U32, ®, err) == 0)
190 nft_rule_expr_set_u32(e, NFT_EXPR_IMM_DREG, reg);
192 datareg_type = nft_jansson_data_reg_parse(root,
"immediatedata",
194 if (datareg_type >= 0) {
195 switch (datareg_type) {
197 e->flags |= (1 << NFT_EXPR_IMM_DATA);
200 e->flags |= (1 << NFT_EXPR_IMM_VERDICT);
203 e->flags |= (1 << NFT_EXPR_IMM_CHAIN);
217 nft_rule_expr_immediate_xml_parse(
struct nft_rule_expr *e, mxml_node_t *tree,
218 struct nft_parse_err *err)
225 if (nft_mxml_reg_parse(tree,
"dreg", ®, MXML_DESCEND_FIRST,
226 NFT_XML_MAND, err) == 0)
227 nft_rule_expr_set_u32(e, NFT_EXPR_IMM_DREG, reg);
229 datareg_type = nft_mxml_data_reg_parse(tree,
"immediatedata",
230 &imm->data, NFT_XML_MAND, err);
231 if (datareg_type >= 0) {
232 switch (datareg_type) {
234 e->flags |= (1 << NFT_EXPR_IMM_DATA);
237 e->flags |= (1 << NFT_EXPR_IMM_VERDICT);
240 e->flags |= (1 << NFT_EXPR_IMM_CHAIN);
255 nft_rule_expr_immediate_snprintf_json(
char *buf,
size_t len,
256 struct nft_rule_expr *e, uint32_t flags)
258 int size = len, offset = 0, ret;
261 if (e->flags & (1 << NFT_EXPR_IMM_DREG)) {
262 ret = snprintf(buf, len,
"\"dreg\":%u,", imm->dreg);
263 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
265 if (e->flags & (1 << NFT_EXPR_IMM_DATA)) {
266 ret = nft_data_reg_snprintf(buf + offset, len, &imm->data,
267 NFT_OUTPUT_JSON, flags, DATA_VALUE);
268 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
270 }
else if (e->flags & (1 << NFT_EXPR_IMM_VERDICT)) {
271 ret = nft_data_reg_snprintf(buf + offset, len, &imm->data,
272 NFT_OUTPUT_JSON, flags, DATA_VERDICT);
273 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
275 }
else if (e->flags & (1 << NFT_EXPR_IMM_CHAIN)) {
276 ret = nft_data_reg_snprintf(buf + offset, len, &imm->data,
277 NFT_OUTPUT_JSON, flags, DATA_CHAIN);
278 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
285 nft_rule_expr_immediate_snprintf_xml(
char *buf,
size_t len,
286 struct nft_rule_expr *e, uint32_t flags)
288 int size = len, offset = 0, ret;
291 if (e->flags & (1 << NFT_EXPR_IMM_DREG)) {
292 ret = snprintf(buf, len,
"<dreg>%u</dreg>", imm->dreg);
293 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
295 if (e->flags & (1 << NFT_EXPR_IMM_DATA)) {
296 ret = nft_data_reg_snprintf(buf + offset, len, &imm->data,
297 NFT_OUTPUT_XML, flags, DATA_VALUE);
298 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
300 }
else if (e->flags & (1 << NFT_EXPR_IMM_VERDICT)) {
301 ret = nft_data_reg_snprintf(buf + offset, len, &imm->data,
302 NFT_OUTPUT_XML, flags, DATA_VERDICT);
303 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
305 }
else if (e->flags & (1 << NFT_EXPR_IMM_CHAIN)) {
306 ret = nft_data_reg_snprintf(buf + offset, len, &imm->data,
307 NFT_OUTPUT_XML, flags, DATA_CHAIN);
308 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
315 nft_rule_expr_immediate_snprintf_default(
char *buf,
size_t len,
316 struct nft_rule_expr *e, uint32_t flags)
318 int size = len, offset = 0, ret;
321 ret = snprintf(buf, len,
"reg %u ", imm->dreg);
322 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
324 if (e->flags & (1 << NFT_EXPR_IMM_DATA)) {
325 ret = nft_data_reg_snprintf(buf+offset, len, &imm->data,
326 NFT_OUTPUT_DEFAULT, flags, DATA_VALUE);
327 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
329 }
else if (e->flags & (1 << NFT_EXPR_IMM_VERDICT)) {
330 ret = nft_data_reg_snprintf(buf+offset, len, &imm->data,
331 NFT_OUTPUT_DEFAULT, flags, DATA_VERDICT);
332 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
334 }
else if (e->flags & (1 << NFT_EXPR_IMM_CHAIN)) {
335 ret = nft_data_reg_snprintf(buf+offset, len, &imm->data,
336 NFT_OUTPUT_DEFAULT, flags, DATA_CHAIN);
337 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
344 nft_rule_expr_immediate_snprintf(
char *buf,
size_t len, uint32_t type,
345 uint32_t flags,
struct nft_rule_expr *e)
348 case NFT_OUTPUT_DEFAULT:
349 return nft_rule_expr_immediate_snprintf_default(buf, len, e, flags);
351 return nft_rule_expr_immediate_snprintf_xml(buf, len, e, flags);
352 case NFT_OUTPUT_JSON:
353 return nft_rule_expr_immediate_snprintf_json(buf, len, e, flags);
360 struct expr_ops expr_ops_immediate = {
363 .max_attr = NFTA_IMMEDIATE_MAX,
364 .set = nft_rule_expr_immediate_set,
365 .get = nft_rule_expr_immediate_get,
366 .parse = nft_rule_expr_immediate_parse,
367 .build = nft_rule_expr_immediate_build,
368 .snprintf = nft_rule_expr_immediate_snprintf,
369 .xml_parse = nft_rule_expr_immediate_xml_parse,
370 .json_parse = nft_rule_expr_immediate_json_parse,
373 static void __init expr_immediate_init(
void)
375 nft_expr_ops_register(&expr_ops_immediate);