]> git.ipfire.org Git - thirdparty/nftables.git/blob - src/netlink.c
datatype: fix leak and cleanup reference counting for struct datatype
[thirdparty/nftables.git] / src / netlink.c
1 /*
2 * Copyright (c) 2008-2012 Patrick McHardy <kaber@trash.net>
3 * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
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
12 #include <nft.h>
13
14 #include <string.h>
15 #include <errno.h>
16 #include <libmnl/libmnl.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <inttypes.h>
20
21 #include <libnftnl/table.h>
22 #include <libnftnl/trace.h>
23 #include <libnftnl/chain.h>
24 #include <libnftnl/expr.h>
25 #include <libnftnl/object.h>
26 #include <libnftnl/set.h>
27 #include <libnftnl/flowtable.h>
28 #include <libnftnl/udata.h>
29 #include <libnftnl/ruleset.h>
30 #include <libnftnl/common.h>
31 #include <libnftnl/udata.h>
32 #include <linux/netfilter/nfnetlink.h>
33 #include <linux/netfilter/nf_tables.h>
34 #include <linux/netfilter.h>
35
36 #include <nftables.h>
37 #include <parser.h>
38 #include <netlink.h>
39 #include <mnl.h>
40 #include <expression.h>
41 #include <statement.h>
42 #include <gmputil.h>
43 #include <utils.h>
44 #include <erec.h>
45 #include <iface.h>
46
47 #define nft_mon_print(monh, ...) nft_print(&monh->ctx->nft->output, __VA_ARGS__)
48
49 const struct input_descriptor indesc_netlink = {
50 .name = "netlink",
51 .type = INDESC_NETLINK,
52 };
53
54 const struct location netlink_location = {
55 .indesc = &indesc_netlink,
56 };
57
58 void __noreturn __netlink_abi_error(const char *file, int line,
59 const char *reason)
60 {
61 fprintf(stderr, "E: Contact urgently your Linux kernel vendor. "
62 "Netlink ABI is broken: %s:%d %s\n", file, line, reason);
63 abort();
64 }
65
66 int netlink_io_error(struct netlink_ctx *ctx, const struct location *loc,
67 const char *fmt, ...)
68 {
69 struct error_record *erec;
70 va_list ap;
71
72 if (loc == NULL)
73 loc = &netlink_location;
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
82 void __noreturn __netlink_init_error(const char *filename, int line,
83 const char *reason)
84 {
85 fprintf(stderr, "%s:%d: Unable to initialize Netlink socket: %s\n",
86 filename, line, reason);
87 exit(NFT_EXIT_NONL);
88 }
89
90 struct nftnl_expr *alloc_nft_expr(const char *name)
91 {
92 struct nftnl_expr *nle;
93
94 nle = nftnl_expr_alloc(name);
95 if (nle == NULL)
96 memory_allocation_error();
97
98 return nle;
99 }
100 static void netlink_gen_key(const struct expr *expr,
101 struct nft_data_linearize *data);
102 static void __netlink_gen_data(const struct expr *expr,
103 struct nft_data_linearize *data, bool expand);
104
105 struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
106 const struct expr *expr)
107 {
108 const struct expr *elem, *data;
109 struct nftnl_set_elem *nlse;
110 struct nft_data_linearize nld;
111 struct nftnl_udata_buf *udbuf = NULL;
112 uint32_t flags = 0;
113 int num_exprs = 0;
114 struct stmt *stmt;
115 struct expr *key;
116
117 nlse = nftnl_set_elem_alloc();
118 if (nlse == NULL)
119 memory_allocation_error();
120
121 data = NULL;
122 if (expr->etype == EXPR_MAPPING) {
123 elem = expr->left;
124 if (!(expr->flags & EXPR_F_INTERVAL_END))
125 data = expr->right;
126 } else {
127 elem = expr;
128 }
129 if (elem->etype != EXPR_SET_ELEM)
130 BUG("Unexpected expression type: got %d\n", elem->etype);
131
132 key = elem->key;
133
134 switch (key->etype) {
135 case EXPR_SET_ELEM_CATCHALL:
136 break;
137 default:
138 if (set->set_flags & NFT_SET_INTERVAL &&
139 key->etype == EXPR_CONCAT && key->field_count > 1) {
140 key->flags |= EXPR_F_INTERVAL;
141 netlink_gen_key(key, &nld);
142 key->flags &= ~EXPR_F_INTERVAL;
143
144 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
145
146 key->flags |= EXPR_F_INTERVAL_END;
147 netlink_gen_key(key, &nld);
148 key->flags &= ~EXPR_F_INTERVAL_END;
149
150 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY_END,
151 &nld.value, nld.len);
152 } else {
153 netlink_gen_key(key, &nld);
154 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
155 }
156 break;
157 }
158
159 if (elem->timeout)
160 nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_TIMEOUT,
161 elem->timeout);
162 if (elem->expiration)
163 nftnl_set_elem_set_u64(nlse, NFTNL_SET_ELEM_EXPIRATION,
164 elem->expiration);
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 }
179 if (elem->comment || expr->elem_flags) {
180 udbuf = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN);
181 if (!udbuf)
182 memory_allocation_error();
183 }
184 if (elem->comment) {
185 if (!nftnl_udata_put_strz(udbuf, NFTNL_UDATA_SET_ELEM_COMMENT,
186 elem->comment))
187 memory_allocation_error();
188 }
189 if (expr->elem_flags) {
190 if (!nftnl_udata_put_u32(udbuf, NFTNL_UDATA_SET_ELEM_FLAGS,
191 expr->elem_flags))
192 memory_allocation_error();
193 }
194 if (udbuf) {
195 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_USERDATA,
196 nftnl_udata_buf_data(udbuf),
197 nftnl_udata_buf_len(udbuf));
198 nftnl_udata_buf_free(udbuf);
199 }
200 if (set_is_datamap(set->set_flags) && data != NULL) {
201 __netlink_gen_data(data, &nld, !(data->flags & EXPR_F_SINGLETON));
202 switch (data->etype) {
203 case EXPR_VERDICT:
204 nftnl_set_elem_set_u32(nlse, NFTNL_SET_ELEM_VERDICT,
205 data->verdict);
206 if (data->chain != NULL)
207 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_CHAIN,
208 nld.chain, strlen(nld.chain));
209 break;
210 case EXPR_CONCAT:
211 assert(nld.len > 0);
212 /* fallthrough */
213 case EXPR_VALUE:
214 case EXPR_RANGE:
215 case EXPR_PREFIX:
216 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_DATA,
217 nld.value, nld.len);
218 break;
219 default:
220 BUG("unexpected set element expression\n");
221 break;
222 }
223 }
224 if (set_is_objmap(set->set_flags) && data != NULL) {
225 netlink_gen_data(data, &nld);
226 nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_OBJREF,
227 nld.value, nld.len);
228 }
229
230 if (expr->flags & EXPR_F_INTERVAL_END)
231 flags |= NFT_SET_ELEM_INTERVAL_END;
232 if (key->etype == EXPR_SET_ELEM_CATCHALL)
233 flags |= NFT_SET_ELEM_CATCHALL;
234
235 if (flags)
236 nftnl_set_elem_set_u32(nlse, NFTNL_SET_ELEM_FLAGS, flags);
237
238 return nlse;
239 }
240
241 void netlink_gen_raw_data(const mpz_t value, enum byteorder byteorder,
242 unsigned int len, struct nft_data_linearize *data)
243 {
244 assert(len > 0);
245 mpz_export_data(data->value, value, byteorder, len);
246 data->len = len;
247 }
248
249 static 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
258 static int __netlink_gen_concat_key(uint32_t flags, const struct expr *i,
259 unsigned char *data)
260 {
261 struct expr *expr;
262
263 switch (i->etype) {
264 case EXPR_RANGE:
265 if (flags & EXPR_F_INTERVAL_END)
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;
275 break;
276 case EXPR_PREFIX:
277 if (flags & EXPR_F_INTERVAL_END) {
278 int count;
279 mpz_t v;
280
281 mpz_init_bitmask(v, i->len - i->prefix_len);
282
283 if (i->byteorder == BYTEORDER_HOST_ENDIAN)
284 mpz_switch_byteorder(v, i->len / BITS_PER_BYTE);
285
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:
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);
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
311 static void netlink_gen_concat_key(const struct expr *expr,
312 struct nft_data_linearize *nld)
313 {
314 unsigned int len = expr->len / BITS_PER_BYTE, offset = 0;
315 unsigned char data[len];
316 const struct expr *i;
317
318 memset(data, 0, len);
319
320 list_for_each_entry(i, &expr->expressions, list)
321 offset += __netlink_gen_concat_key(expr->flags, i, data + offset);
322
323 memcpy(nld->value, data, len);
324 nld->len = len;
325 }
326
327 static 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
355 static 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)
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
374 static 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);
382
383 list_for_each_entry(i, &expr->expressions, list)
384 offset += __netlink_gen_concat_data(expr->flags, i, data + offset);
385
386 memcpy(nld->value, data, len);
387 nld->len = len;
388 }
389
390 static void netlink_gen_concat_data(const struct expr *expr,
391 struct nft_data_linearize *nld, bool expand)
392 {
393 if (expand)
394 __netlink_gen_concat_expand(expr, nld);
395 else
396 __netlink_gen_concat(expr, nld);
397 }
398
399 static void netlink_gen_constant_data(const struct expr *expr,
400 struct nft_data_linearize *data)
401 {
402 assert(expr->etype == EXPR_VALUE);
403 netlink_gen_raw_data(expr->value, expr->byteorder,
404 div_round_up(expr->len, BITS_PER_BYTE), data);
405 }
406
407 static void netlink_gen_chain(const struct expr *expr,
408 struct nft_data_linearize *data)
409 {
410 char chain[NFT_CHAIN_MAXNAMELEN];
411 unsigned int len;
412
413 len = expr->chain->len / BITS_PER_BYTE;
414
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));
423
424 mpz_export_data(chain, expr->chain->value,
425 BYTEORDER_HOST_ENDIAN, len);
426 snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", chain);
427 }
428
429 static void netlink_gen_verdict(const struct expr *expr,
430 struct nft_data_linearize *data)
431 {
432
433 data->verdict = expr->verdict;
434
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;
442 break;
443 }
444 }
445
446 static 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
460 static 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
478 static 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:
485 return netlink_gen_concat_key(expr, data);
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
495 static void __netlink_gen_data(const struct expr *expr,
496 struct nft_data_linearize *data, bool expand)
497 {
498 switch (expr->etype) {
499 case EXPR_VALUE:
500 return netlink_gen_constant_data(expr, data);
501 case EXPR_CONCAT:
502 return netlink_gen_concat_data(expr, data, expand);
503 case EXPR_VERDICT:
504 return netlink_gen_verdict(expr, data);
505 case EXPR_RANGE:
506 return netlink_gen_range(expr, data);
507 case EXPR_PREFIX:
508 return netlink_gen_prefix(expr, data);
509 default:
510 BUG("invalid data expression type %s\n", expr_name(expr));
511 }
512 }
513
514 void netlink_gen_data(const struct expr *expr, struct nft_data_linearize *data)
515 {
516 __netlink_gen_data(expr, data, false);
517 }
518
519 struct expr *netlink_alloc_value(const struct location *loc,
520 const struct nft_data_delinearize *nld)
521 {
522 return constant_expr_alloc(loc, &invalid_type, BYTEORDER_INVALID,
523 nld->len * BITS_PER_BYTE, nld->value);
524 }
525
526 static struct expr *netlink_alloc_verdict(const struct location *loc,
527 const struct nft_data_delinearize *nld)
528 {
529 struct expr *chain;
530
531 switch (nld->verdict) {
532 case NFT_JUMP:
533 case NFT_GOTO:
534 chain = constant_expr_alloc(loc, &string_type,
535 BYTEORDER_HOST_ENDIAN,
536 strlen(nld->chain) * BITS_PER_BYTE,
537 nld->chain);
538 break;
539 default:
540 chain = NULL;
541 break;
542 }
543
544 return verdict_expr_alloc(loc, nld->verdict, chain);
545 }
546
547 struct expr *netlink_alloc_data(const struct location *loc,
548 const struct nft_data_delinearize *nld,
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
559 void netlink_dump_rule(const struct nftnl_rule *nlr, struct netlink_ctx *ctx)
560 {
561 FILE *fp = ctx->nft->output.output_fp;
562
563 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
564 return;
565
566 nftnl_rule_fprintf(fp, nlr, 0, 0);
567 fprintf(fp, "\n");
568 }
569
570 void netlink_dump_expr(const struct nftnl_expr *nle,
571 FILE *fp, unsigned int debug_mask)
572 {
573 if (!(debug_mask & NFT_DEBUG_NETLINK))
574 return;
575
576 nftnl_expr_fprintf(fp, nle, 0, 0);
577 fprintf(fp, "\n");
578 }
579
580 void netlink_dump_chain(const struct nftnl_chain *nlc, struct netlink_ctx *ctx)
581 {
582 FILE *fp = ctx->nft->output.output_fp;
583
584 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
585 return;
586
587 nftnl_chain_fprintf(fp, nlc, 0, 0);
588 fprintf(fp, "\n");
589 }
590
591 static 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
610 static 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
618 struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
619 const struct nftnl_chain *nlc)
620 {
621 const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {};
622 int priority, policy, len = 0, i;
623 const char * const *dev_array;
624 struct chain *chain;
625 const char *udata;
626 uint32_t ulen;
627
628 chain = chain_alloc();
629 chain->handle.family =
630 nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FAMILY);
631 chain->handle.table.name =
632 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_TABLE));
633 chain->handle.chain.name =
634 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_NAME));
635 chain->handle.handle.id =
636 nftnl_chain_get_u64(nlc, NFTNL_CHAIN_HANDLE);
637 if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_FLAGS))
638 chain->flags = nftnl_chain_get_u32(nlc, NFTNL_CHAIN_FLAGS);
639
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)) {
644 chain->hook.num =
645 nftnl_chain_get_u32(nlc, NFTNL_CHAIN_HOOKNUM);
646 chain->hook.name =
647 hooknum2str(chain->handle.family, chain->hook.num);
648 priority = nftnl_chain_get_s32(nlc, NFTNL_CHAIN_PRIO);
649 chain->priority.expr =
650 constant_expr_alloc(&netlink_location,
651 &integer_type,
652 BYTEORDER_HOST_ENDIAN,
653 sizeof(int) * BITS_PER_BYTE,
654 &priority);
655 chain->type.str =
656 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_TYPE));
657 policy = nftnl_chain_get_u32(nlc, NFTNL_CHAIN_POLICY);
658 chain->policy = constant_expr_alloc(&netlink_location,
659 &integer_type,
660 BYTEORDER_HOST_ENDIAN,
661 sizeof(int) * BITS_PER_BYTE,
662 &policy);
663 nftnl_chain_get_u32(nlc, NFTNL_CHAIN_POLICY);
664 if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_DEV)) {
665 chain->dev_array = xmalloc(sizeof(char *) * 2);
666 chain->dev_array_len = 1;
667 chain->dev_array[0] =
668 xstrdup(nftnl_chain_get_str(nlc, NFTNL_CHAIN_DEV));
669 chain->dev_array[1] = NULL;
670 } else if (nftnl_chain_is_set(nlc, NFTNL_CHAIN_DEVICES)) {
671 dev_array = nftnl_chain_get(nlc, NFTNL_CHAIN_DEVICES);
672 while (dev_array[len])
673 len++;
674
675 chain->dev_array = xmalloc((len + 1)* sizeof(char *));
676 for (i = 0; i < len; i++)
677 chain->dev_array[i] = xstrdup(dev_array[i]);
678
679 chain->dev_array[i] = NULL;
680 chain->dev_array_len = len;
681 }
682 chain->flags |= CHAIN_F_BASECHAIN;
683
684 if (chain->dev_array_len) {
685 qsort(chain->dev_array, chain->dev_array_len,
686 sizeof(char *), qsort_device_cmp);
687 }
688 }
689
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");
694 chain_free(chain);
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
701 return chain;
702 }
703
704 static 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
723 struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
724 const struct nftnl_table *nlt)
725 {
726 const struct nftnl_udata *ud[NFTNL_UDATA_TABLE_MAX + 1] = {};
727 struct table *table;
728 const char *udata;
729 uint32_t ulen;
730
731 table = table_alloc();
732 table->handle.family = nftnl_table_get_u32(nlt, NFTNL_TABLE_FAMILY);
733 table->handle.table.name = xstrdup(nftnl_table_get_str(nlt, NFTNL_TABLE_NAME));
734 table->flags = nftnl_table_get_u32(nlt, NFTNL_TABLE_FLAGS);
735 table->handle.handle.id = nftnl_table_get_u64(nlt, NFTNL_TABLE_HANDLE);
736 table->owner = nftnl_table_get_u32(nlt, NFTNL_TABLE_OWNER);
737
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");
742 table_free(table);
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
749 return table;
750 }
751
752 static int list_table_cb(struct nftnl_table *nlt, void *arg)
753 {
754 struct netlink_ctx *ctx = arg;
755 struct table *table;
756
757 table = netlink_delinearize_table(ctx, nlt);
758 list_add_tail(&table->list, &ctx->list);
759
760 return 0;
761 }
762
763 int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h,
764 const struct nft_cache_filter *filter)
765 {
766 struct nftnl_table_list *table_cache;
767 uint32_t family = h->family;
768 const char *table = NULL;
769
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);
776 if (table_cache == NULL) {
777 if (errno == EINTR)
778 return -1;
779
780 return -1;
781 }
782
783 ctx->data = h;
784 nftnl_table_list_foreach(table_cache, list_table_cb, ctx);
785 nftnl_table_list_free(table_cache);
786 return 0;
787 }
788
789 enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype)
790 {
791 switch (dtype->type) {
792 case TYPE_VERDICT:
793 return NFT_DATA_VERDICT;
794 default:
795 return dtype->type;
796 }
797 }
798
799 static const struct datatype *dtype_map_from_kernel(enum nft_data_types type)
800 {
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 */
805 switch (type) {
806 case NFT_DATA_VERDICT:
807 return &verdict_type;
808 default:
809 if (type & ~TYPE_MASK)
810 return concat_type_alloc(type);
811 return datatype_lookup((enum datatypes) type);
812 }
813 }
814
815 void netlink_dump_set(const struct nftnl_set *nls, struct netlink_ctx *ctx)
816 {
817 FILE *fp = ctx->nft->output.output_fp;
818
819 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
820 return;
821
822 nftnl_set_fprintf(fp, nls, 0, 0);
823 fprintf(fp, "\n");
824 }
825
826 static int set_parse_udata_cb(const struct nftnl_udata *attr, void *data)
827 {
828 unsigned char *value = nftnl_udata_get(attr);
829 const struct nftnl_udata **tb = data;
830 uint8_t type = nftnl_udata_type(attr);
831 uint8_t len = nftnl_udata_len(attr);
832
833 switch (type) {
834 case NFTNL_UDATA_SET_KEYBYTEORDER:
835 case NFTNL_UDATA_SET_DATABYTEORDER:
836 case NFTNL_UDATA_SET_MERGE_ELEMENTS:
837 case NFTNL_UDATA_SET_DATA_INTERVAL:
838 if (len != sizeof(uint32_t))
839 return -1;
840 break;
841 case NFTNL_UDATA_SET_KEY_TYPEOF:
842 case NFTNL_UDATA_SET_DATA_TYPEOF:
843 if (len < 3)
844 return -1;
845 break;
846 case NFTNL_UDATA_SET_COMMENT:
847 if (value[len - 1] != '\0')
848 return -1;
849 break;
850 default:
851 return 0;
852 }
853 tb[type] = attr;
854 return 0;
855 }
856
857 static 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;
870 default:
871 return 0;
872 }
873 tb[type] = attr;
874 return 0;
875 }
876
877 static 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
907 static bool set_udata_key_valid(const struct expr *e, uint32_t len)
908 {
909 if (!e)
910 return false;
911
912 return div_round_up(e->len, BITS_PER_BYTE) == len / BITS_PER_BYTE;
913 }
914
915 struct setelem_parse_ctx {
916 struct set *set;
917 struct nft_cache *cache;
918 struct list_head stmt_list;
919 };
920
921 static 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
934 struct set *netlink_delinearize_set(struct netlink_ctx *ctx,
935 const struct nftnl_set *nls)
936 {
937 const struct nftnl_udata *ud[NFTNL_UDATA_SET_MAX + 1] = {};
938 enum byteorder keybyteorder = BYTEORDER_INVALID;
939 enum byteorder databyteorder = BYTEORDER_INVALID;
940 struct expr *typeof_expr_key, *typeof_expr_data;
941 struct setelem_parse_ctx set_parse_ctx;
942 const struct datatype *datatype = NULL;
943 const struct datatype *keytype = NULL;
944 const struct datatype *dtype2 = NULL;
945 const struct datatype *dtype = NULL;
946 const char *udata, *comment = NULL;
947 uint32_t flags, key, objtype = 0;
948 uint32_t data_interval = 0;
949 bool automerge = false;
950 struct set *set;
951 uint32_t ulen;
952 uint32_t klen;
953
954 typeof_expr_key = NULL;
955 typeof_expr_data = NULL;
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
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);
971 GET_U32_UDATA(data_interval, NFTNL_UDATA_SET_DATA_INTERVAL);
972
973 #undef GET_U32_UDATA
974 typeof_expr_key = set_make_key(ud[NFTNL_UDATA_SET_KEY_TYPEOF]);
975 if (ud[NFTNL_UDATA_SET_DATA_TYPEOF])
976 typeof_expr_data = set_make_key(ud[NFTNL_UDATA_SET_DATA_TYPEOF]);
977 if (ud[NFTNL_UDATA_SET_COMMENT])
978 comment = nftnl_udata_get(ud[NFTNL_UDATA_SET_COMMENT]);
979 }
980
981 key = nftnl_set_get_u32(nls, NFTNL_SET_KEY_TYPE);
982 keytype = dtype_map_from_kernel(key);
983 if (keytype == NULL) {
984 netlink_io_error(ctx, NULL, "Unknown data type in set key %u",
985 key);
986 return NULL;
987 }
988
989 flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
990 if (set_is_datamap(flags)) {
991 uint32_t data;
992
993 data = nftnl_set_get_u32(nls, NFTNL_SET_DATA_TYPE);
994 datatype = dtype_map_from_kernel(data);
995 if (datatype == NULL) {
996 netlink_io_error(ctx, NULL,
997 "Unknown data type in set key %u",
998 data);
999 set = NULL;
1000 goto out;
1001 }
1002 }
1003
1004 if (set_is_objmap(flags)) {
1005 objtype = nftnl_set_get_u32(nls, NFTNL_SET_OBJ_TYPE);
1006 assert(!datatype);
1007 datatype = &string_type;
1008 }
1009
1010 set = set_alloc(&netlink_location);
1011 set->handle.family = nftnl_set_get_u32(nls, NFTNL_SET_FAMILY);
1012 set->handle.table.name = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_TABLE));
1013 set->handle.set.name = xstrdup(nftnl_set_get_str(nls, NFTNL_SET_NAME));
1014 set->automerge = automerge;
1015 if (comment)
1016 set->comment = xstrdup(comment);
1017
1018 init_list_head(&set_parse_ctx.stmt_list);
1019
1020 if (nftnl_set_is_set(nls, NFTNL_SET_EXPR)) {
1021 const struct nftnl_expr *nle;
1022 struct stmt *stmt;
1023
1024 nle = nftnl_set_get(nls, NFTNL_SET_EXPR);
1025 stmt = netlink_parse_set_expr(set, &ctx->nft->cache, nle);
1026 list_add_tail(&stmt->list, &set_parse_ctx.stmt_list);
1027 } else if (nftnl_set_is_set(nls, NFTNL_SET_EXPRESSIONS)) {
1028 set_parse_ctx.cache = &ctx->nft->cache;
1029 set_parse_ctx.set = set;
1030 nftnl_set_expr_foreach(nls, set_elem_parse_expressions,
1031 &set_parse_ctx);
1032 }
1033 list_splice_tail(&set_parse_ctx.stmt_list, &set->stmt_list);
1034
1035 if (datatype) {
1036 uint32_t dlen;
1037
1038 dtype2 = set_datatype_alloc(datatype, databyteorder);
1039 klen = nftnl_set_get_u32(nls, NFTNL_SET_DATA_LEN) * BITS_PER_BYTE;
1040
1041 dlen = data_interval ? klen / 2 : klen;
1042
1043 if (set_udata_key_valid(typeof_expr_data, dlen)) {
1044 typeof_expr_data->len = klen;
1045 set->data = typeof_expr_data;
1046 } else {
1047 expr_free(typeof_expr_data);
1048 set->data = constant_expr_alloc(&netlink_location,
1049 dtype2,
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
1058 if (data_interval)
1059 set->data->flags |= EXPR_F_INTERVAL;
1060 }
1061
1062 dtype = set_datatype_alloc(keytype, keybyteorder);
1063 klen = nftnl_set_get_u32(nls, NFTNL_SET_KEY_LEN) * BITS_PER_BYTE;
1064
1065 if (set_udata_key_valid(typeof_expr_key, klen)) {
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
1075 set->flags = nftnl_set_get_u32(nls, NFTNL_SET_FLAGS);
1076 set->handle.handle.id = nftnl_set_get_u64(nls, NFTNL_SET_HANDLE);
1077
1078 set->objtype = objtype;
1079
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);
1084
1085 if (nftnl_set_is_set(nls, NFTNL_SET_POLICY))
1086 set->policy = nftnl_set_get_u32(nls, NFTNL_SET_POLICY);
1087
1088 if (nftnl_set_is_set(nls, NFTNL_SET_DESC_SIZE))
1089 set->desc.size = nftnl_set_get_u32(nls, NFTNL_SET_DESC_SIZE);
1090
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
1102 out:
1103 datatype_free(datatype);
1104 datatype_free(keytype);
1105 datatype_free(dtype2);
1106 datatype_free(dtype);
1107 return set;
1108 }
1109
1110 void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls)
1111 {
1112 struct nftnl_set_elem *nlse;
1113 const struct expr *expr;
1114
1115 list_for_each_entry(expr, &set->expressions, list) {
1116 nlse = alloc_nftnl_setelem(set, expr);
1117 nftnl_set_elem_add(nls, nlse);
1118 }
1119 }
1120
1121 static bool range_expr_is_prefix(const struct expr *range, uint32_t *prefix_len)
1122 {
1123 const struct expr *right = range->right;
1124 const struct expr *left = range->left;
1125 uint32_t len = left->len;
1126 unsigned long n1, n2;
1127 uint32_t plen;
1128 mpz_t bitmask;
1129
1130 mpz_init2(bitmask, left->len);
1131 mpz_xor(bitmask, left->value, right->value);
1132
1133 n1 = mpz_scan0(bitmask, 0);
1134 if (n1 == ULONG_MAX)
1135 goto not_a_prefix;
1136
1137 n2 = mpz_scan1(bitmask, n1 + 1);
1138 if (n2 < len)
1139 goto not_a_prefix;
1140
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
1151 not_a_prefix:
1152 mpz_clear(bitmask);
1153
1154 return false;
1155 }
1156
1157 struct expr *range_expr_to_prefix(struct expr *range)
1158 {
1159 struct expr *prefix;
1160 uint32_t prefix_len;
1161
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;
1168 }
1169
1170 return range;
1171 }
1172
1173 static 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
1190 static struct expr *netlink_parse_interval_elem(const struct set *set,
1191 struct expr *expr)
1192 {
1193 unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
1194 const struct datatype *dtype = set->data->dtype;
1195 struct expr *range, *left, *right;
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
1208 return range_expr_to_prefix(range);
1209 }
1210
1211 static struct expr *concat_elem_expr(const struct set *set, struct expr *key,
1212 const struct datatype *dtype,
1213 struct expr *data, int *off)
1214 {
1215 const struct datatype *subtype;
1216 unsigned int sub_length;
1217 struct expr *expr;
1218
1219 if (key) {
1220 (*off)--;
1221 sub_length = round_up(key->len, BITS_PER_BYTE);
1222
1223 expr = constant_expr_splice(data, sub_length);
1224 expr->dtype = datatype_get(key->dtype);
1225 expr->byteorder = key->byteorder;
1226 expr->len = key->len;
1227 } else {
1228 subtype = concat_subtype_lookup(dtype->type, --(*off));
1229 sub_length = round_up(subtype->size, BITS_PER_BYTE);
1230 expr = constant_expr_splice(data, sub_length);
1231 expr->dtype = subtype;
1232 expr->byteorder = subtype->byteorder;
1233 }
1234
1235 if (expr_basetype(expr)->type == TYPE_STRING ||
1236 (!(set->flags & NFT_SET_INTERVAL) &&
1237 expr->byteorder == BYTEORDER_HOST_ENDIAN))
1238 mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
1239
1240 if (expr->dtype->basetype != NULL &&
1241 expr->dtype->basetype->type == TYPE_BITMASK)
1242 expr = bitmask_expr_to_binops(expr);
1243
1244 data->len -= netlink_padding_len(sub_length);
1245
1246 return expr;
1247 }
1248
1249 static struct expr *netlink_parse_concat_elem_key(const struct set *set,
1250 struct expr *data)
1251 {
1252 const struct datatype *dtype = set->key->dtype;
1253 struct expr *concat, *expr, *n = NULL;
1254 int off = dtype->subtypes;
1255
1256 if (set->key->etype == EXPR_CONCAT)
1257 n = list_first_entry(&set->key->expressions, struct expr, list);
1258
1259 concat = concat_expr_alloc(&data->location);
1260 while (off > 0) {
1261 expr = concat_elem_expr(set, n, dtype, data, &off);
1262 compound_expr_add(concat, expr);
1263 if (set->key->etype == EXPR_CONCAT)
1264 n = list_next_entry(n, list);
1265 }
1266
1267 expr_free(data);
1268
1269 return concat;
1270 }
1271
1272 static 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) {
1284 expr = concat_elem_expr(set, NULL, dtype, data, &off);
1285 list_add_tail(&expr->list, &expressions);
1286 }
1287
1288 if (set->data->flags & EXPR_F_INTERVAL) {
1289 assert(!list_empty(&expressions));
1290
1291 off = dtype->subtypes;
1292
1293 while (off > 0) {
1294 left = list_first_entry(&expressions, struct expr, list);
1295
1296 expr = concat_elem_expr(set, NULL, dtype, data, &off);
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);
1306 }
1307
1308 expr_free(data);
1309
1310 return concat;
1311 }
1312
1313 static int set_elem_parse_udata_cb(const struct nftnl_udata *attr, void *data)
1314 {
1315 const struct nftnl_udata **tb = data;
1316 unsigned char *value = nftnl_udata_get(attr);
1317 uint8_t type = nftnl_udata_type(attr);
1318 uint8_t len = nftnl_udata_len(attr);
1319
1320 switch (type) {
1321 case NFTNL_UDATA_SET_ELEM_COMMENT:
1322 if (value[len - 1] != '\0')
1323 return -1;
1324 break;
1325 case NFTNL_UDATA_SET_ELEM_FLAGS:
1326 if (len != sizeof(uint32_t))
1327 return -1;
1328 break;
1329 default:
1330 return 0;
1331 }
1332 tb[type] = attr;
1333 return 0;
1334 }
1335
1336 static void set_elem_parse_udata(struct nftnl_set_elem *nlse,
1337 struct expr *expr)
1338 {
1339 const struct nftnl_udata *ud[NFTNL_UDATA_SET_ELEM_MAX + 1] = {};
1340 const void *data;
1341 uint32_t len;
1342
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;
1346
1347 if (ud[NFTNL_UDATA_SET_ELEM_COMMENT])
1348 expr->comment =
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]);
1353 }
1354
1355 int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
1356 struct set *set, struct nft_cache *cache)
1357 {
1358 struct setelem_parse_ctx setelem_parse_ctx = {
1359 .set = set,
1360 .cache = cache,
1361 };
1362 struct nft_data_delinearize nld;
1363 struct expr *expr, *key, *data;
1364 uint32_t flags = 0;
1365
1366 init_list_head(&setelem_parse_ctx.stmt_list);
1367
1368 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_KEY))
1369 nld.value = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_KEY, &nld.len);
1370 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_FLAGS))
1371 flags = nftnl_set_elem_get_u32(nlse, NFTNL_SET_ELEM_FLAGS);
1372
1373 key_end:
1374 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_KEY)) {
1375 key = netlink_alloc_value(&netlink_location, &nld);
1376 datatype_set(key, set->key->dtype);
1377 key->byteorder = set->key->byteorder;
1378 if (set->key->dtype->subtypes)
1379 key = netlink_parse_concat_elem_key(set, key);
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 }
1396
1397 expr = set_elem_expr_alloc(&netlink_location, key);
1398 expr->flags |= EXPR_F_KERNEL;
1399
1400 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_TIMEOUT))
1401 expr->timeout = nftnl_set_elem_get_u64(nlse, NFTNL_SET_ELEM_TIMEOUT);
1402 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPIRATION))
1403 expr->expiration = nftnl_set_elem_get_u64(nlse, NFTNL_SET_ELEM_EXPIRATION);
1404 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_USERDATA))
1405 set_elem_parse_udata(nlse, expr);
1406 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPR)) {
1407 const struct nftnl_expr *nle;
1408 struct stmt *stmt;
1409
1410 nle = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_EXPR, NULL);
1411 stmt = netlink_parse_set_expr(set, cache, nle);
1412 list_add_tail(&stmt->list, &setelem_parse_ctx.stmt_list);
1413 } else if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_EXPRESSIONS)) {
1414 nftnl_set_elem_expr_foreach(nlse, set_elem_parse_expressions,
1415 &setelem_parse_ctx);
1416 }
1417 list_splice_tail_init(&setelem_parse_ctx.stmt_list, &expr->stmt_list);
1418
1419 if (flags & NFT_SET_ELEM_INTERVAL_END) {
1420 expr->flags |= EXPR_F_INTERVAL_END;
1421 if (mpz_cmp_ui(set->key->value, 0) == 0)
1422 set->root = true;
1423 }
1424
1425 if (set_is_datamap(set->flags)) {
1426 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_DATA)) {
1427 nld.value = nftnl_set_elem_get(nlse, NFTNL_SET_ELEM_DATA,
1428 &nld.len);
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);
1434 } else
1435 goto out;
1436
1437 data = netlink_alloc_data(&netlink_location, &nld,
1438 set->data->dtype->type == TYPE_VERDICT ?
1439 NFT_REG_VERDICT : NFT_REG_1);
1440 datatype_set(data, set->data->dtype);
1441 data->byteorder = set->data->byteorder;
1442
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);
1447
1448 if (data->byteorder == BYTEORDER_HOST_ENDIAN)
1449 mpz_switch_byteorder(data->value, data->len / BITS_PER_BYTE);
1450
1451 expr = mapping_expr_alloc(&netlink_location, expr, data);
1452 }
1453 if (set_is_objmap(set->flags)) {
1454 if (nftnl_set_elem_is_set(nlse, NFTNL_SET_ELEM_OBJREF)) {
1455 nld.value = nftnl_set_elem_get(nlse,
1456 NFTNL_SET_ELEM_OBJREF,
1457 &nld.len);
1458 } else
1459 goto out;
1460
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);
1466 }
1467 out:
1468 compound_expr_add(set->init, expr);
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
1478 return 0;
1479 }
1480
1481 static int list_setelem_cb(struct nftnl_set_elem *nlse, void *arg)
1482 {
1483 struct netlink_ctx *ctx = arg;
1484 return netlink_delinearize_setelem(nlse, ctx->set, &ctx->nft->cache);
1485 }
1486
1487 static 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
1504 static 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
1523 int netlink_list_setelems(struct netlink_ctx *ctx, const struct handle *h,
1524 struct set *set, bool reset)
1525 {
1526 struct nftnl_set *nls;
1527 int err;
1528
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);
1538
1539 err = mnl_nft_setelem_get(ctx, nls, reset);
1540 if (err < 0) {
1541 nftnl_set_free(nls);
1542 if (errno == EINTR)
1543 return -1;
1544
1545 return 0;
1546 }
1547
1548 ctx->set = set;
1549 set->init = set_expr_alloc(&internal_location, set);
1550 list_setelements(nls, ctx);
1551
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
1557 list_expr_sort(&ctx->set->init->expressions);
1558
1559 nftnl_set_free(nls);
1560 ctx->set = NULL;
1561
1562 return 0;
1563 }
1564
1565 int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
1566 const struct location *loc, struct set *cache_set,
1567 struct set *set, struct expr *init, bool reset)
1568 {
1569 struct nftnl_set *nls, *nls_out = NULL;
1570 int err = 0;
1571
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
1582 alloc_setelem_cache(init, nls);
1583
1584 netlink_dump_set(nls, ctx);
1585
1586 nls_out = mnl_nft_setelem_get_one(ctx, nls, reset);
1587 if (!nls_out) {
1588 nftnl_set_free(nls);
1589 return -1;
1590 }
1591
1592 ctx->set = set;
1593 set->init = set_expr_alloc(loc, set);
1594 list_setelements(nls_out, ctx);
1595
1596 if (set->flags & NFT_SET_INTERVAL && set->desc.field_count > 1)
1597 concat_range_aggregate(set->init);
1598 else if (set->flags & NFT_SET_INTERVAL)
1599 err = get_set_decompose(cache_set, set);
1600 else
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
1607 return err;
1608 }
1609
1610 void netlink_dump_obj(struct nftnl_obj *nln, struct netlink_ctx *ctx)
1611 {
1612 FILE *fp = ctx->nft->output.output_fp;
1613
1614 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
1615 return;
1616
1617 nftnl_obj_fprintf(fp, nln, 0, 0);
1618 fprintf(fp, "\n");
1619 }
1620
1621 static 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
1640 struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx,
1641 struct nftnl_obj *nlo)
1642 {
1643 const struct nftnl_udata *ud[NFTNL_UDATA_OBJ_MAX + 1] = {};
1644 const char *udata;
1645 struct obj *obj;
1646 uint32_t type;
1647 uint32_t ulen;
1648
1649 obj = obj_alloc(&netlink_location);
1650 obj->handle.family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY);
1651 obj->handle.table.name =
1652 xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_TABLE));
1653 obj->handle.obj.name =
1654 xstrdup(nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME));
1655 obj->handle.handle.id =
1656 nftnl_obj_get_u64(nlo, NFTNL_OBJ_HANDLE);
1657 if (nftnl_obj_is_set(nlo, NFTNL_OBJ_USERDATA)) {
1658 udata = nftnl_obj_get_data(nlo, NFTNL_OBJ_USERDATA, &ulen);
1659 if (nftnl_udata_parse(udata, ulen, obj_parse_udata_cb, ud) < 0) {
1660 netlink_io_error(ctx, NULL, "Cannot parse userdata");
1661 obj_free(obj);
1662 return NULL;
1663 }
1664 if (ud[NFTNL_UDATA_OBJ_COMMENT])
1665 obj->comment = xstrdup(nftnl_udata_get(ud[NFTNL_UDATA_OBJ_COMMENT]));
1666 }
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);
1683 break;
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;
1688 case NFT_OBJECT_CT_HELPER:
1689 snprintf(obj->ct_helper.name, sizeof(obj->ct_helper.name), "%s",
1690 nftnl_obj_get_str(nlo, NFTNL_OBJ_CT_HELPER_NAME));
1691 obj->ct_helper.l3proto = nftnl_obj_get_u16(nlo, NFTNL_OBJ_CT_HELPER_L3PROTO);
1692 obj->ct_helper.l4proto = nftnl_obj_get_u8(nlo, NFTNL_OBJ_CT_HELPER_L4PROTO);
1693 break;
1694 case NFT_OBJECT_CT_TIMEOUT:
1695 init_list_head(&obj->ct_timeout.timeout_list);
1696 obj->ct_timeout.l3proto = nftnl_obj_get_u16(nlo, NFTNL_OBJ_CT_TIMEOUT_L3PROTO);
1697 obj->ct_timeout.l4proto = nftnl_obj_get_u8(nlo, NFTNL_OBJ_CT_TIMEOUT_L4PROTO);
1698 memcpy(obj->ct_timeout.timeout,
1699 nftnl_obj_get(nlo, NFTNL_OBJ_CT_TIMEOUT_ARRAY),
1700 NFTNL_CTTIMEOUT_ARRAY_MAX * sizeof(uint32_t));
1701 break;
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;
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;
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;
1734 }
1735 obj->type = type;
1736
1737 return obj;
1738 }
1739
1740 void netlink_dump_flowtable(struct nftnl_flowtable *flo,
1741 struct netlink_ctx *ctx)
1742 {
1743 FILE *fp = ctx->nft->output.output_fp;
1744
1745 if (!(ctx->nft->debug_mask & NFT_DEBUG_NETLINK) || !fp)
1746 return;
1747
1748 nftnl_flowtable_fprintf(fp, flo, 0, 0);
1749 fprintf(fp, "\n");
1750 }
1751
1752 static 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
1764 int netlink_reset_objs(struct netlink_ctx *ctx, const struct cmd *cmd,
1765 uint32_t type, bool dump)
1766 {
1767 const struct handle *h = &cmd->handle;
1768 struct nftnl_obj_list *obj_cache;
1769 int err;
1770
1771 obj_cache = mnl_nft_obj_dump(ctx, h->family,
1772 h->table.name, h->obj.name, type, dump, true);
1773 if (obj_cache == NULL)
1774 return -1;
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
1781 int 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
1830 struct flowtable *
1831 netlink_delinearize_flowtable(struct netlink_ctx *ctx,
1832 struct nftnl_flowtable *nlo)
1833 {
1834 struct flowtable *flowtable;
1835 const char * const *dev_array;
1836 int len = 0, i, priority;
1837
1838 flowtable = flowtable_alloc(&netlink_location);
1839 flowtable->handle.family =
1840 nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FAMILY);
1841 flowtable->handle.table.name =
1842 xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_TABLE));
1843 flowtable->handle.flowtable.name =
1844 xstrdup(nftnl_flowtable_get_str(nlo, NFTNL_FLOWTABLE_NAME));
1845 flowtable->handle.handle.id =
1846 nftnl_flowtable_get_u64(nlo, NFTNL_FLOWTABLE_HANDLE);
1847 if (nftnl_flowtable_is_set(nlo, NFTNL_FLOWTABLE_FLAGS))
1848 flowtable->flags = nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FLAGS);
1849 dev_array = nftnl_flowtable_get(nlo, NFTNL_FLOWTABLE_DEVICES);
1850 while (dev_array[len])
1851 len++;
1852
1853 if (len)
1854 flowtable->dev_array = xmalloc(len * sizeof(char *));
1855 for (i = 0; i < len; i++)
1856 flowtable->dev_array[i] = xstrdup(dev_array[i]);
1857
1858 flowtable->dev_array_len = len;
1859
1860 if (flowtable->dev_array_len) {
1861 qsort(flowtable->dev_array, flowtable->dev_array_len,
1862 sizeof(char *), qsort_device_cmp);
1863 }
1864
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);
1873 flowtable->hook.num =
1874 nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_HOOKNUM);
1875 flowtable->flags =
1876 nftnl_flowtable_get_u32(nlo, NFTNL_FLOWTABLE_FLAGS);
1877
1878 return flowtable;
1879 }
1880
1881 static 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
1893 int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h)
1894 {
1895 struct nftnl_flowtable_list *flowtable_cache;
1896 int err;
1897
1898 flowtable_cache = mnl_nft_flowtable_dump(ctx, h->family,
1899 h->table.name, NULL);
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
1912 static void trace_print_hdr(const struct nftnl_trace *nlt,
1913 struct output_ctx *octx)
1914 {
1915 nft_print(octx, "trace id %08x %s ",
1916 nftnl_trace_get_u32(nlt, NFTNL_TRACE_ID),
1917 family2str(nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY)));
1918 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_TABLE))
1919 nft_print(octx, "%s ",
1920 nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE));
1921 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_CHAIN))
1922 nft_print(octx, "%s ",
1923 nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN));
1924 }
1925
1926 static void trace_print_expr(const struct nftnl_trace *nlt, unsigned int attr,
1927 struct expr *lhs, struct output_ctx *octx)
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
1939 expr_print(rel, octx);
1940 nft_print(octx, " ");
1941 expr_free(rel);
1942 }
1943
1944 static void trace_print_verdict(const struct nftnl_trace *nlt,
1945 struct output_ctx *octx)
1946 {
1947 struct expr *chain_expr = NULL;
1948 const char *chain = NULL;
1949 unsigned int verdict;
1950 struct expr *expr;
1951
1952 verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT);
1953 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) {
1954 chain = xstrdup(nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET));
1955 chain_expr = constant_expr_alloc(&netlink_location,
1956 &string_type,
1957 BYTEORDER_HOST_ENDIAN,
1958 strlen(chain) * BITS_PER_BYTE,
1959 chain);
1960 }
1961 expr = verdict_expr_alloc(&netlink_location, verdict, chain_expr);
1962
1963 nft_print(octx, "verdict ");
1964 expr_print(expr, octx);
1965 expr_free(expr);
1966 }
1967
1968 static 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 ");
1979 expr_print(expr, octx);
1980 expr_free(expr);
1981 }
1982
1983 static struct rule *trace_lookup_rule(const struct nftnl_trace *nlt,
1984 uint64_t rule_handle,
1985 struct nft_cache *cache)
1986 {
1987 struct chain *chain;
1988 struct table *table;
1989 struct handle h;
1990
1991 h.family = nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY);
1992 h.table.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_TABLE);
1993 h.chain.name = nftnl_trace_get_str(nlt, NFTNL_TRACE_CHAIN);
1994
1995 if (!h.table.name)
1996 return NULL;
1997
1998 table = table_cache_find(&cache->table_cache, h.table.name, h.family);
1999 if (!table)
2000 return NULL;
2001
2002 chain = chain_cache_find(table, h.chain.name);
2003 if (!chain)
2004 return NULL;
2005
2006 return rule_lookup(chain, rule_handle);
2007 }
2008
2009 static 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;
2014
2015 rule_handle = nftnl_trace_get_u64(nlt, NFTNL_TRACE_RULE_HANDLE);
2016 rule = trace_lookup_rule(nlt, rule_handle, cache);
2017
2018 trace_print_hdr(nlt, octx);
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
2027 nft_print(octx, " (");
2028 trace_print_verdict(nlt, octx);
2029 nft_print(octx, ")\n");
2030 }
2031
2032 static void trace_gen_stmts(struct list_head *stmts,
2033 struct proto_ctx *ctx, struct payload_dep_ctx *pctx,
2034 const struct nftnl_trace *nlt, unsigned int attr,
2035 enum proto_bases base)
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;
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
2056 restart:
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;
2091 relational_expr_pctx_update(ctx, rel);
2092 }
2093
2094 expr_free(rhs);
2095
2096 n = 0;
2097 next:
2098 list_for_each_entry(stmt, &unordered, list) {
2099 enum proto_bases b = base;
2100
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
2113 if (payload_is_stacked(desc, rel))
2114 b--;
2115
2116 /* Don't strip 'icmp type' from payload dump. */
2117 if (pctx->icmp_type == 0)
2118 payload_dependency_kill(pctx, lhs, ctx->family);
2119 if (lhs->flags & EXPR_F_PROTOCOL)
2120 payload_dependency_store(pctx, stmt, b);
2121
2122 goto next;
2123 }
2124 }
2125
2126 static void trace_print_packet(const struct nftnl_trace *nlt,
2127 struct output_ctx *octx)
2128 {
2129 struct list_head stmts = LIST_HEAD_INIT(stmts);
2130 const struct proto_desc *ll_desc;
2131 struct payload_dep_ctx pctx = {};
2132 struct proto_ctx ctx;
2133 uint16_t dev_type;
2134 uint32_t nfproto;
2135 struct stmt *stmt, *next;
2136
2137 trace_print_hdr(nlt, octx);
2138
2139 nft_print(octx, "packet: ");
2140 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_IIF))
2141 trace_print_expr(nlt, NFTNL_TRACE_IIF,
2142 meta_expr_alloc(&netlink_location,
2143 NFT_META_IIF), octx);
2144 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_OIF))
2145 trace_print_expr(nlt, NFTNL_TRACE_OIF,
2146 meta_expr_alloc(&netlink_location,
2147 NFT_META_OIF), octx);
2148
2149 proto_ctx_init(&ctx, nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY), 0, false);
2150 ll_desc = ctx.protocol[PROTO_BASE_LL_HDR].desc;
2151 if ((ll_desc == &proto_inet || ll_desc == &proto_netdev) &&
2152 nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) {
2153 nfproto = nftnl_trace_get_u32(nlt, NFTNL_TRACE_NFPROTO);
2154
2155 proto_ctx_update(&ctx, PROTO_BASE_LL_HDR, &netlink_location, NULL);
2156 proto_ctx_update(&ctx, PROTO_BASE_NETWORK_HDR, &netlink_location,
2157 proto_find_upper(ll_desc, nfproto));
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) {
2174 stmt_print(stmt, octx);
2175 nft_print(octx, " ");
2176 stmt_free(stmt);
2177 }
2178 nft_print(octx, "\n");
2179 }
2180
2181 int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
2182 struct netlink_mon_handler *monh)
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
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
2199 switch (nftnl_trace_get_u32(nlt, NFTNL_TRACE_TYPE)) {
2200 case NFT_TRACETYPE_RULE:
2201 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_RULE_HANDLE))
2202 trace_print_rule(nlt, &monh->ctx->nft->output,
2203 &monh->ctx->nft->cache);
2204 break;
2205 case NFT_TRACETYPE_POLICY:
2206 trace_print_hdr(nlt, &monh->ctx->nft->output);
2207
2208 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_POLICY)) {
2209 trace_print_policy(nlt, &monh->ctx->nft->output);
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),
2217 &monh->ctx->nft->output);
2218 nft_mon_print(monh, "\n");
2219 break;
2220 case NFT_TRACETYPE_RETURN:
2221 trace_print_hdr(nlt, &monh->ctx->nft->output);
2222
2223 if (nftnl_trace_is_set(nlt, NFTNL_TRACE_VERDICT)) {
2224 trace_print_verdict(nlt, &monh->ctx->nft->output);
2225 nft_mon_print(monh, " ");
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,
2231 NFT_META_MARK),
2232 &monh->ctx->nft->output);
2233 nft_mon_print(monh, "\n");
2234 break;
2235 }
2236
2237 nftnl_trace_free(nlt);
2238 return MNL_CB_OK;
2239 }