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: <20180306210720.19802-2-stephen@networkplumber.org>
Date:   Tue,  6 Mar 2018 13:07:09 -0800
From:   Stephen Hemminger <stephen@...workplumber.org>
To:     dsahern@...il.com
Cc:     netdev@...r.kernel.org, Stephen Hemminger <sthemmin@...rosoft.com>,
        Stephen Hemminger <stephen@...workplumber.org>
Subject: [PATCH iproute2-next v2 01/12] ipneigh: add color and json support

From: Stephen Hemminger <sthemmin@...rosoft.com>

Use json_print to provide json (and color) support to
ip neigh command.

Example:
$ ip -j -p neigh
[ {
        "dst": "192.168.1.29",
        "dev": "enp12s0",
        "state": [ "FAILED" ]
    },{
        "dst": "192.168.1.130",
        "dev": "enp12s0",
        "state": [ "FAILED" ]
    },{
        "dst": "192.168.1.131",
        "dev": "enp12s0",
        "lladdr": "00:15:5d:2a:16:4f",
        "state": [ "STALE" ]
    }
...

Signed-off-by: Stephen Hemminger <stephen@...workplumber.org>
---
 ip/ipneigh.c | 140 +++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 93 insertions(+), 47 deletions(-)

diff --git a/ip/ipneigh.c b/ip/ipneigh.c
index 0735424900f6..925494dbe324 100644
--- a/ip/ipneigh.c
+++ b/ip/ipneigh.c
@@ -23,6 +23,7 @@
 #include "rt_names.h"
 #include "utils.h"
 #include "ip_common.h"
+#include "json_print.h"
 
 #define NUD_VALID	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
 #define MAX_ROUNDS	10
@@ -189,6 +190,46 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
 	return 0;
 }
 
+static void print_cacheinfo(const struct nda_cacheinfo *ci)
+{
+	static int hz;
+
+	if (!hz)
+		hz = get_user_hz();
+
+	if (ci->ndm_refcnt)
+		print_uint(PRINT_ANY, "refcnt",
+				" ref %u", ci->ndm_refcnt);
+
+	print_uint(PRINT_ANY, "used", " used %u", ci->ndm_used / hz);
+	print_uint(PRINT_ANY, "confirmed", "/%u", ci->ndm_confirmed / hz);
+	print_uint(PRINT_ANY, "updated", "/u", ci->ndm_updated / hz);
+}
+
+static void print_neigh_state(unsigned int nud)
+{
+
+	open_json_array(PRINT_JSON,
+			is_json_context() ?  "state" : "");
+
+#define PRINT_FLAG(f)						\
+	if (nud & NUD_##f) {					\
+		nud &= ~NUD_##f;				\
+		print_string(PRINT_ANY, NULL, " %s", #f);	\
+	}
+
+	PRINT_FLAG(INCOMPLETE);
+	PRINT_FLAG(REACHABLE);
+	PRINT_FLAG(STALE);
+	PRINT_FLAG(DELAY);
+	PRINT_FLAG(PROBE);
+	PRINT_FLAG(FAILED);
+	PRINT_FLAG(NOARP);
+	PRINT_FLAG(PERMANENT);
+#undef PRINT_FLAG
+
+	close_json_array(PRINT_JSON, NULL);
+}
 
 int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 {
@@ -221,7 +262,7 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 	if (!(filter.state&r->ndm_state) &&
 	    !(r->ndm_flags & NTF_PROXY) &&
 	    (r->ndm_state || !(filter.state&0x100)) &&
-	     (r->ndm_family != AF_DECnet))
+	    (r->ndm_family != AF_DECnet))
 		return 0;
 
 	if (filter.master && !(n->nlmsg_flags & NLM_F_DUMP_FILTERED)) {
@@ -262,65 +303,68 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 			return 0;
 	}
 
+	open_json_object(NULL);
 	if (n->nlmsg_type == RTM_DELNEIGH)
-		fprintf(fp, "Deleted ");
+		print_bool(PRINT_ANY, "deleted", "Deleted ", true);
 	else if (n->nlmsg_type == RTM_GETNEIGH)
-		fprintf(fp, "miss ");
+		print_null(PRINT_ANY, "miss", "%s ", "miss");
+
 	if (tb[NDA_DST]) {
-		fprintf(fp, "%s ",
-			format_host_rta(r->ndm_family, tb[NDA_DST]));
+		const char *dst;
+
+		dst = format_host_rta(r->ndm_family, tb[NDA_DST]);
+		print_color_string(PRINT_ANY,
+				   ifa_family_color(r->ndm_family),
+				   "dst", "%s ", dst);
 	}
-	if (!filter.index && r->ndm_ifindex)
-		fprintf(fp, "dev %s ", ll_index_to_name(r->ndm_ifindex));
+
+	if (!filter.index && r->ndm_ifindex) {
+		if (!is_json_context())
+			fprintf(fp, "dev ");
+
+		print_color_string(PRINT_ANY, COLOR_IFNAME,
+				   "dev", "%s ",
+				   ll_index_to_name(r->ndm_ifindex));
+	}
+
 	if (tb[NDA_LLADDR]) {
+		const char *lladdr;
 		SPRINT_BUF(b1);
-		fprintf(fp, "lladdr %s", ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
-					      RTA_PAYLOAD(tb[NDA_LLADDR]),
-					      ll_index_to_type(r->ndm_ifindex),
-					      b1, sizeof(b1)));
-	}
-	if (r->ndm_flags & NTF_ROUTER) {
-		fprintf(fp, " router");
-	}
-	if (r->ndm_flags & NTF_PROXY) {
-		fprintf(fp, " proxy");
-	}
-	if (tb[NDA_CACHEINFO] && show_stats) {
-		struct nda_cacheinfo *ci = RTA_DATA(tb[NDA_CACHEINFO]);
-		int hz = get_user_hz();
 
-		if (ci->ndm_refcnt)
-			printf(" ref %d", ci->ndm_refcnt);
-		fprintf(fp, " used %d/%d/%d", ci->ndm_used/hz,
-		       ci->ndm_confirmed/hz, ci->ndm_updated/hz);
-	}
+		lladdr = ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
+				     RTA_PAYLOAD(tb[NDA_LLADDR]),
+				     ll_index_to_type(r->ndm_ifindex),
+				     b1, sizeof(b1));
 
-	if (tb[NDA_PROBES] && show_stats) {
-		__u32 p = rta_getattr_u32(tb[NDA_PROBES]);
+		if (!is_json_context())
+			fprintf(fp, "lladdr ");
 
-		fprintf(fp, " probes %u", p);
+		print_color_string(PRINT_ANY, COLOR_MAC,
+				   "lladdr", "%s", lladdr);
 	}
 
-	if (r->ndm_state) {
-		int nud = r->ndm_state;
-
-		fprintf(fp, " ");
-
-#define PRINT_FLAG(f) if (nud & NUD_##f) { \
-	nud &= ~NUD_##f; fprintf(fp, #f "%s", nud ? "," : ""); }
-		PRINT_FLAG(INCOMPLETE);
-		PRINT_FLAG(REACHABLE);
-		PRINT_FLAG(STALE);
-		PRINT_FLAG(DELAY);
-		PRINT_FLAG(PROBE);
-		PRINT_FLAG(FAILED);
-		PRINT_FLAG(NOARP);
-		PRINT_FLAG(PERMANENT);
-#undef PRINT_FLAG
+	if (r->ndm_flags & NTF_ROUTER)
+		print_null(PRINT_ANY, "router", " %s", "router");
+
+	if (r->ndm_flags & NTF_PROXY)
+		print_null(PRINT_ANY, "proxy", " %s", "proxy");
+
+	if (show_stats) {
+		if (tb[NDA_CACHEINFO])
+			print_cacheinfo(RTA_DATA(tb[NDA_CACHEINFO]));
+
+		if (tb[NDA_PROBES])
+			print_uint(PRINT_ANY, "probes", " probes %u",
+				   rta_getattr_u32(tb[NDA_PROBES]));
 	}
-	fprintf(fp, "\n");
 
-	fflush(fp);
+	if (r->ndm_state)
+		print_neigh_state(r->ndm_state);
+
+	print_string(PRINT_FP, NULL, "\n", "");
+	close_json_object();
+	fflush(stdout);
+
 	return 0;
 }
 
@@ -479,10 +523,12 @@ static int do_show_or_flush(int argc, char **argv, int flush)
 		exit(1);
 	}
 
+	new_json_obj(json);
 	if (rtnl_dump_filter(&rth, print_neigh, stdout) < 0) {
 		fprintf(stderr, "Dump terminated\n");
 		exit(1);
 	}
+	delete_json_obj();
 
 	return 0;
 }
-- 
2.16.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ