2 * Copyright (c) 2008-2012 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Development of this code funded by Astaro AG (http://www.astaro.com/)
16 #include <libmnl/libmnl.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
21 #include <libnftnl/table.h>
22 #include <libnftnl/trace.h>
23 #include <libnftnl/chain.h>
24 #include <libnftnl/expr.h>
25 #include <libnftnl/object.h>
26 #include <libnftnl/set.h>
27 #include <libnftnl/flowtable.h>
28 #include <libnftnl/udata.h>
29 #include <libnftnl/ruleset.h>
30 #include <libnftnl/common.h>
31 #include <libnftnl/udata.h>
32 #include <linux/netfilter/nfnetlink.h>
33 #include <linux/netfilter/nf_tables.h>
34 #include <linux/netfilter.h>
40 #include <expression.h>
41 #include <statement.h>
47 #define nft_mon_print(monh, ...) nft_print(&monh->ctx->nft->output, __VA_ARGS__)
49 const struct input_descriptor indesc_netlink
= {
51 .type
= INDESC_NETLINK
,
54 const struct location netlink_location
= {
55 .indesc
= &indesc_netlink
,
58 void __noreturn
__netlink_abi_error(const char *file
, int line
,
61 fprintf(stderr
, "E: Contact urgently your Linux kernel vendor. "
62 "Netlink ABI is broken: %s:%d %s\n", file
, line
, reason
);
66 int netlink_io_error(struct netlink_ctx
*ctx
, const struct location
*loc
,
69 struct error_record
*erec
;
73 loc
= &netlink_location
;
76 erec
= erec_vcreate(EREC_ERROR
, loc
, fmt
, ap
);
78 erec_queue(erec
, ctx
->msgs
);
82 void __noreturn
__netlink_init_error(const char *filename
, int line
,
85 fprintf(stderr
, "%s:%d: Unable to initialize Netlink socket: %s\n",
86 filename
, line
, reason
);
90 struct nftnl_expr
*alloc_nft_expr(const char *name
)
92 struct nftnl_expr
*nle
;
94 nle
= nftnl_expr_alloc(name
);
96 memory_allocation_error();
100 static void netlink_gen_key(const struct expr
*expr
,
101 struct nft_data_linearize
*data
);
102 static void __netlink_gen_data(const struct expr
*expr
,
103 struct nft_data_linearize
*data
, bool expand
);
105 struct nftnl_set_elem
*alloc_nftnl_setelem(const struct expr
*set
,
106 const struct expr
*expr
)
108 const struct expr
*elem
, *data
;
109 struct nftnl_set_elem
*nlse
;
110 struct nft_data_linearize nld
;
111 struct nftnl_udata_buf
*udbuf
= NULL
;
117 nlse
= nftnl_set_elem_alloc();
119 memory_allocation_error();
122 if (expr
->etype
== EXPR_MAPPING
) {
124 if (!(expr
->flags
& EXPR_F_INTERVAL_END
))
129 if (elem
->etype
!= EXPR_SET_ELEM
)
130 BUG("Unexpected expression type: got %d\n", elem
->etype
);
134 switch (key
->etype
) {
135 case EXPR_SET_ELEM_CATCHALL
:
138 if (set
->set_flags
& NFT_SET_INTERVAL
&&
139 key
->etype
== EXPR_CONCAT
&& key
->field_count
> 1) {
140 key
->flags
|= EXPR_F_INTERVAL
;
141 netlink_gen_key(key
, &nld
);
142 key
->flags
&= ~EXPR_F_INTERVAL
;
144 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_KEY
, &nld
.value
, nld
.len
);
146 key
->flags
|= EXPR_F_INTERVAL_END
;
147 netlink_gen_key(key
, &nld
);
148 key
->flags
&= ~EXPR_F_INTERVAL_END
;
150 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_KEY_END
,
151 &nld
.value
, nld
.len
);
153 netlink_gen_key(key
, &nld
);
154 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_KEY
, &nld
.value
, nld
.len
);
160 nftnl_set_elem_set_u64(nlse
, NFTNL_SET_ELEM_TIMEOUT
,
162 if (elem
->expiration
)
163 nftnl_set_elem_set_u64(nlse
, NFTNL_SET_ELEM_EXPIRATION
,
165 list_for_each_entry(stmt
, &elem
->stmt_list
, list
)
168 if (num_exprs
== 1) {
169 list_for_each_entry(stmt
, &elem
->stmt_list
, list
) {
170 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_EXPR
,
171 netlink_gen_stmt_stateful(stmt
), 0);
173 } else if (num_exprs
> 1) {
174 list_for_each_entry(stmt
, &elem
->stmt_list
, list
) {
175 nftnl_set_elem_add_expr(nlse
,
176 netlink_gen_stmt_stateful(stmt
));
179 if (elem
->comment
|| expr
->elem_flags
) {
180 udbuf
= nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN
);
182 memory_allocation_error();
185 if (!nftnl_udata_put_strz(udbuf
, NFTNL_UDATA_SET_ELEM_COMMENT
,
187 memory_allocation_error();
189 if (expr
->elem_flags
) {
190 if (!nftnl_udata_put_u32(udbuf
, NFTNL_UDATA_SET_ELEM_FLAGS
,
192 memory_allocation_error();
195 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_USERDATA
,
196 nftnl_udata_buf_data(udbuf
),
197 nftnl_udata_buf_len(udbuf
));
198 nftnl_udata_buf_free(udbuf
);
200 if (set_is_datamap(set
->set_flags
) && data
!= NULL
) {
201 __netlink_gen_data(data
, &nld
, !(data
->flags
& EXPR_F_SINGLETON
));
202 switch (data
->etype
) {
204 nftnl_set_elem_set_u32(nlse
, NFTNL_SET_ELEM_VERDICT
,
206 if (data
->chain
!= NULL
)
207 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_CHAIN
,
208 nld
.chain
, strlen(nld
.chain
));
216 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_DATA
,
220 BUG("unexpected set element expression\n");
224 if (set_is_objmap(set
->set_flags
) && data
!= NULL
) {
225 netlink_gen_data(data
, &nld
);
226 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_OBJREF
,
230 if (expr
->flags
& EXPR_F_INTERVAL_END
)
231 flags
|= NFT_SET_ELEM_INTERVAL_END
;
232 if (key
->etype
== EXPR_SET_ELEM_CATCHALL
)
233 flags
|= NFT_SET_ELEM_CATCHALL
;
236 nftnl_set_elem_set_u32(nlse
, NFTNL_SET_ELEM_FLAGS
, flags
);
241 void netlink_gen_raw_data(const mpz_t value
, enum byteorder byteorder
,
242 unsigned int len
, struct nft_data_linearize
*data
)
245 mpz_export_data(data
->value
, value
, byteorder
, len
);
249 static int netlink_export_pad(unsigned char *data
, const mpz_t v
,
250 const struct expr
*i
)
252 mpz_export_data(data
, v
, i
->byteorder
,
253 div_round_up(i
->len
, BITS_PER_BYTE
));
255 return netlink_padded_len(i
->len
) / BITS_PER_BYTE
;
258 static int __netlink_gen_concat_key(uint32_t flags
, const struct expr
*i
,
265 if (flags
& EXPR_F_INTERVAL_END
)
270 if (expr_basetype(expr
)->type
== TYPE_INTEGER
&&
271 expr
->byteorder
== BYTEORDER_HOST_ENDIAN
)
272 mpz_switch_byteorder(expr
->value
, expr
->len
/ BITS_PER_BYTE
);
277 if (flags
& EXPR_F_INTERVAL_END
) {
281 mpz_init_bitmask(v
, i
->len
- i
->prefix_len
);
283 if (i
->byteorder
== BYTEORDER_HOST_ENDIAN
)
284 mpz_switch_byteorder(v
, i
->len
/ BITS_PER_BYTE
);
286 mpz_add(v
, i
->prefix
->value
, v
);
287 count
= netlink_export_pad(data
, v
, i
);
291 return netlink_export_pad(data
, i
->prefix
->value
, i
);
293 /* Switch byteorder only once for singleton values when the set
294 * contains concatenation of intervals.
296 if (!(flags
& EXPR_F_INTERVAL
))
299 expr
= (struct expr
*)i
;
300 if (expr_basetype(expr
)->type
== TYPE_INTEGER
&&
301 expr
->byteorder
== BYTEORDER_HOST_ENDIAN
)
302 mpz_switch_byteorder(expr
->value
, expr
->len
/ BITS_PER_BYTE
);
305 BUG("invalid expression type '%s' in set", expr_ops(i
)->name
);
308 return netlink_export_pad(data
, i
->value
, i
);
311 static void netlink_gen_concat_key(const struct expr
*expr
,
312 struct nft_data_linearize
*nld
)
314 unsigned int len
= expr
->len
/ BITS_PER_BYTE
, offset
= 0;
315 unsigned char data
[len
];
316 const struct expr
*i
;
318 memset(data
, 0, len
);
320 list_for_each_entry(i
, &expr
->expressions
, list
)
321 offset
+= __netlink_gen_concat_key(expr
->flags
, i
, data
+ offset
);
323 memcpy(nld
->value
, data
, len
);
327 static int __netlink_gen_concat_data(int end
, const struct expr
*i
,
332 i
= end
? i
->right
: i
->left
;
339 mpz_init_bitmask(v
, i
->len
- i
->prefix_len
);
340 mpz_add(v
, i
->prefix
->value
, v
);
341 count
= netlink_export_pad(data
, v
, i
);
345 return netlink_export_pad(data
, i
->prefix
->value
, i
);
349 BUG("invalid expression type '%s' in set", expr_ops(i
)->name
);
352 return netlink_export_pad(data
, i
->value
, i
);
355 static void __netlink_gen_concat_expand(const struct expr
*expr
,
356 struct nft_data_linearize
*nld
)
358 unsigned int len
= div_round_up(expr
->len
, BITS_PER_BYTE
) * 2, offset
= 0;
359 unsigned char data
[len
];
360 const struct expr
*i
;
362 memset(data
, 0, len
);
364 list_for_each_entry(i
, &expr
->expressions
, list
)
365 offset
+= __netlink_gen_concat_data(false, i
, data
+ offset
);
367 list_for_each_entry(i
, &expr
->expressions
, list
)
368 offset
+= __netlink_gen_concat_data(true, i
, data
+ offset
);
370 memcpy(nld
->value
, data
, len
);
374 static void __netlink_gen_concat(const struct expr
*expr
,
375 struct nft_data_linearize
*nld
)
377 unsigned int len
= expr
->len
/ BITS_PER_BYTE
, offset
= 0;
378 unsigned char data
[len
];
379 const struct expr
*i
;
381 memset(data
, 0, len
);
383 list_for_each_entry(i
, &expr
->expressions
, list
)
384 offset
+= __netlink_gen_concat_data(expr
->flags
, i
, data
+ offset
);
386 memcpy(nld
->value
, data
, len
);
390 static void netlink_gen_concat_data(const struct expr
*expr
,
391 struct nft_data_linearize
*nld
, bool expand
)
394 __netlink_gen_concat_expand(expr
, nld
);
396 __netlink_gen_concat(expr
, nld
);
399 static void netlink_gen_constant_data(const struct expr
*expr
,
400 struct nft_data_linearize
*data
)
402 assert(expr
->etype
== EXPR_VALUE
);
403 netlink_gen_raw_data(expr
->value
, expr
->byteorder
,
404 div_round_up(expr
->len
, BITS_PER_BYTE
), data
);
407 static void netlink_gen_chain(const struct expr
*expr
,
408 struct nft_data_linearize
*data
)
410 char chain
[NFT_CHAIN_MAXNAMELEN
];
413 len
= expr
->chain
->len
/ BITS_PER_BYTE
;
416 BUG("chain length is 0");
418 if (len
> sizeof(chain
))
419 BUG("chain is too large (%u, %u max)",
420 len
, (unsigned int)sizeof(chain
));
422 memset(chain
, 0, sizeof(chain
));
424 mpz_export_data(chain
, expr
->chain
->value
,
425 BYTEORDER_HOST_ENDIAN
, len
);
426 snprintf(data
->chain
, NFT_CHAIN_MAXNAMELEN
, "%s", chain
);
429 static void netlink_gen_verdict(const struct expr
*expr
,
430 struct nft_data_linearize
*data
)
433 data
->verdict
= expr
->verdict
;
435 switch (expr
->verdict
) {
439 netlink_gen_chain(expr
, data
);
441 data
->chain_id
= expr
->chain_id
;
446 static void netlink_gen_range(const struct expr
*expr
,
447 struct nft_data_linearize
*nld
)
449 unsigned int len
= div_round_up(expr
->left
->len
, BITS_PER_BYTE
) * 2;
450 unsigned char data
[len
];
451 unsigned int offset
= 0;
453 memset(data
, 0, len
);
454 offset
= netlink_export_pad(data
, expr
->left
->value
, expr
->left
);
455 netlink_export_pad(data
+ offset
, expr
->right
->value
, expr
->right
);
456 memcpy(nld
->value
, data
, len
);
460 static void netlink_gen_prefix(const struct expr
*expr
,
461 struct nft_data_linearize
*nld
)
463 unsigned int len
= div_round_up(expr
->len
, BITS_PER_BYTE
) * 2;
464 unsigned char data
[len
];
468 offset
= netlink_export_pad(data
, expr
->prefix
->value
, expr
);
469 mpz_init_bitmask(v
, expr
->len
- expr
->prefix_len
);
470 mpz_add(v
, expr
->prefix
->value
, v
);
471 netlink_export_pad(data
+ offset
, v
, expr
->prefix
);
474 memcpy(nld
->value
, data
, len
);
478 static void netlink_gen_key(const struct expr
*expr
,
479 struct nft_data_linearize
*data
)
481 switch (expr
->etype
) {
483 return netlink_gen_constant_data(expr
, data
);
485 return netlink_gen_concat_key(expr
, data
);
487 return netlink_gen_range(expr
, data
);
489 return netlink_gen_prefix(expr
, data
);
491 BUG("invalid data expression type %s\n", expr_name(expr
));
495 static void __netlink_gen_data(const struct expr
*expr
,
496 struct nft_data_linearize
*data
, bool expand
)
498 switch (expr
->etype
) {
500 return netlink_gen_constant_data(expr
, data
);
502 return netlink_gen_concat_data(expr
, data
, expand
);
504 return netlink_gen_verdict(expr
, data
);
506 return netlink_gen_range(expr
, data
);
508 return netlink_gen_prefix(expr
, data
);
510 BUG("invalid data expression type %s\n", expr_name(expr
));
514 void netlink_gen_data(const struct expr
*expr
, struct nft_data_linearize
*data
)
516 __netlink_gen_data(expr
, data
, false);
519 struct expr
*netlink_alloc_value(const struct location
*loc
,
520 const struct nft_data_delinearize
*nld
)
522 return constant_expr_alloc(loc
, &invalid_type
, BYTEORDER_INVALID
,
523 nld
->len
* BITS_PER_BYTE
, nld
->value
);
526 static struct expr
*netlink_alloc_verdict(const struct location
*loc
,
527 const struct nft_data_delinearize
*nld
)
531 switch (nld
->verdict
) {
534 chain
= constant_expr_alloc(loc
, &string_type
,
535 BYTEORDER_HOST_ENDIAN
,
536 strlen(nld
->chain
) * BITS_PER_BYTE
,
544 return verdict_expr_alloc(loc
, nld
->verdict
, chain
);
547 struct expr
*netlink_alloc_data(const struct location
*loc
,
548 const struct nft_data_delinearize
*nld
,
549 enum nft_registers dreg
)
552 case NFT_REG_VERDICT
:
553 return netlink_alloc_verdict(loc
, nld
);
555 return netlink_alloc_value(loc
, nld
);
559 void netlink_dump_rule(const struct nftnl_rule
*nlr
, struct netlink_ctx
*ctx
)
561 FILE *fp
= ctx
->nft
->output
.output_fp
;
563 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
566 nftnl_rule_fprintf(fp
, nlr
, 0, 0);
570 void netlink_dump_expr(const struct nftnl_expr
*nle
,
571 FILE *fp
, unsigned int debug_mask
)
573 if (!(debug_mask
& NFT_DEBUG_NETLINK
))
576 nftnl_expr_fprintf(fp
, nle
, 0, 0);
580 void netlink_dump_chain(const struct nftnl_chain
*nlc
, struct netlink_ctx
*ctx
)
582 FILE *fp
= ctx
->nft
->output
.output_fp
;
584 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
587 nftnl_chain_fprintf(fp
, nlc
, 0, 0);
591 static int chain_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
593 unsigned char *value
= nftnl_udata_get(attr
);
594 uint8_t type
= nftnl_udata_type(attr
);
595 const struct nftnl_udata
**tb
= data
;
596 uint8_t len
= nftnl_udata_len(attr
);
599 case NFTNL_UDATA_CHAIN_COMMENT
:
600 if (value
[len
- 1] != '\0')
610 static int qsort_device_cmp(const void *a
, const void *b
)
612 const char **x
= (const char **)a
;
613 const char **y
= (const char **)b
;
615 return strcmp(*x
, *y
);
618 struct chain
*netlink_delinearize_chain(struct netlink_ctx
*ctx
,
619 const struct nftnl_chain
*nlc
)
621 const struct nftnl_udata
*ud
[NFTNL_UDATA_OBJ_MAX
+ 1] = {};
622 int priority
, policy
, len
= 0, i
;
623 const char * const *dev_array
;
628 chain
= chain_alloc();
629 chain
->handle
.family
=
630 nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_FAMILY
);
631 chain
->handle
.table
.name
=
632 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_TABLE
));
633 chain
->handle
.chain
.name
=
634 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_NAME
));
635 chain
->handle
.handle
.id
=
636 nftnl_chain_get_u64(nlc
, NFTNL_CHAIN_HANDLE
);
637 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_FLAGS
))
638 chain
->flags
= nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_FLAGS
);
640 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_HOOKNUM
) &&
641 nftnl_chain_is_set(nlc
, NFTNL_CHAIN_PRIO
) &&
642 nftnl_chain_is_set(nlc
, NFTNL_CHAIN_TYPE
) &&
643 nftnl_chain_is_set(nlc
, NFTNL_CHAIN_POLICY
)) {
645 nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_HOOKNUM
);
647 hooknum2str(chain
->handle
.family
, chain
->hook
.num
);
648 priority
= nftnl_chain_get_s32(nlc
, NFTNL_CHAIN_PRIO
);
649 chain
->priority
.expr
=
650 constant_expr_alloc(&netlink_location
,
652 BYTEORDER_HOST_ENDIAN
,
653 sizeof(int) * BITS_PER_BYTE
,
656 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_TYPE
));
657 policy
= nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_POLICY
);
658 chain
->policy
= constant_expr_alloc(&netlink_location
,
660 BYTEORDER_HOST_ENDIAN
,
661 sizeof(int) * BITS_PER_BYTE
,
663 nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_POLICY
);
664 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_DEV
)) {
665 chain
->dev_array
= xmalloc(sizeof(char *) * 2);
666 chain
->dev_array_len
= 1;
667 chain
->dev_array
[0] =
668 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_DEV
));
669 chain
->dev_array
[1] = NULL
;
670 } else if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_DEVICES
)) {
671 dev_array
= nftnl_chain_get(nlc
, NFTNL_CHAIN_DEVICES
);
672 while (dev_array
[len
])
675 chain
->dev_array
= xmalloc((len
+ 1)* sizeof(char *));
676 for (i
= 0; i
< len
; i
++)
677 chain
->dev_array
[i
] = xstrdup(dev_array
[i
]);
679 chain
->dev_array
[i
] = NULL
;
680 chain
->dev_array_len
= len
;
682 chain
->flags
|= CHAIN_F_BASECHAIN
;
684 if (chain
->dev_array_len
) {
685 qsort(chain
->dev_array
, chain
->dev_array_len
,
686 sizeof(char *), qsort_device_cmp
);
690 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_USERDATA
)) {
691 udata
= nftnl_chain_get_data(nlc
, NFTNL_CHAIN_USERDATA
, &ulen
);
692 if (nftnl_udata_parse(udata
, ulen
, chain_parse_udata_cb
, ud
) < 0) {
693 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
697 if (ud
[NFTNL_UDATA_CHAIN_COMMENT
])
698 chain
->comment
= xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_CHAIN_COMMENT
]));
704 static int table_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
706 unsigned char *value
= nftnl_udata_get(attr
);
707 const struct nftnl_udata
**tb
= data
;
708 uint8_t type
= nftnl_udata_type(attr
);
709 uint8_t len
= nftnl_udata_len(attr
);
712 case NFTNL_UDATA_TABLE_COMMENT
:
713 if (value
[len
- 1] != '\0')
723 struct table
*netlink_delinearize_table(struct netlink_ctx
*ctx
,
724 const struct nftnl_table
*nlt
)
726 const struct nftnl_udata
*ud
[NFTNL_UDATA_TABLE_MAX
+ 1] = {};
731 table
= table_alloc();
732 table
->handle
.family
= nftnl_table_get_u32(nlt
, NFTNL_TABLE_FAMILY
);
733 table
->handle
.table
.name
= xstrdup(nftnl_table_get_str(nlt
, NFTNL_TABLE_NAME
));
734 table
->flags
= nftnl_table_get_u32(nlt
, NFTNL_TABLE_FLAGS
);
735 table
->handle
.handle
.id
= nftnl_table_get_u64(nlt
, NFTNL_TABLE_HANDLE
);
736 table
->owner
= nftnl_table_get_u32(nlt
, NFTNL_TABLE_OWNER
);
738 if (nftnl_table_is_set(nlt
, NFTNL_TABLE_USERDATA
)) {
739 udata
= nftnl_table_get_data(nlt
, NFTNL_TABLE_USERDATA
, &ulen
);
740 if (nftnl_udata_parse(udata
, ulen
, table_parse_udata_cb
, ud
) < 0) {
741 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
745 if (ud
[NFTNL_UDATA_TABLE_COMMENT
])
746 table
->comment
= xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_TABLE_COMMENT
]));
752 static int list_table_cb(struct nftnl_table
*nlt
, void *arg
)
754 struct netlink_ctx
*ctx
= arg
;
757 table
= netlink_delinearize_table(ctx
, nlt
);
758 list_add_tail(&table
->list
, &ctx
->list
);
763 int netlink_list_tables(struct netlink_ctx
*ctx
, const struct handle
*h
,
764 const struct nft_cache_filter
*filter
)
766 struct nftnl_table_list
*table_cache
;
767 uint32_t family
= h
->family
;
768 const char *table
= NULL
;
771 family
= filter
->list
.family
;
772 table
= filter
->list
.table
;
775 table_cache
= mnl_nft_table_dump(ctx
, family
, table
);
776 if (table_cache
== NULL
) {
784 nftnl_table_list_foreach(table_cache
, list_table_cb
, ctx
);
785 nftnl_table_list_free(table_cache
);
789 enum nft_data_types
dtype_map_to_kernel(const struct datatype
*dtype
)
791 switch (dtype
->type
) {
793 return NFT_DATA_VERDICT
;
799 static const struct datatype
*dtype_map_from_kernel(enum nft_data_types type
)
801 /* The function always returns ownership of a reference. But for
802 * &verdict_Type and datatype_lookup(), those are static instances,
803 * we can omit the datatype_get() call.
806 case NFT_DATA_VERDICT
:
807 return &verdict_type
;
809 if (type
& ~TYPE_MASK
)
810 return concat_type_alloc(type
);
811 return datatype_lookup((enum datatypes
) type
);
815 void netlink_dump_set(const struct nftnl_set
*nls
, struct netlink_ctx
*ctx
)
817 FILE *fp
= ctx
->nft
->output
.output_fp
;
819 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
822 nftnl_set_fprintf(fp
, nls
, 0, 0);
826 static int set_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
828 unsigned char *value
= nftnl_udata_get(attr
);
829 const struct nftnl_udata
**tb
= data
;
830 uint8_t type
= nftnl_udata_type(attr
);
831 uint8_t len
= nftnl_udata_len(attr
);
834 case NFTNL_UDATA_SET_KEYBYTEORDER
:
835 case NFTNL_UDATA_SET_DATABYTEORDER
:
836 case NFTNL_UDATA_SET_MERGE_ELEMENTS
:
837 case NFTNL_UDATA_SET_DATA_INTERVAL
:
838 if (len
!= sizeof(uint32_t))
841 case NFTNL_UDATA_SET_KEY_TYPEOF
:
842 case NFTNL_UDATA_SET_DATA_TYPEOF
:
846 case NFTNL_UDATA_SET_COMMENT
:
847 if (value
[len
- 1] != '\0')
857 static int set_key_parse_udata(const struct nftnl_udata
*attr
, void *data
)
859 const struct nftnl_udata
**tb
= data
;
860 uint8_t type
= nftnl_udata_type(attr
);
861 uint8_t len
= nftnl_udata_len(attr
);
864 case NFTNL_UDATA_SET_TYPEOF_EXPR
:
865 if (len
!= sizeof(uint32_t))
868 case NFTNL_UDATA_SET_TYPEOF_DATA
:
877 static struct expr
*set_make_key(const struct nftnl_udata
*attr
)
879 const struct nftnl_udata
*ud
[NFTNL_UDATA_SET_TYPEOF_MAX
+ 1] = {};
880 const struct expr_ops
*ops
;
881 enum expr_types etype
;
888 err
= nftnl_udata_parse(nftnl_udata_get(attr
), nftnl_udata_len(attr
),
889 set_key_parse_udata
, ud
);
893 if (!ud
[NFTNL_UDATA_SET_TYPEOF_EXPR
] ||
894 !ud
[NFTNL_UDATA_SET_TYPEOF_DATA
])
897 etype
= nftnl_udata_get_u32(ud
[NFTNL_UDATA_SET_TYPEOF_EXPR
]);
898 ops
= expr_ops_by_type(etype
);
900 expr
= ops
->parse_udata(ud
[NFTNL_UDATA_SET_TYPEOF_DATA
]);
907 static bool set_udata_key_valid(const struct expr
*e
, uint32_t len
)
912 return div_round_up(e
->len
, BITS_PER_BYTE
) == len
/ BITS_PER_BYTE
;
915 struct setelem_parse_ctx
{
917 struct nft_cache
*cache
;
918 struct list_head stmt_list
;
921 static int set_elem_parse_expressions(struct nftnl_expr
*e
, void *data
)
923 struct setelem_parse_ctx
*setelem_parse_ctx
= data
;
924 struct nft_cache
*cache
= setelem_parse_ctx
->cache
;
925 struct set
*set
= setelem_parse_ctx
->set
;
928 stmt
= netlink_parse_set_expr(set
, cache
, e
);
929 list_add_tail(&stmt
->list
, &setelem_parse_ctx
->stmt_list
);
934 struct set
*netlink_delinearize_set(struct netlink_ctx
*ctx
,
935 const struct nftnl_set
*nls
)
937 const struct nftnl_udata
*ud
[NFTNL_UDATA_SET_MAX
+ 1] = {};
938 enum byteorder keybyteorder
= BYTEORDER_INVALID
;
939 enum byteorder databyteorder
= BYTEORDER_INVALID
;
940 struct expr
*typeof_expr_key
, *typeof_expr_data
;
941 struct setelem_parse_ctx set_parse_ctx
;
942 const struct datatype
*datatype
= NULL
;
943 const struct datatype
*keytype
= NULL
;
944 const struct datatype
*dtype2
= NULL
;
945 const struct datatype
*dtype
= NULL
;
946 const char *udata
, *comment
= NULL
;
947 uint32_t flags
, key
, objtype
= 0;
948 uint32_t data_interval
= 0;
949 bool automerge
= false;
954 typeof_expr_key
= NULL
;
955 typeof_expr_data
= NULL
;
957 if (nftnl_set_is_set(nls
, NFTNL_SET_USERDATA
)) {
958 udata
= nftnl_set_get_data(nls
, NFTNL_SET_USERDATA
, &ulen
);
959 if (nftnl_udata_parse(udata
, ulen
, set_parse_udata_cb
, ud
) < 0) {
960 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
964 #define GET_U32_UDATA(var, attr) \
966 var = nftnl_udata_get_u32(ud[attr])
968 GET_U32_UDATA(keybyteorder
, NFTNL_UDATA_SET_KEYBYTEORDER
);
969 GET_U32_UDATA(databyteorder
, NFTNL_UDATA_SET_DATABYTEORDER
);
970 GET_U32_UDATA(automerge
, NFTNL_UDATA_SET_MERGE_ELEMENTS
);
971 GET_U32_UDATA(data_interval
, NFTNL_UDATA_SET_DATA_INTERVAL
);
974 typeof_expr_key
= set_make_key(ud
[NFTNL_UDATA_SET_KEY_TYPEOF
]);
975 if (ud
[NFTNL_UDATA_SET_DATA_TYPEOF
])
976 typeof_expr_data
= set_make_key(ud
[NFTNL_UDATA_SET_DATA_TYPEOF
]);
977 if (ud
[NFTNL_UDATA_SET_COMMENT
])
978 comment
= nftnl_udata_get(ud
[NFTNL_UDATA_SET_COMMENT
]);
981 key
= nftnl_set_get_u32(nls
, NFTNL_SET_KEY_TYPE
);
982 keytype
= dtype_map_from_kernel(key
);
983 if (keytype
== NULL
) {
984 netlink_io_error(ctx
, NULL
, "Unknown data type in set key %u",
989 flags
= nftnl_set_get_u32(nls
, NFTNL_SET_FLAGS
);
990 if (set_is_datamap(flags
)) {
993 data
= nftnl_set_get_u32(nls
, NFTNL_SET_DATA_TYPE
);
994 datatype
= dtype_map_from_kernel(data
);
995 if (datatype
== NULL
) {
996 netlink_io_error(ctx
, NULL
,
997 "Unknown data type in set key %u",
1004 if (set_is_objmap(flags
)) {
1005 objtype
= nftnl_set_get_u32(nls
, NFTNL_SET_OBJ_TYPE
);
1007 datatype
= &string_type
;
1010 set
= set_alloc(&netlink_location
);
1011 set
->handle
.family
= nftnl_set_get_u32(nls
, NFTNL_SET_FAMILY
);
1012 set
->handle
.table
.name
= xstrdup(nftnl_set_get_str(nls
, NFTNL_SET_TABLE
));
1013 set
->handle
.set
.name
= xstrdup(nftnl_set_get_str(nls
, NFTNL_SET_NAME
));
1014 set
->automerge
= automerge
;
1016 set
->comment
= xstrdup(comment
);
1018 init_list_head(&set_parse_ctx
.stmt_list
);
1020 if (nftnl_set_is_set(nls
, NFTNL_SET_EXPR
)) {
1021 const struct nftnl_expr
*nle
;
1024 nle
= nftnl_set_get(nls
, NFTNL_SET_EXPR
);
1025 stmt
= netlink_parse_set_expr(set
, &ctx
->nft
->cache
, nle
);
1026 list_add_tail(&stmt
->list
, &set_parse_ctx
.stmt_list
);
1027 } else if (nftnl_set_is_set(nls
, NFTNL_SET_EXPRESSIONS
)) {
1028 set_parse_ctx
.cache
= &ctx
->nft
->cache
;
1029 set_parse_ctx
.set
= set
;
1030 nftnl_set_expr_foreach(nls
, set_elem_parse_expressions
,
1033 list_splice_tail(&set_parse_ctx
.stmt_list
, &set
->stmt_list
);
1038 dtype2
= set_datatype_alloc(datatype
, databyteorder
);
1039 klen
= nftnl_set_get_u32(nls
, NFTNL_SET_DATA_LEN
) * BITS_PER_BYTE
;
1041 dlen
= data_interval
? klen
/ 2 : klen
;
1043 if (set_udata_key_valid(typeof_expr_data
, dlen
)) {
1044 typeof_expr_data
->len
= klen
;
1045 set
->data
= typeof_expr_data
;
1047 expr_free(typeof_expr_data
);
1048 set
->data
= constant_expr_alloc(&netlink_location
,
1050 databyteorder
, klen
,
1053 /* Can't use 'typeof' keyword, so discard key too */
1054 expr_free(typeof_expr_key
);
1055 typeof_expr_key
= NULL
;
1059 set
->data
->flags
|= EXPR_F_INTERVAL
;
1062 dtype
= set_datatype_alloc(keytype
, keybyteorder
);
1063 klen
= nftnl_set_get_u32(nls
, NFTNL_SET_KEY_LEN
) * BITS_PER_BYTE
;
1065 if (set_udata_key_valid(typeof_expr_key
, klen
)) {
1066 set
->key
= typeof_expr_key
;
1067 set
->key_typeof_valid
= true;
1069 expr_free(typeof_expr_key
);
1070 set
->key
= constant_expr_alloc(&netlink_location
, dtype
,
1075 set
->flags
= nftnl_set_get_u32(nls
, NFTNL_SET_FLAGS
);
1076 set
->handle
.handle
.id
= nftnl_set_get_u64(nls
, NFTNL_SET_HANDLE
);
1078 set
->objtype
= objtype
;
1080 if (nftnl_set_is_set(nls
, NFTNL_SET_TIMEOUT
))
1081 set
->timeout
= nftnl_set_get_u64(nls
, NFTNL_SET_TIMEOUT
);
1082 if (nftnl_set_is_set(nls
, NFTNL_SET_GC_INTERVAL
))
1083 set
->gc_int
= nftnl_set_get_u32(nls
, NFTNL_SET_GC_INTERVAL
);
1085 if (nftnl_set_is_set(nls
, NFTNL_SET_POLICY
))
1086 set
->policy
= nftnl_set_get_u32(nls
, NFTNL_SET_POLICY
);
1088 if (nftnl_set_is_set(nls
, NFTNL_SET_DESC_SIZE
))
1089 set
->desc
.size
= nftnl_set_get_u32(nls
, NFTNL_SET_DESC_SIZE
);
1091 if (nftnl_set_is_set(nls
, NFTNL_SET_DESC_CONCAT
)) {
1092 uint32_t len
= NFT_REG32_COUNT
;
1093 const uint8_t *data
;
1095 data
= nftnl_set_get_data(nls
, NFTNL_SET_DESC_CONCAT
, &len
);
1097 memcpy(set
->desc
.field_len
, data
, len
);
1098 set
->desc
.field_count
= len
;
1103 datatype_free(datatype
);
1104 datatype_free(keytype
);
1105 datatype_free(dtype2
);
1106 datatype_free(dtype
);
1110 void alloc_setelem_cache(const struct expr
*set
, struct nftnl_set
*nls
)
1112 struct nftnl_set_elem
*nlse
;
1113 const struct expr
*expr
;
1115 list_for_each_entry(expr
, &set
->expressions
, list
) {
1116 nlse
= alloc_nftnl_setelem(set
, expr
);
1117 nftnl_set_elem_add(nls
, nlse
);
1121 static bool range_expr_is_prefix(const struct expr
*range
, uint32_t *prefix_len
)
1123 const struct expr
*right
= range
->right
;
1124 const struct expr
*left
= range
->left
;
1125 uint32_t len
= left
->len
;
1126 unsigned long n1
, n2
;
1130 mpz_init2(bitmask
, left
->len
);
1131 mpz_xor(bitmask
, left
->value
, right
->value
);
1133 n1
= mpz_scan0(bitmask
, 0);
1134 if (n1
== ULONG_MAX
)
1137 n2
= mpz_scan1(bitmask
, n1
+ 1);
1143 if (mpz_scan1(left
->value
, 0) < len
- plen
)
1157 struct expr
*range_expr_to_prefix(struct expr
*range
)
1159 struct expr
*prefix
;
1160 uint32_t prefix_len
;
1162 if (range_expr_is_prefix(range
, &prefix_len
)) {
1163 prefix
= prefix_expr_alloc(&range
->location
,
1164 expr_get(range
->left
),
1173 static struct expr
*range_expr_reduce(struct expr
*range
)
1177 if (!mpz_cmp(range
->left
->value
, range
->right
->value
)) {
1178 expr
= expr_get(range
->left
);
1183 if (range
->left
->dtype
->type
!= TYPE_IPADDR
&&
1184 range
->left
->dtype
->type
!= TYPE_IP6ADDR
)
1187 return range_expr_to_prefix(range
);
1190 static struct expr
*netlink_parse_interval_elem(const struct set
*set
,
1193 unsigned int len
= div_round_up(expr
->len
, BITS_PER_BYTE
);
1194 const struct datatype
*dtype
= set
->data
->dtype
;
1195 struct expr
*range
, *left
, *right
;
1198 mpz_export_data(data
, expr
->value
, dtype
->byteorder
, len
);
1199 left
= constant_expr_alloc(&internal_location
, dtype
,
1201 (len
/ 2) * BITS_PER_BYTE
, &data
[0]);
1202 right
= constant_expr_alloc(&internal_location
, dtype
,
1204 (len
/ 2) * BITS_PER_BYTE
, &data
[len
/ 2]);
1205 range
= range_expr_alloc(&expr
->location
, left
, right
);
1208 return range_expr_to_prefix(range
);
1211 static struct expr
*concat_elem_expr(const struct set
*set
, struct expr
*key
,
1212 const struct datatype
*dtype
,
1213 struct expr
*data
, int *off
)
1215 const struct datatype
*subtype
;
1216 unsigned int sub_length
;
1221 sub_length
= round_up(key
->len
, BITS_PER_BYTE
);
1223 expr
= constant_expr_splice(data
, sub_length
);
1224 expr
->dtype
= datatype_get(key
->dtype
);
1225 expr
->byteorder
= key
->byteorder
;
1226 expr
->len
= key
->len
;
1228 subtype
= concat_subtype_lookup(dtype
->type
, --(*off
));
1229 sub_length
= round_up(subtype
->size
, BITS_PER_BYTE
);
1230 expr
= constant_expr_splice(data
, sub_length
);
1231 expr
->dtype
= subtype
;
1232 expr
->byteorder
= subtype
->byteorder
;
1235 if (expr_basetype(expr
)->type
== TYPE_STRING
||
1236 (!(set
->flags
& NFT_SET_INTERVAL
) &&
1237 expr
->byteorder
== BYTEORDER_HOST_ENDIAN
))
1238 mpz_switch_byteorder(expr
->value
, expr
->len
/ BITS_PER_BYTE
);
1240 if (expr
->dtype
->basetype
!= NULL
&&
1241 expr
->dtype
->basetype
->type
== TYPE_BITMASK
)
1242 expr
= bitmask_expr_to_binops(expr
);
1244 data
->len
-= netlink_padding_len(sub_length
);
1249 static struct expr
*netlink_parse_concat_elem_key(const struct set
*set
,
1252 const struct datatype
*dtype
= set
->key
->dtype
;
1253 struct expr
*concat
, *expr
, *n
= NULL
;
1254 int off
= dtype
->subtypes
;
1256 if (set
->key
->etype
== EXPR_CONCAT
)
1257 n
= list_first_entry(&set
->key
->expressions
, struct expr
, list
);
1259 concat
= concat_expr_alloc(&data
->location
);
1261 expr
= concat_elem_expr(set
, n
, dtype
, data
, &off
);
1262 compound_expr_add(concat
, expr
);
1263 if (set
->key
->etype
== EXPR_CONCAT
)
1264 n
= list_next_entry(n
, list
);
1272 static struct expr
*netlink_parse_concat_elem(const struct set
*set
,
1275 const struct datatype
*dtype
= set
->data
->dtype
;
1276 struct expr
*concat
, *expr
, *left
, *range
;
1277 struct list_head expressions
;
1278 int off
= dtype
->subtypes
;
1280 init_list_head(&expressions
);
1282 concat
= concat_expr_alloc(&data
->location
);
1284 expr
= concat_elem_expr(set
, NULL
, dtype
, data
, &off
);
1285 list_add_tail(&expr
->list
, &expressions
);
1288 if (set
->data
->flags
& EXPR_F_INTERVAL
) {
1289 assert(!list_empty(&expressions
));
1291 off
= dtype
->subtypes
;
1294 left
= list_first_entry(&expressions
, struct expr
, list
);
1296 expr
= concat_elem_expr(set
, NULL
, dtype
, data
, &off
);
1297 list_del(&left
->list
);
1299 range
= range_expr_alloc(&data
->location
, left
, expr
);
1300 range
= range_expr_reduce(range
);
1301 compound_expr_add(concat
, range
);
1303 assert(list_empty(&expressions
));
1305 list_splice_tail(&expressions
, &concat
->expressions
);
1313 static int set_elem_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
1315 const struct nftnl_udata
**tb
= data
;
1316 unsigned char *value
= nftnl_udata_get(attr
);
1317 uint8_t type
= nftnl_udata_type(attr
);
1318 uint8_t len
= nftnl_udata_len(attr
);
1321 case NFTNL_UDATA_SET_ELEM_COMMENT
:
1322 if (value
[len
- 1] != '\0')
1325 case NFTNL_UDATA_SET_ELEM_FLAGS
:
1326 if (len
!= sizeof(uint32_t))
1336 static void set_elem_parse_udata(struct nftnl_set_elem
*nlse
,
1339 const struct nftnl_udata
*ud
[NFTNL_UDATA_SET_ELEM_MAX
+ 1] = {};
1343 data
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_USERDATA
, &len
);
1344 if (nftnl_udata_parse(data
, len
, set_elem_parse_udata_cb
, ud
))
1347 if (ud
[NFTNL_UDATA_SET_ELEM_COMMENT
])
1349 xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_SET_ELEM_COMMENT
]));
1350 if (ud
[NFTNL_UDATA_SET_ELEM_FLAGS
])
1352 nftnl_udata_get_u32(ud
[NFTNL_UDATA_SET_ELEM_FLAGS
]);
1355 int netlink_delinearize_setelem(struct nftnl_set_elem
*nlse
,
1356 struct set
*set
, struct nft_cache
*cache
)
1358 struct setelem_parse_ctx setelem_parse_ctx
= {
1362 struct nft_data_delinearize nld
;
1363 struct expr
*expr
, *key
, *data
;
1366 init_list_head(&setelem_parse_ctx
.stmt_list
);
1368 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_KEY
))
1369 nld
.value
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_KEY
, &nld
.len
);
1370 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_FLAGS
))
1371 flags
= nftnl_set_elem_get_u32(nlse
, NFTNL_SET_ELEM_FLAGS
);
1374 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_KEY
)) {
1375 key
= netlink_alloc_value(&netlink_location
, &nld
);
1376 datatype_set(key
, set
->key
->dtype
);
1377 key
->byteorder
= set
->key
->byteorder
;
1378 if (set
->key
->dtype
->subtypes
)
1379 key
= netlink_parse_concat_elem_key(set
, key
);
1381 if (!(set
->flags
& NFT_SET_INTERVAL
) &&
1382 key
->byteorder
== BYTEORDER_HOST_ENDIAN
)
1383 mpz_switch_byteorder(key
->value
, key
->len
/ BITS_PER_BYTE
);
1385 if (key
->dtype
->basetype
!= NULL
&&
1386 key
->dtype
->basetype
->type
== TYPE_BITMASK
)
1387 key
= bitmask_expr_to_binops(key
);
1388 } else if (flags
& NFT_SET_ELEM_CATCHALL
) {
1389 key
= set_elem_catchall_expr_alloc(&netlink_location
);
1390 datatype_set(key
, set
->key
->dtype
);
1391 key
->byteorder
= set
->key
->byteorder
;
1392 key
->len
= set
->key
->len
;
1394 BUG("Unexpected set element with no key\n");
1397 expr
= set_elem_expr_alloc(&netlink_location
, key
);
1398 expr
->flags
|= EXPR_F_KERNEL
;
1400 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_TIMEOUT
))
1401 expr
->timeout
= nftnl_set_elem_get_u64(nlse
, NFTNL_SET_ELEM_TIMEOUT
);
1402 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_EXPIRATION
))
1403 expr
->expiration
= nftnl_set_elem_get_u64(nlse
, NFTNL_SET_ELEM_EXPIRATION
);
1404 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_USERDATA
))
1405 set_elem_parse_udata(nlse
, expr
);
1406 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_EXPR
)) {
1407 const struct nftnl_expr
*nle
;
1410 nle
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_EXPR
, NULL
);
1411 stmt
= netlink_parse_set_expr(set
, cache
, nle
);
1412 list_add_tail(&stmt
->list
, &setelem_parse_ctx
.stmt_list
);
1413 } else if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_EXPRESSIONS
)) {
1414 nftnl_set_elem_expr_foreach(nlse
, set_elem_parse_expressions
,
1415 &setelem_parse_ctx
);
1417 list_splice_tail_init(&setelem_parse_ctx
.stmt_list
, &expr
->stmt_list
);
1419 if (flags
& NFT_SET_ELEM_INTERVAL_END
) {
1420 expr
->flags
|= EXPR_F_INTERVAL_END
;
1421 if (mpz_cmp_ui(set
->key
->value
, 0) == 0)
1425 if (set_is_datamap(set
->flags
)) {
1426 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_DATA
)) {
1427 nld
.value
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_DATA
,
1429 } else if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_CHAIN
)) {
1430 nld
.chain
= nftnl_set_elem_get_str(nlse
, NFTNL_SET_ELEM_CHAIN
);
1431 nld
.verdict
= nftnl_set_elem_get_u32(nlse
, NFTNL_SET_ELEM_VERDICT
);
1432 } else if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_VERDICT
)) {
1433 nld
.verdict
= nftnl_set_elem_get_u32(nlse
, NFTNL_SET_ELEM_VERDICT
);
1437 data
= netlink_alloc_data(&netlink_location
, &nld
,
1438 set
->data
->dtype
->type
== TYPE_VERDICT
?
1439 NFT_REG_VERDICT
: NFT_REG_1
);
1440 datatype_set(data
, set
->data
->dtype
);
1441 data
->byteorder
= set
->data
->byteorder
;
1443 if (set
->data
->dtype
->subtypes
) {
1444 data
= netlink_parse_concat_elem(set
, data
);
1445 } else if (set
->data
->flags
& EXPR_F_INTERVAL
)
1446 data
= netlink_parse_interval_elem(set
, data
);
1448 if (data
->byteorder
== BYTEORDER_HOST_ENDIAN
)
1449 mpz_switch_byteorder(data
->value
, data
->len
/ BITS_PER_BYTE
);
1451 expr
= mapping_expr_alloc(&netlink_location
, expr
, data
);
1453 if (set_is_objmap(set
->flags
)) {
1454 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_OBJREF
)) {
1455 nld
.value
= nftnl_set_elem_get(nlse
,
1456 NFTNL_SET_ELEM_OBJREF
,
1461 data
= netlink_alloc_value(&netlink_location
, &nld
);
1462 data
->dtype
= &string_type
;
1463 data
->byteorder
= BYTEORDER_HOST_ENDIAN
;
1464 mpz_switch_byteorder(data
->value
, data
->len
/ BITS_PER_BYTE
);
1465 expr
= mapping_expr_alloc(&netlink_location
, expr
, data
);
1468 compound_expr_add(set
->init
, expr
);
1470 if (!(flags
& NFT_SET_ELEM_INTERVAL_END
) &&
1471 nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_KEY_END
)) {
1472 flags
|= NFT_SET_ELEM_INTERVAL_END
;
1473 nld
.value
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_KEY_END
,
1481 static int list_setelem_cb(struct nftnl_set_elem
*nlse
, void *arg
)
1483 struct netlink_ctx
*ctx
= arg
;
1484 return netlink_delinearize_setelem(nlse
, ctx
->set
, &ctx
->nft
->cache
);
1487 static int list_setelem_debug_cb(struct nftnl_set_elem
*nlse
, void *arg
)
1491 r
= list_setelem_cb(nlse
, arg
);
1493 struct netlink_ctx
*ctx
= arg
;
1494 FILE *fp
= ctx
->nft
->output
.output_fp
;
1497 nftnl_set_elem_fprintf(fp
, nlse
, 0, 0);
1504 static int list_setelements(struct nftnl_set
*s
, struct netlink_ctx
*ctx
)
1506 FILE *fp
= ctx
->nft
->output
.output_fp
;
1508 if (fp
&& (ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
)) {
1509 const char *table
, *name
;
1510 uint32_t family
= nftnl_set_get_u32(s
, NFTNL_SET_FAMILY
);
1512 table
= nftnl_set_get_str(s
, NFTNL_SET_TABLE
);
1513 name
= nftnl_set_get_str(s
, NFTNL_SET_NAME
);
1515 fprintf(fp
, "%s %s @%s\n", family2str(family
), table
, name
);
1517 return nftnl_set_elem_foreach(s
, list_setelem_debug_cb
, ctx
);
1520 return nftnl_set_elem_foreach(s
, list_setelem_cb
, ctx
);
1523 int netlink_list_setelems(struct netlink_ctx
*ctx
, const struct handle
*h
,
1524 struct set
*set
, bool reset
)
1526 struct nftnl_set
*nls
;
1529 nls
= nftnl_set_alloc();
1531 memory_allocation_error();
1533 nftnl_set_set_u32(nls
, NFTNL_SET_FAMILY
, h
->family
);
1534 nftnl_set_set_str(nls
, NFTNL_SET_TABLE
, h
->table
.name
);
1535 nftnl_set_set_str(nls
, NFTNL_SET_NAME
, h
->set
.name
);
1537 nftnl_set_set_u64(nls
, NFTNL_SET_HANDLE
, h
->handle
.id
);
1539 err
= mnl_nft_setelem_get(ctx
, nls
, reset
);
1541 nftnl_set_free(nls
);
1549 set
->init
= set_expr_alloc(&internal_location
, set
);
1550 list_setelements(nls
, ctx
);
1552 if (set
->flags
& NFT_SET_INTERVAL
&& set
->desc
.field_count
> 1)
1553 concat_range_aggregate(set
->init
);
1554 else if (set
->flags
& NFT_SET_INTERVAL
)
1555 interval_map_decompose(set
->init
);
1557 list_expr_sort(&ctx
->set
->init
->expressions
);
1559 nftnl_set_free(nls
);
1565 int netlink_get_setelem(struct netlink_ctx
*ctx
, const struct handle
*h
,
1566 const struct location
*loc
, struct set
*cache_set
,
1567 struct set
*set
, struct expr
*init
, bool reset
)
1569 struct nftnl_set
*nls
, *nls_out
= NULL
;
1572 nls
= nftnl_set_alloc();
1574 memory_allocation_error();
1576 nftnl_set_set_u32(nls
, NFTNL_SET_FAMILY
, h
->family
);
1577 nftnl_set_set_str(nls
, NFTNL_SET_TABLE
, h
->table
.name
);
1578 nftnl_set_set_str(nls
, NFTNL_SET_NAME
, h
->set
.name
);
1580 nftnl_set_set_u64(nls
, NFTNL_SET_HANDLE
, h
->handle
.id
);
1582 alloc_setelem_cache(init
, nls
);
1584 netlink_dump_set(nls
, ctx
);
1586 nls_out
= mnl_nft_setelem_get_one(ctx
, nls
, reset
);
1588 nftnl_set_free(nls
);
1593 set
->init
= set_expr_alloc(loc
, set
);
1594 list_setelements(nls_out
, ctx
);
1596 if (set
->flags
& NFT_SET_INTERVAL
&& set
->desc
.field_count
> 1)
1597 concat_range_aggregate(set
->init
);
1598 else if (set
->flags
& NFT_SET_INTERVAL
)
1599 err
= get_set_decompose(cache_set
, set
);
1601 list_expr_sort(&ctx
->set
->init
->expressions
);
1603 nftnl_set_free(nls
);
1604 nftnl_set_free(nls_out
);
1610 void netlink_dump_obj(struct nftnl_obj
*nln
, struct netlink_ctx
*ctx
)
1612 FILE *fp
= ctx
->nft
->output
.output_fp
;
1614 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
1617 nftnl_obj_fprintf(fp
, nln
, 0, 0);
1621 static int obj_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
1623 unsigned char *value
= nftnl_udata_get(attr
);
1624 uint8_t type
= nftnl_udata_type(attr
);
1625 const struct nftnl_udata
**tb
= data
;
1626 uint8_t len
= nftnl_udata_len(attr
);
1629 case NFTNL_UDATA_OBJ_COMMENT
:
1630 if (value
[len
- 1] != '\0')
1640 struct obj
*netlink_delinearize_obj(struct netlink_ctx
*ctx
,
1641 struct nftnl_obj
*nlo
)
1643 const struct nftnl_udata
*ud
[NFTNL_UDATA_OBJ_MAX
+ 1] = {};
1649 obj
= obj_alloc(&netlink_location
);
1650 obj
->handle
.family
= nftnl_obj_get_u32(nlo
, NFTNL_OBJ_FAMILY
);
1651 obj
->handle
.table
.name
=
1652 xstrdup(nftnl_obj_get_str(nlo
, NFTNL_OBJ_TABLE
));
1653 obj
->handle
.obj
.name
=
1654 xstrdup(nftnl_obj_get_str(nlo
, NFTNL_OBJ_NAME
));
1655 obj
->handle
.handle
.id
=
1656 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_HANDLE
);
1657 if (nftnl_obj_is_set(nlo
, NFTNL_OBJ_USERDATA
)) {
1658 udata
= nftnl_obj_get_data(nlo
, NFTNL_OBJ_USERDATA
, &ulen
);
1659 if (nftnl_udata_parse(udata
, ulen
, obj_parse_udata_cb
, ud
) < 0) {
1660 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
1664 if (ud
[NFTNL_UDATA_OBJ_COMMENT
])
1665 obj
->comment
= xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_OBJ_COMMENT
]));
1668 type
= nftnl_obj_get_u32(nlo
, NFTNL_OBJ_TYPE
);
1670 case NFT_OBJECT_COUNTER
:
1671 obj
->counter
.packets
=
1672 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_CTR_PKTS
);
1673 obj
->counter
.bytes
=
1674 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_CTR_BYTES
);
1676 case NFT_OBJECT_QUOTA
:
1678 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_QUOTA_BYTES
);
1680 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_QUOTA_CONSUMED
);
1682 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_QUOTA_FLAGS
);
1684 case NFT_OBJECT_SECMARK
:
1685 snprintf(obj
->secmark
.ctx
, sizeof(obj
->secmark
.ctx
), "%s",
1686 nftnl_obj_get_str(nlo
, NFTNL_OBJ_SECMARK_CTX
));
1688 case NFT_OBJECT_CT_HELPER
:
1689 snprintf(obj
->ct_helper
.name
, sizeof(obj
->ct_helper
.name
), "%s",
1690 nftnl_obj_get_str(nlo
, NFTNL_OBJ_CT_HELPER_NAME
));
1691 obj
->ct_helper
.l3proto
= nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_HELPER_L3PROTO
);
1692 obj
->ct_helper
.l4proto
= nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_HELPER_L4PROTO
);
1694 case NFT_OBJECT_CT_TIMEOUT
:
1695 init_list_head(&obj
->ct_timeout
.timeout_list
);
1696 obj
->ct_timeout
.l3proto
= nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_TIMEOUT_L3PROTO
);
1697 obj
->ct_timeout
.l4proto
= nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_TIMEOUT_L4PROTO
);
1698 memcpy(obj
->ct_timeout
.timeout
,
1699 nftnl_obj_get(nlo
, NFTNL_OBJ_CT_TIMEOUT_ARRAY
),
1700 NFTNL_CTTIMEOUT_ARRAY_MAX
* sizeof(uint32_t));
1702 case NFT_OBJECT_LIMIT
:
1704 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_LIMIT_RATE
);
1706 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_LIMIT_UNIT
);
1708 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_LIMIT_BURST
);
1710 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_LIMIT_TYPE
);
1712 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_LIMIT_FLAGS
);
1714 case NFT_OBJECT_CT_EXPECT
:
1715 obj
->ct_expect
.l3proto
=
1716 nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_EXPECT_L3PROTO
);
1717 obj
->ct_expect
.l4proto
=
1718 nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_EXPECT_L4PROTO
);
1719 obj
->ct_expect
.dport
=
1720 nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_EXPECT_DPORT
);
1721 obj
->ct_expect
.timeout
=
1722 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_CT_EXPECT_TIMEOUT
);
1723 obj
->ct_expect
.size
=
1724 nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_EXPECT_SIZE
);
1726 case NFT_OBJECT_SYNPROXY
:
1728 nftnl_obj_get_u16(nlo
, NFTNL_OBJ_SYNPROXY_MSS
);
1729 obj
->synproxy
.wscale
=
1730 nftnl_obj_get_u8(nlo
, NFTNL_OBJ_SYNPROXY_WSCALE
);
1731 obj
->synproxy
.flags
=
1732 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_SYNPROXY_FLAGS
);
1740 void netlink_dump_flowtable(struct nftnl_flowtable
*flo
,
1741 struct netlink_ctx
*ctx
)
1743 FILE *fp
= ctx
->nft
->output
.output_fp
;
1745 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
1748 nftnl_flowtable_fprintf(fp
, flo
, 0, 0);
1752 static int list_obj_cb(struct nftnl_obj
*nls
, void *arg
)
1754 struct netlink_ctx
*ctx
= arg
;
1757 obj
= netlink_delinearize_obj(ctx
, nls
);
1760 list_add_tail(&obj
->list
, &ctx
->list
);
1764 int netlink_reset_objs(struct netlink_ctx
*ctx
, const struct cmd
*cmd
,
1765 uint32_t type
, bool dump
)
1767 const struct handle
*h
= &cmd
->handle
;
1768 struct nftnl_obj_list
*obj_cache
;
1771 obj_cache
= mnl_nft_obj_dump(ctx
, h
->family
,
1772 h
->table
.name
, h
->obj
.name
, type
, dump
, true);
1773 if (obj_cache
== NULL
)
1776 err
= nftnl_obj_list_foreach(obj_cache
, list_obj_cb
, ctx
);
1777 nftnl_obj_list_free(obj_cache
);
1781 int netlink_reset_rules(struct netlink_ctx
*ctx
, const struct cmd
*cmd
,
1784 const struct handle
*h
= &cmd
->handle
;
1785 struct nft_cache_filter f
= {
1786 .list
.table
= h
->table
.name
,
1787 .list
.chain
= h
->chain
.name
,
1788 .list
.rule_handle
= h
->handle
.id
,
1790 struct rule
*rule
, *next
, *crule
, *cnext
;
1791 struct table
*table
;
1792 struct chain
*chain
;
1795 ret
= rule_cache_dump(ctx
, h
, &f
, dump
, true);
1797 list_for_each_entry_safe(rule
, next
, &ctx
->list
, list
) {
1798 table
= table_cache_find(&ctx
->nft
->cache
.table_cache
,
1799 rule
->handle
.table
.name
,
1800 rule
->handle
.family
);
1804 chain
= chain_cache_find(table
, rule
->handle
.chain
.name
);
1808 list_del(&rule
->list
);
1809 list_for_each_entry_safe(crule
, cnext
, &chain
->rules
, list
) {
1810 if (crule
->handle
.handle
.id
!= rule
->handle
.handle
.id
)
1813 list_replace(&crule
->list
, &rule
->list
);
1819 list_add_tail(&rule
->list
, &chain
->rules
);
1822 list_for_each_entry_safe(rule
, next
, &ctx
->list
, list
) {
1823 list_del(&rule
->list
);
1831 netlink_delinearize_flowtable(struct netlink_ctx
*ctx
,
1832 struct nftnl_flowtable
*nlo
)
1834 struct flowtable
*flowtable
;
1835 const char * const *dev_array
;
1836 int len
= 0, i
, priority
;
1838 flowtable
= flowtable_alloc(&netlink_location
);
1839 flowtable
->handle
.family
=
1840 nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_FAMILY
);
1841 flowtable
->handle
.table
.name
=
1842 xstrdup(nftnl_flowtable_get_str(nlo
, NFTNL_FLOWTABLE_TABLE
));
1843 flowtable
->handle
.flowtable
.name
=
1844 xstrdup(nftnl_flowtable_get_str(nlo
, NFTNL_FLOWTABLE_NAME
));
1845 flowtable
->handle
.handle
.id
=
1846 nftnl_flowtable_get_u64(nlo
, NFTNL_FLOWTABLE_HANDLE
);
1847 if (nftnl_flowtable_is_set(nlo
, NFTNL_FLOWTABLE_FLAGS
))
1848 flowtable
->flags
= nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_FLAGS
);
1849 dev_array
= nftnl_flowtable_get(nlo
, NFTNL_FLOWTABLE_DEVICES
);
1850 while (dev_array
[len
])
1854 flowtable
->dev_array
= xmalloc(len
* sizeof(char *));
1855 for (i
= 0; i
< len
; i
++)
1856 flowtable
->dev_array
[i
] = xstrdup(dev_array
[i
]);
1858 flowtable
->dev_array_len
= len
;
1860 if (flowtable
->dev_array_len
) {
1861 qsort(flowtable
->dev_array
, flowtable
->dev_array_len
,
1862 sizeof(char *), qsort_device_cmp
);
1865 priority
= nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_PRIO
);
1866 flowtable
->priority
.expr
=
1867 constant_expr_alloc(&netlink_location
,
1869 BYTEORDER_HOST_ENDIAN
,
1873 flowtable
->hook
.num
=
1874 nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_HOOKNUM
);
1876 nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_FLAGS
);
1881 static int list_flowtable_cb(struct nftnl_flowtable
*nls
, void *arg
)
1883 struct netlink_ctx
*ctx
= arg
;
1884 struct flowtable
*flowtable
;
1886 flowtable
= netlink_delinearize_flowtable(ctx
, nls
);
1887 if (flowtable
== NULL
)
1889 list_add_tail(&flowtable
->list
, &ctx
->list
);
1893 int netlink_list_flowtables(struct netlink_ctx
*ctx
, const struct handle
*h
)
1895 struct nftnl_flowtable_list
*flowtable_cache
;
1898 flowtable_cache
= mnl_nft_flowtable_dump(ctx
, h
->family
,
1899 h
->table
.name
, NULL
);
1900 if (flowtable_cache
== NULL
) {
1907 err
= nftnl_flowtable_list_foreach(flowtable_cache
, list_flowtable_cb
, ctx
);
1908 nftnl_flowtable_list_free(flowtable_cache
);
1912 static void trace_print_hdr(const struct nftnl_trace
*nlt
,
1913 struct output_ctx
*octx
)
1915 nft_print(octx
, "trace id %08x %s ",
1916 nftnl_trace_get_u32(nlt
, NFTNL_TRACE_ID
),
1917 family2str(nftnl_trace_get_u32(nlt
, NFTNL_TRACE_FAMILY
)));
1918 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_TABLE
))
1919 nft_print(octx
, "%s ",
1920 nftnl_trace_get_str(nlt
, NFTNL_TRACE_TABLE
));
1921 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_CHAIN
))
1922 nft_print(octx
, "%s ",
1923 nftnl_trace_get_str(nlt
, NFTNL_TRACE_CHAIN
));
1926 static void trace_print_expr(const struct nftnl_trace
*nlt
, unsigned int attr
,
1927 struct expr
*lhs
, struct output_ctx
*octx
)
1929 struct expr
*rhs
, *rel
;
1933 data
= nftnl_trace_get_data(nlt
, attr
, &len
);
1934 rhs
= constant_expr_alloc(&netlink_location
,
1935 lhs
->dtype
, lhs
->byteorder
,
1936 len
* BITS_PER_BYTE
, data
);
1937 rel
= relational_expr_alloc(&netlink_location
, OP_EQ
, lhs
, rhs
);
1939 expr_print(rel
, octx
);
1940 nft_print(octx
, " ");
1944 static void trace_print_verdict(const struct nftnl_trace
*nlt
,
1945 struct output_ctx
*octx
)
1947 struct expr
*chain_expr
= NULL
;
1948 const char *chain
= NULL
;
1949 unsigned int verdict
;
1952 verdict
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_VERDICT
);
1953 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_JUMP_TARGET
)) {
1954 chain
= xstrdup(nftnl_trace_get_str(nlt
, NFTNL_TRACE_JUMP_TARGET
));
1955 chain_expr
= constant_expr_alloc(&netlink_location
,
1957 BYTEORDER_HOST_ENDIAN
,
1958 strlen(chain
) * BITS_PER_BYTE
,
1961 expr
= verdict_expr_alloc(&netlink_location
, verdict
, chain_expr
);
1963 nft_print(octx
, "verdict ");
1964 expr_print(expr
, octx
);
1968 static void trace_print_policy(const struct nftnl_trace
*nlt
,
1969 struct output_ctx
*octx
)
1971 unsigned int policy
;
1974 policy
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_POLICY
);
1976 expr
= verdict_expr_alloc(&netlink_location
, policy
, NULL
);
1978 nft_print(octx
, "policy ");
1979 expr_print(expr
, octx
);
1983 static struct rule
*trace_lookup_rule(const struct nftnl_trace
*nlt
,
1984 uint64_t rule_handle
,
1985 struct nft_cache
*cache
)
1987 struct chain
*chain
;
1988 struct table
*table
;
1991 h
.family
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_FAMILY
);
1992 h
.table
.name
= nftnl_trace_get_str(nlt
, NFTNL_TRACE_TABLE
);
1993 h
.chain
.name
= nftnl_trace_get_str(nlt
, NFTNL_TRACE_CHAIN
);
1998 table
= table_cache_find(&cache
->table_cache
, h
.table
.name
, h
.family
);
2002 chain
= chain_cache_find(table
, h
.chain
.name
);
2006 return rule_lookup(chain
, rule_handle
);
2009 static void trace_print_rule(const struct nftnl_trace
*nlt
,
2010 struct output_ctx
*octx
, struct nft_cache
*cache
)
2012 uint64_t rule_handle
;
2015 rule_handle
= nftnl_trace_get_u64(nlt
, NFTNL_TRACE_RULE_HANDLE
);
2016 rule
= trace_lookup_rule(nlt
, rule_handle
, cache
);
2018 trace_print_hdr(nlt
, octx
);
2021 nft_print(octx
, "rule ");
2022 rule_print(rule
, octx
);
2024 nft_print(octx
, "unknown rule handle %" PRIu64
, rule_handle
);
2027 nft_print(octx
, " (");
2028 trace_print_verdict(nlt
, octx
);
2029 nft_print(octx
, ")\n");
2032 static void trace_gen_stmts(struct list_head
*stmts
,
2033 struct proto_ctx
*ctx
, struct payload_dep_ctx
*pctx
,
2034 const struct nftnl_trace
*nlt
, unsigned int attr
,
2035 enum proto_bases base
)
2037 struct list_head unordered
= LIST_HEAD_INIT(unordered
);
2038 struct list_head list
;
2039 struct expr
*rel
, *lhs
, *rhs
, *tmp
, *nexpr
;
2041 const struct proto_desc
*desc
;
2046 if (!nftnl_trace_is_set(nlt
, attr
))
2048 hdr
= nftnl_trace_get_data(nlt
, attr
, &hlen
);
2050 lhs
= payload_expr_alloc(&netlink_location
, NULL
, 0);
2051 payload_init_raw(lhs
, base
, 0, hlen
* BITS_PER_BYTE
);
2052 rhs
= constant_expr_alloc(&netlink_location
,
2053 &invalid_type
, BYTEORDER_INVALID
,
2054 hlen
* BITS_PER_BYTE
, hdr
);
2057 init_list_head(&list
);
2058 payload_expr_expand(&list
, lhs
, ctx
);
2062 list_for_each_entry_safe(lhs
, nexpr
, &list
, list
) {
2063 if (desc
&& desc
!= ctx
->protocol
[base
].desc
) {
2064 /* Chained protocols */
2065 lhs
->payload
.offset
= 0;
2066 if (ctx
->protocol
[base
].desc
== NULL
)
2071 tmp
= constant_expr_splice(rhs
, lhs
->len
);
2072 expr_set_type(tmp
, lhs
->dtype
, lhs
->byteorder
);
2073 if (tmp
->byteorder
== BYTEORDER_HOST_ENDIAN
)
2074 mpz_switch_byteorder(tmp
->value
, tmp
->len
/ BITS_PER_BYTE
);
2076 /* Skip unknown and filtered expressions */
2077 desc
= lhs
->payload
.desc
;
2078 if (lhs
->dtype
== &invalid_type
||
2079 desc
->checksum_key
== payload_hdr_field(lhs
) ||
2080 desc
->format
.filter
& (1 << payload_hdr_field(lhs
))) {
2086 rel
= relational_expr_alloc(&lhs
->location
, OP_EQ
, lhs
, tmp
);
2087 stmt
= expr_stmt_alloc(&rel
->location
, rel
);
2088 list_add_tail(&stmt
->list
, &unordered
);
2090 desc
= ctx
->protocol
[base
].desc
;
2091 relational_expr_pctx_update(ctx
, rel
);
2098 list_for_each_entry(stmt
, &unordered
, list
) {
2099 enum proto_bases b
= base
;
2104 /* Move statements to result list in defined order */
2105 desc
= lhs
->payload
.desc
;
2106 if (desc
->format
.order
[n
] &&
2107 desc
->format
.order
[n
] != payload_hdr_field(lhs
))
2110 list_move_tail(&stmt
->list
, stmts
);
2113 if (payload_is_stacked(desc
, rel
))
2116 /* Don't strip 'icmp type' from payload dump. */
2117 if (pctx
->icmp_type
== 0)
2118 payload_dependency_kill(pctx
, lhs
, ctx
->family
);
2119 if (lhs
->flags
& EXPR_F_PROTOCOL
)
2120 payload_dependency_store(pctx
, stmt
, b
);
2126 static void trace_print_packet(const struct nftnl_trace
*nlt
,
2127 struct output_ctx
*octx
)
2129 struct list_head stmts
= LIST_HEAD_INIT(stmts
);
2130 const struct proto_desc
*ll_desc
;
2131 struct payload_dep_ctx pctx
= {};
2132 struct proto_ctx ctx
;
2135 struct stmt
*stmt
, *next
;
2137 trace_print_hdr(nlt
, octx
);
2139 nft_print(octx
, "packet: ");
2140 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_IIF
))
2141 trace_print_expr(nlt
, NFTNL_TRACE_IIF
,
2142 meta_expr_alloc(&netlink_location
,
2143 NFT_META_IIF
), octx
);
2144 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_OIF
))
2145 trace_print_expr(nlt
, NFTNL_TRACE_OIF
,
2146 meta_expr_alloc(&netlink_location
,
2147 NFT_META_OIF
), octx
);
2149 proto_ctx_init(&ctx
, nftnl_trace_get_u32(nlt
, NFTNL_TRACE_FAMILY
), 0, false);
2150 ll_desc
= ctx
.protocol
[PROTO_BASE_LL_HDR
].desc
;
2151 if ((ll_desc
== &proto_inet
|| ll_desc
== &proto_netdev
) &&
2152 nftnl_trace_is_set(nlt
, NFTNL_TRACE_NFPROTO
)) {
2153 nfproto
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_NFPROTO
);
2155 proto_ctx_update(&ctx
, PROTO_BASE_LL_HDR
, &netlink_location
, NULL
);
2156 proto_ctx_update(&ctx
, PROTO_BASE_NETWORK_HDR
, &netlink_location
,
2157 proto_find_upper(ll_desc
, nfproto
));
2159 if (ctx
.protocol
[PROTO_BASE_LL_HDR
].desc
== NULL
&&
2160 nftnl_trace_is_set(nlt
, NFTNL_TRACE_IIFTYPE
)) {
2161 dev_type
= nftnl_trace_get_u16(nlt
, NFTNL_TRACE_IIFTYPE
);
2162 proto_ctx_update(&ctx
, PROTO_BASE_LL_HDR
, &netlink_location
,
2163 proto_dev_desc(dev_type
));
2166 trace_gen_stmts(&stmts
, &ctx
, &pctx
, nlt
, NFTNL_TRACE_LL_HEADER
,
2168 trace_gen_stmts(&stmts
, &ctx
, &pctx
, nlt
, NFTNL_TRACE_NETWORK_HEADER
,
2169 PROTO_BASE_NETWORK_HDR
);
2170 trace_gen_stmts(&stmts
, &ctx
, &pctx
, nlt
, NFTNL_TRACE_TRANSPORT_HEADER
,
2171 PROTO_BASE_TRANSPORT_HDR
);
2173 list_for_each_entry_safe(stmt
, next
, &stmts
, list
) {
2174 stmt_print(stmt
, octx
);
2175 nft_print(octx
, " ");
2178 nft_print(octx
, "\n");
2181 int netlink_events_trace_cb(const struct nlmsghdr
*nlh
, int type
,
2182 struct netlink_mon_handler
*monh
)
2184 struct nftnl_trace
*nlt
;
2186 assert(type
== NFT_MSG_TRACE
);
2188 nlt
= nftnl_trace_alloc();
2190 memory_allocation_error();
2192 if (nftnl_trace_nlmsg_parse(nlh
, nlt
) < 0)
2193 netlink_abi_error();
2195 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_LL_HEADER
) ||
2196 nftnl_trace_is_set(nlt
, NFTNL_TRACE_NETWORK_HEADER
))
2197 trace_print_packet(nlt
, &monh
->ctx
->nft
->output
);
2199 switch (nftnl_trace_get_u32(nlt
, NFTNL_TRACE_TYPE
)) {
2200 case NFT_TRACETYPE_RULE
:
2201 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_RULE_HANDLE
))
2202 trace_print_rule(nlt
, &monh
->ctx
->nft
->output
,
2203 &monh
->ctx
->nft
->cache
);
2205 case NFT_TRACETYPE_POLICY
:
2206 trace_print_hdr(nlt
, &monh
->ctx
->nft
->output
);
2208 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_POLICY
)) {
2209 trace_print_policy(nlt
, &monh
->ctx
->nft
->output
);
2210 nft_mon_print(monh
, " ");
2213 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_MARK
))
2214 trace_print_expr(nlt
, NFTNL_TRACE_MARK
,
2215 meta_expr_alloc(&netlink_location
,
2217 &monh
->ctx
->nft
->output
);
2218 nft_mon_print(monh
, "\n");
2220 case NFT_TRACETYPE_RETURN
:
2221 trace_print_hdr(nlt
, &monh
->ctx
->nft
->output
);
2223 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_VERDICT
)) {
2224 trace_print_verdict(nlt
, &monh
->ctx
->nft
->output
);
2225 nft_mon_print(monh
, " ");
2228 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_MARK
))
2229 trace_print_expr(nlt
, NFTNL_TRACE_MARK
,
2230 meta_expr_alloc(&netlink_location
,
2232 &monh
->ctx
->nft
->output
);
2233 nft_mon_print(monh
, "\n");
2237 nftnl_trace_free(nlt
);