netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Harald Welte <laforge@gnumonks.org>
To: netfilter-devel@vger.kernel.org
Subject: [PATCH] Add JSON output formatting to nfacct utility
Date: Mon, 22 Feb 2016 10:12:36 +0100	[thread overview]
Message-ID: <1456132356-23474-1-git-send-email-laforge@gnumonks.org> (raw)

This is based on the JSON support patch of libnetfilter_acct.
---
 nfacct.8     |  2 ++
 src/nfacct.c | 89 ++++++++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 68 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..d46ee91 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,38 @@ 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("{ \"timestamp\" : %lld, \n"
+			       "  \"nfacct_counters\" : [\n",
+			       (long long) time(NULL));
+			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 +195,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 +228,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 +293,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 +304,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 +485,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 +502,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 +547,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 +558,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 +703,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 +728,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.7.0


             reply	other threads:[~2016-02-22  9:39 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-22  9:12 Harald Welte [this message]
2016-02-29 11:43 ` [PATCH] Add JSON output formatting to nfacct utility Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1456132356-23474-1-git-send-email-laforge@gnumonks.org \
    --to=laforge@gnumonks.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).