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