libnftnl 1.2.9
ruleset.c
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
4 * (C) 2013 by Arturo Borrero Gonzalez <arturo@debian.org>
5 * (C) 2013 by Alvaro Neira Ayuso <alvaroneay@gmail.com>
6 *
7 * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
8 */
9
10#include <errno.h>
11
12#include "internal.h"
13#include <stdlib.h>
14
15#include <libmnl/libmnl.h>
16#include <libnftnl/ruleset.h>
17#include <libnftnl/table.h>
18#include <libnftnl/chain.h>
19#include <libnftnl/set.h>
20#include <libnftnl/rule.h>
21
23 struct nftnl_table_list *table_list;
24 struct nftnl_chain_list *chain_list;
25 struct nftnl_set_list *set_list;
26 struct nftnl_rule_list *rule_list;
27
28 uint16_t flags;
29};
30
32 enum nftnl_cmd_type cmd;
33 enum nftnl_ruleset_type type;
34 union {
35 struct nftnl_table *table;
36 struct nftnl_chain *chain;
37 struct nftnl_rule *rule;
38 struct nftnl_set *set;
39 struct nftnl_set_elem *set_elem;
40 };
41 void *data;
42
43 /* These fields below are not exposed to the user */
44 uint32_t format;
45 uint32_t set_id;
46 struct nftnl_set_list *set_list;
47
48 int (*cb)(const struct nftnl_parse_ctx *ctx);
49 uint16_t flags;
50};
51
52EXPORT_SYMBOL(nftnl_ruleset_alloc);
53struct nftnl_ruleset *nftnl_ruleset_alloc(void)
54{
55 return calloc(1, sizeof(struct nftnl_ruleset));
56}
57
58EXPORT_SYMBOL(nftnl_ruleset_free);
59void nftnl_ruleset_free(const struct nftnl_ruleset *r)
60{
61 if (r->flags & (1 << NFTNL_RULESET_TABLELIST))
62 nftnl_table_list_free(r->table_list);
63 if (r->flags & (1 << NFTNL_RULESET_CHAINLIST))
64 nftnl_chain_list_free(r->chain_list);
65 if (r->flags & (1 << NFTNL_RULESET_SETLIST))
66 nftnl_set_list_free(r->set_list);
67 if (r->flags & (1 << NFTNL_RULESET_RULELIST))
68 nftnl_rule_list_free(r->rule_list);
69 xfree(r);
70}
71
72EXPORT_SYMBOL(nftnl_ruleset_is_set);
73bool nftnl_ruleset_is_set(const struct nftnl_ruleset *r, uint16_t attr)
74{
75 return r->flags & (1 << attr);
76}
77
78EXPORT_SYMBOL(nftnl_ruleset_unset);
79void nftnl_ruleset_unset(struct nftnl_ruleset *r, uint16_t attr)
80{
81 if (!(r->flags & (1 << attr)))
82 return;
83
84 switch (attr) {
85 case NFTNL_RULESET_TABLELIST:
86 nftnl_table_list_free(r->table_list);
87 break;
88 case NFTNL_RULESET_CHAINLIST:
89 nftnl_chain_list_free(r->chain_list);
90 break;
91 case NFTNL_RULESET_SETLIST:
92 nftnl_set_list_free(r->set_list);
93 break;
94 case NFTNL_RULESET_RULELIST:
95 nftnl_rule_list_free(r->rule_list);
96 break;
97 }
98 r->flags &= ~(1 << attr);
99}
100
101EXPORT_SYMBOL(nftnl_ruleset_set);
102void nftnl_ruleset_set(struct nftnl_ruleset *r, uint16_t attr, void *data)
103{
104 switch (attr) {
105 case NFTNL_RULESET_TABLELIST:
106 nftnl_ruleset_unset(r, NFTNL_RULESET_TABLELIST);
107 r->table_list = data;
108 break;
109 case NFTNL_RULESET_CHAINLIST:
110 nftnl_ruleset_unset(r, NFTNL_RULESET_CHAINLIST);
111 r->chain_list = data;
112 break;
113 case NFTNL_RULESET_SETLIST:
114 nftnl_ruleset_unset(r, NFTNL_RULESET_SETLIST);
115 r->set_list = data;
116 break;
117 case NFTNL_RULESET_RULELIST:
118 nftnl_ruleset_unset(r, NFTNL_RULESET_RULELIST);
119 r->rule_list = data;
120 break;
121 default:
122 return;
123 }
124 r->flags |= (1 << attr);
125}
126
127EXPORT_SYMBOL(nftnl_ruleset_get);
128void *nftnl_ruleset_get(const struct nftnl_ruleset *r, uint16_t attr)
129{
130 if (!(r->flags & (1 << attr)))
131 return NULL;
132
133 switch (attr) {
134 case NFTNL_RULESET_TABLELIST:
135 return r->table_list;
136 case NFTNL_RULESET_CHAINLIST:
137 return r->chain_list;
138 case NFTNL_RULESET_SETLIST:
139 return r->set_list;
140 case NFTNL_RULESET_RULELIST:
141 return r->rule_list;
142 default:
143 return NULL;
144 }
145}
146
147EXPORT_SYMBOL(nftnl_ruleset_ctx_free);
148void nftnl_ruleset_ctx_free(const struct nftnl_parse_ctx *ctx)
149{
150 switch (ctx->type) {
151 case NFTNL_RULESET_TABLE:
152 nftnl_table_free(ctx->table);
153 break;
154 case NFTNL_RULESET_CHAIN:
155 nftnl_chain_free(ctx->chain);
156 break;
157 case NFTNL_RULESET_RULE:
158 nftnl_rule_free(ctx->rule);
159 break;
160 case NFTNL_RULESET_SET:
161 case NFTNL_RULESET_SET_ELEMS:
162 nftnl_set_free(ctx->set);
163 break;
164 case NFTNL_RULESET_RULESET:
165 case NFTNL_RULESET_UNSPEC:
166 break;
167 }
168}
169
170EXPORT_SYMBOL(nftnl_ruleset_ctx_is_set);
171bool nftnl_ruleset_ctx_is_set(const struct nftnl_parse_ctx *ctx, uint16_t attr)
172{
173 return ctx->flags & (1 << attr);
174}
175
176EXPORT_SYMBOL(nftnl_ruleset_ctx_get);
177void *nftnl_ruleset_ctx_get(const struct nftnl_parse_ctx *ctx, uint16_t attr)
178{
179 if (!(ctx->flags & (1 << attr)))
180 return NULL;
181
182 switch (attr) {
183 case NFTNL_RULESET_CTX_CMD:
184 return (void *)&ctx->cmd;
185 case NFTNL_RULESET_CTX_TYPE:
186 return (void *)&ctx->type;
187 case NFTNL_RULESET_CTX_TABLE:
188 return ctx->table;
189 case NFTNL_RULESET_CTX_CHAIN:
190 return ctx->chain;
191 case NFTNL_RULESET_CTX_RULE:
192 return ctx->rule;
193 case NFTNL_RULESET_CTX_SET:
194 return ctx->set;
195 case NFTNL_RULESET_CTX_DATA:
196 return ctx->data;
197 default:
198 return NULL;
199 }
200}
201
202EXPORT_SYMBOL(nftnl_ruleset_ctx_get_u32);
203uint32_t nftnl_ruleset_ctx_get_u32(const struct nftnl_parse_ctx *ctx, uint16_t attr)
204{
205 const void *ret = nftnl_ruleset_ctx_get(ctx, attr);
206 return ret == NULL ? 0 : *((uint32_t *)ret);
207}
208
209
210EXPORT_SYMBOL(nftnl_ruleset_parse_file_cb);
211int nftnl_ruleset_parse_file_cb(enum nftnl_parse_type type, FILE *fp,
212 struct nftnl_parse_err *err, void *data,
213 int (*cb)(const struct nftnl_parse_ctx *ctx))
214{
215 errno = EOPNOTSUPP;
216 return -1;
217}
218
219EXPORT_SYMBOL(nftnl_ruleset_parse_buffer_cb);
220int nftnl_ruleset_parse_buffer_cb(enum nftnl_parse_type type, const char *buffer,
221 struct nftnl_parse_err *err, void *data,
222 int (*cb)(const struct nftnl_parse_ctx *ctx))
223{
224 errno = EOPNOTSUPP;
225 return -1;
226}
227
228static int nftnl_ruleset_cb(const struct nftnl_parse_ctx *ctx)
229{
230 struct nftnl_ruleset *r = ctx->data;
231
232 if (ctx->cmd != NFTNL_CMD_ADD)
233 return -1;
234
235 switch (ctx->type) {
236 case NFTNL_RULESET_TABLE:
237 if (r->table_list == NULL) {
238 r->table_list = nftnl_table_list_alloc();
239 if (r->table_list == NULL)
240 return -1;
241
242 nftnl_ruleset_set(r, NFTNL_RULESET_TABLELIST,
243 r->table_list);
244 }
245 nftnl_table_list_add_tail(ctx->table, r->table_list);
246 break;
247 case NFTNL_RULESET_CHAIN:
248 if (r->chain_list == NULL) {
249 r->chain_list = nftnl_chain_list_alloc();
250 if (r->chain_list == NULL)
251 return -1;
252
253 nftnl_ruleset_set(r, NFTNL_RULESET_CHAINLIST,
254 r->chain_list);
255 }
256 nftnl_chain_list_add_tail(ctx->chain, r->chain_list);
257 break;
258 case NFTNL_RULESET_SET:
259 if (r->set_list == NULL) {
260 r->set_list = nftnl_set_list_alloc();
261 if (r->set_list == NULL)
262 return -1;
263
264 nftnl_ruleset_set(r, NFTNL_RULESET_SETLIST,
265 r->set_list);
266 }
267 nftnl_set_list_add_tail(ctx->set, r->set_list);
268 break;
269 case NFTNL_RULESET_RULE:
270 if (r->rule_list == NULL) {
271 r->rule_list = nftnl_rule_list_alloc();
272 if (r->rule_list == NULL)
273 return -1;
274
275 nftnl_ruleset_set(r, NFTNL_RULESET_RULELIST,
276 r->rule_list);
277 }
278 nftnl_rule_list_add_tail(ctx->rule, r->rule_list);
279 break;
280 case NFTNL_RULESET_RULESET:
281 break;
282 default:
283 return -1;
284 }
285
286 return 0;
287}
288
289EXPORT_SYMBOL(nftnl_ruleset_parse);
290int nftnl_ruleset_parse(struct nftnl_ruleset *r, enum nftnl_parse_type type,
291 const char *data, struct nftnl_parse_err *err)
292{
293 errno = EOPNOTSUPP;
294 return -1;
295}
296
297EXPORT_SYMBOL(nftnl_ruleset_parse_file);
298int nftnl_ruleset_parse_file(struct nftnl_ruleset *rs, enum nftnl_parse_type type,
299 FILE *fp, struct nftnl_parse_err *err)
300{
301 return nftnl_ruleset_parse_file_cb(type, fp, err, rs, nftnl_ruleset_cb);
302}
303
304static int
305nftnl_ruleset_snprintf_table(char *buf, size_t remain,
306 const struct nftnl_ruleset *rs, uint32_t type,
307 uint32_t flags)
308{
309 struct nftnl_table *t;
310 struct nftnl_table_list_iter *ti;
311 const char *sep = "";
312 int ret, offset = 0;
313
314 ti = nftnl_table_list_iter_create(rs->table_list);
315 if (ti == NULL)
316 return 0;
317
318 t = nftnl_table_list_iter_next(ti);
319 while (t != NULL) {
320 ret = snprintf(buf + offset, remain, "%s", sep);
321 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
322
323 ret = nftnl_table_snprintf(buf + offset, remain, t, type, flags);
324 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
325
326 t = nftnl_table_list_iter_next(ti);
327 sep = "\n";
328 }
329 nftnl_table_list_iter_destroy(ti);
330
331 return offset;
332}
333
334static int
335nftnl_ruleset_snprintf_chain(char *buf, size_t remain,
336 const struct nftnl_ruleset *rs, uint32_t type,
337 uint32_t flags)
338{
339 struct nftnl_chain *c;
340 struct nftnl_chain_list_iter *ci;
341 const char *sep = "";
342 int ret, offset = 0;
343
344 ci = nftnl_chain_list_iter_create(rs->chain_list);
345 if (ci == NULL)
346 return 0;
347
348 c = nftnl_chain_list_iter_next(ci);
349 while (c != NULL) {
350 ret = snprintf(buf + offset, remain, "%s", sep);
351 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
352
353 ret = nftnl_chain_snprintf(buf + offset, remain, c, type, flags);
354 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
355
356 c = nftnl_chain_list_iter_next(ci);
357 sep = "\n";
358 }
359 nftnl_chain_list_iter_destroy(ci);
360
361 return offset;
362}
363
364static int
365nftnl_ruleset_snprintf_set(char *buf, size_t remain,
366 const struct nftnl_ruleset *rs, uint32_t type,
367 uint32_t flags)
368{
369 struct nftnl_set *s;
370 struct nftnl_set_list_iter *si;
371 const char *sep = "";
372 int ret, offset = 0;
373
374 si = nftnl_set_list_iter_create(rs->set_list);
375 if (si == NULL)
376 return 0;
377
378 s = nftnl_set_list_iter_next(si);
379 while (s != NULL) {
380 ret = snprintf(buf + offset, remain, "%s", sep);
381 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
382
383 ret = nftnl_set_snprintf(buf + offset, remain, s, type, flags);
384 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
385
386 s = nftnl_set_list_iter_next(si);
387 sep = "\n";
388 }
389 nftnl_set_list_iter_destroy(si);
390
391 return offset;
392}
393
394static int
395nftnl_ruleset_snprintf_rule(char *buf, size_t remain,
396 const struct nftnl_ruleset *rs, uint32_t type,
397 uint32_t flags)
398{
399 struct nftnl_rule *r;
400 struct nftnl_rule_list_iter *ri;
401 const char *sep = "";
402 int ret, offset = 0;
403
404 ri = nftnl_rule_list_iter_create(rs->rule_list);
405 if (ri == NULL)
406 return 0;
407
408 r = nftnl_rule_list_iter_next(ri);
409 while (r != NULL) {
410 ret = snprintf(buf + offset, remain, "%s", sep);
411 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
412
413 ret = nftnl_rule_snprintf(buf + offset, remain, r, type, flags);
414 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
415
416 r = nftnl_rule_list_iter_next(ri);
417 sep = "\n";
418 }
419 nftnl_rule_list_iter_destroy(ri);
420
421 return offset;
422}
423
424static int
425nftnl_ruleset_do_snprintf(char *buf, size_t remain,
426 const struct nftnl_ruleset *rs,
427 uint32_t cmd, uint32_t type, uint32_t flags)
428{
429 uint32_t inner_flags = flags;
430 const char *sep = "";
431 int ret, offset = 0;
432
433 /* dont pass events flags to child calls of _snprintf() */
434 inner_flags &= ~NFTNL_OF_EVENT_ANY;
435
436 if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_TABLELIST) &&
437 (!nftnl_table_list_is_empty(rs->table_list))) {
438 ret = nftnl_ruleset_snprintf_table(buf + offset, remain, rs,
439 type, inner_flags);
440 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
441
442 if (ret > 0)
443 sep = "\n";
444 }
445
446 if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_CHAINLIST) &&
447 (!nftnl_chain_list_is_empty(rs->chain_list))) {
448 ret = snprintf(buf + offset, remain, "%s", sep);
449 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
450
451 ret = nftnl_ruleset_snprintf_chain(buf + offset, remain, rs,
452 type, inner_flags);
453 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
454
455 if (ret > 0)
456 sep = "\n";
457 }
458
459 if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_SETLIST) &&
460 (!nftnl_set_list_is_empty(rs->set_list))) {
461 ret = snprintf(buf + offset, remain, "%s", sep);
462 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
463
464 ret = nftnl_ruleset_snprintf_set(buf + offset, remain, rs,
465 type, inner_flags);
466 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
467
468 if (ret > 0)
469 sep = "\n";
470 }
471
472 if (nftnl_ruleset_is_set(rs, NFTNL_RULESET_RULELIST) &&
473 (!nftnl_rule_list_is_empty(rs->rule_list))) {
474 ret = snprintf(buf + offset, remain, "%s", sep);
475 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
476
477 ret = nftnl_ruleset_snprintf_rule(buf + offset, remain, rs,
478 type, inner_flags);
479 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
480 }
481
482 return offset;
483}
484
485EXPORT_SYMBOL(nftnl_ruleset_snprintf);
486int nftnl_ruleset_snprintf(char *buf, size_t size, const struct nftnl_ruleset *r,
487 uint32_t type, uint32_t flags)
488{
489 if (size)
490 buf[0] = '\0';
491
492 if (type != NFTNL_OUTPUT_DEFAULT) {
493 errno = EOPNOTSUPP;
494 return -1;
495 }
496 return nftnl_ruleset_do_snprintf(buf, size, r, nftnl_flag2cmd(flags),
497 type, flags);
498}
499
500static int nftnl_ruleset_fprintf_tables(FILE *fp, const struct nftnl_ruleset *rs,
501 uint32_t type, uint32_t flags)
502{
503 int len = 0, ret = 0;
504 struct nftnl_table *t;
505 struct nftnl_table_list_iter *ti;
506 const char *sep = "";
507
508 ti = nftnl_table_list_iter_create(rs->table_list);
509 if (ti == NULL)
510 return -1;
511
512 t = nftnl_table_list_iter_next(ti);
513 while (t != NULL) {
514 ret = fprintf(fp, "%s", sep);
515 if (ret < 0)
516 goto err;
517
518 len += ret;
519
520 ret = nftnl_table_fprintf(fp, t, type, flags);
521 if (ret < 0)
522 goto err;
523
524 len += ret;
525
526 t = nftnl_table_list_iter_next(ti);
527 sep = "\n";
528
529 }
530 nftnl_table_list_iter_destroy(ti);
531
532 return len;
533err:
534 nftnl_table_list_iter_destroy(ti);
535 return -1;
536}
537
538static int nftnl_ruleset_fprintf_chains(FILE *fp, const struct nftnl_ruleset *rs,
539 uint32_t type, uint32_t flags)
540{
541 int len = 0, ret = 0;
542 struct nftnl_chain *o;
543 struct nftnl_chain_list_iter *i;
544 const char *sep = "";
545
546 i = nftnl_chain_list_iter_create(rs->chain_list);
547 if (i == NULL)
548 return -1;
549
550 o = nftnl_chain_list_iter_next(i);
551 while (o != NULL) {
552 ret = fprintf(fp, "%s", sep);
553 if (ret < 0)
554 goto err;
555
556 len += ret;
557
558 ret = nftnl_chain_fprintf(fp, o, type, flags);
559 if (ret < 0)
560 goto err;
561
562 len += ret;
563
564 o = nftnl_chain_list_iter_next(i);
565 sep = "\n";
566 }
567 nftnl_chain_list_iter_destroy(i);
568
569 return len;
570err:
571 nftnl_chain_list_iter_destroy(i);
572 return -1;
573}
574
575static int nftnl_ruleset_fprintf_sets(FILE *fp, const struct nftnl_ruleset *rs,
576 uint32_t type, uint32_t flags)
577{
578 int len = 0, ret = 0;
579 struct nftnl_set *o;
580 struct nftnl_set_list_iter *i;
581 const char *sep = "";
582
583 i = nftnl_set_list_iter_create(rs->set_list);
584 if (i == NULL)
585 return -1;
586
587 o = nftnl_set_list_iter_next(i);
588 while (o != NULL) {
589 ret = fprintf(fp, "%s", sep);
590 if (ret < 0)
591 goto err;
592
593 len += ret;
594
595 ret = nftnl_set_fprintf(fp, o, type, flags);
596 if (ret < 0)
597 goto err;
598
599 len += ret;
600
601 o = nftnl_set_list_iter_next(i);
602 sep = "\n";
603 }
604 nftnl_set_list_iter_destroy(i);
605
606 return len;
607err:
608 nftnl_set_list_iter_destroy(i);
609 return -1;
610}
611
612static int nftnl_ruleset_fprintf_rules(FILE *fp, const struct nftnl_ruleset *rs,
613 uint32_t type, uint32_t flags)
614{
615 int len = 0, ret = 0;
616 struct nftnl_rule *o;
617 struct nftnl_rule_list_iter *i;
618 const char *sep = "";
619
620 i = nftnl_rule_list_iter_create(rs->rule_list);
621 if (i == NULL)
622 return -1;
623
624 o = nftnl_rule_list_iter_next(i);
625 while (o != NULL) {
626 ret = fprintf(fp, "%s", sep);
627 if (ret < 0)
628 goto err;
629
630 len += ret;
631
632 ret = nftnl_rule_fprintf(fp, o, type, flags);
633 if (ret < 0)
634 goto err;
635
636 len += ret;
637
638 o = nftnl_rule_list_iter_next(i);
639 sep = "\n";
640 }
641 nftnl_rule_list_iter_destroy(i);
642
643 return len;
644err:
645 nftnl_rule_list_iter_destroy(i);
646 return -1;
647}
648
649#define NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len) \
650 if (ret < 0) \
651 return -1; \
652 len += ret;
653
654static int nftnl_ruleset_cmd_fprintf(FILE *fp, const struct nftnl_ruleset *rs,
655 uint32_t cmd, uint32_t type, uint32_t flags)
656{
657 int len = 0, ret = 0;
658 uint32_t inner_flags = flags;
659 const char *sep = "";
660
661 /* dont pass events flags to child calls of _snprintf() */
662 inner_flags &= ~NFTNL_OF_EVENT_ANY;
663
664 if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_TABLELIST)) &&
665 (!nftnl_table_list_is_empty(rs->table_list))) {
666 ret = nftnl_ruleset_fprintf_tables(fp, rs, type, inner_flags);
667 NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
668
669 if (ret > 0)
670 sep = "\n";
671 }
672
673 if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_CHAINLIST)) &&
674 (!nftnl_chain_list_is_empty(rs->chain_list))) {
675 ret = fprintf(fp, "%s", sep);
676 NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
677
678 ret = nftnl_ruleset_fprintf_chains(fp, rs, type, inner_flags);
679 NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
680
681 if (ret > 0)
682 sep = "\n";
683 }
684
685 if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_SETLIST)) &&
686 (!nftnl_set_list_is_empty(rs->set_list))) {
687 ret = fprintf(fp, "%s", sep);
688 NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
689
690 ret = nftnl_ruleset_fprintf_sets(fp, rs, type, inner_flags);
691 NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
692
693 if (ret > 0)
694 sep = "\n";
695 }
696
697 if ((nftnl_ruleset_is_set(rs, NFTNL_RULESET_RULELIST)) &&
698 (!nftnl_rule_list_is_empty(rs->rule_list))) {
699 ret = fprintf(fp, "%s", sep);
700 NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
701
702 ret = nftnl_ruleset_fprintf_rules(fp, rs, type, inner_flags);
703 NFTNL_FPRINTF_RETURN_OR_FIXLEN(ret, len);
704 }
705
706 return len;
707}
708
709EXPORT_SYMBOL(nftnl_ruleset_fprintf);
710int nftnl_ruleset_fprintf(FILE *fp, const struct nftnl_ruleset *rs, uint32_t type,
711 uint32_t flags)
712{
713 return nftnl_ruleset_cmd_fprintf(fp, rs, nftnl_flag2cmd(flags), type,
714 flags);
715}