]> git.ipfire.org Git - thirdparty/libnftnl.git/commitdiff
src: Use nftnl_buf to export XML/JSON rules
authorElise Lennion <elise.lennion@gmail.com>
Thu, 2 Mar 2017 18:34:13 +0000 (15:34 -0300)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 3 Mar 2017 09:56:26 +0000 (10:56 +0100)
This completes the use of nftnl_buf and its auxiliary functions to
export XML/JSON rules.

Highly based on work from Shivani Bhardwaj <shivanib134@gmail.com>.

Signed-off-by: Elise Lennion <elise.lennion@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/buffer.h
src/buffer.c
src/rule.c

index c5716570f9d0692a5b322c369a6d40b39e16bf3b..f5568953c4dc05f0fa15698618f1765dc3b47337 100644 (file)
@@ -4,6 +4,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+struct nftnl_expr;
+
 struct nftnl_buf {
        char            *buf;
        size_t          size;
@@ -35,12 +37,18 @@ int nftnl_buf_u64(struct nftnl_buf *b, int type, uint64_t value, const char *tag
 int nftnl_buf_str(struct nftnl_buf *b, int type, const char *str, const char *tag);
 int nftnl_buf_reg(struct nftnl_buf *b, int type, union nftnl_data_reg *reg,
                int reg_type, const char *tag);
+int nftnl_buf_expr_open(struct nftnl_buf *b, int type);
+int nftnl_buf_expr_close(struct nftnl_buf *b, int type);
+int nftnl_buf_expr(struct nftnl_buf *b, int type, uint32_t flags,
+                  struct nftnl_expr *expr);
 
 #define BASE                   "base"
 #define BYTES                  "bytes"
 #define BURST                  "burst"
 #define CHAIN                  "chain"
 #define CODE                   "code"
+#define COMPAT_FLAGS           "compat_flags"
+#define COMPAT_PROTO           "compat_proto"
 #define CONSUMED               "consumed"
 #define DATA                   "data"
 #define DEVICE                 "device"
@@ -64,10 +72,12 @@ int nftnl_buf_reg(struct nftnl_buf *b, int type, union nftnl_data_reg *reg,
 #define PACKETS                        "packets"
 #define PKTS                   "pkts"
 #define POLICY                 "policy"
+#define POSITION               "position"
 #define PREFIX                 "prefix"
 #define PRIO                   "prio"
 #define QTHRESH                        "qthreshold"
 #define RATE                   "rate"
+#define RULE                   "rule"
 #define SET                    "set"
 #define SET_NAME               "set_name"
 #define SIZE                   "size"
@@ -93,5 +103,6 @@ int nftnl_buf_reg(struct nftnl_buf *b, int type, union nftnl_data_reg *reg,
 #define FLUSH                  "flush"
 #define MODULUS                        "modulus"
 #define SEED                   "seed"
+#define ID                     "id"
 
 #endif
index d97d517814a9e6cd92cec5b05a677ee1b633c721..f9d5a838c4ab65d7519bb3d77f4abb29c97b8625 100644 (file)
@@ -171,3 +171,49 @@ int nftnl_buf_reg(struct nftnl_buf *b, int type, union nftnl_data_reg *reg,
        }
        return 0;
 }
+
+int nftnl_buf_expr_open(struct nftnl_buf *b, int type)
+{
+       switch (type) {
+       case NFTNL_OUTPUT_XML:
+               return 0;
+       case NFTNL_OUTPUT_JSON:
+               return nftnl_buf_put(b, "\"expr\":[");
+       }
+       return 0;
+}
+
+int nftnl_buf_expr_close(struct nftnl_buf *b, int type)
+{
+       switch (type) {
+       case NFTNL_OUTPUT_XML:
+               return 0;
+       case NFTNL_OUTPUT_JSON:
+               nftnl_buf_done(b);
+               return nftnl_buf_put(b, "]");
+       }
+       return 0;
+}
+
+int nftnl_buf_expr(struct nftnl_buf *b, int type, uint32_t flags,
+                  struct nftnl_expr *expr)
+{
+       int ret;
+
+       switch (type) {
+       case NFTNL_OUTPUT_XML:
+               return 0;
+       case NFTNL_OUTPUT_JSON:
+               nftnl_buf_put(b, "{");
+               nftnl_buf_str(b, type, expr->ops->name, TYPE);
+               ret = expr->ops->snprintf(b->buf + b->off, b->len, type, flags,
+                                         expr);
+               if (ret > 0)
+                       nftnl_buf_update(b, ret);
+               else
+                       nftnl_buf_done(b);
+
+               return nftnl_buf_put(b, "},");
+       }
+       return 0;
+}
index 31cd3ed7dc9993ff7a3fbd28523b21ba64201e4d..6c221417d7f45fe378701bdb70f6d9362d3f347d 100644 (file)
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <ctype.h>
+#include <buffer.h>
 
 #include <libmnl/libmnl.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -671,88 +672,41 @@ int nftnl_rule_parse_file(struct nftnl_rule *r, enum nftnl_parse_type type,
 }
 EXPORT_SYMBOL(nftnl_rule_parse_file);
 
-static int nftnl_rule_snprintf_json(char *buf, size_t size,
-                                   const struct nftnl_rule *r,
-                                   uint32_t type, uint32_t flags)
+static int nftnl_rule_export(char *buf, size_t size,
+                            const struct nftnl_rule *r,
+                            uint32_t type, uint32_t flags)
 {
-       int ret, len = size, offset = 0;
        struct nftnl_expr *expr;
 
-       ret = snprintf(buf, len, "{\"rule\":{");
-       SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+       NFTNL_BUF_INIT(b, buf, size);
 
-       if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
-               ret = snprintf(buf+offset, len, "\"family\":\"%s\",",
-                              nftnl_family2str(r->family));
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-       }
+       nftnl_buf_open(&b, type, RULE);
 
-       if (r->flags & (1 << NFTNL_RULE_TABLE)) {
-               ret = snprintf(buf+offset, len, "\"table\":\"%s\",",
-                              r->table);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-       }
-
-       if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
-               ret = snprintf(buf+offset, len, "\"chain\":\"%s\",",
-                              r->chain);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-       }
-       if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
-               ret = snprintf(buf+offset, len, "\"handle\":%llu,",
-                              (unsigned long long)r->handle);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-       }
-
-       if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO) ||
-           r->flags & (1 << NFTNL_RULE_COMPAT_FLAGS)) {
-               ret = snprintf(buf+offset, len, "\"compat_flags\":%u,"
-                                               "\"compat_proto\":%u,",
-                              r->compat.flags, r->compat.proto);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-       }
-
-       if (r->flags & (1 << NFTNL_RULE_POSITION)) {
-               ret = snprintf(buf+offset, len, "\"position\":%"PRIu64",",
-                              r->position);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-       }
-
-       if (r->flags & (1 << NFTNL_RULE_ID)) {
-               ret = snprintf(buf+offset, len, "\"id\":%u,", r->id);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-       }
-
-       ret = snprintf(buf+offset, len, "\"expr\":[");
-       SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-
-       list_for_each_entry(expr, &r->expr_list, head) {
-               ret = snprintf(buf+offset, len,
-                              "{\"type\":\"%s\",", expr->ops->name);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-
-               ret = expr->ops->snprintf(buf+offset, len, type, flags, expr);
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
-
-               /*
-                * Remove comma from the first element if there is type
-                * key-value pair only. Example: "expr":[{"type":"log"}]
-                */
-               if (ret == 0) {
-                       offset--;
-                       len--;
-               }
+       if (r->flags & (1 << NFTNL_RULE_FAMILY))
+               nftnl_buf_str(&b, type, nftnl_family2str(r->family), FAMILY);
+       if (r->flags & (1 << NFTNL_RULE_TABLE))
+               nftnl_buf_str(&b, type, r->table, TABLE);
+       if (r->flags & (1 << NFTNL_RULE_CHAIN))
+               nftnl_buf_str(&b, type, r->chain, CHAIN);
+       if (r->flags & (1 << NFTNL_RULE_HANDLE))
+               nftnl_buf_u64(&b, type, r->handle, HANDLE);
+       if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO))
+               nftnl_buf_u32(&b, type, r->compat.proto, COMPAT_PROTO);
+       if (r->flags & (1 << NFTNL_RULE_COMPAT_FLAGS))
+               nftnl_buf_u32(&b, type, r->compat.flags, COMPAT_FLAGS);
+       if (r->flags & (1 << NFTNL_RULE_POSITION))
+               nftnl_buf_u64(&b, type, r->position, POSITION);
+       if (r->flags & (1 << NFTNL_RULE_ID))
+               nftnl_buf_u32(&b, type, r->id, ID);
 
-               ret = snprintf(buf+offset, len, "},");
-               SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+       nftnl_buf_expr_open(&b, type);
+       list_for_each_entry(expr, &r->expr_list, head)
+               nftnl_buf_expr(&b, type, flags, expr);
+       nftnl_buf_expr_close(&b, type);
 
-       }
-       /* Remove comma from last element */
-       offset--;
-       ret = snprintf(buf+offset, len, "]}}");
-       SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+       nftnl_buf_close(&b, type, RULE);
 
-       return offset;
+       return nftnl_buf_done(&b);
 }
 
 static int nftnl_rule_snprintf_default(char *buf, size_t size,
@@ -849,7 +803,7 @@ static int nftnl_rule_cmd_snprintf(char *buf, size_t size,
                                                inner_flags);
                break;
        case NFTNL_OUTPUT_JSON:
-               ret = nftnl_rule_snprintf_json(buf+offset, len, r, type,
+               ret = nftnl_rule_export(buf+offset, len, r, type,
                                             inner_flags);
                break;
        case NFTNL_OUTPUT_XML: