nfacct: Add patches for direct JSON output format
Rather than parsing the existing XML or standard output of the nfacct utility, and then piping that into a perl/python script for formatting to JSON, we teach nfacct to generate JSON directly. This seems like the proper way to do it. The patches will be submitted mainline.
This commit is contained in:
parent
88f39279bc
commit
d3ae677639
|
@ -0,0 +1,95 @@
|
|||
From 1ac986e0bee1cbfc8039c259617bb9bdba1d6e75 Mon Sep 17 00:00:00 2001
|
||||
From: Harald Welte <laforge@gnumonks.org>
|
||||
Date: Tue, 19 May 2015 22:09:45 +0200
|
||||
Subject: [PATCH] add JSON output format
|
||||
|
||||
the original output format looks a bit like JSON, but isn't. The XML
|
||||
output is useful if you deal with XML, but a lot of applications prefer
|
||||
more lightweight formats like YAML/JSON.
|
||||
|
||||
This adds the JSON output format to libnetfilter_acct, which will
|
||||
subsequently be used by a similar change in the nfacct utility.
|
||||
---
|
||||
include/libnetfilter_acct/libnetfilter_acct.h | 1 +
|
||||
src/libnetfilter_acct.c | 46 +++++++++++++++++++++++++++
|
||||
2 files changed, 47 insertions(+)
|
||||
|
||||
diff --git a/include/libnetfilter_acct/libnetfilter_acct.h b/include/libnetfilter_acct/libnetfilter_acct.h
|
||||
index c6ed858..647490f 100644
|
||||
--- a/include/libnetfilter_acct/libnetfilter_acct.h
|
||||
+++ b/include/libnetfilter_acct/libnetfilter_acct.h
|
||||
@@ -41,6 +41,7 @@ int nfacct_nlmsg_parse_payload(const struct nlmsghdr *nlh, struct nfacct *nfacct
|
||||
|
||||
#define NFACCT_SNPRINTF_T_PLAIN 0
|
||||
#define NFACCT_SNPRINTF_T_XML 1
|
||||
+#define NFACCT_SNPRINTF_T_JSON 2
|
||||
|
||||
int nfacct_snprintf(char *buf, size_t size, struct nfacct *nfacct, uint16_t type, uint16_t flags);
|
||||
|
||||
diff --git a/src/libnetfilter_acct.c b/src/libnetfilter_acct.c
|
||||
index bb15c68..b0bcf67 100644
|
||||
--- a/src/libnetfilter_acct.c
|
||||
+++ b/src/libnetfilter_acct.c
|
||||
@@ -297,6 +297,49 @@ nfacct_snprintf_plain(char *buf, size_t rem, struct nfacct *nfacct,
|
||||
return len;
|
||||
}
|
||||
|
||||
+static int
|
||||
+nfacct_snprintf_json(char *buf, size_t rem, struct nfacct *nfacct,
|
||||
+ uint16_t flags)
|
||||
+{
|
||||
+ int ret = 0, offset = 0, len = 0;
|
||||
+
|
||||
+ if (flags & NFACCT_SNPRINTF_F_FULL) {
|
||||
+ ret = snprintf(buf, rem,
|
||||
+ " { \"pkts\" : %"PRIu64", \"bytes\" : %"PRIu64"",
|
||||
+ nfacct_attr_get_u64(nfacct, NFACCT_ATTR_PKTS),
|
||||
+ nfacct_attr_get_u64(nfacct, NFACCT_ATTR_BYTES));
|
||||
+ SNPRINTF_CHECK(ret, rem, offset, len);
|
||||
+
|
||||
+ if (nfacct->flags) {
|
||||
+ uint32_t mode;
|
||||
+ char *mode_name;
|
||||
+
|
||||
+ mode = nfacct_attr_get_u64(nfacct, NFACCT_ATTR_FLAGS);
|
||||
+ if (mode & NFACCT_F_QUOTA_PKTS)
|
||||
+ mode_name = "packet";
|
||||
+ else if (mode & NFACCT_F_QUOTA_BYTES)
|
||||
+ mode_name = "byte";
|
||||
+ else
|
||||
+ mode_name = "unknown";
|
||||
+
|
||||
+ ret = snprintf(buf + offset, rem,
|
||||
+ ", \"quota\" : %"PRIu64", \"mode\" = \"%s\""\
|
||||
+ ", \"overquota\" = %u",
|
||||
+ nfacct_attr_get_u64(nfacct, NFACCT_ATTR_QUOTA),
|
||||
+ mode_name,
|
||||
+ mode & NFACCT_F_OVERQUOTA ? 1 : 0);
|
||||
+ SNPRINTF_CHECK(ret, rem, offset, len);
|
||||
+ }
|
||||
+
|
||||
+ ret = snprintf(buf + offset, rem, ", \"name\" : \"%s\" }",
|
||||
+ nfacct_attr_get_str(nfacct, NFACCT_ATTR_NAME));
|
||||
+ }
|
||||
+ /* non-F_FULL doesn't seem to make sense in JSON */
|
||||
+ SNPRINTF_CHECK(ret, rem, offset, len);
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
#define BUFFER_SIZE(ret, size, rem, offset) \
|
||||
size += ret; \
|
||||
if (ret > rem) \
|
||||
@@ -393,6 +436,9 @@ int nfacct_snprintf(char *buf, size_t size, struct nfacct *nfacct,
|
||||
case NFACCT_SNPRINTF_T_XML:
|
||||
ret = nfacct_snprintf_xml(buf, size, nfacct, flags);
|
||||
break;
|
||||
+ case NFACCT_SNPRINTF_T_JSON:
|
||||
+ ret = nfacct_snprintf_json(buf, size, nfacct, flags);
|
||||
+ break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
--
|
||||
2.1.4
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
SUMMARY = "libnetfilter_acct is the userspace library providing interface to extended accounting infrastructure."
|
||||
HOMEPAGE = "http://www.netfilter.org/projects/libnetfilter_acct/index.html"
|
||||
LICENSE = "LGPLv2.1+"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c"
|
||||
PV="1.0.2+git${SRCPV}"
|
||||
PR = "r0"
|
||||
|
||||
DEPENDS = "libmnl"
|
||||
|
||||
SRC_URI = "git://git.netfilter.org/libnetfilter_acct;branch=master \
|
||||
file://0001-add-JSON-output-format.patch \
|
||||
"
|
||||
SRCREV = "a9fea38024e6bde9118cc12bc8417b207ffc4da9"
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
inherit autotools pkgconfig
|
|
@ -0,0 +1,213 @@
|
|||
From aefba0f03444345dd5384631203f61647637175d Mon Sep 17 00:00:00 2001
|
||||
From: Harald Welte <laforge@gnumonks.org>
|
||||
Date: Tue, 19 May 2015 22:12:06 +0200
|
||||
Subject: [PATCH] Add JSON output formatting to nfacct utility
|
||||
|
||||
This is based on the JSON support patch of libnetfilter_acct.
|
||||
---
|
||||
nfacct.8 | 2 ++
|
||||
src/nfacct.c | 87 ++++++++++++++++++++++++++++++++++++++++++++----------------
|
||||
2 files changed, 66 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/nfacct.8 b/nfacct.8
|
||||
index 0c3249c..bf563ae 100644
|
||||
--- a/nfacct.8
|
||||
+++ b/nfacct.8
|
||||
@@ -47,6 +47,8 @@ That atomically obtains and resets the counters.
|
||||
.TP
|
||||
.BI "xml "
|
||||
That displays the output in XML format.
|
||||
+.BI "json "
|
||||
+That displays the output in JSON format.
|
||||
.PP
|
||||
.SH SEE ALSO
|
||||
.BR iptables (8)
|
||||
diff --git a/src/nfacct.c b/src/nfacct.c
|
||||
index 2546a6e..a55655a 100644
|
||||
--- a/src/nfacct.c
|
||||
+++ b/src/nfacct.c
|
||||
@@ -137,13 +137,13 @@ int main(int argc, char *argv[])
|
||||
return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
-static bool xml_header = false;
|
||||
+static bool fmt_header = false;
|
||||
|
||||
static int nfacct_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct nfacct *nfacct;
|
||||
char buf[4096];
|
||||
- bool *xml = (bool *)data;
|
||||
+ int *fmt = (int *)data;
|
||||
|
||||
nfacct = nfacct_alloc();
|
||||
if (nfacct == NULL) {
|
||||
@@ -156,17 +156,36 @@ static int nfacct_cb(const struct nlmsghdr *nlh, void *data)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
- if (*xml && !xml_header) {
|
||||
- printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
- "<nfacct>\n");
|
||||
- xml_header = true;
|
||||
+ switch (*fmt) {
|
||||
+ case NFACCT_SNPRINTF_T_XML:
|
||||
+ if (!fmt_header) {
|
||||
+ printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
||||
+ "<nfacct>\n");
|
||||
+ fmt_header = true;
|
||||
+ }
|
||||
+ break;
|
||||
+ case NFACCT_SNPRINTF_T_JSON:
|
||||
+ if (!fmt_header) {
|
||||
+ printf("{ \"nfacct_counters\" : [\n");
|
||||
+ fmt_header = true;
|
||||
+ } else
|
||||
+ printf(",\n");
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
}
|
||||
|
||||
- nfacct_snprintf(buf, sizeof(buf), nfacct,
|
||||
- *xml ? NFACCT_SNPRINTF_T_XML :
|
||||
- NFACCT_SNPRINTF_T_PLAIN,
|
||||
+ nfacct_snprintf(buf, sizeof(buf), nfacct, *fmt,
|
||||
NFACCT_SNPRINTF_F_FULL);
|
||||
- printf("%s\n", buf);
|
||||
+ printf("%s", buf);
|
||||
+ switch (*fmt) {
|
||||
+ case NFACCT_SNPRINTF_T_JSON:
|
||||
+ /* no newline in JSON case */
|
||||
+ break;
|
||||
+ default:
|
||||
+ putchar('\n');
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
err_free:
|
||||
nfacct_free(nfacct);
|
||||
@@ -174,9 +193,26 @@ err:
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
+static void _print_footer(int fmt)
|
||||
+{
|
||||
+ if (fmt_header) {
|
||||
+ switch (fmt) {
|
||||
+ case NFACCT_SNPRINTF_T_XML:
|
||||
+ printf("</nfacct>\n");
|
||||
+ break;
|
||||
+ case NFACCT_SNPRINTF_T_JSON:
|
||||
+ printf("\n] }\n");
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int nfacct_cmd_list(int argc, char *argv[])
|
||||
{
|
||||
- bool zeroctr = false, xml = false;
|
||||
+ bool zeroctr = false;
|
||||
+ int fmt = NFACCT_SNPRINTF_T_PLAIN;
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
@@ -190,9 +226,13 @@ static int nfacct_cmd_list(int argc, char *argv[])
|
||||
duparg(argv[i]);
|
||||
zeroctr = true;
|
||||
} else if (strncmp(argv[i], "xml", strlen(argv[i])) == 0) {
|
||||
- if (xml)
|
||||
+ if (fmt)
|
||||
+ duparg(argv[i]);
|
||||
+ fmt = NFACCT_SNPRINTF_T_XML;
|
||||
+ } else if (strncmp(argv[i], "json", strlen(argv[i])) == 0) {
|
||||
+ if (fmt)
|
||||
duparg(argv[i]);
|
||||
- xml = true;
|
||||
+ fmt = NFACCT_SNPRINTF_T_JSON;
|
||||
} else if (strncmp(argv[i], "counters", strlen(argv[i])) == 0) {
|
||||
if (mask || value)
|
||||
duparg(argv[i]);
|
||||
@@ -251,7 +291,7 @@ static int nfacct_cmd_list(int argc, char *argv[])
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
while (ret > 0) {
|
||||
- ret = mnl_cb_run(buf, ret, seq, portid, nfacct_cb, &xml);
|
||||
+ ret = mnl_cb_run(buf, ret, seq, portid, nfacct_cb, &fmt);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
@@ -262,8 +302,7 @@ static int nfacct_cmd_list(int argc, char *argv[])
|
||||
}
|
||||
mnl_socket_close(nl);
|
||||
|
||||
- if (xml_header)
|
||||
- printf("</nfacct>\n");
|
||||
+ _print_footer(fmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -444,7 +483,8 @@ static int nfacct_cmd_delete(int argc, char *argv[])
|
||||
|
||||
static int nfacct_cmd_get(int argc, char *argv[])
|
||||
{
|
||||
- bool zeroctr = false, xml = false;
|
||||
+ bool zeroctr = false;
|
||||
+ int fmt = NFACCT_SNPRINTF_T_PLAIN;
|
||||
struct mnl_socket *nl;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
@@ -460,7 +500,9 @@ static int nfacct_cmd_get(int argc, char *argv[])
|
||||
if (strncmp(argv[i], "reset", strlen(argv[i])) == 0) {
|
||||
zeroctr = true;
|
||||
} else if (strncmp(argv[i], "xml", strlen(argv[i])) == 0) {
|
||||
- xml = true;
|
||||
+ fmt = NFACCT_SNPRINTF_T_XML;
|
||||
+ } else if (strncmp(argv[i], "json", strlen(argv[i])) == 0) {
|
||||
+ fmt = NFACCT_SNPRINTF_T_JSON;
|
||||
} else {
|
||||
nfacct_perror("unknown argument");
|
||||
return -1;
|
||||
@@ -503,7 +545,7 @@ static int nfacct_cmd_get(int argc, char *argv[])
|
||||
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
while (ret > 0) {
|
||||
- ret = mnl_cb_run(buf, ret, seq, portid, nfacct_cb, &xml);
|
||||
+ ret = mnl_cb_run(buf, ret, seq, portid, nfacct_cb, &fmt);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
|
||||
@@ -514,8 +556,7 @@ static int nfacct_cmd_get(int argc, char *argv[])
|
||||
}
|
||||
mnl_socket_close(nl);
|
||||
|
||||
- if (xml_header)
|
||||
- printf("</nfacct>\n");
|
||||
+ _print_footer(fmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -660,7 +701,7 @@ static int nfacct_cmd_restore(int argc, char *argv[])
|
||||
static int nfacct_cmd_monitor(int argc, char *argv[])
|
||||
{
|
||||
struct mnl_socket *nl;
|
||||
- bool xml = false;
|
||||
+ int fmt = NFACCT_SNPRINTF_T_PLAIN;
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
int ret, option = NFNLGRP_ACCT_QUOTA;
|
||||
|
||||
@@ -685,7 +726,7 @@ static int nfacct_cmd_monitor(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
|
||||
- ret = mnl_cb_run(buf, ret, 0, 0, nfacct_cb, &xml);
|
||||
+ ret = mnl_cb_run(buf, ret, 0, 0, nfacct_cb, &fmt);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
}
|
||||
--
|
||||
2.1.4
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
SUMMARY = "nfacct is the command line tool to create/retrieve/delete accounting objects"
|
||||
HOMEPAGE = "http://www.netfilter.org/projects/nfacct/downloads.html"
|
||||
LICENSE = "GPLv2+"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=8ca43cbc842c2336e835926c2166c28b"
|
||||
PV="1.0.1+git${SRCPV}"
|
||||
|
||||
DEPENDS = "libmnl libnetfilter-acct"
|
||||
|
||||
SRC_URI = "git://git.netfilter.org/nfacct;branch=master \
|
||||
file://0001-Add-JSON-output-formatting-to-nfacct-utility.patch \
|
||||
"
|
||||
SRCREV = "4437682babe86de7435d4fc839437f99e998b79c"
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
RDEPENDS_${PN} += "kernel-module-xt-nfacct kernel-module-nfnetlink-acct"
|
||||
|
||||
inherit autotools pkgconfig
|
Loading…
Reference in New Issue