]> git.ipfire.org Git - thirdparty/nftables.git/blame - src/netlink.c
datatype: fix leak and cleanup reference counting for struct datatype
[thirdparty/nftables.git] / src / netlink.c
CommitLineData
fac10ea7 1/*
a5dadd72 2 * Copyright (c) 2008-2012 Patrick McHardy <kaber@trash.net>
aae836a7 3 * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
fac10ea7
PM
4 *
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.
8 *
9 * Development of this code funded by Astaro AG (http://www.astaro.com/)
10 */
11
b4add075
TH
12#include <nft.h>
13
aae836a7 14#include <string.h>
aae836a7
PNA
15#include <errno.h>
16#include <libmnl/libmnl.h>
cb86c169
ABG
17#include <netinet/in.h>
18#include <arpa/inet.h>
bd9f3633 19#include <inttypes.h>
aae836a7 20
1c2c506d 21#include <libnftnl/table.h>
be5d9120 22#include <libnftnl/trace.h>
1c2c506d
PNA
23#include <libnftnl/chain.h>
24#include <libnftnl/expr.h>
4d38878b 25#include <libnftnl/object.h>
1c2c506d 26#include <libnftnl/set.h>
db0697ce 27#include <libnftnl/flowtable.h>
61f851be 28#include <libnftnl/udata.h>
2fa54d8a 29#include <libnftnl/ruleset.h>
f9563c0f 30#include <libnftnl/common.h>
6e48df53 31#include <libnftnl/udata.h>
f9563c0f 32#include <linux/netfilter/nfnetlink.h>
fac10ea7 33#include <linux/netfilter/nf_tables.h>
cb86c169 34#include <linux/netfilter.h>
fac10ea7
PM
35
36#include <nftables.h>
6e48df53 37#include <parser.h>
fac10ea7 38#include <netlink.h>
aae836a7 39#include <mnl.h>
fac10ea7 40#include <expression.h>
be5d9120 41#include <statement.h>
53fc2c7a 42#include <gmputil.h>
fac10ea7
PM
43#include <utils.h>
44#include <erec.h>
be5d9120 45#include <iface.h>
fac10ea7 46
2dc07bcd 47#define nft_mon_print(monh, ...) nft_print(&monh->ctx->nft->output, __VA_ARGS__)
2535ba70 48
a144995d
PM
49const struct input_descriptor indesc_netlink = {
50 .name = "netlink",
51 .type = INDESC_NETLINK,
52};
53
54const struct location netlink_location = {
55 .indesc = &indesc_netlink,
56};
57
52f169d3
AB
58void __noreturn __netlink_abi_error(const char *file, int line,
59 const char *reason)
f9563c0f
AB
60{
61 fprintf(stderr, "E: Contact urgently your Linux kernel vendor. "
52f169d3 62 "Netlink ABI is broken: %s:%d %s\n", file, line, reason);
5adbd76e 63 abort();
fac10ea7
PM
64}
65
a72315d2
PNA
66int netlink_io_error(struct netlink_ctx *ctx, const struct location *loc,
67 const char *fmt, ...)
fac10ea7
PM
68{
69 struct error_record *erec;
70 va_list ap;
71
72 if (loc == NULL)
a144995d 73 loc = &netlink_location;
fac10ea7
PM
74
75 va_start(ap, fmt);
76 erec = erec_vcreate(EREC_ERROR, loc, fmt, ap);
77 va_end(ap);
78 erec_queue(erec, ctx->msgs);
79 return -1;
80}
81
62812246
PNA
82void __noreturn __netlink_init_error(const char *filename, int line,
83 const char *reason)
1be55ff3 84{
62812246
PNA
85 fprintf(stderr, "%s:%d: Unable to initialize Netlink socket: %s\n",
86 filename, line, reason);
1be55ff3
AB
87 exit(NFT_EXIT_NONL);
88}
89
d6f06c30 90struct nftnl_expr *alloc_nft_expr(const char *name)
fac10ea7 91{
d6f06c30 92 struct nftnl_expr *nle;
fac10ea7 93
d6f06c30 94 nle = nftnl_expr_alloc(name);
aae836a7 95 if (nle == NULL)
fac10ea7 96 memory_allocation_error();
e7b568e1 97
fac10ea7
PM
98 return nle;
99}
80669876
PNA
100static void netlink_gen_key(const struct expr *expr,
101 struct nft_data_linearize *data);
039a1494
PNA
102static void __netlink_gen_data(const struct expr *expr,
103 struct nft_data_linearize *data, bool expand);
66746e7d 104
b4b234f5
PNA
105struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
106 const struct expr *expr)
ebfd6822 107{
8ac2f3b2 108 const struct expr *elem, *data;
d6f06c30 109 struct nftnl_set_elem *nlse;
aae836a7 110 struct nft_data_linearize nld;
6089630f 111 struct nftnl_udata_buf *udbuf = NULL;
419d1968 112 uint32_t flags = 0;
e6d1d0d6
PNA
113 int num_exprs = 0;
114 struct stmt *stmt;
8ac2f3b2 115 struct expr *key;
ebfd6822 116
d6f06c30 117 nlse = nftnl_set_elem_alloc();
ebfd6822
PM
118 if (nlse == NULL)
119 memory_allocation_error();
120
52532335 121 data = NULL;
72931553 122 if (expr->etype == EXPR_MAPPING) {
52532335
PM
123 elem = expr->left;
124 if (!(expr->flags & EXPR_F_INTERVAL_END))
125 data = expr->right;
aae836a7 126 } else {
52532335
PM
127 elem = expr;
128 }
3d6cf7f3
FW
129 if (elem->etype != EXPR_SET_ELEM)
130 BUG("Unexpected expression type: got %d\n", elem->etype);
131
52532335
PM
132 key = elem->key;
133
419d1968
PNA
134 switch (key->etype) {
135 case EXPR_SET_ELEM_CATCHALL:
136 break;
137 default:
b0c6deab
PNA
138 if (set->set_flags & NFT_SET_INTERVAL &&
139 key->etype == EXPR_CONCAT && key->field_count > 1) {
508f3a27 140 key->flags |= EXPR_F_INTERVAL;
80669876 141 netlink_gen_key(key, &nld);
508f3a27
PNA
142 key->flags &= ~EXPR_F_INTERVAL;
143
144 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
145
419d1968 146 key->flags |= EXPR_F_INTERVAL_END;
80669876 147 netlink_gen_key(key, &nld);
419d1968
PNA
148 key->flags &= ~EXPR_F_INTERVAL_END;
149
150 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY_END,
151 &nld.value, nld.len);
508f3a27 152 } else {
80669876 153 netlink_gen_key(key, &nld);
508f3a27 154 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
419d1968
PNA
155 }
156 break;
8ac2f3b2
SB
157 }
158
7b524897 159 if (elem->timeout)
d6f06c30 160 nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_TIMEOUT,
947b4fe1 161 elem->timeout);
24f33c71
LGL
162 if (elem->expiration)
163 nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_EXPIRATION,
164 elem->expiration);
e6d1d0d6
PNA
165 list_for_each_entry(stmt, &elem->stmt_list, list)
166 num_exprs++;
167
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);
172 }
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));
177 }
178 }
6089630f 179 if (elem->comment || expr->elem_flags) {
61f851be
CFG
180 udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
181 if (!udbuf)
182 memory_allocation_error();
6089630f
PS
183 }
184 if (elem->comment) {
10da57e3 185 if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_SET_ELEM_COMMENT,
61f851be
CFG
186 elem->comment))
187 memory_allocation_error();
6089630f
PS
188 }
189 if (expr->elem_flags) {
10da57e3 190 if (!nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_ELEM_FLAGS,
6089630f
PS
191 expr->elem_flags))
192 memory_allocation_error();
193 }
194 if (udbuf) {
d6f06c30 195 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_USERDATA,
61f851be
CFG
196 nftnl_udata_buf_data(udbuf),
197 nftnl_udata_buf_len(udbuf));
198 nftnl_udata_buf_free(udbuf);
199 }
0fd53234 200 if (set_is_datamap(set->set_flags) && data != NULL) {
66746e7d 201 __netlink_gen_data(data, &nld, !(data->flags & EXPR_F_SINGLETON));
72931553 202 switch (data->etype) {
a54d7b05 203 case EXPR_VERDICT:
d6f06c30 204 nftnl_set_elem_set_u32(nlse, NFTNL_SET_ELEM_VERDICT,
947b4fe1 205 data->verdict);
52532335 206 if (data->chain != NULL)
d6f06c30 207 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_CHAIN,
947b4fe1 208 nld.chain, strlen(nld.chain));
a54d7b05 209 break;
6f0d90ec
FW
210 case EXPR_CONCAT:
211 assert(nld.len > 0);
212 /* fallthrough */
a54d7b05 213 case EXPR_VALUE:
9599d9d2
PNA
214 case EXPR_RANGE:
215 case EXPR_PREFIX:
d6f06c30 216 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_DATA,
947b4fe1 217 nld.value, nld.len);
a54d7b05
PNA
218 break;
219 default:
220 BUG("unexpected set element expression\n");
221 break;
aae836a7 222 }
ebfd6822 223 }
0fd53234 224 if (set_is_objmap(set->set_flags) && data != NULL) {
deaf962e
PNA
225 netlink_gen_data(data, &nld);
226 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_OBJREF,
227 nld.value, nld.len);
228 }
ebfd6822 229
e7b568e1 230 if (expr->flags & EXPR_F_INTERVAL_END)
419d1968
PNA
231 flags |= NFT_SET_ELEM_INTERVAL_END;
232 if (key->etype == EXPR_SET_ELEM_CATCHALL)
233 flags |= NFT_SET_ELEM_CATCHALL;
234
235 if (flags)
236 nftnl_set_elem_set_u32(nlse, NFTNL_SET_ELEM_FLAGS, flags);
ebfd6822
PM
237
238 return nlse;
239}
240
aae836a7
PNA
241void netlink_gen_raw_data(const mpz_t value, enum byteorder byteorder,
242 unsigned int len, struct nft_data_linearize *data)
fac10ea7 243{
fac10ea7 244 assert(len > 0);
aae836a7
PNA
245 mpz_export_data(data->value, value, byteorder, len);
246 data->len = len;
fac10ea7
PM
247}
248
8ac2f3b2
SB
249static int netlink_export_pad(unsigned char *data, const mpz_t v,
250 const struct expr *i)
251{
252 mpz_export_data(data, v, i->byteorder,
253 div_round_up(i->len, BITS_PER_BYTE));
254
255 return netlink_padded_len(i->len) / BITS_PER_BYTE;
256}
257
9582a075
PNA
258static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
259 unsigned char *data)
8ac2f3b2 260{
1017d323
PNA
261 struct expr *expr;
262
8ac2f3b2
SB
263 switch (i->etype) {
264 case EXPR_RANGE:
508f3a27 265 if (flags & EXPR_F_INTERVAL_END)
1017d323
PNA
266 expr = i->right;
267 else
268 expr = i->left;
269
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);
273
274 i = expr;
8ac2f3b2
SB
275 break;
276 case EXPR_PREFIX:
508f3a27 277 if (flags & EXPR_F_INTERVAL_END) {
8ac2f3b2
SB
278 int count;
279 mpz_t v;
280
281 mpz_init_bitmask(v, i->len - i->prefix_len);
806ab081
FW
282
283 if (i->byteorder == BYTEORDER_HOST_ENDIAN)
284 mpz_switch_byteorder(v, i->len / BITS_PER_BYTE);
285
8ac2f3b2
SB
286 mpz_add(v, i->prefix->value, v);
287 count = netlink_export_pad(data, v, i);
288 mpz_clear(v);
289 return count;
290 }
291 return netlink_export_pad(data, i->prefix->value, i);
292 case EXPR_VALUE:
508f3a27
PNA
293 /* Switch byteorder only once for singleton values when the set
294 * contains concatenation of intervals.
295 */
296 if (!(flags & EXPR_F_INTERVAL))
297 break;
298
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);
8ac2f3b2
SB
303 break;
304 default:
305 BUG("invalid expression type '%s' in set", expr_ops(i)->name);
306 }
307
308 return netlink_export_pad(data, i->value, i);
309}
310
9582a075
PNA
311static void netlink_gen_concat_key(const struct expr *expr,
312 struct nft_data_linearize *nld)
53fc2c7a 313{
8ac2f3b2 314 unsigned int len = expr->len / BITS_PER_BYTE, offset = 0;
8ac2f3b2 315 unsigned char data[len];
53fc2c7a 316 const struct expr *i;
aae836a7 317
8ac2f3b2
SB
318 memset(data, 0, len);
319
320 list_for_each_entry(i, &expr->expressions, list)
9582a075 321 offset += __netlink_gen_concat_key(expr->flags, i, data + offset);
8ac2f3b2
SB
322
323 memcpy(nld->value, data, len);
324 nld->len = len;
53fc2c7a
PM
325}
326
9582a075
PNA
327static int __netlink_gen_concat_data(int end, const struct expr *i,
328 unsigned char *data)
329{
330 switch (i->etype) {
331 case EXPR_RANGE:
332 i = end ? i->right : i->left;
333 break;
334 case EXPR_PREFIX:
335 if (end) {
336 int count;
337 mpz_t v;
338
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);
342 mpz_clear(v);
343 return count;
344 }
345 return netlink_export_pad(data, i->prefix->value, i);
346 case EXPR_VALUE:
347 break;
348 default:
349 BUG("invalid expression type '%s' in set", expr_ops(i)->name);
350 }
351
352 return netlink_export_pad(data, i->value, i);
353}
354
66746e7d
PNA
355static void __netlink_gen_concat_expand(const struct expr *expr,
356 struct nft_data_linearize *nld)
357{
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;
361
362 memset(data, 0, len);
363
364 list_for_each_entry(i, &expr->expressions, list)
9582a075
PNA
365 offset += __netlink_gen_concat_data(false, i, data + offset);
366
367 list_for_each_entry(i, &expr->expressions, list)
368 offset += __netlink_gen_concat_data(true, i, data + offset);
369
370 memcpy(nld->value, data, len);
371 nld->len = len;
372}
373
374static void __netlink_gen_concat(const struct expr *expr,
375 struct nft_data_linearize *nld)
376{
377 unsigned int len = expr->len / BITS_PER_BYTE, offset = 0;
378 unsigned char data[len];
379 const struct expr *i;
380
381 memset(data, 0, len);
66746e7d
PNA
382
383 list_for_each_entry(i, &expr->expressions, list)
9582a075 384 offset += __netlink_gen_concat_data(expr->flags, i, data + offset);
66746e7d
PNA
385
386 memcpy(nld->value, data, len);
387 nld->len = len;
388}
389
390static void netlink_gen_concat_data(const struct expr *expr,
9582a075 391 struct nft_data_linearize *nld, bool expand)
66746e7d
PNA
392{
393 if (expand)
394 __netlink_gen_concat_expand(expr, nld);
395 else
396 __netlink_gen_concat(expr, nld);
397}
398
aae836a7
PNA
399static void netlink_gen_constant_data(const struct expr *expr,
400 struct nft_data_linearize *data)
53fc2c7a 401{
72931553 402 assert(expr->etype == EXPR_VALUE);
aae836a7
PNA
403 netlink_gen_raw_data(expr->value, expr->byteorder,
404 div_round_up(expr->len, BITS_PER_BYTE), data);
53fc2c7a
PM
405}
406
c330152b
PNA
407static void netlink_gen_chain(const struct expr *expr,
408 struct nft_data_linearize *data)
53fc2c7a 409{
f1e8a129 410 char chain[NFT_CHAIN_MAXNAMELEN];
fb6d826a 411 unsigned int len;
f1e8a129 412
c330152b 413 len = expr->chain->len / BITS_PER_BYTE;
53fc2c7a 414
c330152b
PNA
415 if (!len)
416 BUG("chain length is 0");
417
418 if (len > sizeof(chain))
419 BUG("chain is too large (%u, %u max)",
420 len, (unsigned int)sizeof(chain));
421
422 memset(chain, 0, sizeof(chain));
fb6d826a 423
c330152b
PNA
424 mpz_export_data(chain, expr->chain->value,
425 BYTEORDER_HOST_ENDIAN, len);
426 snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", chain);
427}
fb6d826a 428
c330152b
PNA
429static void netlink_gen_verdict(const struct expr *expr,
430 struct nft_data_linearize *data)
431{
fb6d826a 432
c330152b 433 data->verdict = expr->verdict;
fb6d826a 434
c330152b
PNA
435 switch (expr->verdict) {
436 case NFT_JUMP:
437 case NFT_GOTO:
438 if (expr->chain)
439 netlink_gen_chain(expr, data);
440 else
441 data->chain_id = expr->chain_id;
53fc2c7a
PM
442 break;
443 }
53fc2c7a
PM
444}
445
9599d9d2
PNA
446static void netlink_gen_range(const struct expr *expr,
447 struct nft_data_linearize *nld)
448{
449 unsigned int len = div_round_up(expr->left->len, BITS_PER_BYTE) * 2;
450 unsigned char data[len];
451 unsigned int offset = 0;
452
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);
457 nld->len = len;
458}
459
460static void netlink_gen_prefix(const struct expr *expr,
461 struct nft_data_linearize *nld)
462{
463 unsigned int len = div_round_up(expr->len, BITS_PER_BYTE) * 2;
464 unsigned char data[len];
465 int offset;
466 mpz_t v;
467
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);
472 mpz_clear(v);
473
474 memcpy(nld->value, data, len);
475 nld->len = len;
476}
477
80669876
PNA
478static void netlink_gen_key(const struct expr *expr,
479 struct nft_data_linearize *data)
480{
481 switch (expr->etype) {
482 case EXPR_VALUE:
483 return netlink_gen_constant_data(expr, data);
484 case EXPR_CONCAT:
9582a075 485 return netlink_gen_concat_key(expr, data);
80669876
PNA
486 case EXPR_RANGE:
487 return netlink_gen_range(expr, data);
488 case EXPR_PREFIX:
489 return netlink_gen_prefix(expr, data);
490 default:
491 BUG("invalid data expression type %s\n", expr_name(expr));
492 }
493}
494
039a1494
PNA
495static void __netlink_gen_data(const struct expr *expr,
496 struct nft_data_linearize *data, bool expand)
53fc2c7a 497{
72931553 498 switch (expr->etype) {
53fc2c7a 499 case EXPR_VALUE:
aae836a7 500 return netlink_gen_constant_data(expr, data);
53fc2c7a 501 case EXPR_CONCAT:
66746e7d 502 return netlink_gen_concat_data(expr, data, expand);
53fc2c7a 503 case EXPR_VERDICT:
aae836a7 504 return netlink_gen_verdict(expr, data);
9599d9d2
PNA
505 case EXPR_RANGE:
506 return netlink_gen_range(expr, data);
507 case EXPR_PREFIX:
508 return netlink_gen_prefix(expr, data);
53fc2c7a 509 default:
68e76238 510 BUG("invalid data expression type %s\n", expr_name(expr));
53fc2c7a
PM
511 }
512}
513
66746e7d
PNA
514void netlink_gen_data(const struct expr *expr, struct nft_data_linearize *data)
515{
516 __netlink_gen_data(expr, data, false);
517}
518
53fc2c7a 519struct expr *netlink_alloc_value(const struct location *loc,
aae836a7 520 const struct nft_data_delinearize *nld)
53fc2c7a
PM
521{
522 return constant_expr_alloc(loc, &invalid_type, BYTEORDER_INVALID,
aae836a7 523 nld->len * BITS_PER_BYTE, nld->value);
53fc2c7a
PM
524}
525
526static struct expr *netlink_alloc_verdict(const struct location *loc,
aae836a7 527 const struct nft_data_delinearize *nld)
53fc2c7a 528{
f1e8a129 529 struct expr *chain;
53fc2c7a 530
aae836a7 531 switch (nld->verdict) {
53fc2c7a
PM
532 case NFT_JUMP:
533 case NFT_GOTO:
f1e8a129
FFM
534 chain = constant_expr_alloc(loc, &string_type,
535 BYTEORDER_HOST_ENDIAN,
142350f1
PNA
536 strlen(nld->chain) * BITS_PER_BYTE,
537 nld->chain);
53fc2c7a
PM
538 break;
539 default:
540 chain = NULL;
541 break;
542 }
543
aae836a7 544 return verdict_expr_alloc(loc, nld->verdict, chain);
53fc2c7a
PM
545}
546
547struct expr *netlink_alloc_data(const struct location *loc,
aae836a7 548 const struct nft_data_delinearize *nld,
53fc2c7a
PM
549 enum nft_registers dreg)
550{
551 switch (dreg) {
552 case NFT_REG_VERDICT:
553 return netlink_alloc_verdict(loc, nld);
554 default:
555 return netlink_alloc_value(loc, nld);
556 }
557}
558
2535ba70 559void netlink_dump_rule(const struct nftnl_rule *nlr, struct netlink_ctx *ctx)
fac10ea7 560{
2dc07bcd 561 FILE *fp = ctx->nft->output.output_fp;
7c1ccf81 562
2dc07bcd 563 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
fac10ea7 564 return;
fac10ea7 565
2535ba70
PS
566 nftnl_rule_fprintf(fp, nlr, 0, 0);
567 fprintf(fp, "\n");
fac10ea7
PM
568}
569
89122493
PS
570void netlink_dump_expr(const struct nftnl_expr *nle,
571 FILE *fp, unsigned int debug_mask)
fac10ea7 572{
6db6ec4d 573 if (!(debug_mask & NFT_DEBUG_NETLINK))
aae836a7 574 return;
fac10ea7 575
8dee5e43
PS
576 nftnl_expr_fprintf(fp, nle, 0, 0);
577 fprintf(fp, "\n");
fac10ea7
PM
578}
579
2535ba70 580void netlink_dump_chain(const struct nftnl_chain *nlc, struct netlink_ctx *ctx)
aae836a7 581{
2dc07bcd 582 FILE *fp = ctx->nft->output.output_fp;
aae836a7 583
2dc07bcd 584 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
aae836a7
PNA
585 return;
586
2535ba70
PS
587 nftnl_chain_fprintf(fp, nlc, 0, 0);
588 fprintf(fp, "\n");
aae836a7
PNA
589}
590
702ac2b7
JGG
591static int chain_parse_udata_cb(const struct nftnl_udata *attr, void *data)
592{
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);
597
598 switch (type) {
599 case NFTNL_UDATA_CHAIN_COMMENT:
600 if (value[len - 1] != '\0')
601 return -1;
602 break;
603 default:
604 return 0;
605 }
606 tb[type] = attr;
607 return 0;
608}
609
8161ea94
PNA
610static int qsort_device_cmp(const void *a, const void *b)
611{
612 const char **x = (const char **)a;
613 const char **y = (const char **)b;
614
615 return strcmp(*x, *y);
616}
617
fbcb888b
PNA
618struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
619 const struct nftnl_chain *nlc)
fac10ea7 620{
702ac2b7 621 const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {};
3fdc7541
PNA
622 int priority, policy, len = 0, i;
623 const char * const *dev_array;
fac10ea7 624 struct chain *chain;
702ac2b7
JGG
625 const char *udata;
626 uint32_t ulen;
7c1ccf81 627
4e7b7ddd 628 chain = chain_alloc();
aae836a7 629 chain->handle.family =
d6f06c30 630 nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FAMILY);
cf646426 631 chain->handle.table.name =
d6f06c30 632 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_TABLE));
4e7b7ddd
PNA
633 chain->handle.chain.name =
634 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_NAME));
5db9dc92 635 chain->handle.handle.id =
d6f06c30 636 nftnl_chain_get_u64(nlc, NFTNL_CHAIN_HANDLE);
d42bd56c
PNA
637 if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_FLAGS))
638 chain->flags = nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FLAGS);
2e27f246 639
d6f06c30
PNA
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)) {
673d82af 644 chain->hook.num =
d6f06c30 645 nftnl_chain_get_u32(nlc, NFTNL_CHAIN_HOOKNUM);
673d82af
PNA
646 chain->hook.name =
647 hooknum2str(chain->handle.family, chain->hook.num);
627c451b
FFM
648 priority = nftnl_chain_get_s32(nlc, NFTNL_CHAIN_PRIO);
649 chain->priority.expr =
650 constant_expr_alloc(&netlink_location,
651 &integer_type,
652 BYTEORDER_HOST_ENDIAN,
653 sizeof(int) * BITS_PER_BYTE,
654 &priority);
50087981 655 chain->type.str =
d6f06c30 656 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_TYPE));
dba4a9b4
FFM
657 policy = nftnl_chain_get_u32(nlc, NFTNL_CHAIN_POLICY);
658 chain->policy = constant_expr_alloc(&netlink_location,
659 &integer_type,
660 BYTEORDER_HOST_ENDIAN,
661 sizeof(int) * BITS_PER_BYTE,
662 &policy);
d6f06c30
PNA
663 nftnl_chain_get_u32(nlc, NFTNL_CHAIN_POLICY);
664 if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_DEV)) {
90d451ff 665 chain->dev_array = xmalloc(sizeof(char *) * 2);
3fdc7541
PNA
666 chain->dev_array_len = 1;
667 chain->dev_array[0] =
d6f06c30 668 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_DEV));
3fdc7541
PNA
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])
673 len++;
674
90d451ff 675 chain->dev_array = xmalloc((len + 1)* sizeof(char *));
3fdc7541
PNA
676 for (i = 0; i < len; i++)
677 chain->dev_array[i] = xstrdup(dev_array[i]);
678
679 chain->dev_array[i] = NULL;
680 chain->dev_array_len = len;
6c43069e 681 }
4318642b 682 chain->flags |= CHAIN_F_BASECHAIN;
8161ea94
PNA
683
684 if (chain->dev_array_len) {
685 qsort(chain->dev_array, chain->dev_array_len,
686 sizeof(char *), qsort_device_cmp);
687 }
2e27f246 688 }
aae836a7 689
702ac2b7
JGG
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");
04f7af9d 694 chain_free(chain);
702ac2b7
JGG
695 return NULL;
696 }
697 if (ud[NFTNL_UDATA_CHAIN_COMMENT])
698 chain->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_CHAIN_COMMENT]));
699 }
700
38756bcd
AB
701 return chain;
702}
703
c156232a
JGG
704static int table_parse_udata_cb(const struct nftnl_udata *attr, void *data)
705{
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);
710
711 switch (type) {
712 case NFTNL_UDATA_TABLE_COMMENT:
713 if (value[len - 1] != '\0')
714 return -1;
715 break;
716 default:
717 return 0;
718 }
719 tb[type] = attr;
720 return 0;
721}
722
fbcb888b
PNA
723struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
724 const struct nftnl_table *nlt)
aae836a7 725{
c156232a 726 const struct nftnl_udata *ud[NFTNL_UDATA_TABLE_MAX + 1] = {};
aae836a7 727 struct table *table;
c156232a
JGG
728 const char *udata;
729 uint32_t ulen;
aae836a7 730
fac10ea7 731 table = table_alloc();
947b4fe1 732 table->handle.family = nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY);
cf646426 733 table->handle.table.name = xstrdup(nftnl_table_get_str(nlt, NFTNL_TABLE_NAME));
947b4fe1 734 table->flags = nftnl_table_get_u32(nlt, NFTNL_TABLE_FLAGS);
0f830263 735 table->handle.handle.id = nftnl_table_get_u64(nlt, NFTNL_TABLE_HANDLE);
6d085b22 736 table->owner = nftnl_table_get_u32(nlt, NFTNL_TABLE_OWNER);
aae836a7 737
c156232a
JGG
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");
47640634 742 table_free(table);
c156232a
JGG
743 return NULL;
744 }
745 if (ud[NFTNL_UDATA_TABLE_COMMENT])
746 table->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_TABLE_COMMENT]));
747 }
748
af657c08
AB
749 return table;
750}
751
d6f06c30 752static int list_table_cb(struct nftnl_table *nlt, void *arg)
af657c08
AB
753{
754 struct netlink_ctx *ctx = arg;
dcb0a614 755 struct table *table;
af657c08 756
dcb0a614
PNA
757 table = netlink_delinearize_table(ctx, nlt);
758 list_add_tail(&table->list, &ctx->list);
af657c08 759
aae836a7 760 return 0;
fac10ea7
PM
761}
762
a37212f2
PS
763int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h,
764 const struct nft_cache_filter *filter)
fac10ea7 765{
d6f06c30 766 struct nftnl_table_list *table_cache;
a37212f2
PS
767 uint32_t family = h->family;
768 const char *table = NULL;
fac10ea7 769
a37212f2
PS
770 if (filter) {
771 family = filter->list.family;
772 table = filter->list.table;
773 }
774
775 table_cache = mnl_nft_table_dump(ctx, family, table);
09f81768
PNA
776 if (table_cache == NULL) {
777 if (errno == EINTR)
778 return -1;
779
3cfb9e4b 780 return -1;
09f81768 781 }
fac10ea7 782
0f830263 783 ctx->data = h;
d6f06c30
PNA
784 nftnl_table_list_foreach(table_cache, list_table_cb, ctx);
785 nftnl_table_list_free(table_cache);
fac10ea7
PM
786 return 0;
787}
788
d6ed28a3 789enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype)
ebfd6822
PM
790{
791 switch (dtype->type) {
792 case TYPE_VERDICT:
793 return NFT_DATA_VERDICT;
794 default:
795 return dtype->type;
796 }
797}
798
343a5170 799static const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
ebfd6822 800{
8519ab03
TH
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.
804 */
ebfd6822
PM
805 switch (type) {
806 case NFT_DATA_VERDICT:
807 return &verdict_type;
808 default:
551d2a09
PM
809 if (type & ~TYPE_MASK)
810 return concat_type_alloc(type);
bb1be655 811 return datatype_lookup((enum datatypes) type);
ebfd6822
PM
812 }
813}
814
2535ba70 815void netlink_dump_set(const struct nftnl_set *nls, struct netlink_ctx *ctx)
ebfd6822 816{
2dc07bcd 817 FILE *fp = ctx->nft->output.output_fp;
ebfd6822 818
2dc07bcd 819 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
aae836a7 820 return;
ebfd6822 821
2535ba70
PS
822 nftnl_set_fprintf(fp, nls, 0, 0);
823 fprintf(fp, "\n");
ebfd6822
PM
824}
825
10bdec0a
PNA
826static int set_parse_udata_cb(const struct nftnl_udata *attr, void *data)
827{
0864c2d4 828 unsigned char *value = nftnl_udata_get(attr);
10bdec0a
PNA
829 const struct nftnl_udata **tb = data;
830 uint8_t type = nftnl_udata_type(attr);
831 uint8_t len = nftnl_udata_len(attr);
832
833 switch (type) {
10da57e3
PS
834 case NFTNL_UDATA_SET_KEYBYTEORDER:
835 case NFTNL_UDATA_SET_DATABYTEORDER:
836 case NFTNL_UDATA_SET_MERGE_ELEMENTS:
9599d9d2 837 case NFTNL_UDATA_SET_DATA_INTERVAL:
10bdec0a
PNA
838 if (len != sizeof(uint32_t))
839 return -1;
840 break;
6e48df53
FW
841 case NFTNL_UDATA_SET_KEY_TYPEOF:
842 case NFTNL_UDATA_SET_DATA_TYPEOF:
843 if (len < 3)
844 return -1;
845 break;
0864c2d4
JGG
846 case NFTNL_UDATA_SET_COMMENT:
847 if (value[len - 1] != '\0')
848 return -1;
849 break;
6e48df53
FW
850 default:
851 return 0;
852 }
853 tb[type] = attr;
854 return 0;
855}
856
857static int set_key_parse_udata(const struct nftnl_udata *attr, void *data)
858{
859 const struct nftnl_udata **tb = data;
860 uint8_t type = nftnl_udata_type(attr);
861 uint8_t len = nftnl_udata_len(attr);
862
863 switch (type) {
864 case NFTNL_UDATA_SET_TYPEOF_EXPR:
865 if (len != sizeof(uint32_t))
866 return -1;
867 break;
868 case NFTNL_UDATA_SET_TYPEOF_DATA:
869 break;
10bdec0a
PNA
870 default:
871 return 0;
872 }
873 tb[type] = attr;
874 return 0;
875}
876
6e48df53
FW
877static struct expr *set_make_key(const struct nftnl_udata *attr)
878{
879 const struct nftnl_udata *ud[NFTNL_UDATA_SET_TYPEOF_MAX + 1] = {};
880 const struct expr_ops *ops;
881 enum expr_types etype;
882 struct expr *expr;
883 int err;
884
885 if (!attr)
886 return NULL;
887
888 err = nftnl_udata_parse(nftnl_udata_get(attr), nftnl_udata_len(attr),
889 set_key_parse_udata, ud);
890 if (err < 0)
891 return NULL;
892
893 if (!ud[NFTNL_UDATA_SET_TYPEOF_EXPR] ||
894 !ud[NFTNL_UDATA_SET_TYPEOF_DATA])
895 return NULL;
896
897 etype = nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_TYPEOF_EXPR]);
898 ops = expr_ops_by_type(etype);
899
900 expr = ops->parse_udata(ud[NFTNL_UDATA_SET_TYPEOF_DATA]);
901 if (!expr)
902 return NULL;
903
904 return expr;
905}
906
ea31855d 907static bool set_udata_key_valid(const struct expr *e, uint32_t len)
6e48df53
FW
908{
909 if (!e)
910 return false;
911
912 return div_round_up(e->len, BITS_PER_BYTE) == len / BITS_PER_BYTE;
913}
914
e6d1d0d6
PNA
915struct setelem_parse_ctx {
916 struct set *set;
917 struct nft_cache *cache;
918 struct list_head stmt_list;
919};
920
921static int set_elem_parse_expressions(struct nftnl_expr *e, void *data)
922{
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;
926 struct stmt *stmt;
927
928 stmt = netlink_parse_set_expr(set, cache, e);
929 list_add_tail(&stmt->list, &setelem_parse_ctx->stmt_list);
930
931 return 0;
932}
933
fbcb888b
PNA
934struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
935 const struct nftnl_set *nls)
cc1c2620 936{
10da57e3 937 const struct nftnl_udata *ud[NFTNL_UDATA_SET_MAX + 1] = {};
fb2d2de9 938 enum byteorder keybyteorder = BYTEORDER_INVALID;
e6ca6739 939 enum byteorder databyteorder = BYTEORDER_INVALID;
6e48df53 940 struct expr *typeof_expr_key, *typeof_expr_data;
e6d1d0d6 941 struct setelem_parse_ctx set_parse_ctx;
8519ab03
TH
942 const struct datatype *datatype = NULL;
943 const struct datatype *keytype = NULL;
944 const struct datatype *dtype2 = NULL;
945 const struct datatype *dtype = NULL;
0864c2d4 946 const char *udata, *comment = NULL;
343a5170 947 uint32_t flags, key, objtype = 0;
9599d9d2 948 uint32_t data_interval = 0;
30f66792 949 bool automerge = false;
fb2d2de9
PNA
950 struct set *set;
951 uint32_t ulen;
6e48df53
FW
952 uint32_t klen;
953
954 typeof_expr_key = NULL;
955 typeof_expr_data = NULL;
fb2d2de9
PNA
956
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");
961 return NULL;
962 }
963
10da57e3
PS
964#define GET_U32_UDATA(var, attr) \
965 if (ud[attr]) \
966 var = nftnl_udata_get_u32(ud[attr])
967
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);
9599d9d2 971 GET_U32_UDATA(data_interval, NFTNL_UDATA_SET_DATA_INTERVAL);
10da57e3
PS
972
973#undef GET_U32_UDATA
6e48df53
FW
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]);
0864c2d4 977 if (ud[NFTNL_UDATA_SET_COMMENT])
accd7a34 978 comment = nftnl_udata_get(ud[NFTNL_UDATA_SET_COMMENT]);
fb2d2de9 979 }
cc1c2620 980
d6f06c30 981 key = nftnl_set_get_u32(nls, NFTNL_SET_KEY_TYPE);
cc1c2620
AB
982 keytype = dtype_map_from_kernel(key);
983 if (keytype == NULL) {
984 netlink_io_error(ctx, NULL, "Unknown data type in set key %u",
985 key);
986 return NULL;
987 }
988
d6f06c30 989 flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
0fd53234 990 if (set_is_datamap(flags)) {
343a5170
FW
991 uint32_t data;
992
d6f06c30 993 data = nftnl_set_get_u32(nls, NFTNL_SET_DATA_TYPE);
cc1c2620
AB
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",
998 data);
8519ab03
TH
999 set = NULL;
1000 goto out;
cc1c2620 1001 }
343a5170 1002 }
cc1c2620 1003
0fd53234 1004 if (set_is_objmap(flags)) {
deaf962e 1005 objtype = nftnl_set_get_u32(nls, NFTNL_SET_OBJ_TYPE);
6e48df53 1006 assert(!datatype);
deaf962e
PNA
1007 datatype = &string_type;
1008 }
1009
cc1c2620 1010 set = set_alloc(&netlink_location);
d6f06c30 1011 set->handle.family = nftnl_set_get_u32(nls, NFTNL_SET_FAMILY);
cf646426 1012 set->handle.table.name = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_TABLE));
12d57b50 1013 set->handle.set.name = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_NAME));
30f66792 1014 set->automerge = automerge;
0864c2d4 1015 if (comment)
accd7a34 1016 set->comment = xstrdup(comment);
cc1c2620 1017
e6d1d0d6
PNA
1018 init_list_head(&set_parse_ctx.stmt_list);
1019
6d80e0f1
PNA
1020 if (nftnl_set_is_set(nls, NFTNL_SET_EXPR)) {
1021 const struct nftnl_expr *nle;
e6d1d0d6 1022 struct stmt *stmt;
6d80e0f1
PNA
1023
1024 nle = nftnl_set_get(nls, NFTNL_SET_EXPR);
e6d1d0d6
PNA
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,
1031 &set_parse_ctx);
6d80e0f1 1032 }
e6d1d0d6 1033 list_splice_tail(&set_parse_ctx.stmt_list, &set->stmt_list);
6d80e0f1 1034
6e48df53 1035 if (datatype) {
0583bac2
FW
1036 uint32_t dlen;
1037
8519ab03 1038 dtype2 = set_datatype_alloc(datatype, databyteorder);
6e48df53
FW
1039 klen = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE;
1040
0583bac2
FW
1041 dlen = data_interval ? klen / 2 : klen;
1042
1043 if (set_udata_key_valid(typeof_expr_data, dlen)) {
1044 typeof_expr_data->len = klen;
6e48df53
FW
1045 set->data = typeof_expr_data;
1046 } else {
1047 expr_free(typeof_expr_data);
1048 set->data = constant_expr_alloc(&netlink_location,
8519ab03 1049 dtype2,
6e48df53
FW
1050 databyteorder, klen,
1051 NULL);
1052
1053 /* Can't use 'typeof' keyword, so discard key too */
1054 expr_free(typeof_expr_key);
1055 typeof_expr_key = NULL;
1056 }
1057
9599d9d2
PNA
1058 if (data_interval)
1059 set->data->flags |= EXPR_F_INTERVAL;
6e48df53
FW
1060 }
1061
1062 dtype = set_datatype_alloc(keytype, keybyteorder);
1063 klen = nftnl_set_get_u32(nls, NFTNL_SET_KEY_LEN) * BITS_PER_BYTE;
1064
ea31855d 1065 if (set_udata_key_valid(typeof_expr_key, klen)) {
6e48df53
FW
1066 set->key = typeof_expr_key;
1067 set->key_typeof_valid = true;
1068 } else {
1069 expr_free(typeof_expr_key);
1070 set->key = constant_expr_alloc(&netlink_location, dtype,
1071 keybyteorder, klen,
1072 NULL);
1073 }
1074
d6f06c30 1075 set->flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
f4a34d25 1076 set->handle.handle.id = nftnl_set_get_u64(nls, NFTNL_SET_HANDLE);
cc1c2620 1077
deaf962e
PNA
1078 set->objtype = objtype;
1079
d6f06c30
PNA
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);
38a077f7 1084
d6f06c30
PNA
1085 if (nftnl_set_is_set(nls, NFTNL_SET_POLICY))
1086 set->policy = nftnl_set_get_u32(nls, NFTNL_SET_POLICY);
90a0f8c4 1087
d6f06c30 1088 if (nftnl_set_is_set(nls, NFTNL_SET_DESC_SIZE))
947b4fe1 1089 set->desc.size = nftnl_set_get_u32(nls, NFTNL_SET_DESC_SIZE);
90a0f8c4 1090
6156ba34
SB
1091 if (nftnl_set_is_set(nls, NFTNL_SET_DESC_CONCAT)) {
1092 uint32_t len = NFT_REG32_COUNT;
1093 const uint8_t *data;
1094
1095 data = nftnl_set_get_data(nls, NFTNL_SET_DESC_CONCAT, &len);
1096 if (data) {
1097 memcpy(set->desc.field_len, data, len);
1098 set->desc.field_count = len;
1099 }
1100 }
1101
8519ab03
TH
1102out:
1103 datatype_free(datatype);
1104 datatype_free(keytype);
1105 datatype_free(dtype2);
1106 datatype_free(dtype);
cc1c2620
AB
1107 return set;
1108}
1109
d6ed28a3 1110void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls)
ebfd6822 1111{
d6f06c30 1112 struct nftnl_set_elem *nlse;
ebfd6822 1113 const struct expr *expr;
ebfd6822 1114
ebfd6822 1115 list_for_each_entry(expr, &set->expressions, list) {
deaf962e 1116 nlse = alloc_nftnl_setelem(set, expr);
d6f06c30 1117 nftnl_set_elem_add(nls, nlse);
ebfd6822 1118 }
ebfd6822
PM
1119}
1120
34f31e74 1121static bool range_expr_is_prefix(const struct expr *range, uint32_t *prefix_len)
9599d9d2 1122{
34f31e74
PNA
1123 const struct expr *right = range->right;
1124 const struct expr *left = range->left;
1125 uint32_t len = left->len;
9599d9d2 1126 unsigned long n1, n2;
34f31e74
PNA
1127 uint32_t plen;
1128 mpz_t bitmask;
9599d9d2 1129
34f31e74
PNA
1130 mpz_init2(bitmask, left->len);
1131 mpz_xor(bitmask, left->value, right->value);
9599d9d2 1132
34f31e74
PNA
1133 n1 = mpz_scan0(bitmask, 0);
1134 if (n1 == ULONG_MAX)
1135 goto not_a_prefix;
9599d9d2 1136
34f31e74
PNA
1137 n2 = mpz_scan1(bitmask, n1 + 1);
1138 if (n2 < len)
1139 goto not_a_prefix;
9599d9d2 1140
34f31e74
PNA
1141 plen = len - n1;
1142
1143 if (mpz_scan1(left->value, 0) < len - plen)
1144 goto not_a_prefix;
1145
1146 mpz_clear(bitmask);
1147 *prefix_len = plen;
1148
1149 return true;
1150
1151not_a_prefix:
1152 mpz_clear(bitmask);
1153
1154 return false;
9599d9d2
PNA
1155}
1156
ee4391d0 1157struct expr *range_expr_to_prefix(struct expr *range)
9599d9d2 1158{
34f31e74
PNA
1159 struct expr *prefix;
1160 uint32_t prefix_len;
9599d9d2 1161
34f31e74
PNA
1162 if (range_expr_is_prefix(range, &prefix_len)) {
1163 prefix = prefix_expr_alloc(&range->location,
1164 expr_get(range->left),
1165 prefix_len);
1166 expr_free(range);
1167 return prefix;
9599d9d2 1168 }
9599d9d2
PNA
1169
1170 return range;
1171}
1172
66746e7d
PNA
1173static struct expr *range_expr_reduce(struct expr *range)
1174{
1175 struct expr *expr;
1176
1177 if (!mpz_cmp(range->left->value, range->right->value)) {
1178 expr = expr_get(range->left);
1179 expr_free(range);
1180 return expr;
1181 }
1182
1183 if (range->left->dtype->type != TYPE_IPADDR &&
1184 range->left->dtype->type != TYPE_IP6ADDR)
1185 return range;
1186
1187 return range_expr_to_prefix(range);
1188}
1189
1190static struct expr *netlink_parse_interval_elem(const struct set *set,
9599d9d2
PNA
1191 struct expr *expr)
1192{
1193 unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
66746e7d 1194 const struct datatype *dtype = set->data->dtype;
9599d9d2
PNA
1195 struct expr *range, *left, *right;
1196 char data[len];
1197
1198 mpz_export_data(data, expr->value, dtype->byteorder, len);
1199 left = constant_expr_alloc(&internal_location, dtype,
1200 dtype->byteorder,
1201 (len / 2) * BITS_PER_BYTE, &data[0]);
1202 right = constant_expr_alloc(&internal_location, dtype,
1203 dtype->byteorder,
1204 (len / 2) * BITS_PER_BYTE, &data[len / 2]);
1205 range = range_expr_alloc(&expr->location, left, right);
1206 expr_free(expr);
1207
ee4391d0 1208 return range_expr_to_prefix(range);
9599d9d2
PNA
1209}
1210
1017d323 1211static struct expr *concat_elem_expr(const struct set *set, struct expr *key,
66746e7d
PNA
1212 const struct datatype *dtype,
1213 struct expr *data, int *off)
a93bc179
PM
1214{
1215 const struct datatype *subtype;
c1c223f1 1216 unsigned int sub_length;
64bb3f43 1217 struct expr *expr;
66746e7d 1218
64bb3f43
PNA
1219 if (key) {
1220 (*off)--;
c1c223f1
FW
1221 sub_length = round_up(key->len, BITS_PER_BYTE);
1222
1223 expr = constant_expr_splice(data, sub_length);
64bb3f43
PNA
1224 expr->dtype = datatype_get(key->dtype);
1225 expr->byteorder = key->byteorder;
1226 expr->len = key->len;
1227 } else {
1228 subtype = concat_subtype_lookup(dtype->type, --(*off));
c1c223f1
FW
1229 sub_length = round_up(subtype->size, BITS_PER_BYTE);
1230 expr = constant_expr_splice(data, sub_length);
64bb3f43
PNA
1231 expr->dtype = subtype;
1232 expr->byteorder = subtype->byteorder;
1233 }
66746e7d 1234
1017d323
PNA
1235 if (expr_basetype(expr)->type == TYPE_STRING ||
1236 (!(set->flags & NFT_SET_INTERVAL) &&
1237 expr->byteorder == BYTEORDER_HOST_ENDIAN))
66746e7d
PNA
1238 mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
1239
1240 if (expr->dtype->basetype != NULL &&
1241 expr->dtype->basetype->type == TYPE_BITMASK)
1242 expr = bitmask_expr_to_binops(expr);
1243
c1c223f1 1244 data->len -= netlink_padding_len(sub_length);
66746e7d
PNA
1245
1246 return expr;
1247}
1248
1249static struct expr *netlink_parse_concat_elem_key(const struct set *set,
1250 struct expr *data)
1251{
1252 const struct datatype *dtype = set->key->dtype;
64bb3f43 1253 struct expr *concat, *expr, *n = NULL;
a93bc179
PM
1254 int off = dtype->subtypes;
1255
64bb3f43
PNA
1256 if (set->key->etype == EXPR_CONCAT)
1257 n = list_first_entry(&set->key->expressions, struct expr, list);
1258
a93bc179
PM
1259 concat = concat_expr_alloc(&data->location);
1260 while (off > 0) {
1017d323 1261 expr = concat_elem_expr(set, n, dtype, data, &off);
66746e7d 1262 compound_expr_add(concat, expr);
64bb3f43
PNA
1263 if (set->key->etype == EXPR_CONCAT)
1264 n = list_next_entry(n, list);
66746e7d
PNA
1265 }
1266
1267 expr_free(data);
1268
1269 return concat;
1270}
1271
1272static struct expr *netlink_parse_concat_elem(const struct set *set,
1273 struct expr *data)
1274{
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;
1279
1280 init_list_head(&expressions);
1281
1282 concat = concat_expr_alloc(&data->location);
1283 while (off > 0) {
1017d323 1284 expr = concat_elem_expr(set, NULL, dtype, data, &off);
66746e7d
PNA
1285 list_add_tail(&expr->list, &expressions);
1286 }
a93bc179 1287
66746e7d
PNA
1288 if (set->data->flags & EXPR_F_INTERVAL) {
1289 assert(!list_empty(&expressions));
a93bc179 1290
66746e7d 1291 off = dtype->subtypes;
a93bc179 1292
66746e7d
PNA
1293 while (off > 0) {
1294 left = list_first_entry(&expressions, struct expr, list);
a93bc179 1295
1017d323 1296 expr = concat_elem_expr(set, NULL, dtype, data, &off);
66746e7d
PNA
1297 list_del(&left->list);
1298
1299 range = range_expr_alloc(&data->location, left, expr);
1300 range = range_expr_reduce(range);
1301 compound_expr_add(concat, range);
1302 }
1303 assert(list_empty(&expressions));
1304 } else {
1305 list_splice_tail(&expressions, &concat->expressions);
a93bc179 1306 }
66746e7d 1307
a93bc179
PM
1308 expr_free(data);
1309
1310 return concat;
1311}
1312
6089630f 1313static int set_elem_parse_udata_cb(const struct nftnl_udata *attr, void *data)
61f851be 1314{
6089630f 1315 const struct nftnl_udata **tb = data;
61f851be
CFG
1316 unsigned char *value = nftnl_udata_get(attr);
1317 uint8_t type = nftnl_udata_type(attr);
1318 uint8_t len = nftnl_udata_len(attr);
61f851be
CFG
1319
1320 switch (type) {
10da57e3 1321 case NFTNL_UDATA_SET_ELEM_COMMENT:
61f851be
CFG
1322 if (value[len - 1] != '\0')
1323 return -1;
1324 break;
10da57e3 1325 case NFTNL_UDATA_SET_ELEM_FLAGS:
6089630f
PS
1326 if (len != sizeof(uint32_t))
1327 return -1;
1328 break;
61f851be
CFG
1329 default:
1330 return 0;
1331 }
1332 tb[type] = attr;
1333 return 0;
1334}
1335
6089630f
PS
1336static void set_elem_parse_udata(struct nftnl_set_elem *nlse,
1337 struct expr *expr)
61f851be 1338{
10da57e3 1339 const struct nftnl_udata *ud[NFTNL_UDATA_SET_ELEM_MAX + 1] = {};
6089630f
PS
1340 const void *data;
1341 uint32_t len;
61f851be 1342
6089630f
PS
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))
1345 return;
61f851be 1346
10da57e3 1347 if (ud[NFTNL_UDATA_SET_ELEM_COMMENT])
6089630f 1348 expr->comment =
10da57e3
PS
1349 xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_SET_ELEM_COMMENT]));
1350 if (ud[NFTNL_UDATA_SET_ELEM_FLAGS])
1351 expr->elem_flags =
1352 nftnl_udata_get_u32(ud[NFTNL_UDATA_SET_ELEM_FLAGS]);
61f851be
CFG
1353}
1354
fbcb888b 1355int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
fbae6328 1356 struct set *set, struct nft_cache *cache)
ebfd6822 1357{
e6d1d0d6
PNA
1358 struct setelem_parse_ctx setelem_parse_ctx = {
1359 .set = set,
1360 .cache = cache,
1361 };
aae836a7 1362 struct nft_data_delinearize nld;
52532335 1363 struct expr *expr, *key, *data;
aae836a7 1364 uint32_t flags = 0;
7c1ccf81 1365
e6d1d0d6
PNA
1366 init_list_head(&setelem_parse_ctx.stmt_list);
1367
419d1968
PNA
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);
d6f06c30
PNA
1370 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_FLAGS))
1371 flags = nftnl_set_elem_get_u32(nlse, NFTNL_SET_ELEM_FLAGS);
ebfd6822 1372
8ac2f3b2 1373key_end:
419d1968
PNA
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)
66746e7d 1379 key = netlink_parse_concat_elem_key(set, key);
419d1968
PNA
1380
1381 if (!(set->flags & NFT_SET_INTERVAL) &&
1382 key->byteorder == BYTEORDER_HOST_ENDIAN)
1383 mpz_switch_byteorder(key->value, key->len / BITS_PER_BYTE);
1384
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;
1393 } else {
1394 BUG("Unexpected set element with no key\n");
1395 }
ebfd6822 1396
52532335 1397 expr = set_elem_expr_alloc(&netlink_location, key);
f1cc44ed 1398 expr->flags |= EXPR_F_KERNEL;
242965f4 1399
d6f06c30
PNA
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);
6089630f
PS
1404 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_USERDATA))
1405 set_elem_parse_udata(nlse, expr);
2d74990a 1406 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPR)) {
3ed5e31f 1407 const struct nftnl_expr *nle;
e6d1d0d6 1408 struct stmt *stmt;
3ed5e31f 1409
2d74990a 1410 nle = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_EXPR, NULL);
e6d1d0d6
PNA
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);
3ed5e31f 1416 }
0693edb9 1417 list_splice_tail_init(&setelem_parse_ctx.stmt_list, &expr->stmt_list);
e6d1d0d6 1418
fbae6328 1419 if (flags & NFT_SET_ELEM_INTERVAL_END) {
ebfd6822 1420 expr->flags |= EXPR_F_INTERVAL_END;
fbae6328
PNA
1421 if (mpz_cmp_ui(set->key->value, 0) == 0)
1422 set->root = true;
1423 }
deaf962e 1424
0fd53234 1425 if (set_is_datamap(set->flags)) {
d6f06c30
PNA
1426 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_DATA)) {
1427 nld.value = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_DATA,
947b4fe1 1428 &nld.len);
d6f06c30
PNA
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);
aae836a7
PNA
1434 } else
1435 goto out;
1436
a144995d 1437 data = netlink_alloc_data(&netlink_location, &nld,
343a5170 1438 set->data->dtype->type == TYPE_VERDICT ?
ebfd6822 1439 NFT_REG_VERDICT : NFT_REG_1);
343a5170
FW
1440 datatype_set(data, set->data->dtype);
1441 data->byteorder = set->data->byteorder;
6f0d90ec 1442
66746e7d
PNA
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);
6f0d90ec 1447
a54d7b05
PNA
1448 if (data->byteorder == BYTEORDER_HOST_ENDIAN)
1449 mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
ebfd6822 1450
a144995d 1451 expr = mapping_expr_alloc(&netlink_location, expr, data);
deaf962e 1452 }
0fd53234 1453 if (set_is_objmap(set->flags)) {
0d2b22cb
PNA
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,
1457 &nld.len);
1458 } else
1459 goto out;
1460
deaf962e
PNA
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);
ebfd6822 1466 }
aae836a7 1467out:
ebfd6822 1468 compound_expr_add(set->init, expr);
8ac2f3b2
SB
1469
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,
1474 &nld.len);
1475 goto key_end;
1476 }
1477
aae836a7 1478 return 0;
ebfd6822
PM
1479}
1480
d6f06c30 1481static int list_setelem_cb(struct nftnl_set_elem *nlse, void *arg)
3e1c7b67
AB
1482{
1483 struct netlink_ctx *ctx = arg;
2dc07bcd 1484 return netlink_delinearize_setelem(nlse, ctx->set, &ctx->nft->cache);
3e1c7b67
AB
1485}
1486
ca2e6e0d
FW
1487static int list_setelem_debug_cb(struct nftnl_set_elem *nlse, void *arg)
1488{
1489 int r;
1490
1491 r = list_setelem_cb(nlse, arg);
1492 if (r == 0) {
1493 struct netlink_ctx *ctx = arg;
1494 FILE *fp = ctx->nft->output.output_fp;
1495
1496 fprintf(fp, "\t");
1497 nftnl_set_elem_fprintf(fp, nlse, 0, 0);
1498 fprintf(fp, "\n");
1499 }
1500
1501 return r;
1502}
1503
1504static int list_setelements(struct nftnl_set *s, struct netlink_ctx *ctx)
1505{
1506 FILE *fp = ctx->nft->output.output_fp;
1507
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);
1511
1512 table = nftnl_set_get_str(s, NFTNL_SET_TABLE);
1513 name = nftnl_set_get_str(s, NFTNL_SET_NAME);
1514
1515 fprintf(fp, "%s %s @%s\n", family2str(family), table, name);
1516
1517 return nftnl_set_elem_foreach(s, list_setelem_debug_cb, ctx);
1518 }
1519
1520 return nftnl_set_elem_foreach(s, list_setelem_cb, ctx);
1521}
1522
760bd167 1523int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h,
83e0f440 1524 struct set *set, bool reset)
ebfd6822 1525{
d6f06c30 1526 struct nftnl_set *nls;
ebfd6822
PM
1527 int err;
1528
d6ed28a3
PNA
1529 nls = nftnl_set_alloc();
1530 if (nls == NULL)
1531 memory_allocation_error();
1532
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);
1536 if (h->handle.id)
1537 nftnl_set_set_u64(nls, NFTNL_SET_HANDLE, h->handle.id);
7c1ccf81 1538
83e0f440 1539 err = mnl_nft_setelem_get(ctx, nls, reset);
09f81768 1540 if (err < 0) {
d6f06c30 1541 nftnl_set_free(nls);
09f81768
PNA
1542 if (errno == EINTR)
1543 return -1;
1544
760bd167 1545 return 0;
09f81768 1546 }
ebfd6822
PM
1547
1548 ctx->set = set;
760bd167 1549 set->init = set_expr_alloc(&internal_location, set);
ca2e6e0d 1550 list_setelements(nls, ctx);
14ee0a97 1551
8ac2f3b2
SB
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);
1556 else
14ee0a97
EL
1557 list_expr_sort(&ctx->set->init->expressions);
1558
d6f06c30 1559 nftnl_set_free(nls);
ebfd6822
PM
1560 ctx->set = NULL;
1561
760bd167 1562 return 0;
ebfd6822 1563}
a72315d2 1564
a43cc8d5 1565int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
ac4b25b3 1566 const struct location *loc, struct set *cache_set,
83e0f440 1567 struct set *set, struct expr *init, bool reset)
a43cc8d5
PNA
1568{
1569 struct nftnl_set *nls, *nls_out = NULL;
8ac2f3b2 1570 int err = 0;
a43cc8d5 1571
d6ed28a3
PNA
1572 nls = nftnl_set_alloc();
1573 if (nls == NULL)
1574 memory_allocation_error();
1575
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);
1579 if (h->handle.id)
1580 nftnl_set_set_u64(nls, NFTNL_SET_HANDLE, h->handle.id);
1581
a43cc8d5
PNA
1582 alloc_setelem_cache(init, nls);
1583
1584 netlink_dump_set(nls, ctx);
1585
83e0f440 1586 nls_out = mnl_nft_setelem_get_one(ctx, nls, reset);
da5f97e3
PNA
1587 if (!nls_out) {
1588 nftnl_set_free(nls);
70cb4bbd 1589 return -1;
da5f97e3 1590 }
a43cc8d5
PNA
1591
1592 ctx->set = set;
1593 set->init = set_expr_alloc(loc, set);
ca2e6e0d 1594 list_setelements(nls_out, ctx);
a43cc8d5 1595
8ac2f3b2
SB
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)
ac4b25b3 1599 err = get_set_decompose(cache_set, set);
8ac2f3b2 1600 else
a43cc8d5
PNA
1601 list_expr_sort(&ctx->set->init->expressions);
1602
1603 nftnl_set_free(nls);
1604 nftnl_set_free(nls_out);
1605 ctx->set = NULL;
1606
8ac2f3b2 1607 return err;
a43cc8d5
PNA
1608}
1609
2535ba70 1610void netlink_dump_obj(struct nftnl_obj *nln, struct netlink_ctx *ctx)
4d38878b 1611{
2dc07bcd 1612 FILE *fp = ctx->nft->output.output_fp;
4d38878b 1613
2dc07bcd 1614 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
4d38878b
PNA
1615 return;
1616
2535ba70
PS
1617 nftnl_obj_fprintf(fp, nln, 0, 0);
1618 fprintf(fp, "\n");
4d38878b
PNA
1619}
1620
293c9b11
JGG
1621static int obj_parse_udata_cb(const struct nftnl_udata *attr, void *data)
1622{
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);
1627
1628 switch (type) {
1629 case NFTNL_UDATA_OBJ_COMMENT:
1630 if (value[len - 1] != '\0')
1631 return -1;
1632 break;
1633 default:
1634 return 0;
1635 }
1636 tb[type] = attr;
1637 return 0;
1638}
1639
fbcb888b
PNA
1640struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
1641 struct nftnl_obj *nlo)
4756d92e 1642{
293c9b11
JGG
1643 const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {};
1644 const char *udata;
4756d92e
PNA
1645 struct obj *obj;
1646 uint32_t type;
293c9b11 1647 uint32_t ulen;
4756d92e
PNA
1648
1649 obj = obj_alloc(&netlink_location);
1650 obj->handle.family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY);
cf646426 1651 obj->handle.table.name =
4756d92e 1652 xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_TABLE));
b2a76466 1653 obj->handle.obj.name =
4756d92e 1654 xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME));
832b2862
HS
1655 obj->handle.handle.id =
1656 nftnl_obj_get_u64(nlo, NFTNL_OBJ_HANDLE);
293c9b11
JGG
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");
97b5d4bb 1661 obj_free(obj);
293c9b11
JGG
1662 return NULL;
1663 }
1664 if (ud[NFTNL_UDATA_OBJ_COMMENT])
1665 obj->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_OBJ_COMMENT]));
1666 }
4756d92e
PNA
1667
1668 type = nftnl_obj_get_u32(nlo, NFTNL_OBJ_TYPE);
1669 switch (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);
1675 break;
1676 case NFT_OBJECT_QUOTA:
1677 obj->quota.bytes =
1678 nftnl_obj_get_u64(nlo, NFTNL_OBJ_QUOTA_BYTES);
1679 obj->quota.used =
1680 nftnl_obj_get_u64(nlo, NFTNL_OBJ_QUOTA_CONSUMED);
1681 obj->quota.flags =
1682 nftnl_obj_get_u32(nlo, NFTNL_OBJ_QUOTA_FLAGS);
5ca4eb30 1683 break;
3bc84e5c
CG
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));
1687 break;
5ca4eb30 1688 case NFT_OBJECT_CT_HELPER:
f63405f9 1689 snprintf(obj->ct_helper.name, sizeof(obj->ct_helper.name), "%s",
5ca4eb30 1690 nftnl_obj_get_str(nlo, NFTNL_OBJ_CT_HELPER_NAME));
f63405f9
FW
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);
5ca4eb30 1693 break;
c7c94802 1694 case NFT_OBJECT_CT_TIMEOUT:
7a0e2672 1695 init_list_head(&obj->ct_timeout.timeout_list);
c7c94802
HS
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));
1701 break;
c0697eab
PBG
1702 case NFT_OBJECT_LIMIT:
1703 obj->limit.rate =
1704 nftnl_obj_get_u64(nlo, NFTNL_OBJ_LIMIT_RATE);
1705 obj->limit.unit =
1706 nftnl_obj_get_u64(nlo, NFTNL_OBJ_LIMIT_UNIT);
1707 obj->limit.burst =
1708 nftnl_obj_get_u32(nlo, NFTNL_OBJ_LIMIT_BURST);
1709 obj->limit.type =
1710 nftnl_obj_get_u32(nlo, NFTNL_OBJ_LIMIT_TYPE);
1711 obj->limit.flags =
1712 nftnl_obj_get_u32(nlo, NFTNL_OBJ_LIMIT_FLAGS);
1713 break;
1dd08fcf
SV
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);
1725 break;
f44ab88b
FFM
1726 case NFT_OBJECT_SYNPROXY:
1727 obj->synproxy.mss =
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);
1733 break;
4756d92e
PNA
1734 }
1735 obj->type = type;
1736
1737 return obj;
1738}
1739
15ab9872
PNA
1740void netlink_dump_flowtable(struct nftnl_flowtable *flo,
1741 struct netlink_ctx *ctx)
92911b36 1742{
2dc07bcd 1743 FILE *fp = ctx->nft->output.output_fp;
92911b36 1744
2dc07bcd 1745 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
92911b36
PNA
1746 return;
1747
1748 nftnl_flowtable_fprintf(fp, flo, 0, 0);
1749 fprintf(fp, "\n");
1750}
1751
4756d92e
PNA
1752static int list_obj_cb(struct nftnl_obj *nls, void *arg)
1753{
1754 struct netlink_ctx *ctx = arg;
1755 struct obj *obj;
1756
1757 obj = netlink_delinearize_obj(ctx, nls);
1758 if (obj == NULL)
1759 return -1;
1760 list_add_tail(&obj->list, &ctx->list);
1761 return 0;
1762}
1763
2daca4fa
PNA
1764int netlink_reset_objs(struct netlink_ctx *ctx, const struct cmd *cmd,
1765 uint32_t type, bool dump)
8ec2e843 1766{
2daca4fa 1767 const struct handle *h = &cmd->handle;
8ec2e843
PNA
1768 struct nftnl_obj_list *obj_cache;
1769 int err;
1770
657fdefc 1771 obj_cache = mnl_nft_obj_dump(ctx, h->family,
b2a76466 1772 h->table.name, h->obj.name, type, dump, true);
a8ba88c3
PNA
1773 if (obj_cache == NULL)
1774 return -1;
4756d92e
PNA
1775
1776 err = nftnl_obj_list_foreach(obj_cache, list_obj_cb, ctx);
1777 nftnl_obj_list_free(obj_cache);
1778 return err;
1779}
1780
1694df2d
PS
1781int netlink_reset_rules(struct netlink_ctx *ctx, const struct cmd *cmd,
1782 bool dump)
1783{
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,
1789 };
1790 struct rule *rule, *next, *crule, *cnext;
1791 struct table *table;
1792 struct chain *chain;
1793 int ret;
1794
1795 ret = rule_cache_dump(ctx, h, &f, dump, true);
1796
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);
1801 if (!table)
1802 continue;
1803
1804 chain = chain_cache_find(table, rule->handle.chain.name);
1805 if (!chain)
1806 continue;
1807
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)
1811 continue;
1812
1813 list_replace(&crule->list, &rule->list);
1814 rule_free(crule);
1815 rule = NULL;
1816 break;
1817 }
1818 if (rule) {
1819 list_add_tail(&rule->list, &chain->rules);
1820 }
1821 }
1822 list_for_each_entry_safe(rule, next, &ctx->list, list) {
1823 list_del(&rule->list);
1824 rule_free(rule);
1825 }
1826
1827 return ret;
1828}
1829
560963c4 1830struct flowtable *
db0697ce
PNA
1831netlink_delinearize_flowtable(struct netlink_ctx *ctx,
1832 struct nftnl_flowtable *nlo)
1833{
1834 struct flowtable *flowtable;
71f755e5 1835 const char * const *dev_array;
627c451b 1836 int len = 0, i, priority;
db0697ce
PNA
1837
1838 flowtable = flowtable_alloc(&netlink_location);
1839 flowtable->handle.family =
1840 nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FAMILY);
cf646426 1841 flowtable->handle.table.name =
db0697ce 1842 xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_TABLE));
81c51fc1 1843 flowtable->handle.flowtable.name =
db0697ce 1844 xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_NAME));
91487a80
EJ
1845 flowtable->handle.handle.id =
1846 nftnl_flowtable_get_u64(nlo, NFTNL_FLOWTABLE_HANDLE);
8e6cc9f3
FW
1847 if (nftnl_flowtable_is_set(nlo, NFTNL_FLOWTABLE_FLAGS))
1848 flowtable->flags = nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FLAGS);
71f755e5
FW
1849 dev_array = nftnl_flowtable_get(nlo, NFTNL_FLOWTABLE_DEVICES);
1850 while (dev_array[len])
db0697ce
PNA
1851 len++;
1852
927d5674
PS
1853 if (len)
1854 flowtable->dev_array = xmalloc(len * sizeof(char *));
db0697ce
PNA
1855 for (i = 0; i < len; i++)
1856 flowtable->dev_array[i] = xstrdup(dev_array[i]);
1857
1858 flowtable->dev_array_len = len;
1859
8161ea94
PNA
1860 if (flowtable->dev_array_len) {
1861 qsort(flowtable->dev_array, flowtable->dev_array_len,
1862 sizeof(char *), qsort_device_cmp);
1863 }
1864
627c451b
FFM
1865 priority = nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_PRIO);
1866 flowtable->priority.expr =
1867 constant_expr_alloc(&netlink_location,
1868 &integer_type,
1869 BYTEORDER_HOST_ENDIAN,
1870 sizeof(int) *
1871 BITS_PER_BYTE,
1872 &priority);
673d82af 1873 flowtable->hook.num =
db0697ce 1874 nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_HOOKNUM);
b119428c
PNA
1875 flowtable->flags =
1876 nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FLAGS);
db0697ce
PNA
1877
1878 return flowtable;
1879}
1880
1881static int list_flowtable_cb(struct nftnl_flowtable *nls, void *arg)
1882{
1883 struct netlink_ctx *ctx = arg;
1884 struct flowtable *flowtable;
1885
1886 flowtable = netlink_delinearize_flowtable(ctx, nls);
1887 if (flowtable == NULL)
1888 return -1;
1889 list_add_tail(&flowtable->list, &ctx->list);
1890 return 0;
1891}
1892
d163ba4d 1893int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h)
db0697ce
PNA
1894{
1895 struct nftnl_flowtable_list *flowtable_cache;
1896 int err;
1897
cb4b07d0
PS
1898 flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family,
1899 h->table.name, NULL);
db0697ce
PNA
1900 if (flowtable_cache == NULL) {
1901 if (errno == EINTR)
1902 return -1;
1903
1904 return 0;
1905 }
1906
1907 err = nftnl_flowtable_list_foreach(flowtable_cache, list_flowtable_cb, ctx);
1908 nftnl_flowtable_list_free(flowtable_cache);
1909 return err;
1910}
1911
65747284
PS
1912static void trace_print_hdr(const struct nftnl_trace *nlt,
1913 struct output_ctx *octx)
be5d9120 1914{
65747284
PS
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)));
be5d9120 1918 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_TABLE))
65747284
PS
1919 nft_print(octx, "%s ",
1920 nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE));
be5d9120 1921 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CHAIN))
65747284
PS
1922 nft_print(octx, "%s ",
1923 nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN));
be5d9120
PM
1924}
1925
1926static void trace_print_expr(const struct nftnl_trace *nlt, unsigned int attr,
35f6cd32 1927 struct expr *lhs, struct output_ctx *octx)
be5d9120
PM
1928{
1929 struct expr *rhs, *rel;
1930 const void *data;
1931 uint32_t len;
1932
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);
1938
35f6cd32 1939 expr_print(rel, octx);
65747284 1940 nft_print(octx, " ");
be5d9120
PM
1941 expr_free(rel);
1942}
1943
35f6cd32
VR
1944static void trace_print_verdict(const struct nftnl_trace *nlt,
1945 struct output_ctx *octx)
be5d9120 1946{
f1e8a129 1947 struct expr *chain_expr = NULL;
be5d9120
PM
1948 const char *chain = NULL;
1949 unsigned int verdict;
1950 struct expr *expr;
1951
1952 verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT);
f1e8a129 1953 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
be5d9120 1954 chain = xstrdup(nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET));
f1e8a129
FFM
1955 chain_expr = constant_expr_alloc(&netlink_location,
1956 &string_type,
1957 BYTEORDER_HOST_ENDIAN,
619327e3 1958 strlen(chain) * BITS_PER_BYTE,
f1e8a129
FFM
1959 chain);
1960 }
1961 expr = verdict_expr_alloc(&netlink_location, verdict, chain_expr);
be5d9120 1962
78ba4ffd
FW
1963 nft_print(octx, "verdict ");
1964 expr_print(expr, octx);
1965 expr_free(expr);
1966}
1967
1968static void trace_print_policy(const struct nftnl_trace *nlt,
1969 struct output_ctx *octx)
1970{
1971 unsigned int policy;
1972 struct expr *expr;
1973
1974 policy = nftnl_trace_get_u32(nlt, NFTNL_TRACE_POLICY);
1975
1976 expr = verdict_expr_alloc(&netlink_location, policy, NULL);
1977
1978 nft_print(octx, "policy ");
35f6cd32 1979 expr_print(expr, octx);
be5d9120
PM
1980 expr_free(expr);
1981}
1982
0bbd101a
LR
1983static struct rule *trace_lookup_rule(const struct nftnl_trace *nlt,
1984 uint64_t rule_handle,
1985 struct nft_cache *cache)
be5d9120 1986{
be5d9120 1987 struct chain *chain;
0bbd101a 1988 struct table *table;
be5d9120
PM
1989 struct handle h;
1990
1991 h.family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
0bbd101a
LR
1992 h.table.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
1993 h.chain.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
be5d9120 1994
cf646426 1995 if (!h.table.name)
0bbd101a 1996 return NULL;
be5d9120 1997
5ec5c706 1998 table = table_cache_find(&cache->table_cache, h.table.name, h.family);
be5d9120 1999 if (!table)
0bbd101a 2000 return NULL;
be5d9120 2001
797b4f34 2002 chain = chain_cache_find(table, h.chain.name);
be5d9120 2003 if (!chain)
0bbd101a
LR
2004 return NULL;
2005
2006 return rule_lookup(chain, rule_handle);
2007}
2008
2009static void trace_print_rule(const struct nftnl_trace *nlt,
2010 struct output_ctx *octx, struct nft_cache *cache)
2011{
2012 uint64_t rule_handle;
2013 struct rule *rule;
be5d9120
PM
2014
2015 rule_handle = nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE);
0bbd101a 2016 rule = trace_lookup_rule(nlt, rule_handle, cache);
be5d9120 2017
65747284 2018 trace_print_hdr(nlt, octx);
0bbd101a
LR
2019
2020 if (rule) {
2021 nft_print(octx, "rule ");
2022 rule_print(rule, octx);
2023 } else {
2024 nft_print(octx, "unknown rule handle %" PRIu64, rule_handle);
2025 }
2026
65747284 2027 nft_print(octx, " (");
35f6cd32 2028 trace_print_verdict(nlt, octx);
65747284 2029 nft_print(octx, ")\n");
be5d9120
PM
2030}
2031
2032static 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)
2036{
2037 struct list_head unordered = LIST_HEAD_INIT(unordered);
2038 struct list_head list;
2039 struct expr *rel, *lhs, *rhs, *tmp, *nexpr;
2040 struct stmt *stmt;
2041 const struct proto_desc *desc;
2042 const void *hdr;
2043 uint32_t hlen;
2044 unsigned int n;
be5d9120
PM
2045
2046 if (!nftnl_trace_is_set(nlt, attr))
2047 return;
2048 hdr = nftnl_trace_get_data(nlt, attr, &hlen);
2049
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);
2055
2056restart:
2057 init_list_head(&list);
2058 payload_expr_expand(&list, lhs, ctx);
2059 expr_free(lhs);
2060
2061 desc = NULL;
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)
2067 break;
2068 goto restart;
2069 }
2070
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);
2075
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))) {
2081 expr_free(lhs);
2082 expr_free(tmp);
2083 continue;
2084 }
2085
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);
2089
2090 desc = ctx->protocol[base].desc;
a2c55e04 2091 relational_expr_pctx_update(ctx, rel);
be5d9120
PM
2092 }
2093
2094 expr_free(rhs);
2095
2096 n = 0;
2097next:
2098 list_for_each_entry(stmt, &unordered, list) {
6217dfe0
JS
2099 enum proto_bases b = base;
2100
be5d9120
PM
2101 rel = stmt->expr;
2102 lhs = rel->left;
2103
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))
2108 continue;
2109
2110 list_move_tail(&stmt->list, stmts);
2111 n++;
2112
6217dfe0
JS
2113 if (payload_is_stacked(desc, rel))
2114 b--;
be5d9120 2115
70d05dc5
JS
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)
6217dfe0 2120 payload_dependency_store(pctx, stmt, b);
be5d9120
PM
2121
2122 goto next;
2123 }
2124}
2125
35f6cd32
VR
2126static void trace_print_packet(const struct nftnl_trace *nlt,
2127 struct output_ctx *octx)
be5d9120
PM
2128{
2129 struct list_head stmts = LIST_HEAD_INIT(stmts);
9604b087 2130 const struct proto_desc *ll_desc;
be5d9120
PM
2131 struct payload_dep_ctx pctx = {};
2132 struct proto_ctx ctx;
2133 uint16_t dev_type;
2134 uint32_t nfproto;
2135 struct stmt *stmt, *next;
2136
65747284 2137 trace_print_hdr(nlt, octx);
be5d9120 2138
65747284 2139 nft_print(octx, "packet: ");
be5d9120
PM
2140 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_IIF))
2141 trace_print_expr(nlt, NFTNL_TRACE_IIF,
2142 meta_expr_alloc(&netlink_location,
35f6cd32 2143 NFT_META_IIF), octx);
be5d9120
PM
2144 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_OIF))
2145 trace_print_expr(nlt, NFTNL_TRACE_OIF,
2146 meta_expr_alloc(&netlink_location,
35f6cd32 2147 NFT_META_OIF), octx);
be5d9120 2148
75b096c0 2149 proto_ctx_init(&ctx, nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY), 0, false);
9604b087
FW
2150 ll_desc = ctx.protocol[PROTO_BASE_LL_HDR].desc;
2151 if ((ll_desc == &proto_inet || ll_desc == &proto_netdev) &&
be5d9120
PM
2152 nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) {
2153 nfproto = nftnl_trace_get_u32(nlt, NFTNL_TRACE_NFPROTO);
9604b087 2154
be5d9120
PM
2155 proto_ctx_update(&ctx, PROTO_BASE_LL_HDR, &netlink_location, NULL);
2156 proto_ctx_update(&ctx, PROTO_BASE_NETWORK_HDR, &netlink_location,
9604b087 2157 proto_find_upper(ll_desc, nfproto));
be5d9120
PM
2158 }
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));
2164 }
2165
2166 trace_gen_stmts(&stmts, &ctx, &pctx, nlt, NFTNL_TRACE_LL_HEADER,
2167 PROTO_BASE_LL_HDR);
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);
2172
2173 list_for_each_entry_safe(stmt, next, &stmts, list) {
35f6cd32 2174 stmt_print(stmt, octx);
65747284 2175 nft_print(octx, " ");
be5d9120
PM
2176 stmt_free(stmt);
2177 }
65747284 2178 nft_print(octx, "\n");
be5d9120
PM
2179}
2180
fbcb888b
PNA
2181int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
2182 struct netlink_mon_handler *monh)
be5d9120
PM
2183{
2184 struct nftnl_trace *nlt;
2185
2186 assert(type == NFT_MSG_TRACE);
2187
2188 nlt = nftnl_trace_alloc();
2189 if (!nlt)
2190 memory_allocation_error();
2191
2192 if (nftnl_trace_nlmsg_parse(nlh, nlt) < 0)
2193 netlink_abi_error();
2194
871fb4ea
FW
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);
2198
be5d9120
PM
2199 switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) {
2200 case NFT_TRACETYPE_RULE:
be5d9120 2201 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE))
2dc07bcd
PNA
2202 trace_print_rule(nlt, &monh->ctx->nft->output,
2203 &monh->ctx->nft->cache);
be5d9120
PM
2204 break;
2205 case NFT_TRACETYPE_POLICY:
2dc07bcd 2206 trace_print_hdr(nlt, &monh->ctx->nft->output);
78ba4ffd
FW
2207
2208 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_POLICY)) {
2dc07bcd 2209 trace_print_policy(nlt, &monh->ctx->nft->output);
78ba4ffd
FW
2210 nft_mon_print(monh, " ");
2211 }
2212
2213 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_MARK))
2214 trace_print_expr(nlt, NFTNL_TRACE_MARK,
2215 meta_expr_alloc(&netlink_location,
2216 NFT_META_MARK),
2dc07bcd 2217 &monh->ctx->nft->output);
78ba4ffd
FW
2218 nft_mon_print(monh, "\n");
2219 break;
be5d9120 2220 case NFT_TRACETYPE_RETURN:
2dc07bcd 2221 trace_print_hdr(nlt, &monh->ctx->nft->output);
be5d9120
PM
2222
2223 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_VERDICT)) {
2dc07bcd 2224 trace_print_verdict(nlt, &monh->ctx->nft->output);
65747284 2225 nft_mon_print(monh, " ");
be5d9120
PM
2226 }
2227
2228 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_MARK))
2229 trace_print_expr(nlt, NFTNL_TRACE_MARK,
2230 meta_expr_alloc(&netlink_location,
35f6cd32 2231 NFT_META_MARK),
2dc07bcd 2232 &monh->ctx->nft->output);
65747284 2233 nft_mon_print(monh, "\n");
be5d9120
PM
2234 break;
2235 }
2236
2237 nftnl_trace_free(nlt);
2238 return MNL_CB_OK;
2239}