]> git.ipfire.org Git - thirdparty/libnftnl.git/commitdiff
src: add fprintf API functions
authorArturo Borrero <arturo.borrero.glez@gmail.com>
Tue, 29 Oct 2013 22:44:25 +0000 (23:44 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 3 Nov 2013 21:11:56 +0000 (22:11 +0100)
Now it's possible to print directly from libnftables to a file or
other stream. The caller must explicitly print the trailing '\n'
in this call.

The error reporting of fprintf (< 0) is respected. However, we have
already print some information in case that the default (plain text)
output is used, that output is mostly intended for debugging so it
should not be a problem.

Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
14 files changed:
include/libnftables/chain.h
include/libnftables/rule.h
include/libnftables/ruleset.h
include/libnftables/set.h
include/libnftables/table.h
src/chain.c
src/internal.h
src/libnftables.map
src/rule.c
src/ruleset.c
src/set.c
src/set_elem.c
src/table.c
src/utils.c

index d85a2a2a9a3fe46213b88569714343ba3a47b3cb..66f19c00f8bb57952e17859986be6c22b8b12ae7 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _CHAIN_H_
 #define _CHAIN_H_
 
+#include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>
 
@@ -60,6 +61,7 @@ enum nft_chain_parse_type {
 
 int nft_chain_parse(struct nft_chain *c, enum nft_chain_parse_type type, const char *data);
 int nft_chain_snprintf(char *buf, size_t size, struct nft_chain *t, uint32_t type, uint32_t flags);
+int nft_chain_fprintf(FILE *fp, struct nft_chain *c, uint32_t type, uint32_t flags);
 
 struct nlmsghdr *nft_chain_nlmsg_build_hdr(char *buf, uint16_t cmd, uint16_t family, uint16_t type, uint32_t seq);
 int nft_chain_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_chain *t);
index a501d2dc0b465e9b1073fa4b46c80c52baa238fc..cdbd8d2b4c37f85bb93e7f591f4ae64f594e54e2 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _RULE_H_
 #define _RULE_H_
 
+#include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>
 
@@ -58,6 +59,7 @@ enum nft_rule_parse_type {
 
 int nft_rule_parse(struct nft_rule *r, enum nft_rule_parse_type type, const char *data);
 int nft_rule_snprintf(char *buf, size_t size, struct nft_rule *t, uint32_t type, uint32_t flags);
+int nft_rule_fprintf(FILE *fp, struct nft_rule *r, uint32_t type, uint32_t flags);
 
 struct nlmsghdr *nft_rule_nlmsg_build_hdr(char *buf, uint16_t cmd, uint16_t family, uint16_t type, uint32_t seq);
 int nft_rule_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_rule *t);
index a4a12790192702ebb7e2b930261768348c2b4c59..35e4d7110ed9548a647a85ab58d369f3e0714328 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _RULESET_H_
 #define _RULESET_H_
 
+#include <stdio.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -37,6 +39,7 @@ enum nft_ruleset_parse_type {
 
 int nft_ruleset_parse(struct nft_ruleset *rs, enum nft_ruleset_parse_type type, const char *data);
 int nft_ruleset_snprintf(char *buf, size_t size, const struct nft_ruleset *rs, uint32_t type, uint32_t flags);
+int nft_ruleset_fprintf(FILE *fp, const struct nft_ruleset *rs, uint32_t type, uint32_t flags);
 
 #ifdef __cplusplus
 } /* extern "C" */
index 14a6327e2fa1a80634cfd9efd56368dafc7abf55..a0870090150b0684091d9e98d7987a7e0a156fa1 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _NFT_SET_H_
 #define _NFT_SET_H_
 
+#include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>
 
@@ -38,6 +39,7 @@ int nft_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set *s);
 int nft_set_elems_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set *s);
 
 int nft_set_snprintf(char *buf, size_t size, struct nft_set *s, uint32_t type, uint32_t flags);
+int nft_set_fprintf(FILE *fp, struct nft_set *s, uint32_t type, uint32_t flags);
 
 struct nft_set_list;
 
@@ -108,6 +110,7 @@ int nft_set_elem_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_set_elem *s)
 
 int nft_set_elem_parse(struct nft_set_elem *e, enum nft_set_parse_type type, const char *data);
 int nft_set_elem_snprintf(char *buf, size_t size, struct nft_set_elem *s, uint32_t type, uint32_t flags);
+int nft_set_elem_fprintf(FILE *fp, struct nft_set_elem *se, uint32_t type, uint32_t flags);
 
 int nft_set_elem_foreach(struct nft_set *s, int (*cb)(struct nft_set_elem *e, void *data), void *data);
 
index 42a4aa7bf449277a3be41b382bba5df0870e05f4..4a323bdf1cc26cb4da6a8be3c88016fbb9f6b9ee 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _TABLE_H_
 #define _TABLE_H_
 
+#include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>
 
@@ -48,6 +49,7 @@ enum nft_table_parse_type {
 
 int nft_table_parse(struct nft_table *t, enum nft_table_parse_type type, const char *data);
 int nft_table_snprintf(char *buf, size_t size, struct nft_table *t, uint32_t type, uint32_t flags);
+int nft_table_fprintf(FILE *fp, struct nft_table *t, uint32_t type, uint32_t flags);
 
 struct nlmsghdr *nft_table_nlmsg_build_hdr(char *buf, uint16_t cmd, uint16_t family, uint16_t type, uint32_t seq);
 int nft_table_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_table *t);
index 6179f683b3a4085d37cb09da96c8ecd1dcacb4a7..cdb398f5869394577d0dcf50f69a6280e9546340 100644 (file)
@@ -851,6 +851,19 @@ int nft_chain_snprintf(char *buf, size_t size, struct nft_chain *c,
 }
 EXPORT_SYMBOL(nft_chain_snprintf);
 
+static inline int nft_chain_do_snprintf(char *buf, size_t size, void *c,
+                                       uint32_t type, uint32_t flags)
+{
+       return nft_chain_snprintf(buf, size, c, type, flags);
+}
+
+int nft_chain_fprintf(FILE *fp, struct nft_chain *c, uint32_t type,
+                     uint32_t flags)
+{
+       return nft_fprintf(fp, c, type, flags, nft_chain_do_snprintf);
+}
+EXPORT_SYMBOL(nft_chain_fprintf);
+
 struct nft_chain_list {
        struct list_head list;
 };
index b29288acc59b852f64b7e8635b39e9ac934cb104..6449a9f0fa810ee9f58c02aa0542de2c6a58a9c5 100644 (file)
@@ -17,6 +17,8 @@
 #define BASE_DEC 10
 #define BASE_HEX 16
 
+#define NFT_SNPRINTF_BUFSIZ 4096
+
 enum nft_type {
        NFT_TYPE_U8,
        NFT_TYPE_U16,
@@ -88,6 +90,8 @@ const char *nft_verdict2str(uint32_t verdict);
 int nft_str2verdict(const char *verdict);
 int nft_get_value(enum nft_type type, void *val, void *out);
 
+int nft_fprintf(FILE *fp, void *obj, uint32_t type, uint32_t flags, int (*snprintf_cb)(char *buf, size_t bufsiz, void *obj, uint32_t type, uint32_t flags));
+
 void xfree(const void *ptr);
 
 struct expr_ops;
index 12234031efe92ffa6891ca43211d22ee5e342481..aa477142d610ba1b6729f23b045303125ba7d46b 100644 (file)
@@ -12,6 +12,7 @@ global:
   nft_table_attr_get_str;
   nft_table_parse;
   nft_table_snprintf;
+  nft_table_fprintf;
   nft_table_nlmsg_build_hdr;
   nft_table_nlmsg_build_payload;
   nft_table_nlmsg_parse;
@@ -42,6 +43,7 @@ global:
   nft_chain_attr_get_str;
   nft_chain_parse;
   nft_chain_snprintf;
+  nft_chain_fprintf;
   nft_chain_nlmsg_build_hdr;
   nft_chain_nlmsg_build_payload;
   nft_chain_nlmsg_parse;
@@ -71,6 +73,7 @@ global:
   nft_rule_attr_get_str;
   nft_rule_parse;
   nft_rule_snprintf;
+  nft_rule_fprintf;
   nft_rule_nlmsg_build_hdr;
   nft_rule_nlmsg_build_payload;
   nft_rule_nlmsg_parse;
@@ -126,6 +129,7 @@ global:
   nft_set_nlmsg_parse;
   nft_set_parse;
   nft_set_snprintf;
+  nft_set_fprintf;
 
   nft_set_list_alloc;
   nft_set_list_free;
@@ -157,6 +161,7 @@ global:
   nft_set_elem_nlmsg_parse;
   nft_set_elem_parse;
   nft_set_elem_snprintf;
+  nft_set_elem_fprinf;
 
   nft_set_elems_nlmsg_build_payload;
   nft_set_elems_nlmsg_parse;
@@ -176,6 +181,7 @@ global:
   nft_ruleset_attr_get;
   nft_ruleset_parse;
   nft_ruleset_snprintf;
+  nft_ruleset_fprintf;
 
 local: *;
 };
index d135f388fc4a59ebb2db14681f91d4faebb73d56..3b45dc75af43dbed0826cde49be57f2fd6ec48b8 100644 (file)
@@ -819,6 +819,19 @@ int nft_rule_snprintf(char *buf, size_t size, struct nft_rule *r,
 }
 EXPORT_SYMBOL(nft_rule_snprintf);
 
+static inline int nft_rule_do_snprintf(char *buf, size_t size, void *r,
+                                      uint32_t type, uint32_t flags)
+{
+       return nft_rule_snprintf(buf, size, r, type, flags);
+}
+
+int nft_rule_fprintf(FILE *fp, struct nft_rule *r, uint32_t type,
+                    uint32_t flags)
+{
+       return nft_fprintf(fp, r, type, flags, nft_rule_do_snprintf);
+}
+EXPORT_SYMBOL(nft_rule_fprintf);
+
 int nft_rule_expr_foreach(struct nft_rule *r,
                           int (*cb)(struct nft_rule_expr *e, void *data),
                           void *data)
index 24b849b6fa8696e7e5c7d19672092f5991bb2bb4..ee2c60abee03a480b9bf5a996aa23a96a5799888 100644 (file)
@@ -813,3 +813,206 @@ int nft_ruleset_snprintf(char *buf, size_t size, const struct nft_ruleset *r,
        }
 }
 EXPORT_SYMBOL(nft_ruleset_snprintf);
+
+static int nft_ruleset_fprintf_tables(FILE *fp, const struct nft_ruleset *rs,
+                                     uint32_t type, uint32_t flags)
+{
+       int len = 0, ret = 0;
+       struct nft_table *t;
+       struct nft_table_list_iter *ti;
+
+       ti = nft_table_list_iter_create(rs->table_list);
+       if (ti == NULL)
+               return -1;
+
+       t = nft_table_list_iter_next(ti);
+       while (t != NULL) {
+               ret = nft_table_fprintf(fp, t, type, flags);
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+
+               t = nft_table_list_iter_next(ti);
+
+               ret = fprintf(fp, "%s", nft_ruleset_o_separator(t, type));
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+       }
+       nft_table_list_iter_destroy(ti);
+
+       return len;
+err:
+       nft_table_list_iter_destroy(ti);
+       return -1;
+}
+
+static int nft_ruleset_fprintf_chains(FILE *fp, const struct nft_ruleset *rs,
+                                     uint32_t type, uint32_t flags)
+{
+       int len = 0, ret = 0;
+       struct nft_chain *o;
+       struct nft_chain_list_iter *i;
+
+       i = nft_chain_list_iter_create(rs->chain_list);
+       if (i == NULL)
+               return -1;
+
+       o = nft_chain_list_iter_next(i);
+       while (o != NULL) {
+               ret = nft_chain_fprintf(fp, o, type, flags);
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+
+               o = nft_chain_list_iter_next(i);
+
+               ret = fprintf(fp, "%s", nft_ruleset_o_separator(o, type));
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+       }
+       nft_chain_list_iter_destroy(i);
+
+       return len;
+err:
+       nft_chain_list_iter_destroy(i);
+       return -1;
+}
+
+static int nft_ruleset_fprintf_sets(FILE *fp, const struct nft_ruleset *rs,
+                                   uint32_t type, uint32_t flags)
+{
+       int len = 0, ret = 0;
+       struct nft_set *o;
+       struct nft_set_list_iter *i;
+
+       i = nft_set_list_iter_create(rs->set_list);
+       if (i == NULL)
+               return -1;
+
+       o = nft_set_list_iter_next(i);
+       while (o != NULL) {
+               ret = nft_set_fprintf(fp, o, type, flags);
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+
+               o = nft_set_list_iter_next(i);
+
+               ret = fprintf(fp, "%s", nft_ruleset_o_separator(o, type));
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+       }
+       nft_set_list_iter_destroy(i);
+
+       return len;
+err:
+       nft_set_list_iter_destroy(i);
+       return -1;
+}
+
+static int nft_ruleset_fprintf_rules(FILE *fp, const struct nft_ruleset *rs,
+                                   uint32_t type, uint32_t flags)
+{
+       int len = 0, ret = 0;
+       struct nft_rule *o;
+       struct nft_rule_list_iter *i;
+
+       i = nft_rule_list_iter_create(rs->rule_list);
+       if (i == NULL)
+               return -1;
+
+       o = nft_rule_list_iter_next(i);
+       while (o != NULL) {
+               ret = nft_rule_fprintf(fp, o, type, flags);
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+
+               o = nft_rule_list_iter_next(i);
+
+               ret = fprintf(fp, "%s", nft_ruleset_o_separator(o, type));
+               if (ret < 0)
+                       goto err;
+
+               len += ret;
+       }
+       nft_rule_list_iter_destroy(i);
+
+       return len;
+err:
+       nft_rule_list_iter_destroy(i);
+       return -1;
+}
+
+#define NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len) \
+       if (ret < 0)                            \
+               return -1;                      \
+       len += ret;
+
+int nft_ruleset_fprintf(FILE *fp, const struct nft_ruleset *rs, uint32_t type,
+                       uint32_t flags)
+{
+       int len = 0, ret = 0;
+       void *prev = NULL;
+
+       ret = fprintf(fp, "%s", nft_ruleset_o_opentag(type));
+       NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+       if ((nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_TABLELIST)) &&
+           (!nft_table_list_is_empty(rs->table_list))) {
+               ret = nft_ruleset_fprintf_tables(fp, rs, type, flags);
+               NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+               if (ret > 0)
+                       prev = rs->table_list;
+       }
+
+       if ((nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_CHAINLIST)) &&
+           (!nft_chain_list_is_empty(rs->chain_list))) {
+               ret = fprintf(fp, "%s", nft_ruleset_o_separator(prev, type));
+               NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+               ret = nft_ruleset_fprintf_chains(fp, rs, type, flags);
+               NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+               if (ret > 0)
+                       prev = rs->chain_list;
+       }
+
+       if ((nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_SETLIST)) &&
+           (!nft_set_list_is_empty(rs->set_list))) {
+               ret = fprintf(fp, "%s", nft_ruleset_o_separator(prev, type));
+               NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+               ret = nft_ruleset_fprintf_sets(fp, rs, type, flags);
+               NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+               if (ret > 0)
+                       prev = rs->set_list;
+       }
+
+       if ((nft_ruleset_attr_is_set(rs, NFT_RULESET_ATTR_RULELIST)) &&
+           (!nft_rule_list_is_empty(rs->rule_list))) {
+               ret = fprintf(fp, "%s", nft_ruleset_o_separator(prev, type));
+               NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+               ret = nft_ruleset_fprintf_rules(fp, rs, type, flags);
+               NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+       }
+
+       ret = fprintf(fp, "%s", nft_ruleset_o_closetag(type));
+       NFT_FPRINTF_RETURN_OR_FIXLEN(ret, len);
+
+       return len;
+}
+EXPORT_SYMBOL(nft_ruleset_fprintf);
index 2c6e6a6da97c8ab2c6556b21d1fbd90379d41d7f..9620006b43c5147ebb3dd9148ded2e1504632394 100644 (file)
--- a/src/set.c
+++ b/src/set.c
@@ -668,6 +668,19 @@ int nft_set_snprintf(char *buf, size_t size, struct nft_set *s,
 }
 EXPORT_SYMBOL(nft_set_snprintf);
 
+static inline int nft_set_do_snprintf(char *buf, size_t size, void *s,
+                                     uint32_t type, uint32_t flags)
+{
+       return nft_set_snprintf(buf, size, s, type, flags);
+}
+
+int nft_set_fprintf(FILE *fp, struct nft_set *s, uint32_t type,
+                   uint32_t flags)
+{
+       return nft_fprintf(fp, s, type, flags, nft_set_do_snprintf);
+}
+EXPORT_SYMBOL(nft_set_fprintf);
+
 void nft_set_elem_add(struct nft_set *s, struct nft_set_elem *elem)
 {
        list_add_tail(&elem->head, &s->element_list);
index 5ef46f2e06e9b1c086cf9a9875ac2410692f76c4..516905d60d05cc3b521c15896d13792997f83f62 100644 (file)
@@ -577,6 +577,19 @@ int nft_set_elem_snprintf(char *buf, size_t size, struct nft_set_elem *e,
 }
 EXPORT_SYMBOL(nft_set_elem_snprintf);
 
+static inline int nft_set_elem_do_snprintf(char *buf, size_t size, void *e,
+                                          uint32_t type, uint32_t flags)
+{
+       return nft_set_elem_snprintf(buf, size, e, type, flags);
+}
+
+int nft_set_elem_fprintf(FILE *fp, struct nft_set_elem *se, uint32_t type,
+                        uint32_t flags)
+{
+       return nft_fprintf(fp, se, type, flags, nft_set_elem_do_snprintf);
+}
+EXPORT_SYMBOL(nft_set_elem_fprintf);
+
 int nft_set_elem_foreach(struct nft_set *s,
                         int (*cb)(struct nft_set_elem *e, void *data),
                         void *data)
index d3ff188727a6e8ae5698e725accad93f5d93c350..d1acc7c1f82f593d77169da9752c6e72f1e33bbb 100644 (file)
@@ -388,6 +388,19 @@ int nft_table_snprintf(char *buf, size_t size, struct nft_table *t,
 }
 EXPORT_SYMBOL(nft_table_snprintf);
 
+static inline int nft_table_do_snprintf(char *buf, size_t size, void *t,
+                                       uint32_t type, uint32_t flags)
+{
+       return nft_table_snprintf(buf, size, t, type, flags);
+}
+
+int nft_table_fprintf(FILE *fp, struct nft_table *t, uint32_t type,
+                     uint32_t flags)
+{
+       return nft_fprintf(fp, t, type, flags, nft_table_do_snprintf);
+}
+EXPORT_SYMBOL(nft_table_fprintf);
+
 struct nft_table_list {
        struct list_head list;
 };
index 9a0bcfec1fc1d615ed3970104da09abfd4788eb7..24159178ed17d7b6c9e3883858f00bec5389563f 100644 (file)
@@ -174,3 +174,30 @@ void xfree(const void *ptr)
 {
        free((void *)ptr);
 }
+
+int nft_fprintf(FILE *fp, void *obj, uint32_t type, uint32_t flags,
+               int (*snprintf_cb)(char *buf, size_t bufsiz, void *obj,
+                                  uint32_t type, uint32_t flags))
+{
+       char _buf[NFT_SNPRINTF_BUFSIZ];
+       char *buf = _buf;
+       size_t bufsiz = sizeof(_buf);
+       int ret;
+
+       ret = snprintf_cb(buf, bufsiz, obj, type, flags);
+       if (ret > NFT_SNPRINTF_BUFSIZ) {
+               buf = calloc(1, ret);
+               if (buf == NULL)
+                       return -1;
+
+               bufsiz = ret;
+               ret = snprintf_cb(buf, bufsiz, obj, type, flags);
+       }
+
+       ret = fprintf(fp, "%s", buf);
+
+       if (buf != _buf)
+               xfree(buf);
+
+       return ret;
+}