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