ip multicast command JSON support
Subsystems (2)
cover ip multicast command JSON support
From: Stephen Hemminger <[email protected]>
Update maddr and mroute to support JSON.
Fix bug in ipmroute that causes it print error on every unicast route.
Stephen Hemminger (3):
ipmaddr: json and color support
ipmroute: don't complain about unicast routes
ipmroute: convert to output JSON
ip/ipmaddr.c | 69 ++++++++++++++++++++------------ ip/ipmroute.c | 124 +++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 123 insertions(+), 70 deletions(-)
Signature · 1 line
2.16.1
PATCH 1/3 ipmaddr: json and color support
From: Stephen Hemminger <[email protected]>
Support printing mulitcast addresses in json and color mode. Output format is unchanged for normal use.
--- ip/ipmaddr.c | 69 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 26 deletions(-)
ip/ipmaddr.c +43 -26
@@ -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) { - cur_index = list->index; -fprintf (fp,"%d:\t%s%s" , cur_index, list->name, _SL_); - }else if (cur_index != list->index) { + +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\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)
Signature · 1 line
2.16.1
PATCH 2/3 ipmroute: don't complain about unicast routes
In reply to Stephen HemmingerFrom: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.
--- ip/ipmroute.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
ip/ipmroute.c +3 -4
@@ -75,15 +75,14 @@ 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))); + +if (r->rtm_type !=RTN_MULTICAST )return 0 ; - }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len); table =rtm_get_table (r, tb); +if (filter.tb >0 && filter.tb != table)return 0 ;
Signature · 1 line
2.16.1
Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes
Hello!
Quoted 21 lines · Stephen Hemminger
From: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.Signed-off-by Stephen Hemminger <[email protected]>--- ip/ipmroute.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)ip/ipmroute.c +0
-2@@ -75,15 +75,14 @@ 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",
ip/ipmroute.c int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) · line 85
Quoted 10 lines
ip/ipmroute.c +3
-2- rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); + +if (r->rtm_type !=RTN_MULTICAST )return 0 ; - }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len); table =rtm_get_table (r, tb); +
Why?
ip/ipmroute.c int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) · line 88
Quoted 3 lines
ip/ipmroute.c +0
-0if (filter.tb >0 && filter.tb != table)return 0 ;
MBR, Sergei
Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes
Quoted 38 lines · On Wed, 7 Mar 2018 11:43:33 +0300 Sergei Shtylyov…
Hello!
Quoted 21 lines · Stephen Hemminger
From: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.Signed-off-by Stephen Hemminger <[email protected]>--- ip/ipmroute.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)ip/ipmroute.c +0
-2@@ -75,15 +75,14 @@ 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",ip/ipmroute.c int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) · line 85
Quoted 10 lines
ip/ipmroute.c +3
-2- rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); + +if (r->rtm_type !=RTN_MULTICAST )return 0 ; - }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len); table =rtm_get_table (r, tb); +Why?
Quoted 5 lines
ip/ipmroute.c int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) · line 88
Quoted 3 lines
ip/ipmroute.c +0
-0if (filter.tb >0 && filter.tb != table)return 0 ;MBR, Sergei
The kernel dumps all routes in response to the RTM_GETROUTE and therefore all routes show up in print_mroute. On my system (which has no mcast), I get this with standard 4.14 kernel and ip commands.
$ ip mroute Not a multicast route (type: unicast) Not a multicast route (type: unicast) Not a multicast route (type: unicast) Not a multicast route (type: unicast) Not a multicast route (type: unicast) Not a multicast route (type: broadcast) Not a multicast route (type: local) Not a multicast route (type: local) Not a multicast route (type: broadcast) Not a multicast route (type: broadcast) Not a multicast route (type: local)
Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes
Quoted 42 lines · Stephen Hemminger
Quoted 42 lines
Hello!
Quoted 21 lines · Stephen Hemminger
From: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.Signed-off-by Stephen Hemminger <[email protected]>--- ip/ipmroute.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)ip/ipmroute.c +0
-2@@ -75,15 +75,14 @@ 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",ip/ipmroute.c int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) · line 85
Quoted 10 lines
ip/ipmroute.c +3
-2- rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); + +if (r->rtm_type !=RTN_MULTICAST )return 0 ; - }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len); table =rtm_get_table (r, tb); +Why?
Quoted 3 lines
ip/ipmroute.c +0
-0if (filter.tb >0 && filter.tb != table)return 0 ;
Quoted 5 lines
Quoted 1 line
MBR, Sergei
The kernel dumps all routes in response to the
RTM_GETROUTEand therefore all routes show up inprint_mroute. On my system (which has no mcast), I get this with standard 4.14 kernel and ip commands.
I was merely asking about a double new line... :-)
MBR, Sergei
Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes
In reply to Stephen HemmingerQuoted 24 lines · On Tue, 6 Mar 2018 17:03:54 -0800 Stephen Hemminger…
From: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.Signed-off-by Stephen Hemminger <[email protected]>--- ip/ipmroute.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)ip/ipmroute.c +2
-3@@ -75,15 +75,14 @@ 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))); + +if (r->rtm_type !=RTN_MULTICAST )
ip/ipmroute.c int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) · line 88
Quoted 10 lines
ip/ipmroute.c +1
-1return 0 ; - }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len); table =rtm_get_table (r, tb); +if (filter.tb >0 && filter.tb != table)return 0 ;
Actually, this is a recent kernel regression. Should be fixed there
Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes
Quoted 33 lines · Stephen Hemminger
Quoted 30 lines · On Tue, 6 Mar 2018 17:03:54 -0800 Stephen Hemminger…
From: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.Signed-off-by Stephen Hemminger <[email protected]>--- ip/ipmroute.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)ip/ipmroute.c +2
-4@@ -75,15 +75,14 @@ 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))); + +if (r->rtm_type !=RTN_MULTICAST )return 0 ; - }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len); table =rtm_get_table (r, tb);
Quoted 7 lines
ip/ipmroute.c int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) · line 88
Quoted 4 lines
ip/ipmroute.c +1
-0+if (filter.tb >0 && filter.tb != table)return 0 ;Actually, this is a recent kernel regression. Should be fixed there
from Yuval's recent multicast convergence changes?
Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes
In reply to Stephen HemmingerQuoted 7 lines · On Tue, 6 Mar 2018 17:03:54 -0800 Stephen Hemminger…
From: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.Signed-off-by Stephen Hemminger <[email protected]>
I found the issue (in kernel) but not sure how to deal with it. If kernel is built without multicast routing configured !CONFIG_IP_MROUTE then the netlink request to return multicast routes will return all routes!
This is because in the kernel the way route dump works is that each address family registers a callback to dump routes for a specific address family. If that address family is not registered then the fall back is to address family PF_UNSPEC which has a handler that dumps all routes.
Unfortunately, changing that behavior in kernel will certainly break some user. And there is no direct way to determine multicast routing is enabled in ip mroute code.
Maybe just change the message in ip mroute to do:
ip/ipmroute.c +2 -3
@@ -76,9 +76,8 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)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,"Multicast routing does not appear to be enabled\n" ); +return -1 ; }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len);
Re: [PATCH iproute2-next 2/3] ipmroute: don't complain about unicast routes
Quoted 15 lines · Stephen Hemminger
Quoted 7 lines · On Tue, 6 Mar 2018 17:03:54 -0800 Stephen Hemminger…
From: Stephen Hemminger <[email protected]>
Every non-multicast route prints an error message.
Kernel doesn't filter out unicast routes, it is up to filter function to do this.Signed-off-by Stephen Hemminger <[email protected]>I found the issue (in kernel) but not sure how to deal with it. If kernel is built without multicast routing configured !CONFIG_IP_MROUTE then the netlink request to return multicast routes will return all routes!
Quoted 5 lines
This is because in the kernel the way route dump works is that each address family registers a callback to dump routes for a specific address family. If that address family is not registered then the fall back is to address family
PF_UNSPECwhich has a handler that dumps all routes.
If I ask the kernel for IP{6}MR address family and the kernel returns a dump of all address families, that seems like a kernel bug to me. From a short review it seems to be that way for a long time. I guess iproute2 has no choice but to adapt to the kernel design.
Are you going to resubmit this series?
Quoted 24 lines
Unfortunately, changing that behavior in kernel will certainly break some user. And there is no direct way to determine multicast routing is enabled in ip mroute code.
Maybe just change the message in ip mroute to do:
ip/ipmroute.c +2
-3@@ -76,9 +76,8 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)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,"Multicast routing does not appear to be enabled\n" ); +return -1 ; }parse_rtattr (tb,RTA_MAX ,RTM_RTA (r), len);
PATCH 3/3 ipmroute: convert to output JSON
In reply to Stephen HemmingerFrom: Stephen Hemminger <[email protected]>
Should be no change for non-json case except putting color on address if desired.
--- ip/ipmroute.c | 117 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 40 deletions(-)
ip/ipmroute.c +77 -40
@@ -29,6 +29,7 @@#include <rt_names.h> #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;
@@ -102,30 +102,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, " ); + src ="unknown" ; +if (tb[RTA_DST ]) -snprintf (obuf + len,sizeof (obuf) - len, -"%s)" ,rt_addr_n2a_rta (family, tb[RTA_DST ])); + dst =rt_addr_n2a_r (family,RTA_PAYLOAD (tb[RTA_DST ]), +RTA_DATA (tb[RTA_DST ]), b2,sizeof (b2));else -snprintf (obuf + len,sizeof (obuf) - len,"unknown) " ); + 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); + } -fprintf (fp,"%-32s Iif: " , obuf);if (iif) -fprintf (fp,"%-10s " ,ll_index_to_name (iif)); +print_color_string (PRINT_ANY ,COLOR_IFNAME , +"iif" ,"%-10s " ,ll_index_to_name (iif));else -fprintf (fp,"unresolved " ); +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 (;;) {
@@ -134,47 +148,67 @@ 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" ); -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); -if (mfcs->mfcs_wrong_if) -fprintf (fp,", %" PRIu64" arrived on wrong iif." , - (uint64_t )mfcs->mfcs_wrong_if); - } -if (show_stats && tb[RTA_EXPIRES ]) { -struct timeval tv; +print_null (PRINT_ANY ,"offload" ," offload" ,NULL ); + +if (show_stats) { +if ( tb[RTA_MFC_STATS ]) { +struct rta_mfc_stats *mfcs =RTA_DATA (tb[RTA_MFC_STATS ]); -__jiffies_to_tv (&tv,rta_getattr_u64 (tb[RTA_EXPIRES ])); -fprintf (fp,", Age %4i.%.2i" , (int )tv.tv_sec, - (int )tv.tv_usec/10000 ); +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) +print_uint (PRINT_ANY ,"wrong_if" , +", %" PRIu64" arrived on wrong iif." , + mfcs->mfcs_wrong_if); + } + +if (tb[RTA_EXPIRES ]) { +struct timeval tv; +double age; + +__jiffies_to_tv (&tv,rta_getattr_u64 (tb[RTA_EXPIRES ])); + 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 +289,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)
Signature · 1 line
2.16.1