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/)
15 #include <libmnl/libmnl.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
20 #include <libnftnl/table.h>
21 #include <libnftnl/trace.h>
22 #include <libnftnl/chain.h>
23 #include <libnftnl/expr.h>
24 #include <libnftnl/object.h>
25 #include <libnftnl/set.h>
26 #include <libnftnl/flowtable.h>
27 #include <libnftnl/udata.h>
28 #include <libnftnl/ruleset.h>
29 #include <libnftnl/common.h>
30 #include <libnftnl/udata.h>
31 #include <linux/netfilter/nfnetlink.h>
32 #include <linux/netfilter/nf_tables.h>
33 #include <linux/netfilter.h>
39 #include <expression.h>
40 #include <statement.h>
46 #define nft_mon_print(monh, ...) nft_print(&monh->ctx->nft->output, __VA_ARGS__)
48 const struct input_descriptor indesc_netlink
= {
50 .type
= INDESC_NETLINK
,
53 const struct location netlink_location
= {
54 .indesc
= &indesc_netlink
,
57 void __noreturn
__netlink_abi_error(const char *file
, int line
,
60 fprintf(stderr
, "E: Contact urgently your Linux kernel vendor. "
61 "Netlink ABI is broken: %s:%d %s\n", file
, line
, reason
);
65 int netlink_io_error(struct netlink_ctx
*ctx
, const struct location
*loc
,
68 struct error_record
*erec
;
72 loc
= &netlink_location
;
75 erec
= erec_vcreate(EREC_ERROR
, loc
, fmt
, ap
);
77 erec_queue(erec
, ctx
->msgs
);
81 void __noreturn
__netlink_init_error(const char *filename
, int line
,
84 fprintf(stderr
, "%s:%d: Unable to initialize Netlink socket: %s\n",
85 filename
, line
, reason
);
89 struct nftnl_expr
*alloc_nft_expr(const char *name
)
91 struct nftnl_expr
*nle
;
93 nle
= nftnl_expr_alloc(name
);
95 memory_allocation_error();
99 static void netlink_gen_key(const struct expr
*expr
,
100 struct nft_data_linearize
*data
);
101 static void __netlink_gen_data(const struct expr
*expr
,
102 struct nft_data_linearize
*data
, bool expand
);
104 struct nftnl_set_elem
*alloc_nftnl_setelem(const struct expr
*set
,
105 const struct expr
*expr
)
107 const struct expr
*elem
, *data
;
108 struct nftnl_set_elem
*nlse
;
109 struct nft_data_linearize nld
;
110 struct nftnl_udata_buf
*udbuf
= NULL
;
116 nlse
= nftnl_set_elem_alloc();
118 memory_allocation_error();
121 if (expr
->etype
== EXPR_MAPPING
) {
123 if (!(expr
->flags
& EXPR_F_INTERVAL_END
))
128 if (elem
->etype
!= EXPR_SET_ELEM
)
129 BUG("Unexpected expression type: got %d\n", elem
->etype
);
133 switch (key
->etype
) {
134 case EXPR_SET_ELEM_CATCHALL
:
137 if (set
->set_flags
& NFT_SET_INTERVAL
&&
138 key
->etype
== EXPR_CONCAT
&& key
->field_count
> 1) {
139 key
->flags
|= EXPR_F_INTERVAL
;
140 netlink_gen_key(key
, &nld
);
141 key
->flags
&= ~EXPR_F_INTERVAL
;
143 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_KEY
, &nld
.value
, nld
.len
);
145 key
->flags
|= EXPR_F_INTERVAL_END
;
146 netlink_gen_key(key
, &nld
);
147 key
->flags
&= ~EXPR_F_INTERVAL_END
;
149 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_KEY_END
,
150 &nld
.value
, nld
.len
);
152 netlink_gen_key(key
, &nld
);
153 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_KEY
, &nld
.value
, nld
.len
);
159 uint64_t timeout
= elem
->timeout
;
161 if (elem
->timeout
== NFT_NEVER_TIMEOUT
)
164 nftnl_set_elem_set_u64(nlse
, NFTNL_SET_ELEM_TIMEOUT
, timeout
);
166 if (elem
->expiration
)
167 nftnl_set_elem_set_u64(nlse
, NFTNL_SET_ELEM_EXPIRATION
,
169 list_for_each_entry(stmt
, &elem
->stmt_list
, list
)
172 if (num_exprs
== 1) {
173 list_for_each_entry(stmt
, &elem
->stmt_list
, list
) {
174 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_EXPR
,
175 netlink_gen_stmt_stateful(stmt
), 0);
177 } else if (num_exprs
> 1) {
178 list_for_each_entry(stmt
, &elem
->stmt_list
, list
) {
179 nftnl_set_elem_add_expr(nlse
,
180 netlink_gen_stmt_stateful(stmt
));
183 if (elem
->comment
|| expr
->flags
& EXPR_F_INTERVAL_OPEN
) {
184 udbuf
= nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN
);
186 memory_allocation_error();
189 if (!nftnl_udata_put_strz(udbuf
, NFTNL_UDATA_SET_ELEM_COMMENT
,
191 memory_allocation_error();
193 if (expr
->flags
& EXPR_F_INTERVAL_OPEN
) {
194 if (!nftnl_udata_put_u32(udbuf
, NFTNL_UDATA_SET_ELEM_FLAGS
,
195 NFTNL_SET_ELEM_F_INTERVAL_OPEN
))
196 memory_allocation_error();
199 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_USERDATA
,
200 nftnl_udata_buf_data(udbuf
),
201 nftnl_udata_buf_len(udbuf
));
202 nftnl_udata_buf_free(udbuf
);
204 if (set_is_datamap(set
->set_flags
) && data
!= NULL
) {
205 __netlink_gen_data(data
, &nld
, !(data
->flags
& EXPR_F_SINGLETON
));
206 switch (data
->etype
) {
208 nftnl_set_elem_set_u32(nlse
, NFTNL_SET_ELEM_VERDICT
,
210 if (data
->chain
!= NULL
)
211 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_CHAIN
,
212 nld
.chain
, strlen(nld
.chain
));
219 case EXPR_RANGE_VALUE
:
221 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_DATA
,
225 BUG("unexpected set element expression\n");
229 if (set_is_objmap(set
->set_flags
) && data
!= NULL
) {
230 netlink_gen_data(data
, &nld
);
231 nftnl_set_elem_set(nlse
, NFTNL_SET_ELEM_OBJREF
,
235 if (expr
->flags
& EXPR_F_INTERVAL_END
)
236 flags
|= NFT_SET_ELEM_INTERVAL_END
;
237 if (key
->etype
== EXPR_SET_ELEM_CATCHALL
)
238 flags
|= NFT_SET_ELEM_CATCHALL
;
241 nftnl_set_elem_set_u32(nlse
, NFTNL_SET_ELEM_FLAGS
, flags
);
246 void netlink_gen_raw_data(const mpz_t value
, enum byteorder byteorder
,
247 unsigned int len
, struct nft_data_linearize
*data
)
250 mpz_export_data(data
->value
, value
, byteorder
, len
);
254 static int netlink_export_pad(unsigned char *data
, const mpz_t v
,
255 const struct expr
*i
)
257 mpz_export_data(data
, v
, i
->byteorder
,
258 div_round_up(i
->len
, BITS_PER_BYTE
));
260 return netlink_padded_len(i
->len
) / BITS_PER_BYTE
;
263 static void byteorder_switch_expr_value(mpz_t v
, const struct expr
*e
)
265 mpz_switch_byteorder(v
, div_round_up(e
->len
, BITS_PER_BYTE
));
268 static int __netlink_gen_concat_key(uint32_t flags
, const struct expr
*i
,
277 if (flags
& EXPR_F_INTERVAL_END
)
282 mpz_init_set(value
, expr
->value
);
284 if (expr_basetype(expr
)->type
== TYPE_INTEGER
&&
285 expr
->byteorder
== BYTEORDER_HOST_ENDIAN
)
286 byteorder_switch_expr_value(value
, expr
);
290 case EXPR_RANGE_VALUE
:
291 if (flags
& EXPR_F_INTERVAL_END
)
292 mpz_init_set(value
, i
->range
.high
);
294 mpz_init_set(value
, i
->range
.low
);
296 if (expr_basetype(i
)->type
== TYPE_INTEGER
&&
297 i
->byteorder
== BYTEORDER_HOST_ENDIAN
)
298 byteorder_switch_expr_value(value
, i
);
302 if (flags
& EXPR_F_INTERVAL_END
) {
306 mpz_init_bitmask(v
, i
->len
- i
->prefix_len
);
308 if (i
->byteorder
== BYTEORDER_HOST_ENDIAN
)
309 byteorder_switch_expr_value(v
, i
);
311 mpz_add(v
, i
->prefix
->value
, v
);
312 count
= netlink_export_pad(data
, v
, i
);
316 return netlink_export_pad(data
, i
->prefix
->value
, i
);
318 mpz_init_set(value
, i
->value
);
320 /* Switch byteorder to big endian representation when the set
321 * contains concatenation of intervals.
323 if (!(flags
& (EXPR_F_INTERVAL
| EXPR_F_INTERVAL_END
)))
326 expr
= (struct expr
*)i
;
327 if (expr_basetype(expr
)->type
== TYPE_INTEGER
&&
328 expr
->byteorder
== BYTEORDER_HOST_ENDIAN
)
329 byteorder_switch_expr_value(value
, expr
);
332 BUG("invalid expression type '%s' in set", expr_ops(i
)->name
);
335 ret
= netlink_export_pad(data
, value
, i
);
341 static void nft_data_memcpy(struct nft_data_linearize
*nld
,
342 const void *src
, unsigned int len
)
344 if (len
> sizeof(nld
->value
))
345 BUG("nld buffer overflow: want to copy %u, max %u\n", len
, (unsigned int)sizeof(nld
->value
));
347 memcpy(nld
->value
, src
, len
);
351 static void netlink_gen_concat_key(const struct expr
*expr
,
352 struct nft_data_linearize
*nld
)
354 unsigned int len
= netlink_padded_len(expr
->len
) / BITS_PER_BYTE
;
355 unsigned char data
[NFT_MAX_EXPR_LEN_BYTES
];
356 unsigned int offset
= 0;
357 const struct expr
*i
;
359 if (len
> sizeof(data
))
360 BUG("Value export of %u bytes would overflow", len
);
362 memset(data
, 0, sizeof(data
));
364 list_for_each_entry(i
, &expr
->expressions
, list
)
365 offset
+= __netlink_gen_concat_key(expr
->flags
, i
, data
+ offset
);
367 nft_data_memcpy(nld
, data
, len
);
370 static int __netlink_gen_concat_data(int end
, const struct expr
*i
,
383 mpz_init_set(value
, i
->value
);
385 case EXPR_RANGE_VALUE
:
387 mpz_init_set(value
, i
->range
.high
);
389 mpz_init_set(value
, i
->range
.low
);
395 mpz_init_bitmask(value
, i
->len
- i
->prefix_len
);
396 mpz_add(value
, i
->prefix
->value
, value
);
397 count
= netlink_export_pad(data
, value
, i
);
401 return netlink_export_pad(data
, i
->prefix
->value
, i
);
403 mpz_init_set(value
, i
->value
);
406 BUG("invalid expression type '%s' in set", expr_ops(i
)->name
);
409 ret
= netlink_export_pad(data
, value
, i
);
415 static void __netlink_gen_concat_expand(const struct expr
*expr
,
416 struct nft_data_linearize
*nld
)
418 unsigned int len
= (netlink_padded_len(expr
->len
) / BITS_PER_BYTE
) * 2;
419 unsigned char data
[NFT_MAX_EXPR_LEN_BYTES
];
420 unsigned int offset
= 0;
421 const struct expr
*i
;
423 if (len
> sizeof(data
))
424 BUG("Value export of %u bytes would overflow", len
);
426 memset(data
, 0, sizeof(data
));
428 list_for_each_entry(i
, &expr
->expressions
, list
)
429 offset
+= __netlink_gen_concat_data(false, i
, data
+ offset
);
431 list_for_each_entry(i
, &expr
->expressions
, list
)
432 offset
+= __netlink_gen_concat_data(true, i
, data
+ offset
);
434 nft_data_memcpy(nld
, data
, len
);
437 static void __netlink_gen_concat(const struct expr
*expr
,
438 struct nft_data_linearize
*nld
)
440 unsigned int len
= netlink_padded_len(expr
->len
) / BITS_PER_BYTE
;
441 unsigned char data
[NFT_MAX_EXPR_LEN_BYTES
];
442 unsigned int offset
= 0;
443 const struct expr
*i
;
445 if (len
> sizeof(data
))
446 BUG("Value export of %u bytes would overflow", len
);
448 memset(data
, 0, sizeof(data
));
450 list_for_each_entry(i
, &expr
->expressions
, list
)
451 offset
+= __netlink_gen_concat_data(expr
->flags
, i
, data
+ offset
);
453 nft_data_memcpy(nld
, data
, len
);
456 static void netlink_gen_concat_data(const struct expr
*expr
,
457 struct nft_data_linearize
*nld
, bool expand
)
460 __netlink_gen_concat_expand(expr
, nld
);
462 __netlink_gen_concat(expr
, nld
);
465 static void netlink_gen_constant_data(const struct expr
*expr
,
466 struct nft_data_linearize
*data
)
468 assert(expr
->etype
== EXPR_VALUE
);
469 netlink_gen_raw_data(expr
->value
, expr
->byteorder
,
470 div_round_up(expr
->len
, BITS_PER_BYTE
), data
);
473 static void netlink_gen_chain(const struct expr
*expr
,
474 struct nft_data_linearize
*data
)
476 char chain
[NFT_CHAIN_MAXNAMELEN
];
479 len
= expr
->chain
->len
/ BITS_PER_BYTE
;
482 BUG("chain length is 0");
484 if (len
> sizeof(chain
))
485 BUG("chain is too large (%u, %u max)",
486 len
, (unsigned int)sizeof(chain
));
488 memset(chain
, 0, sizeof(chain
));
490 mpz_export_data(chain
, expr
->chain
->value
,
491 BYTEORDER_HOST_ENDIAN
, len
);
492 snprintf(data
->chain
, NFT_CHAIN_MAXNAMELEN
, "%s", chain
);
495 static void netlink_gen_verdict(const struct expr
*expr
,
496 struct nft_data_linearize
*data
)
499 data
->verdict
= expr
->verdict
;
501 switch (expr
->verdict
) {
505 netlink_gen_chain(expr
, data
);
507 data
->chain_id
= expr
->chain_id
;
512 static void netlink_gen_range(const struct expr
*expr
,
513 struct nft_data_linearize
*nld
)
515 unsigned int len
= (netlink_padded_len(expr
->left
->len
) / BITS_PER_BYTE
) * 2;
516 unsigned char data
[NFT_MAX_EXPR_LEN_BYTES
];
519 if (len
> sizeof(data
))
520 BUG("Value export of %u bytes would overflow", len
);
522 memset(data
, 0, sizeof(data
));
523 offset
= netlink_export_pad(data
, expr
->left
->value
, expr
->left
);
524 netlink_export_pad(data
+ offset
, expr
->right
->value
, expr
->right
);
525 nft_data_memcpy(nld
, data
, len
);
528 static void netlink_gen_range_value(const struct expr
*expr
,
529 struct nft_data_linearize
*nld
)
531 unsigned int len
= (netlink_padded_len(expr
->len
) / BITS_PER_BYTE
) * 2;
532 unsigned char data
[NFT_MAX_EXPR_LEN_BYTES
];
535 if (len
> sizeof(data
))
536 BUG("Value export of %u bytes would overflow", len
);
538 memset(data
, 0, sizeof(data
));
539 offset
= netlink_export_pad(data
, expr
->range
.low
, expr
);
540 netlink_export_pad(data
+ offset
, expr
->range
.high
, expr
);
541 nft_data_memcpy(nld
, data
, len
);
544 static void netlink_gen_prefix(const struct expr
*expr
,
545 struct nft_data_linearize
*nld
)
547 unsigned int len
= (netlink_padded_len(expr
->len
) / BITS_PER_BYTE
) * 2;
548 unsigned char data
[NFT_MAX_EXPR_LEN_BYTES
];
552 if (len
> sizeof(data
))
553 BUG("Value export of %u bytes would overflow", len
);
555 offset
= netlink_export_pad(data
, expr
->prefix
->value
, expr
);
556 mpz_init_bitmask(v
, expr
->len
- expr
->prefix_len
);
557 mpz_add(v
, expr
->prefix
->value
, v
);
558 netlink_export_pad(data
+ offset
, v
, expr
->prefix
);
561 nft_data_memcpy(nld
, data
, len
);
564 static void netlink_gen_key(const struct expr
*expr
,
565 struct nft_data_linearize
*data
)
567 switch (expr
->etype
) {
569 return netlink_gen_constant_data(expr
, data
);
571 return netlink_gen_concat_key(expr
, data
);
573 return netlink_gen_range(expr
, data
);
575 return netlink_gen_prefix(expr
, data
);
577 BUG("invalid data expression type %s\n", expr_name(expr
));
581 static void __netlink_gen_data(const struct expr
*expr
,
582 struct nft_data_linearize
*data
, bool expand
)
584 switch (expr
->etype
) {
586 return netlink_gen_constant_data(expr
, data
);
588 return netlink_gen_concat_data(expr
, data
, expand
);
590 return netlink_gen_verdict(expr
, data
);
592 return netlink_gen_range(expr
, data
);
593 case EXPR_RANGE_VALUE
:
594 return netlink_gen_range_value(expr
, data
);
596 return netlink_gen_prefix(expr
, data
);
598 BUG("invalid data expression type %s\n", expr_name(expr
));
602 void netlink_gen_data(const struct expr
*expr
, struct nft_data_linearize
*data
)
604 __netlink_gen_data(expr
, data
, false);
607 struct expr
*netlink_alloc_value(const struct location
*loc
,
608 const struct nft_data_delinearize
*nld
)
610 return constant_expr_alloc(loc
, &invalid_type
, BYTEORDER_INVALID
,
611 nld
->len
* BITS_PER_BYTE
, nld
->value
);
614 static struct expr
*netlink_alloc_verdict(const struct location
*loc
,
615 const struct nft_data_delinearize
*nld
)
619 switch (nld
->verdict
) {
622 chain
= constant_expr_alloc(loc
, &string_type
,
623 BYTEORDER_HOST_ENDIAN
,
624 strlen(nld
->chain
) * BITS_PER_BYTE
,
632 return verdict_expr_alloc(loc
, nld
->verdict
, chain
);
635 struct expr
*netlink_alloc_data(const struct location
*loc
,
636 const struct nft_data_delinearize
*nld
,
637 enum nft_registers dreg
)
640 case NFT_REG_VERDICT
:
641 return netlink_alloc_verdict(loc
, nld
);
643 return netlink_alloc_value(loc
, nld
);
647 void netlink_dump_rule(const struct nftnl_rule
*nlr
, struct netlink_ctx
*ctx
)
649 FILE *fp
= ctx
->nft
->output
.output_fp
;
651 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
654 nftnl_rule_fprintf(fp
, nlr
, 0, 0);
658 void netlink_dump_expr(const struct nftnl_expr
*nle
,
659 FILE *fp
, unsigned int debug_mask
)
661 if (!(debug_mask
& NFT_DEBUG_NETLINK
))
664 nftnl_expr_fprintf(fp
, nle
, 0, 0);
668 void netlink_dump_chain(const struct nftnl_chain
*nlc
, struct netlink_ctx
*ctx
)
670 FILE *fp
= ctx
->nft
->output
.output_fp
;
672 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
675 nftnl_chain_fprintf(fp
, nlc
, 0, 0);
679 static int chain_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
681 unsigned char *value
= nftnl_udata_get(attr
);
682 uint8_t type
= nftnl_udata_type(attr
);
683 const struct nftnl_udata
**tb
= data
;
684 uint8_t len
= nftnl_udata_len(attr
);
687 case NFTNL_UDATA_CHAIN_COMMENT
:
688 if (value
[len
- 1] != '\0')
698 static int qsort_device_cmp(const void *a
, const void *b
)
700 const char **x
= (const char **)a
;
701 const char **y
= (const char **)b
;
703 return strcmp(*x
, *y
);
706 struct chain
*netlink_delinearize_chain(struct netlink_ctx
*ctx
,
707 const struct nftnl_chain
*nlc
)
709 const struct nftnl_udata
*ud
[NFTNL_UDATA_CHAIN_MAX
+ 1] = {};
710 int priority
, policy
, len
= 0, i
;
711 const char * const *dev_array
;
716 chain
= chain_alloc();
717 chain
->handle
.family
=
718 nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_FAMILY
);
719 chain
->handle
.table
.name
=
720 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_TABLE
));
721 chain
->handle
.chain
.name
=
722 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_NAME
));
723 chain
->handle
.handle
.id
=
724 nftnl_chain_get_u64(nlc
, NFTNL_CHAIN_HANDLE
);
725 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_FLAGS
))
726 chain
->flags
= nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_FLAGS
);
728 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_HOOKNUM
) &&
729 nftnl_chain_is_set(nlc
, NFTNL_CHAIN_PRIO
) &&
730 nftnl_chain_is_set(nlc
, NFTNL_CHAIN_TYPE
) &&
731 nftnl_chain_is_set(nlc
, NFTNL_CHAIN_POLICY
)) {
733 nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_HOOKNUM
);
735 hooknum2str(chain
->handle
.family
, chain
->hook
.num
);
736 priority
= nftnl_chain_get_s32(nlc
, NFTNL_CHAIN_PRIO
);
737 chain
->priority
.expr
=
738 constant_expr_alloc(&netlink_location
,
740 BYTEORDER_HOST_ENDIAN
,
741 sizeof(int) * BITS_PER_BYTE
,
744 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_TYPE
));
745 policy
= nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_POLICY
);
746 chain
->policy
= constant_expr_alloc(&netlink_location
,
748 BYTEORDER_HOST_ENDIAN
,
749 sizeof(int) * BITS_PER_BYTE
,
751 nftnl_chain_get_u32(nlc
, NFTNL_CHAIN_POLICY
);
752 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_DEV
)) {
753 chain
->dev_array
= xmalloc(sizeof(char *) * 2);
754 chain
->dev_array_len
= 1;
755 chain
->dev_array
[0] =
756 xstrdup(nftnl_chain_get_str(nlc
, NFTNL_CHAIN_DEV
));
757 chain
->dev_array
[1] = NULL
;
758 } else if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_DEVICES
)) {
759 dev_array
= nftnl_chain_get(nlc
, NFTNL_CHAIN_DEVICES
);
760 while (dev_array
[len
])
763 chain
->dev_array
= xmalloc((len
+ 1)* sizeof(char *));
764 for (i
= 0; i
< len
; i
++)
765 chain
->dev_array
[i
] = xstrdup(dev_array
[i
]);
767 chain
->dev_array
[i
] = NULL
;
768 chain
->dev_array_len
= len
;
770 chain
->flags
|= CHAIN_F_BASECHAIN
;
772 if (chain
->dev_array_len
) {
773 qsort(chain
->dev_array
, chain
->dev_array_len
,
774 sizeof(char *), qsort_device_cmp
);
778 if (nftnl_chain_is_set(nlc
, NFTNL_CHAIN_USERDATA
)) {
779 udata
= nftnl_chain_get_data(nlc
, NFTNL_CHAIN_USERDATA
, &ulen
);
780 if (nftnl_udata_parse(udata
, ulen
, chain_parse_udata_cb
, ud
) < 0) {
781 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
785 if (ud
[NFTNL_UDATA_CHAIN_COMMENT
])
786 chain
->comment
= xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_CHAIN_COMMENT
]));
792 static int table_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
794 unsigned char *value
= nftnl_udata_get(attr
);
795 const struct nftnl_udata
**tb
= data
;
796 uint8_t type
= nftnl_udata_type(attr
);
797 uint8_t len
= nftnl_udata_len(attr
);
800 case NFTNL_UDATA_TABLE_COMMENT
:
801 if (value
[len
- 1] != '\0')
811 struct table
*netlink_delinearize_table(struct netlink_ctx
*ctx
,
812 const struct nftnl_table
*nlt
)
814 const struct nftnl_udata
*ud
[NFTNL_UDATA_TABLE_MAX
+ 1] = {};
819 table
= table_alloc();
820 table
->handle
.family
= nftnl_table_get_u32(nlt
, NFTNL_TABLE_FAMILY
);
821 table
->handle
.table
.name
= xstrdup(nftnl_table_get_str(nlt
, NFTNL_TABLE_NAME
));
822 table
->flags
= nftnl_table_get_u32(nlt
, NFTNL_TABLE_FLAGS
);
823 table
->handle
.handle
.id
= nftnl_table_get_u64(nlt
, NFTNL_TABLE_HANDLE
);
824 table
->owner
= nftnl_table_get_u32(nlt
, NFTNL_TABLE_OWNER
);
826 if (nftnl_table_is_set(nlt
, NFTNL_TABLE_USERDATA
)) {
827 udata
= nftnl_table_get_data(nlt
, NFTNL_TABLE_USERDATA
, &ulen
);
828 if (nftnl_udata_parse(udata
, ulen
, table_parse_udata_cb
, ud
) < 0) {
829 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
833 if (ud
[NFTNL_UDATA_TABLE_COMMENT
])
834 table
->comment
= xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_TABLE_COMMENT
]));
840 static int list_table_cb(struct nftnl_table
*nlt
, void *arg
)
842 struct netlink_ctx
*ctx
= arg
;
845 table
= netlink_delinearize_table(ctx
, nlt
);
846 list_add_tail(&table
->list
, &ctx
->list
);
851 int netlink_list_tables(struct netlink_ctx
*ctx
, const struct handle
*h
,
852 const struct nft_cache_filter
*filter
)
854 struct nftnl_table_list
*table_cache
;
855 uint32_t family
= h
->family
;
856 const char *table
= NULL
;
859 family
= filter
->list
.family
;
860 table
= filter
->list
.table
;
863 table_cache
= mnl_nft_table_dump(ctx
, family
, table
);
864 if (table_cache
== NULL
) {
872 nftnl_table_list_foreach(table_cache
, list_table_cb
, ctx
);
873 nftnl_table_list_free(table_cache
);
877 enum nft_data_types
dtype_map_to_kernel(const struct datatype
*dtype
)
879 switch (dtype
->type
) {
881 return NFT_DATA_VERDICT
;
887 static const struct datatype
*dtype_map_from_kernel(enum nft_data_types type
)
889 /* The function always returns ownership of a reference. But for
890 * &verdict_Type and datatype_lookup(), those are static instances,
891 * we can omit the datatype_get() call.
894 case NFT_DATA_VERDICT
:
895 return &verdict_type
;
897 if (type
& ~TYPE_MASK
)
898 return concat_type_alloc(type
);
899 return datatype_lookup((enum datatypes
) type
);
903 void netlink_dump_set(const struct nftnl_set
*nls
, struct netlink_ctx
*ctx
)
905 FILE *fp
= ctx
->nft
->output
.output_fp
;
908 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
911 family
= nftnl_set_get_u32(nls
, NFTNL_SET_FAMILY
);
912 fprintf(fp
, "family %d ", family
);
913 nftnl_set_fprintf(fp
, nls
, 0, 0);
917 static int set_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
919 unsigned char *value
= nftnl_udata_get(attr
);
920 const struct nftnl_udata
**tb
= data
;
921 uint8_t type
= nftnl_udata_type(attr
);
922 uint8_t len
= nftnl_udata_len(attr
);
925 case NFTNL_UDATA_SET_KEYBYTEORDER
:
926 case NFTNL_UDATA_SET_DATABYTEORDER
:
927 case NFTNL_UDATA_SET_MERGE_ELEMENTS
:
928 case NFTNL_UDATA_SET_DATA_INTERVAL
:
929 if (len
!= sizeof(uint32_t))
932 case NFTNL_UDATA_SET_KEY_TYPEOF
:
933 case NFTNL_UDATA_SET_DATA_TYPEOF
:
937 case NFTNL_UDATA_SET_COMMENT
:
938 if (value
[len
- 1] != '\0')
948 static int set_key_parse_udata(const struct nftnl_udata
*attr
, void *data
)
950 const struct nftnl_udata
**tb
= data
;
951 uint8_t type
= nftnl_udata_type(attr
);
952 uint8_t len
= nftnl_udata_len(attr
);
955 case NFTNL_UDATA_SET_TYPEOF_EXPR
:
956 if (len
!= sizeof(uint32_t))
959 case NFTNL_UDATA_SET_TYPEOF_DATA
:
968 static struct expr
*set_make_key(const struct nftnl_udata
*attr
)
970 const struct nftnl_udata
*ud
[NFTNL_UDATA_SET_TYPEOF_MAX
+ 1] = {};
971 const struct expr_ops
*ops
;
979 err
= nftnl_udata_parse(nftnl_udata_get(attr
), nftnl_udata_len(attr
),
980 set_key_parse_udata
, ud
);
984 if (!ud
[NFTNL_UDATA_SET_TYPEOF_EXPR
] ||
985 !ud
[NFTNL_UDATA_SET_TYPEOF_DATA
])
988 etype
= nftnl_udata_get_u32(ud
[NFTNL_UDATA_SET_TYPEOF_EXPR
]);
989 ops
= expr_ops_by_type_u32(etype
);
990 if (!ops
|| !ops
->parse_udata
)
993 expr
= ops
->parse_udata(ud
[NFTNL_UDATA_SET_TYPEOF_DATA
]);
1000 static bool set_udata_key_valid(const struct expr
*e
, uint32_t len
)
1005 return div_round_up(e
->len
, BITS_PER_BYTE
) == len
/ BITS_PER_BYTE
;
1008 struct setelem_parse_ctx
{
1010 struct nft_cache
*cache
;
1011 struct list_head stmt_list
;
1014 static int set_elem_parse_expressions(struct nftnl_expr
*e
, void *data
)
1016 struct setelem_parse_ctx
*setelem_parse_ctx
= data
;
1017 struct nft_cache
*cache
= setelem_parse_ctx
->cache
;
1018 struct set
*set
= setelem_parse_ctx
->set
;
1021 stmt
= netlink_parse_set_expr(set
, cache
, e
);
1023 list_add_tail(&stmt
->list
, &setelem_parse_ctx
->stmt_list
);
1028 struct set
*netlink_delinearize_set(struct netlink_ctx
*ctx
,
1029 const struct nftnl_set
*nls
)
1031 const struct nftnl_udata
*ud
[NFTNL_UDATA_SET_MAX
+ 1] = {};
1032 enum byteorder keybyteorder
= BYTEORDER_INVALID
;
1033 enum byteorder databyteorder
= BYTEORDER_INVALID
;
1034 struct setelem_parse_ctx set_parse_ctx
;
1035 const struct datatype
*datatype
= NULL
;
1036 const struct datatype
*keytype
= NULL
;
1037 const struct datatype
*dtype2
= NULL
;
1038 const struct datatype
*dtype
= NULL
;
1039 struct expr
*typeof_expr_data
= NULL
;
1040 struct expr
*typeof_expr_key
= NULL
;
1041 const char *udata
, *comment
= NULL
;
1042 uint32_t flags
, key
, objtype
= 0;
1043 uint32_t data_interval
= 0;
1044 bool automerge
= false;
1049 if (nftnl_set_is_set(nls
, NFTNL_SET_USERDATA
)) {
1050 udata
= nftnl_set_get_data(nls
, NFTNL_SET_USERDATA
, &ulen
);
1051 if (nftnl_udata_parse(udata
, ulen
, set_parse_udata_cb
, ud
) < 0) {
1052 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
1056 #define GET_U32_UDATA(var, attr) \
1058 var = nftnl_udata_get_u32(ud[attr])
1060 GET_U32_UDATA(keybyteorder
, NFTNL_UDATA_SET_KEYBYTEORDER
);
1061 GET_U32_UDATA(databyteorder
, NFTNL_UDATA_SET_DATABYTEORDER
);
1062 GET_U32_UDATA(automerge
, NFTNL_UDATA_SET_MERGE_ELEMENTS
);
1063 GET_U32_UDATA(data_interval
, NFTNL_UDATA_SET_DATA_INTERVAL
);
1065 #undef GET_U32_UDATA
1066 typeof_expr_key
= set_make_key(ud
[NFTNL_UDATA_SET_KEY_TYPEOF
]);
1067 if (ud
[NFTNL_UDATA_SET_DATA_TYPEOF
])
1068 typeof_expr_data
= set_make_key(ud
[NFTNL_UDATA_SET_DATA_TYPEOF
]);
1069 if (ud
[NFTNL_UDATA_SET_COMMENT
])
1070 comment
= nftnl_udata_get(ud
[NFTNL_UDATA_SET_COMMENT
]);
1073 key
= nftnl_set_get_u32(nls
, NFTNL_SET_KEY_TYPE
);
1074 keytype
= dtype_map_from_kernel(key
);
1075 if (keytype
== NULL
) {
1076 netlink_io_error(ctx
, NULL
, "Unknown data type in set key %u",
1081 flags
= nftnl_set_get_u32(nls
, NFTNL_SET_FLAGS
);
1082 if (set_is_datamap(flags
)) {
1085 data
= nftnl_set_get_u32(nls
, NFTNL_SET_DATA_TYPE
);
1086 datatype
= dtype_map_from_kernel(data
);
1087 if (datatype
== NULL
) {
1088 netlink_io_error(ctx
, NULL
,
1089 "Unknown data type in set key %u",
1096 if (set_is_objmap(flags
)) {
1097 objtype
= nftnl_set_get_u32(nls
, NFTNL_SET_OBJ_TYPE
);
1099 datatype
= &string_type
;
1102 set
= set_alloc(&netlink_location
);
1103 set
->handle
.family
= nftnl_set_get_u32(nls
, NFTNL_SET_FAMILY
);
1104 set
->handle
.table
.name
= xstrdup(nftnl_set_get_str(nls
, NFTNL_SET_TABLE
));
1105 set
->handle
.set
.name
= xstrdup(nftnl_set_get_str(nls
, NFTNL_SET_NAME
));
1106 set
->automerge
= automerge
;
1108 set
->comment
= xstrdup(comment
);
1110 init_list_head(&set_parse_ctx
.stmt_list
);
1112 if (nftnl_set_is_set(nls
, NFTNL_SET_EXPR
)) {
1113 const struct nftnl_expr
*nle
;
1116 nle
= nftnl_set_get(nls
, NFTNL_SET_EXPR
);
1117 stmt
= netlink_parse_set_expr(set
, &ctx
->nft
->cache
, nle
);
1118 list_add_tail(&stmt
->list
, &set_parse_ctx
.stmt_list
);
1119 } else if (nftnl_set_is_set(nls
, NFTNL_SET_EXPRESSIONS
)) {
1120 set_parse_ctx
.cache
= &ctx
->nft
->cache
;
1121 set_parse_ctx
.set
= set
;
1122 nftnl_set_expr_foreach(nls
, set_elem_parse_expressions
,
1125 list_splice_tail(&set_parse_ctx
.stmt_list
, &set
->stmt_list
);
1127 set
->flags
= nftnl_set_get_u32(nls
, NFTNL_SET_FLAGS
);
1132 dtype2
= set_datatype_alloc(datatype
, databyteorder
);
1133 klen
= nftnl_set_get_u32(nls
, NFTNL_SET_DATA_LEN
) * BITS_PER_BYTE
;
1135 dlen
= data_interval
? klen
/ 2 : klen
;
1137 if (set_udata_key_valid(typeof_expr_data
, dlen
)) {
1138 typeof_expr_data
->len
= klen
;
1139 set
->data
= typeof_expr_data
;
1140 typeof_expr_data
= NULL
;
1141 } else if (set
->flags
& NFT_SET_OBJECT
) {
1142 set
->data
= constant_expr_alloc(&netlink_location
,
1144 databyteorder
, klen
,
1147 set
->data
= constant_expr_alloc(&netlink_location
,
1149 databyteorder
, klen
,
1152 /* Can't use 'typeof' keyword, so discard key too */
1153 expr_free(typeof_expr_key
);
1154 typeof_expr_key
= NULL
;
1158 set
->data
->flags
|= EXPR_F_INTERVAL
;
1161 dtype
= set_datatype_alloc(keytype
, keybyteorder
);
1162 klen
= nftnl_set_get_u32(nls
, NFTNL_SET_KEY_LEN
) * BITS_PER_BYTE
;
1164 if (set_udata_key_valid(typeof_expr_key
, klen
)) {
1165 set
->key
= typeof_expr_key
;
1166 typeof_expr_key
= NULL
;
1167 set
->key_typeof_valid
= true;
1169 set
->key
= constant_expr_alloc(&netlink_location
, dtype
,
1174 set
->handle
.handle
.id
= nftnl_set_get_u64(nls
, NFTNL_SET_HANDLE
);
1176 set
->objtype
= objtype
;
1178 if (nftnl_set_is_set(nls
, NFTNL_SET_TIMEOUT
))
1179 set
->timeout
= nftnl_set_get_u64(nls
, NFTNL_SET_TIMEOUT
);
1180 if (nftnl_set_is_set(nls
, NFTNL_SET_GC_INTERVAL
))
1181 set
->gc_int
= nftnl_set_get_u32(nls
, NFTNL_SET_GC_INTERVAL
);
1183 if (nftnl_set_is_set(nls
, NFTNL_SET_POLICY
))
1184 set
->policy
= nftnl_set_get_u32(nls
, NFTNL_SET_POLICY
);
1186 if (nftnl_set_is_set(nls
, NFTNL_SET_DESC_SIZE
))
1187 set
->desc
.size
= nftnl_set_get_u32(nls
, NFTNL_SET_DESC_SIZE
);
1189 if (nftnl_set_is_set(nls
, NFTNL_SET_COUNT
))
1190 set
->count
= nftnl_set_get_u32(nls
, NFTNL_SET_COUNT
);
1192 if (nftnl_set_is_set(nls
, NFTNL_SET_DESC_CONCAT
)) {
1193 uint32_t len
= NFT_REG32_COUNT
;
1194 const uint8_t *data
;
1196 data
= nftnl_set_get_data(nls
, NFTNL_SET_DESC_CONCAT
, &len
);
1198 memcpy(set
->desc
.field_len
, data
, len
);
1199 set
->desc
.field_count
= len
;
1204 expr_free(typeof_expr_data
);
1205 expr_free(typeof_expr_key
);
1206 datatype_free(datatype
);
1207 datatype_free(keytype
);
1208 datatype_free(dtype2
);
1209 datatype_free(dtype
);
1213 void alloc_setelem_cache(const struct expr
*set
, struct nftnl_set
*nls
)
1215 struct nftnl_set_elem
*nlse
;
1216 const struct expr
*expr
;
1218 list_for_each_entry(expr
, &set
->expressions
, list
) {
1219 nlse
= alloc_nftnl_setelem(set
, expr
);
1220 nftnl_set_elem_add(nls
, nlse
);
1224 static bool range_expr_is_prefix(const struct expr
*range
, uint32_t *prefix_len
)
1226 const struct expr
*right
= range
->right
;
1227 const struct expr
*left
= range
->left
;
1228 uint32_t len
= left
->len
;
1229 unsigned long n1
, n2
;
1233 mpz_init2(bitmask
, left
->len
);
1234 mpz_xor(bitmask
, left
->value
, right
->value
);
1236 n1
= mpz_scan0(bitmask
, 0);
1237 if (n1
== ULONG_MAX
)
1240 n2
= mpz_scan1(bitmask
, n1
+ 1);
1246 if (mpz_scan1(left
->value
, 0) < len
- plen
)
1260 struct expr
*range_expr_to_prefix(struct expr
*range
)
1262 struct expr
*prefix
;
1263 uint32_t prefix_len
;
1265 if (range_expr_is_prefix(range
, &prefix_len
)) {
1266 prefix
= prefix_expr_alloc(&range
->location
,
1267 expr_get(range
->left
),
1276 static struct expr
*range_expr_reduce(struct expr
*range
)
1280 if (!mpz_cmp(range
->left
->value
, range
->right
->value
)) {
1281 expr
= expr_get(range
->left
);
1286 if (range
->left
->dtype
->type
!= TYPE_IPADDR
&&
1287 range
->left
->dtype
->type
!= TYPE_IP6ADDR
)
1290 return range_expr_to_prefix(range
);
1293 static struct expr
*netlink_parse_interval_elem(const struct set
*set
,
1296 unsigned int len
= netlink_padded_len(expr
->len
) / BITS_PER_BYTE
;
1297 const struct datatype
*dtype
= set
->data
->dtype
;
1298 struct expr
*range
, *left
, *right
;
1299 char data
[NFT_MAX_EXPR_LEN_BYTES
];
1301 if (len
> sizeof(data
))
1302 BUG("Value export of %u bytes would overflow", len
);
1304 memset(data
, 0, sizeof(data
));
1306 mpz_export_data(data
, expr
->value
, dtype
->byteorder
, len
);
1307 left
= constant_expr_alloc(&internal_location
, dtype
,
1309 (len
/ 2) * BITS_PER_BYTE
, &data
[0]);
1310 right
= constant_expr_alloc(&internal_location
, dtype
,
1312 (len
/ 2) * BITS_PER_BYTE
, &data
[len
/ 2]);
1313 range
= range_expr_alloc(&expr
->location
, left
, right
);
1316 return range_expr_to_prefix(range
);
1319 static struct expr
*concat_elem_expr(const struct set
*set
, struct expr
*key
,
1320 const struct datatype
*dtype
,
1321 struct expr
*data
, int *off
)
1323 const struct datatype
*subtype
;
1324 unsigned int sub_length
;
1329 sub_length
= round_up(key
->len
, BITS_PER_BYTE
);
1331 expr
= constant_expr_splice(data
, sub_length
);
1332 expr
->dtype
= datatype_get(key
->dtype
);
1333 expr
->byteorder
= key
->byteorder
;
1334 expr
->len
= key
->len
;
1336 subtype
= concat_subtype_lookup(dtype
->type
, --(*off
));
1337 sub_length
= round_up(subtype
->size
, BITS_PER_BYTE
);
1338 expr
= constant_expr_splice(data
, sub_length
);
1339 expr
->dtype
= subtype
;
1340 expr
->byteorder
= subtype
->byteorder
;
1343 if (expr_basetype(expr
)->type
== TYPE_STRING
||
1344 (!(set
->flags
& NFT_SET_INTERVAL
) &&
1345 expr
->byteorder
== BYTEORDER_HOST_ENDIAN
))
1346 mpz_switch_byteorder(expr
->value
, expr
->len
/ BITS_PER_BYTE
);
1348 if (expr
->dtype
->basetype
!= NULL
&&
1349 expr
->dtype
->basetype
->type
== TYPE_BITMASK
)
1350 expr
= bitmask_expr_to_binops(expr
);
1352 data
->len
-= netlink_padding_len(sub_length
);
1357 static struct expr
*netlink_parse_concat_elem_key(const struct set
*set
,
1360 const struct datatype
*dtype
= set
->key
->dtype
;
1361 struct expr
*concat
, *expr
, *n
= NULL
;
1362 int off
= dtype
->subtypes
;
1364 if (set
->key
->etype
== EXPR_CONCAT
)
1365 n
= list_first_entry(&set
->key
->expressions
, struct expr
, list
);
1367 concat
= concat_expr_alloc(&data
->location
);
1369 expr
= concat_elem_expr(set
, n
, dtype
, data
, &off
);
1370 compound_expr_add(concat
, expr
);
1371 if (set
->key
->etype
== EXPR_CONCAT
)
1372 n
= list_next_entry(n
, list
);
1380 static struct expr
*netlink_parse_concat_elem(const struct set
*set
,
1383 const struct datatype
*dtype
= set
->data
->dtype
;
1384 struct expr
*concat
, *expr
, *left
, *range
;
1385 struct list_head expressions
;
1386 int off
= dtype
->subtypes
;
1388 init_list_head(&expressions
);
1390 concat
= concat_expr_alloc(&data
->location
);
1392 expr
= concat_elem_expr(set
, NULL
, dtype
, data
, &off
);
1393 list_add_tail(&expr
->list
, &expressions
);
1396 if (set
->data
->flags
& EXPR_F_INTERVAL
) {
1397 assert(!list_empty(&expressions
));
1399 off
= dtype
->subtypes
;
1402 left
= list_first_entry(&expressions
, struct expr
, list
);
1404 expr
= concat_elem_expr(set
, NULL
, dtype
, data
, &off
);
1405 list_del(&left
->list
);
1407 range
= range_expr_alloc(&data
->location
, left
, expr
);
1408 range
= range_expr_reduce(range
);
1409 compound_expr_add(concat
, range
);
1411 assert(list_empty(&expressions
));
1413 list_splice_tail(&expressions
, &concat
->expressions
);
1421 static int set_elem_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
1423 const struct nftnl_udata
**tb
= data
;
1424 unsigned char *value
= nftnl_udata_get(attr
);
1425 uint8_t type
= nftnl_udata_type(attr
);
1426 uint8_t len
= nftnl_udata_len(attr
);
1429 case NFTNL_UDATA_SET_ELEM_COMMENT
:
1430 if (value
[len
- 1] != '\0')
1433 case NFTNL_UDATA_SET_ELEM_FLAGS
:
1434 if (len
!= sizeof(uint32_t))
1444 static void set_elem_parse_udata(struct nftnl_set_elem
*nlse
,
1447 const struct nftnl_udata
*ud
[NFTNL_UDATA_SET_ELEM_MAX
+ 1] = {};
1451 data
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_USERDATA
, &len
);
1452 if (nftnl_udata_parse(data
, len
, set_elem_parse_udata_cb
, ud
))
1455 if (ud
[NFTNL_UDATA_SET_ELEM_COMMENT
])
1457 xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_SET_ELEM_COMMENT
]));
1458 if (ud
[NFTNL_UDATA_SET_ELEM_FLAGS
]) {
1459 uint32_t elem_flags
;
1462 nftnl_udata_get_u32(ud
[NFTNL_UDATA_SET_ELEM_FLAGS
]);
1463 if (elem_flags
& NFTNL_SET_ELEM_F_INTERVAL_OPEN
)
1464 expr
->flags
|= EXPR_F_INTERVAL_OPEN
;
1468 int netlink_delinearize_setelem(struct netlink_ctx
*ctx
,
1469 struct nftnl_set_elem
*nlse
,
1472 struct setelem_parse_ctx setelem_parse_ctx
= {
1474 .cache
= &ctx
->nft
->cache
,
1476 struct nft_data_delinearize nld
;
1477 struct expr
*expr
, *key
, *data
;
1480 init_list_head(&setelem_parse_ctx
.stmt_list
);
1482 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_KEY
))
1483 nld
.value
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_KEY
, &nld
.len
);
1484 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_FLAGS
))
1485 flags
= nftnl_set_elem_get_u32(nlse
, NFTNL_SET_ELEM_FLAGS
);
1488 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_KEY
)) {
1489 key
= netlink_alloc_value(&netlink_location
, &nld
);
1490 datatype_set(key
, set
->key
->dtype
);
1491 key
->byteorder
= set
->key
->byteorder
;
1492 if (set
->key
->dtype
->subtypes
)
1493 key
= netlink_parse_concat_elem_key(set
, key
);
1495 if (!(set
->flags
& NFT_SET_INTERVAL
) &&
1496 key
->byteorder
== BYTEORDER_HOST_ENDIAN
)
1497 mpz_switch_byteorder(key
->value
, key
->len
/ BITS_PER_BYTE
);
1499 if (key
->dtype
->basetype
!= NULL
&&
1500 key
->dtype
->basetype
->type
== TYPE_BITMASK
)
1501 key
= bitmask_expr_to_binops(key
);
1502 } else if (flags
& NFT_SET_ELEM_CATCHALL
) {
1503 key
= set_elem_catchall_expr_alloc(&netlink_location
);
1504 datatype_set(key
, set
->key
->dtype
);
1505 key
->byteorder
= set
->key
->byteorder
;
1506 key
->len
= set
->key
->len
;
1508 netlink_io_error(ctx
, NULL
,
1509 "Unexpected set element with no key");
1513 expr
= set_elem_expr_alloc(&netlink_location
, key
);
1514 expr
->flags
|= EXPR_F_KERNEL
;
1516 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_TIMEOUT
)) {
1517 expr
->timeout
= nftnl_set_elem_get_u64(nlse
, NFTNL_SET_ELEM_TIMEOUT
);
1518 if (expr
->timeout
== 0)
1519 expr
->timeout
= NFT_NEVER_TIMEOUT
;
1522 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_EXPIRATION
))
1523 expr
->expiration
= nftnl_set_elem_get_u64(nlse
, NFTNL_SET_ELEM_EXPIRATION
);
1524 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_USERDATA
)) {
1525 set_elem_parse_udata(nlse
, expr
);
1527 set
->elem_has_comment
= true;
1529 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_EXPR
)) {
1530 const struct nftnl_expr
*nle
;
1533 nle
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_EXPR
, NULL
);
1534 stmt
= netlink_parse_set_expr(set
, &ctx
->nft
->cache
, nle
);
1535 list_add_tail(&stmt
->list
, &setelem_parse_ctx
.stmt_list
);
1536 } else if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_EXPRESSIONS
)) {
1537 nftnl_set_elem_expr_foreach(nlse
, set_elem_parse_expressions
,
1538 &setelem_parse_ctx
);
1540 list_splice_tail_init(&setelem_parse_ctx
.stmt_list
, &expr
->stmt_list
);
1542 if (flags
& NFT_SET_ELEM_INTERVAL_END
) {
1543 expr
->flags
|= EXPR_F_INTERVAL_END
;
1544 if (mpz_cmp_ui(set
->key
->value
, 0) == 0)
1548 if (set_is_datamap(set
->flags
)) {
1549 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_DATA
)) {
1550 nld
.value
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_DATA
,
1552 } else if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_CHAIN
)) {
1553 nld
.chain
= nftnl_set_elem_get_str(nlse
, NFTNL_SET_ELEM_CHAIN
);
1554 nld
.verdict
= nftnl_set_elem_get_u32(nlse
, NFTNL_SET_ELEM_VERDICT
);
1555 } else if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_VERDICT
)) {
1556 nld
.verdict
= nftnl_set_elem_get_u32(nlse
, NFTNL_SET_ELEM_VERDICT
);
1560 data
= netlink_alloc_data(&netlink_location
, &nld
,
1561 set
->data
->dtype
->type
== TYPE_VERDICT
?
1562 NFT_REG_VERDICT
: NFT_REG_1
);
1564 if (set
->data
->dtype
->is_typeof
)
1565 datatype_set(data
, set
->data
->dtype
->basetype
);
1567 datatype_set(data
, set
->data
->dtype
);
1568 data
->byteorder
= set
->data
->byteorder
;
1570 if (set
->data
->dtype
->subtypes
) {
1571 data
= netlink_parse_concat_elem(set
, data
);
1572 } else if (set
->data
->flags
& EXPR_F_INTERVAL
)
1573 data
= netlink_parse_interval_elem(set
, data
);
1575 if (data
->byteorder
== BYTEORDER_HOST_ENDIAN
)
1576 mpz_switch_byteorder(data
->value
, data
->len
/ BITS_PER_BYTE
);
1578 expr
= mapping_expr_alloc(&netlink_location
, expr
, data
);
1580 if (set_is_objmap(set
->flags
)) {
1581 if (nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_OBJREF
)) {
1582 nld
.value
= nftnl_set_elem_get(nlse
,
1583 NFTNL_SET_ELEM_OBJREF
,
1588 data
= netlink_alloc_value(&netlink_location
, &nld
);
1589 data
->dtype
= &string_type
;
1590 data
->byteorder
= BYTEORDER_HOST_ENDIAN
;
1591 mpz_switch_byteorder(data
->value
, data
->len
/ BITS_PER_BYTE
);
1592 expr
= mapping_expr_alloc(&netlink_location
, expr
, data
);
1595 compound_expr_add(set
->init
, expr
);
1597 if (!(flags
& NFT_SET_ELEM_INTERVAL_END
) &&
1598 nftnl_set_elem_is_set(nlse
, NFTNL_SET_ELEM_KEY_END
)) {
1599 flags
|= NFT_SET_ELEM_INTERVAL_END
;
1600 nld
.value
= nftnl_set_elem_get(nlse
, NFTNL_SET_ELEM_KEY_END
,
1608 static int list_setelem_cb(struct nftnl_set_elem
*nlse
, void *arg
)
1610 struct netlink_ctx
*ctx
= arg
;
1611 return netlink_delinearize_setelem(ctx
, nlse
, ctx
->set
);
1614 static int list_setelem_debug_cb(struct nftnl_set_elem
*nlse
, void *arg
)
1618 r
= list_setelem_cb(nlse
, arg
);
1620 struct netlink_ctx
*ctx
= arg
;
1621 FILE *fp
= ctx
->nft
->output
.output_fp
;
1624 nftnl_set_elem_fprintf(fp
, nlse
, 0, 0);
1631 static int list_setelements(struct nftnl_set
*s
, struct netlink_ctx
*ctx
)
1633 FILE *fp
= ctx
->nft
->output
.output_fp
;
1635 if (fp
&& (ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
)) {
1636 const char *table
, *name
;
1637 uint32_t family
= nftnl_set_get_u32(s
, NFTNL_SET_FAMILY
);
1639 table
= nftnl_set_get_str(s
, NFTNL_SET_TABLE
);
1640 name
= nftnl_set_get_str(s
, NFTNL_SET_NAME
);
1642 fprintf(fp
, "%s %s @%s\n", family2str(family
), table
, name
);
1644 return nftnl_set_elem_foreach(s
, list_setelem_debug_cb
, ctx
);
1647 return nftnl_set_elem_foreach(s
, list_setelem_cb
, ctx
);
1650 int netlink_list_setelems(struct netlink_ctx
*ctx
, const struct handle
*h
,
1651 struct set
*set
, bool reset
)
1653 struct nftnl_set
*nls
;
1656 nls
= nftnl_set_alloc();
1658 memory_allocation_error();
1660 nftnl_set_set_u32(nls
, NFTNL_SET_FAMILY
, h
->family
);
1661 nftnl_set_set_str(nls
, NFTNL_SET_TABLE
, h
->table
.name
);
1662 nftnl_set_set_str(nls
, NFTNL_SET_NAME
, h
->set
.name
);
1664 nftnl_set_set_u64(nls
, NFTNL_SET_HANDLE
, h
->handle
.id
);
1666 err
= mnl_nft_setelem_get(ctx
, nls
, reset
);
1668 nftnl_set_free(nls
);
1676 set
->init
= set_expr_alloc(&internal_location
, set
);
1677 list_setelements(nls
, ctx
);
1679 if (set
->flags
& NFT_SET_INTERVAL
&& set
->desc
.field_count
> 1)
1680 concat_range_aggregate(set
->init
);
1681 else if (set
->flags
& NFT_SET_INTERVAL
)
1682 interval_map_decompose(set
->init
);
1684 list_expr_sort(&ctx
->set
->init
->expressions
);
1686 nftnl_set_free(nls
);
1692 int netlink_get_setelem(struct netlink_ctx
*ctx
, const struct handle
*h
,
1693 const struct location
*loc
, struct set
*cache_set
,
1694 struct set
*set
, struct expr
*init
, bool reset
)
1696 struct nftnl_set
*nls
, *nls_out
= NULL
;
1699 nls
= nftnl_set_alloc();
1701 memory_allocation_error();
1703 nftnl_set_set_u32(nls
, NFTNL_SET_FAMILY
, h
->family
);
1704 nftnl_set_set_str(nls
, NFTNL_SET_TABLE
, h
->table
.name
);
1705 nftnl_set_set_str(nls
, NFTNL_SET_NAME
, h
->set
.name
);
1707 nftnl_set_set_u64(nls
, NFTNL_SET_HANDLE
, h
->handle
.id
);
1709 alloc_setelem_cache(init
, nls
);
1711 netlink_dump_set(nls
, ctx
);
1713 nls_out
= mnl_nft_setelem_get_one(ctx
, nls
, reset
);
1715 nftnl_set_free(nls
);
1720 set
->init
= set_expr_alloc(loc
, set
);
1721 list_setelements(nls_out
, ctx
);
1723 if (set
->flags
& NFT_SET_INTERVAL
&& set
->desc
.field_count
> 1)
1724 concat_range_aggregate(set
->init
);
1725 else if (set
->flags
& NFT_SET_INTERVAL
)
1726 err
= get_set_decompose(cache_set
, set
);
1728 list_expr_sort(&ctx
->set
->init
->expressions
);
1730 nftnl_set_free(nls
);
1731 nftnl_set_free(nls_out
);
1737 void netlink_dump_obj(struct nftnl_obj
*nln
, struct netlink_ctx
*ctx
)
1739 FILE *fp
= ctx
->nft
->output
.output_fp
;
1741 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
1744 nftnl_obj_fprintf(fp
, nln
, 0, 0);
1748 static int obj_parse_udata_cb(const struct nftnl_udata
*attr
, void *data
)
1750 unsigned char *value
= nftnl_udata_get(attr
);
1751 uint8_t type
= nftnl_udata_type(attr
);
1752 const struct nftnl_udata
**tb
= data
;
1753 uint8_t len
= nftnl_udata_len(attr
);
1756 case NFTNL_UDATA_OBJ_COMMENT
:
1757 if (value
[len
- 1] != '\0')
1767 struct obj
*netlink_delinearize_obj(struct netlink_ctx
*ctx
,
1768 struct nftnl_obj
*nlo
)
1770 const struct nftnl_udata
*ud
[NFTNL_UDATA_OBJ_MAX
+ 1] = {};
1776 obj
= obj_alloc(&netlink_location
);
1777 obj
->handle
.family
= nftnl_obj_get_u32(nlo
, NFTNL_OBJ_FAMILY
);
1778 obj
->handle
.table
.name
=
1779 xstrdup(nftnl_obj_get_str(nlo
, NFTNL_OBJ_TABLE
));
1780 obj
->handle
.obj
.name
=
1781 xstrdup(nftnl_obj_get_str(nlo
, NFTNL_OBJ_NAME
));
1782 obj
->handle
.handle
.id
=
1783 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_HANDLE
);
1784 if (nftnl_obj_is_set(nlo
, NFTNL_OBJ_USERDATA
)) {
1785 udata
= nftnl_obj_get_data(nlo
, NFTNL_OBJ_USERDATA
, &ulen
);
1786 if (nftnl_udata_parse(udata
, ulen
, obj_parse_udata_cb
, ud
) < 0) {
1787 netlink_io_error(ctx
, NULL
, "Cannot parse userdata");
1791 if (ud
[NFTNL_UDATA_OBJ_COMMENT
])
1792 obj
->comment
= xstrdup(nftnl_udata_get(ud
[NFTNL_UDATA_OBJ_COMMENT
]));
1795 type
= nftnl_obj_get_u32(nlo
, NFTNL_OBJ_TYPE
);
1797 case NFT_OBJECT_COUNTER
:
1798 obj
->counter
.packets
=
1799 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_CTR_PKTS
);
1800 obj
->counter
.bytes
=
1801 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_CTR_BYTES
);
1803 case NFT_OBJECT_QUOTA
:
1805 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_QUOTA_BYTES
);
1807 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_QUOTA_CONSUMED
);
1809 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_QUOTA_FLAGS
);
1811 case NFT_OBJECT_SECMARK
:
1812 snprintf(obj
->secmark
.ctx
, sizeof(obj
->secmark
.ctx
), "%s",
1813 nftnl_obj_get_str(nlo
, NFTNL_OBJ_SECMARK_CTX
));
1815 case NFT_OBJECT_CT_HELPER
:
1816 snprintf(obj
->ct_helper
.name
, sizeof(obj
->ct_helper
.name
), "%s",
1817 nftnl_obj_get_str(nlo
, NFTNL_OBJ_CT_HELPER_NAME
));
1818 obj
->ct_helper
.l3proto
= nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_HELPER_L3PROTO
);
1819 obj
->ct_helper
.l4proto
= nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_HELPER_L4PROTO
);
1821 case NFT_OBJECT_CT_TIMEOUT
:
1822 init_list_head(&obj
->ct_timeout
.timeout_list
);
1823 obj
->ct_timeout
.l3proto
= nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_TIMEOUT_L3PROTO
);
1824 obj
->ct_timeout
.l4proto
= nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_TIMEOUT_L4PROTO
);
1825 if (nftnl_obj_is_set(nlo
, NFTNL_OBJ_CT_TIMEOUT_ARRAY
))
1826 memcpy(obj
->ct_timeout
.timeout
,
1827 nftnl_obj_get(nlo
, NFTNL_OBJ_CT_TIMEOUT_ARRAY
),
1828 NFTNL_CTTIMEOUT_ARRAY_MAX
* sizeof(uint32_t));
1830 case NFT_OBJECT_LIMIT
:
1832 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_LIMIT_RATE
);
1834 nftnl_obj_get_u64(nlo
, NFTNL_OBJ_LIMIT_UNIT
);
1836 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_LIMIT_BURST
);
1838 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_LIMIT_TYPE
);
1840 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_LIMIT_FLAGS
);
1842 case NFT_OBJECT_CT_EXPECT
:
1843 obj
->ct_expect
.l3proto
=
1844 nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_EXPECT_L3PROTO
);
1845 obj
->ct_expect
.l4proto
=
1846 nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_EXPECT_L4PROTO
);
1847 obj
->ct_expect
.dport
=
1848 nftnl_obj_get_u16(nlo
, NFTNL_OBJ_CT_EXPECT_DPORT
);
1849 obj
->ct_expect
.timeout
=
1850 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_CT_EXPECT_TIMEOUT
);
1851 obj
->ct_expect
.size
=
1852 nftnl_obj_get_u8(nlo
, NFTNL_OBJ_CT_EXPECT_SIZE
);
1854 case NFT_OBJECT_SYNPROXY
:
1856 nftnl_obj_get_u16(nlo
, NFTNL_OBJ_SYNPROXY_MSS
);
1857 obj
->synproxy
.wscale
=
1858 nftnl_obj_get_u8(nlo
, NFTNL_OBJ_SYNPROXY_WSCALE
);
1859 obj
->synproxy
.flags
=
1860 nftnl_obj_get_u32(nlo
, NFTNL_OBJ_SYNPROXY_FLAGS
);
1863 netlink_io_error(ctx
, NULL
, "Unknown object type %u", type
);
1872 void netlink_dump_flowtable(struct nftnl_flowtable
*flo
,
1873 struct netlink_ctx
*ctx
)
1875 FILE *fp
= ctx
->nft
->output
.output_fp
;
1877 if (!(ctx
->nft
->debug_mask
& NFT_DEBUG_NETLINK
) || !fp
)
1880 nftnl_flowtable_fprintf(fp
, flo
, 0, 0);
1885 netlink_delinearize_flowtable(struct netlink_ctx
*ctx
,
1886 struct nftnl_flowtable
*nlo
)
1888 struct flowtable
*flowtable
;
1889 const char * const *dev_array
;
1890 int len
= 0, i
, priority
;
1892 flowtable
= flowtable_alloc(&netlink_location
);
1893 flowtable
->handle
.family
=
1894 nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_FAMILY
);
1895 flowtable
->handle
.table
.name
=
1896 xstrdup(nftnl_flowtable_get_str(nlo
, NFTNL_FLOWTABLE_TABLE
));
1897 flowtable
->handle
.flowtable
.name
=
1898 xstrdup(nftnl_flowtable_get_str(nlo
, NFTNL_FLOWTABLE_NAME
));
1899 flowtable
->handle
.handle
.id
=
1900 nftnl_flowtable_get_u64(nlo
, NFTNL_FLOWTABLE_HANDLE
);
1901 if (nftnl_flowtable_is_set(nlo
, NFTNL_FLOWTABLE_FLAGS
))
1902 flowtable
->flags
= nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_FLAGS
);
1903 dev_array
= nftnl_flowtable_get(nlo
, NFTNL_FLOWTABLE_DEVICES
);
1904 while (dev_array
&& dev_array
[len
])
1908 flowtable
->dev_array
= xmalloc(len
* sizeof(char *));
1909 for (i
= 0; i
< len
; i
++)
1910 flowtable
->dev_array
[i
] = xstrdup(dev_array
[i
]);
1912 flowtable
->dev_array_len
= len
;
1914 if (flowtable
->dev_array_len
) {
1915 qsort(flowtable
->dev_array
, flowtable
->dev_array_len
,
1916 sizeof(char *), qsort_device_cmp
);
1919 if (nftnl_flowtable_is_set(nlo
, NFTNL_FLOWTABLE_PRIO
)) {
1920 priority
= nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_PRIO
);
1921 flowtable
->priority
.expr
=
1922 constant_expr_alloc(&netlink_location
,
1924 BYTEORDER_HOST_ENDIAN
,
1929 flowtable
->hook
.num
=
1930 nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_HOOKNUM
);
1932 nftnl_flowtable_get_u32(nlo
, NFTNL_FLOWTABLE_FLAGS
);
1937 static int list_flowtable_cb(struct nftnl_flowtable
*nls
, void *arg
)
1939 struct netlink_ctx
*ctx
= arg
;
1940 struct flowtable
*flowtable
;
1942 flowtable
= netlink_delinearize_flowtable(ctx
, nls
);
1943 if (flowtable
== NULL
)
1945 list_add_tail(&flowtable
->list
, &ctx
->list
);
1949 int netlink_list_flowtables(struct netlink_ctx
*ctx
, const struct handle
*h
)
1951 struct nftnl_flowtable_list
*flowtable_cache
;
1954 flowtable_cache
= mnl_nft_flowtable_dump(ctx
, h
->family
,
1955 h
->table
.name
, NULL
);
1956 if (flowtable_cache
== NULL
) {
1963 err
= nftnl_flowtable_list_foreach(flowtable_cache
, list_flowtable_cb
, ctx
);
1964 nftnl_flowtable_list_free(flowtable_cache
);
1968 static void trace_print_hdr(const struct nftnl_trace
*nlt
,
1969 struct output_ctx
*octx
)
1971 nft_print(octx
, "trace id %08x %s ",
1972 nftnl_trace_get_u32(nlt
, NFTNL_TRACE_ID
),
1973 family2str(nftnl_trace_get_u32(nlt
, NFTNL_TRACE_FAMILY
)));
1974 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_TABLE
))
1975 nft_print(octx
, "%s ",
1976 nftnl_trace_get_str(nlt
, NFTNL_TRACE_TABLE
));
1977 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_CHAIN
))
1978 nft_print(octx
, "%s ",
1979 nftnl_trace_get_str(nlt
, NFTNL_TRACE_CHAIN
));
1982 static void trace_print_expr(const struct nftnl_trace
*nlt
, unsigned int attr
,
1983 struct expr
*lhs
, struct output_ctx
*octx
)
1985 struct expr
*rhs
, *rel
;
1989 data
= nftnl_trace_get_data(nlt
, attr
, &len
);
1990 rhs
= constant_expr_alloc(&netlink_location
,
1991 lhs
->dtype
, lhs
->byteorder
,
1992 len
* BITS_PER_BYTE
, data
);
1993 rel
= relational_expr_alloc(&netlink_location
, OP_EQ
, lhs
, rhs
);
1995 expr_print(rel
, octx
);
1996 nft_print(octx
, " ");
2000 static void trace_print_verdict(const struct nftnl_trace
*nlt
,
2001 struct output_ctx
*octx
)
2003 struct expr
*chain_expr
= NULL
;
2004 const char *chain
= NULL
;
2005 unsigned int verdict
;
2008 verdict
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_VERDICT
);
2009 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_JUMP_TARGET
)) {
2010 chain
= xstrdup(nftnl_trace_get_str(nlt
, NFTNL_TRACE_JUMP_TARGET
));
2011 chain_expr
= constant_expr_alloc(&netlink_location
,
2013 BYTEORDER_HOST_ENDIAN
,
2014 strlen(chain
) * BITS_PER_BYTE
,
2017 expr
= verdict_expr_alloc(&netlink_location
, verdict
, chain_expr
);
2019 nft_print(octx
, "verdict ");
2020 expr_print(expr
, octx
);
2024 static void trace_print_policy(const struct nftnl_trace
*nlt
,
2025 struct output_ctx
*octx
)
2027 unsigned int policy
;
2030 policy
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_POLICY
);
2032 expr
= verdict_expr_alloc(&netlink_location
, policy
, NULL
);
2034 nft_print(octx
, "policy ");
2035 expr_print(expr
, octx
);
2039 static struct rule
*trace_lookup_rule(const struct nftnl_trace
*nlt
,
2040 uint64_t rule_handle
,
2041 struct nft_cache
*cache
)
2043 struct chain
*chain
;
2044 struct table
*table
;
2047 h
.family
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_FAMILY
);
2048 h
.table
.name
= nftnl_trace_get_str(nlt
, NFTNL_TRACE_TABLE
);
2049 h
.chain
.name
= nftnl_trace_get_str(nlt
, NFTNL_TRACE_CHAIN
);
2054 table
= table_cache_find(&cache
->table_cache
, h
.table
.name
, h
.family
);
2058 chain
= chain_cache_find(table
, h
.chain
.name
);
2062 return rule_lookup(chain
, rule_handle
);
2065 static void trace_print_rule(const struct nftnl_trace
*nlt
,
2066 struct output_ctx
*octx
, struct nft_cache
*cache
)
2068 uint64_t rule_handle
;
2071 rule_handle
= nftnl_trace_get_u64(nlt
, NFTNL_TRACE_RULE_HANDLE
);
2072 rule
= trace_lookup_rule(nlt
, rule_handle
, cache
);
2074 trace_print_hdr(nlt
, octx
);
2077 nft_print(octx
, "rule ");
2078 rule_print(rule
, octx
);
2080 nft_print(octx
, "unknown rule handle %" PRIu64
, rule_handle
);
2083 nft_print(octx
, " (");
2084 trace_print_verdict(nlt
, octx
);
2085 nft_print(octx
, ")\n");
2088 static void trace_gen_stmts(struct list_head
*stmts
,
2089 struct proto_ctx
*ctx
, struct payload_dep_ctx
*pctx
,
2090 const struct nftnl_trace
*nlt
, unsigned int attr
,
2091 enum proto_bases base
)
2093 struct list_head unordered
= LIST_HEAD_INIT(unordered
);
2094 struct list_head list
;
2095 struct expr
*rel
, *lhs
, *rhs
, *tmp
, *nexpr
;
2097 const struct proto_desc
*desc
;
2102 if (!nftnl_trace_is_set(nlt
, attr
))
2104 hdr
= nftnl_trace_get_data(nlt
, attr
, &hlen
);
2106 lhs
= payload_expr_alloc(&netlink_location
, NULL
, 0);
2107 payload_init_raw(lhs
, base
, 0, hlen
* BITS_PER_BYTE
);
2108 rhs
= constant_expr_alloc(&netlink_location
,
2109 &invalid_type
, BYTEORDER_INVALID
,
2110 hlen
* BITS_PER_BYTE
, hdr
);
2113 init_list_head(&list
);
2114 payload_expr_expand(&list
, lhs
, ctx
);
2118 list_for_each_entry_safe(lhs
, nexpr
, &list
, list
) {
2119 if (desc
&& desc
!= ctx
->protocol
[base
].desc
) {
2120 /* Chained protocols */
2121 lhs
->payload
.offset
= 0;
2122 if (ctx
->protocol
[base
].desc
== NULL
)
2127 tmp
= constant_expr_splice(rhs
, lhs
->len
);
2128 expr_set_type(tmp
, lhs
->dtype
, lhs
->byteorder
);
2129 if (tmp
->byteorder
== BYTEORDER_HOST_ENDIAN
)
2130 mpz_switch_byteorder(tmp
->value
, tmp
->len
/ BITS_PER_BYTE
);
2132 /* Skip unknown and filtered expressions */
2133 desc
= lhs
->payload
.desc
;
2134 if (lhs
->dtype
== &invalid_type
||
2135 lhs
->payload
.tmpl
== &proto_unknown_template
||
2136 desc
->checksum_key
== payload_hdr_field(lhs
) ||
2137 desc
->format
.filter
& (1 << payload_hdr_field(lhs
))) {
2143 rel
= relational_expr_alloc(&lhs
->location
, OP_EQ
, lhs
, tmp
);
2144 stmt
= expr_stmt_alloc(&rel
->location
, rel
);
2145 list_add_tail(&stmt
->list
, &unordered
);
2147 desc
= ctx
->protocol
[base
].desc
;
2148 relational_expr_pctx_update(ctx
, rel
);
2155 list_for_each_entry(stmt
, &unordered
, list
) {
2156 enum proto_bases b
= base
;
2161 /* Move statements to result list in defined order */
2162 desc
= lhs
->payload
.desc
;
2163 if (desc
->format
.order
[n
] &&
2164 desc
->format
.order
[n
] != payload_hdr_field(lhs
))
2167 list_move_tail(&stmt
->list
, stmts
);
2170 if (payload_is_stacked(desc
, rel
))
2173 /* Don't strip 'icmp type' from payload dump. */
2174 if (pctx
->icmp_type
== 0)
2175 payload_dependency_kill(pctx
, lhs
, ctx
->family
);
2176 if (lhs
->flags
& EXPR_F_PROTOCOL
)
2177 payload_dependency_store(pctx
, stmt
, b
);
2183 static void trace_print_packet(const struct nftnl_trace
*nlt
,
2184 struct output_ctx
*octx
)
2186 struct list_head stmts
= LIST_HEAD_INIT(stmts
);
2187 const struct proto_desc
*ll_desc
;
2188 struct payload_dep_ctx pctx
= {};
2189 struct proto_ctx ctx
;
2192 struct stmt
*stmt
, *next
;
2194 trace_print_hdr(nlt
, octx
);
2196 nft_print(octx
, "packet: ");
2197 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_IIF
))
2198 trace_print_expr(nlt
, NFTNL_TRACE_IIF
,
2199 meta_expr_alloc(&netlink_location
,
2200 NFT_META_IIF
), octx
);
2201 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_OIF
))
2202 trace_print_expr(nlt
, NFTNL_TRACE_OIF
,
2203 meta_expr_alloc(&netlink_location
,
2204 NFT_META_OIF
), octx
);
2206 proto_ctx_init(&ctx
, nftnl_trace_get_u32(nlt
, NFTNL_TRACE_FAMILY
), 0, false);
2207 ll_desc
= ctx
.protocol
[PROTO_BASE_LL_HDR
].desc
;
2208 if ((ll_desc
== &proto_inet
|| ll_desc
== &proto_netdev
) &&
2209 nftnl_trace_is_set(nlt
, NFTNL_TRACE_NFPROTO
)) {
2210 nfproto
= nftnl_trace_get_u32(nlt
, NFTNL_TRACE_NFPROTO
);
2212 proto_ctx_update(&ctx
, PROTO_BASE_LL_HDR
, &netlink_location
, NULL
);
2213 proto_ctx_update(&ctx
, PROTO_BASE_NETWORK_HDR
, &netlink_location
,
2214 proto_find_upper(ll_desc
, nfproto
));
2216 if (ctx
.protocol
[PROTO_BASE_LL_HDR
].desc
== NULL
&&
2217 nftnl_trace_is_set(nlt
, NFTNL_TRACE_IIFTYPE
)) {
2218 dev_type
= nftnl_trace_get_u16(nlt
, NFTNL_TRACE_IIFTYPE
);
2219 proto_ctx_update(&ctx
, PROTO_BASE_LL_HDR
, &netlink_location
,
2220 proto_dev_desc(dev_type
));
2223 trace_gen_stmts(&stmts
, &ctx
, &pctx
, nlt
, NFTNL_TRACE_LL_HEADER
,
2225 trace_gen_stmts(&stmts
, &ctx
, &pctx
, nlt
, NFTNL_TRACE_NETWORK_HEADER
,
2226 PROTO_BASE_NETWORK_HDR
);
2227 trace_gen_stmts(&stmts
, &ctx
, &pctx
, nlt
, NFTNL_TRACE_TRANSPORT_HEADER
,
2228 PROTO_BASE_TRANSPORT_HDR
);
2230 list_for_each_entry_safe(stmt
, next
, &stmts
, list
) {
2231 stmt_print(stmt
, octx
);
2232 nft_print(octx
, " ");
2235 nft_print(octx
, "\n");
2238 int netlink_events_trace_cb(const struct nlmsghdr
*nlh
, int type
,
2239 struct netlink_mon_handler
*monh
)
2241 struct nftnl_trace
*nlt
;
2243 assert(type
== NFT_MSG_TRACE
);
2245 nlt
= nftnl_trace_alloc();
2247 memory_allocation_error();
2249 if (nftnl_trace_nlmsg_parse(nlh
, nlt
) < 0)
2250 netlink_abi_error();
2252 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_LL_HEADER
) ||
2253 nftnl_trace_is_set(nlt
, NFTNL_TRACE_NETWORK_HEADER
))
2254 trace_print_packet(nlt
, &monh
->ctx
->nft
->output
);
2256 switch (nftnl_trace_get_u32(nlt
, NFTNL_TRACE_TYPE
)) {
2257 case NFT_TRACETYPE_RULE
:
2258 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_RULE_HANDLE
))
2259 trace_print_rule(nlt
, &monh
->ctx
->nft
->output
,
2260 &monh
->ctx
->nft
->cache
);
2262 case NFT_TRACETYPE_POLICY
:
2263 trace_print_hdr(nlt
, &monh
->ctx
->nft
->output
);
2265 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_POLICY
)) {
2266 trace_print_policy(nlt
, &monh
->ctx
->nft
->output
);
2267 nft_mon_print(monh
, " ");
2270 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_MARK
))
2271 trace_print_expr(nlt
, NFTNL_TRACE_MARK
,
2272 meta_expr_alloc(&netlink_location
,
2274 &monh
->ctx
->nft
->output
);
2275 nft_mon_print(monh
, "\n");
2277 case NFT_TRACETYPE_RETURN
:
2278 trace_print_hdr(nlt
, &monh
->ctx
->nft
->output
);
2280 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_VERDICT
)) {
2281 trace_print_verdict(nlt
, &monh
->ctx
->nft
->output
);
2282 nft_mon_print(monh
, " ");
2285 if (nftnl_trace_is_set(nlt
, NFTNL_TRACE_MARK
))
2286 trace_print_expr(nlt
, NFTNL_TRACE_MARK
,
2287 meta_expr_alloc(&netlink_location
,
2289 &monh
->ctx
->nft
->output
);
2290 nft_mon_print(monh
, "\n");
2294 nftnl_trace_free(nlt
);