lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1439232744-19505-6-git-send-email-matthias.tafelmeier@gmx.net>
Date:	Mon, 10 Aug 2015 20:52:19 +0200
From:	Matthias Tafelmeier <matthias.tafelmeier@....net>
To:	netdev@...r.kernel.org
Cc:	hagen@...u.net, shemminger@...l.org, fw@...len.de,
	edumazet@...gle.com, daniel@...earbox.net
Subject: [PATCH 05/10] ss: framed skeleton for json output in ss

This patch just adds the --json flag to ss. Also it ensures proper
stats components bracketization – that goes for ex. TCP, UDP, NETLINK etc.

Moreover, this patch prevents human readable headers to be printed. The
first element flag ensures, that every first output json container
element is treated specially, while all the others are treated equally.
That is, only the first one does not print a coma ahead of itself. The
rest does. This mechanism ensures the correct coma setting as demaned by
the spec. Illustration in the following:

PSEUDOCODE:

{ >>>> no comma
	{first }
>>>>	,
	{sec}
>>>>	,
	{third}
	.
	.
	.
}

Signed-off-by: Matthias Tafelmeier <matthias.tafelmeier@....net>
Suggested-by: Hagen Paul Pfeifer <hagen@...u.net>
---
 misc/ss.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 155 insertions(+), 43 deletions(-)

diff --git a/misc/ss.c b/misc/ss.c
index 1b3ef90..8fb6e7d 100644
--- a/misc/ss.c
+++ b/misc/ss.c
@@ -34,6 +34,9 @@
 #include "libnetlink.h"
 #include "namespace.h"
 #include "SNAPSHOT.h"
+#include "ss_out_fmt.h"
+#include "ss_json_fmt.h"
+#include "ss_types.h"
 
 #include <linux/tcp.h>
 #include <linux/sock_diag.h>
@@ -101,6 +104,7 @@ int show_sock_ctx = 0;
 /* If show_users & show_proc_ctx only do user_ent_hash_build() once */
 int user_ent_hash_build_init = 0;
 int follow_events = 0;
+int json_output = 0;
 
 int netid_width;
 int state_width;
@@ -714,7 +718,6 @@ static int is_ephemeral(int port)
 	return (port >= ip_local_port_min && port<= ip_local_port_max);
 }
 
-
 static const char *__resolve_service(int port)
 {
 	struct scache *c;
@@ -3064,6 +3067,9 @@ static int print_summary(void)
 
 	printf("\n");
 
+	if (json_output && has_successor)
+		printf(",\n");
+
 	return 0;
 }
 
@@ -3090,6 +3096,7 @@ static void _usage(FILE *dest)
 "   -z, --contexts      display process and socket SELinux security contexts\n"
 "   -N, --net           switch to the specified network namespace name\n"
 "\n"
+"   -j, --json          format output in JSON\n"
 "   -4, --ipv4          display only IP version 4 sockets\n"
 "   -6, --ipv6          display only IP version 6 sockets\n"
 "   -0, --packet        display PACKET sockets\n"
@@ -3189,6 +3196,7 @@ static const struct option long_opts[] = {
 	{ "help", 0, 0, 'h' },
 	{ "context", 0, 0, 'Z' },
 	{ "contexts", 0, 0, 'z' },
+	{ "json", 0, 0, 'j' },
 	{ "net", 1, 0, 'N' },
 	{ 0 }
 
@@ -3204,7 +3212,7 @@ int main(int argc, char *argv[])
 	int ch;
 	int state_filter = 0;
 
-	while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbEf:miA:D:F:vVzZN:",
+	while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spbEf:miA:D:F:vVzZN:j",
 				 long_opts, NULL)) != EOF) {
 		switch(ch) {
 		case 'n':
@@ -3383,6 +3391,10 @@ int main(int argc, char *argv[])
 			if (netns_switch(optarg))
 				exit(1);
 			break;
+		case 'j':
+			fmt_type = FMT_JSON;
+			json_output = 1;
+			break;
 		case 'h':
 		case '?':
 			help();
@@ -3464,11 +3476,33 @@ int main(int argc, char *argv[])
 				exit(-1);
 			}
 		}
+		printf("\"TCP\": [\n");
 		inet_show_netlink(&current_filter, dump_fp, IPPROTO_TCP);
+		res_json_fmt_branch(current_filter.dbs & (1<<NETLINK_DB) ||
+				current_filter.dbs & PACKET_DBM ||
+				current_filter.dbs & UNIX_DBM ||
+				current_filter.dbs & (1<<RAW_DB) ||
+				current_filter.dbs & (1<<UDP_DB) ||
+				current_filter.dbs & (1<<TCP_DB) ||
+				current_filter.dbs & (1<<DCCP_DB), ']');
 		fflush(dump_fp);
 		exit(0);
 	}
 
+	if (do_summary) {
+		print_summary(current_filter.dbs & PACKET_DBM ||
+				current_filter.dbs & UNIX_DBM ||
+				current_filter.dbs & (1<<RAW_DB) ||
+				current_filter.dbs & (1<<UDP_DB) ||
+				current_filter.dbs & (1<<TCP_DB) ||
+				current_filter.dbs & (1<<DCCP_DB));
+		if (do_default && argc == 0) {
+			if (json_output)
+				printf("}\n");
+			exit(0);
+		}
+	}
+
 	if (ssfilter_parse(&current_filter.f, argc, argv, filter_fp))
 		usage();
 
@@ -3490,62 +3524,140 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	addrp_width = screen_width;
-	addrp_width -= netid_width+1;
-	addrp_width -= state_width+1;
-	addrp_width -= 14;
+	if (!json_output) {
+
+		addrp_width = screen_width;
+		addrp_width -= netid_width + 1;
+		addrp_width -= state_width + 1;
+		addrp_width -= 14;
+
+		if (addrp_width & 1) {
+			if (netid_width)
+				netid_width++;
+			else if (state_width)
+				state_width++;
+		}
+
+		addrp_width /= 2;
+		addrp_width--;
+
+		serv_width = resolve_services ? 7 : 5;
+
+		if (addrp_width < 15 + serv_width + 1)
+			addrp_width = 15 + serv_width + 1;
 
-	if (addrp_width&1) {
+		addr_width = addrp_width - serv_width - 1;
 		if (netid_width)
-			netid_width++;
-		else if (state_width)
-			state_width++;
-	}
+			printf("%-*s ", netid_width, "Netid");
+		if (state_width)
+			printf("%-*s ", state_width, "State");
+		printf("%-6s %-6s ", "Recv-Q", "Send-Q");
 
-	addrp_width /= 2;
-	addrp_width--;
+		/* Make enough space for the local/remote port field */
+		addr_width -= 13;
+		serv_width += 13;
 
-	serv_width = resolve_services ? 7 : 5;
+		printf("%*s:%-*s %*s:%-*s\n",
+				addr_width, "Local Address", serv_width, "Port",
+				addr_width, "Peer Address", serv_width, "Port");
+	}
 
-	if (addrp_width < 15+serv_width+1)
-		addrp_width = 15+serv_width+1;
+	fflush(stdout);
 
-	addr_width = addrp_width - serv_width - 1;
+	if (current_filter.dbs & (1<<NETLINK_DB)) {
+		if (json_output) {
+			printf("\"NETLINK\": [\n");
+			netlink_show(&current_filter);
+			json_first_elem = 1;
+			res_json_fmt_branch(current_filter.dbs & PACKET_DBM ||
+					current_filter.dbs & UNIX_DBM ||
+					current_filter.dbs & (1<<RAW_DB) ||
+					current_filter.dbs & (1<<UDP_DB) ||
+					current_filter.dbs & (1<<TCP_DB) ||
+					current_filter.dbs & (1<<DCCP_DB), ']');
+		} else
+			netlink_show(&current_filter);
+	}
+	if (current_filter.dbs & PACKET_DBM) {
+		if (json_output) {
+			printf("\"PACKET\": [\n");
+			packet_show(&current_filter);
+			json_first_elem = 1;
+			res_json_fmt_branch(
+					current_filter.dbs & UNIX_DBM ||
+					current_filter.dbs & (1<<RAW_DB) ||
+					current_filter.dbs & (1<<UDP_DB) ||
+					current_filter.dbs & (1<<TCP_DB) ||
+					current_filter.dbs & (1<<DCCP_DB), ']');
+		} else
+			packet_show(&current_filter);
+	}
+	if (current_filter.dbs & UNIX_DBM) {
+		if (json_output) {
+			printf("\"UNIX\": [\n");
+			unix_show(&current_filter);
+			json_first_elem = 1;
+			res_json_fmt_branch(
+					current_filter.dbs & (1<<RAW_DB) ||
+					current_filter.dbs & (1<<UDP_DB) ||
+					current_filter.dbs & (1<<TCP_DB) ||
+					current_filter.dbs & (1<<DCCP_DB), ']');
 
-	if (netid_width)
-		printf("%-*s ", netid_width, "Netid");
-	if (state_width)
-		printf("%-*s ", state_width, "State");
-	printf("%-6s %-6s ", "Recv-Q", "Send-Q");
+		} else
+			unix_show(&current_filter);
+	}
+	if (current_filter.dbs & (1<<RAW_DB)) {
+		if (json_output) {
+			printf("\"RAW\": [\n");
+			raw_show(&current_filter);
+			json_first_elem = 1;
+			res_json_fmt_branch(
+					current_filter.dbs & (1<<UDP_DB) ||
+					current_filter.dbs & (1<<TCP_DB) ||
+					current_filter.dbs & (1<<DCCP_DB), ']');
 
-	/* Make enough space for the local/remote port field */
-	addr_width -= 13;
-	serv_width += 13;
+		} else
+			raw_show(&current_filter);
+	}
+	if (current_filter.dbs & (1<<UDP_DB)) {
+		if (json_output) {
+			printf("\"UDP\": [\n");
+			udp_show(&current_filter);
+			json_first_elem = 1;
+			res_json_fmt_branch(
+					current_filter.dbs & (1<<TCP_DB) ||
+					current_filter.dbs & (1<<DCCP_DB), ']');
 
-	printf("%*s:%-*s %*s:%-*s\n",
-	       addr_width, "Local Address", serv_width, "Port",
-	       addr_width, "Peer Address", serv_width, "Port");
+		} else
+			udp_show(&current_filter);
+	}
+	if (current_filter.dbs & (1<<TCP_DB)) {
+		if (json_output) {
+			printf("\"TCP\": [\n");
+			tcp_show(&current_filter, IPPROTO_TCP);
+			json_first_elem = 1;
+			res_json_fmt_branch(
+					current_filter.dbs & (1<<DCCP_DB), ']');
+		} else
+			tcp_show(&current_filter, IPPROTO_TCP);
+	}
+	if (current_filter.dbs & (1<<DCCP_DB)) {
+		if (json_output) {
+			printf("\"DCCP\": [\n");
+			tcp_show(&current_filter, IPPROTO_DCCP);
+			printf("]\n");
+		} else
+			tcp_show(&current_filter, IPPROTO_DCCP);
+	}
+
+	if (json_output)
+		printf("}\n");
 
 	fflush(stdout);
 
 	if (follow_events)
 		exit(handle_follow_request(&current_filter));
 
-	if (current_filter.dbs & (1<<NETLINK_DB))
-		netlink_show(&current_filter);
-	if (current_filter.dbs & PACKET_DBM)
-		packet_show(&current_filter);
-	if (current_filter.dbs & UNIX_DBM)
-		unix_show(&current_filter);
-	if (current_filter.dbs & (1<<RAW_DB))
-		raw_show(&current_filter);
-	if (current_filter.dbs & (1<<UDP_DB))
-		udp_show(&current_filter);
-	if (current_filter.dbs & (1<<TCP_DB))
-		tcp_show(&current_filter, IPPROTO_TCP);
-	if (current_filter.dbs & (1<<DCCP_DB))
-		tcp_show(&current_filter, IPPROTO_DCCP);
-
 	if (show_users || show_proc_ctx || show_sock_ctx)
 		user_ent_destroy();
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ