diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c index d7bf1f99..a4849902 100644 --- a/ip/ipmaddr.c +++ b/ip/ipmaddr.c @@ -28,6 +28,7 @@ #include "rt_names.h" #include "utils.h" #include "ip_common.h" +#include "json_print.h" static struct { char *dev; @@ -193,50 +194,66 @@ static void read_igmp6(struct ma_info **result_p) static void print_maddr(FILE *fp, struct ma_info *list) { - fprintf(fp, "\t"); + print_string(PRINT_FP, NULL, "\t", NULL); + open_json_object(NULL); if (list->addr.family == AF_PACKET) { SPRINT_BUF(b1); - fprintf(fp, "link %s", ll_addr_n2a((unsigned char *)list->addr.data, - list->addr.bytelen, 0, - b1, sizeof(b1))); + + print_string(PRINT_FP, NULL, "link ", NULL); + print_color_string(PRINT_ANY, COLOR_MAC, "link", "%s", + ll_addr_n2a((void *)list->addr.data, list->addr.bytelen, + 0, b1, sizeof(b1))); } else { - switch (list->addr.family) { - case AF_INET: - fprintf(fp, "inet "); - break; - case AF_INET6: - fprintf(fp, "inet6 "); - break; - default: - fprintf(fp, "family %d ", list->addr.family); - break; - } - fprintf(fp, "%s", - format_host(list->addr.family, - -1, list->addr.data)); + print_string(PRINT_ANY, "family", "%-5s ", + family_name(list->addr.family)); + print_color_string(PRINT_ANY, ifa_family_color(list->addr.family), + "address", "%s", + format_host(list->addr.family, + -1, list->addr.data)); } + if (list->users != 1) - fprintf(fp, " users %d", list->users); + print_uint(PRINT_ANY, "users", " users %u", list->users); + if (list->features) - fprintf(fp, " %s", list->features); - fprintf(fp, "\n"); + print_string(PRINT_ANY, "features", " %s", list->features); + + print_string(PRINT_FP, NULL, "\n", NULL); + close_json_object(); } static void print_mlist(FILE *fp, struct ma_info *list) { int cur_index = 0; + new_json_obj(json); for (; list; list = list->next) { - if (oneline) { + + if (list->index != cur_index || oneline) { + if (cur_index) { + close_json_array(PRINT_JSON, NULL); + close_json_object(); + } + open_json_object(NULL); + + print_uint(PRINT_ANY, "ifindex", "%d:", list->index); + print_color_string(PRINT_ANY, COLOR_IFNAME, + "ifname", "\t%s", list->name); + print_string(PRINT_FP, NULL, "%s", _SL_); cur_index = list->index; - fprintf(fp, "%d:\t%s%s", cur_index, list->name, _SL_); - } else if (cur_index != list->index) { - cur_index = list->index; - fprintf(fp, "%d:\t%s\n", cur_index, list->name); + + open_json_array(PRINT_JSON, "maddr"); } + print_maddr(fp, list); } + if (cur_index) { + close_json_array(PRINT_JSON, NULL); + close_json_object(); + } + + delete_json_obj(); } static int multiaddr_list(int argc, char **argv) diff --git a/ip/ipmroute.c b/ip/ipmroute.c index 5c232e8a..59c5b771 100644 --- a/ip/ipmroute.c +++ b/ip/ipmroute.c @@ -29,6 +29,7 @@ #include #include "utils.h" #include "ip_common.h" +#include "json_print.h" static void usage(void) __attribute__((noreturn)); @@ -53,13 +54,12 @@ struct rtfilter { int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { - FILE *fp = (FILE *)arg; struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[RTA_MAX+1]; - char obuf[256]; - + const char *src, *dst; SPRINT_BUF(b1); + SPRINT_BUF(b2); __u32 table; int iif = 0; int family; @@ -75,10 +75,11 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); return -1; } + if (r->rtm_type != RTN_MULTICAST) { - fprintf(stderr, "Not a multicast route (type: %s)\n", - rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); - return 0; + fprintf(stderr, + "Non multicast route received, kernel does support IP multicast?\n"); + return -1; } parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); @@ -103,30 +104,44 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) family = get_real_family(r->rtm_type, r->rtm_family); + open_json_object(NULL); if (n->nlmsg_type == RTM_DELROUTE) - fprintf(fp, "Deleted "); + print_bool(PRINT_ANY, "deleted", "Deleted ", true); if (tb[RTA_SRC]) - len = snprintf(obuf, sizeof(obuf), - "(%s, ", rt_addr_n2a_rta(family, tb[RTA_SRC])); + src = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_SRC]), + RTA_DATA(tb[RTA_SRC]), b1, sizeof(b1)); else - len = sprintf(obuf, "(unknown, "); - if (tb[RTA_DST]) - snprintf(obuf + len, sizeof(obuf) - len, - "%s)", rt_addr_n2a_rta(family, tb[RTA_DST])); - else - snprintf(obuf + len, sizeof(obuf) - len, "unknown) "); + src = "unknown"; - fprintf(fp, "%-32s Iif: ", obuf); - if (iif) - fprintf(fp, "%-10s ", ll_index_to_name(iif)); + if (tb[RTA_DST]) + dst = rt_addr_n2a_r(family, RTA_PAYLOAD(tb[RTA_DST]), + RTA_DATA(tb[RTA_DST]), b2, sizeof(b2)); else - fprintf(fp, "unresolved "); + dst = "unknown"; + + if (is_json_context()) { + print_string(PRINT_JSON, "src", NULL, src); + print_string(PRINT_JSON, "dst", NULL, dst); + } else { + char obuf[256]; + + snprintf(obuf, sizeof(obuf), "(%s,%s)", src, dst); + print_string(PRINT_FP, NULL, + "%-32s Iif: ", obuf); + } + + if (iif) + print_color_string(PRINT_ANY, COLOR_IFNAME, + "iif", "%-10s ", ll_index_to_name(iif)); + else + print_string(PRINT_ANY,"iif", "%s ", "unresolved"); if (tb[RTA_MULTIPATH]) { struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]); int first = 1; + open_json_array(PRINT_JSON, "multipath"); len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); for (;;) { @@ -135,47 +150,65 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (nh->rtnh_len > len) break; + open_json_object(NULL); if (first) { - fprintf(fp, "Oifs: "); + print_string(PRINT_FP, NULL, "Oifs: ", NULL); first = 0; } - fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex)); + + print_color_string(PRINT_ANY, COLOR_IFNAME, + "oif", "%s", ll_index_to_name(nh->rtnh_ifindex)); + if (nh->rtnh_hops > 1) - fprintf(fp, "(ttl %d) ", nh->rtnh_hops); + print_uint(PRINT_ANY, + "ttl", "(ttl %u) ", nh->rtnh_hops); else - fprintf(fp, " "); + print_string(PRINT_FP, NULL, " ", NULL); + + close_json_object(); len -= NLMSG_ALIGN(nh->rtnh_len); nh = RTNH_NEXT(nh); } + close_json_array(PRINT_JSON, NULL); } - fprintf(fp, " State: %s", - r->rtm_flags & RTNH_F_UNRESOLVED ? "unresolved" : "resolved"); + + print_string(PRINT_ANY, "state", " State: %s", + (r->rtm_flags & RTNH_F_UNRESOLVED) ? "unresolved" : "resolved"); + if (r->rtm_flags & RTNH_F_OFFLOAD) - fprintf(fp, " offload"); + print_null(PRINT_ANY, "offload", " offload", NULL); + if (show_stats && tb[RTA_MFC_STATS]) { struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]); - fprintf(fp, "%s %"PRIu64" packets, %"PRIu64" bytes", _SL_, - (uint64_t)mfcs->mfcs_packets, - (uint64_t)mfcs->mfcs_bytes); + print_string(PRINT_FP, NULL, "%s", _SL_); + print_uint(PRINT_ANY, "packets", " %"PRIu64" packets,", + mfcs->mfcs_packets); + print_uint(PRINT_ANY, "bytes", " %"PRIu64" bytes", mfcs->mfcs_bytes); + if (mfcs->mfcs_wrong_if) - fprintf(fp, ", %"PRIu64" arrived on wrong iif.", - (uint64_t)mfcs->mfcs_wrong_if); + print_uint(PRINT_ANY, "wrong_if", + ", %"PRIu64" arrived on wrong iif.", + mfcs->mfcs_wrong_if); } + if (show_stats && tb[RTA_EXPIRES]) { struct timeval tv; + double age; __jiffies_to_tv(&tv, rta_getattr_u64(tb[RTA_EXPIRES])); - fprintf(fp, ", Age %4i.%.2i", (int)tv.tv_sec, - (int)tv.tv_usec/10000); + age = tv.tv_sec; + age += tv.tv_usec / 1000000.; + print_float(PRINT_ANY, "expires", + ", Age %.2f", age); } if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb) - fprintf(fp, " Table: %s", - rtnl_rttable_n2a(table, b1, sizeof(b1))); + print_string(PRINT_ANY, "table", " Table: %s", + rtnl_rttable_n2a(table, b1, sizeof(b1))); - fprintf(fp, "\n"); - fflush(fp); + print_string(PRINT_FP, NULL, "\n", NULL); + close_json_object(); return 0; } @@ -255,12 +288,15 @@ static int mroute_list(int argc, char **argv) return 1; } + new_json_obj(json); if (rtnl_dump_filter(&rth, print_mroute, stdout) < 0) { + delete_json_obj(); fprintf(stderr, "Dump terminated\n"); exit(1); } + delete_json_obj(); - exit(0); + return 0; } int do_multiroute(int argc, char **argv)