--- embedaddon/mtr/ui/report.c 2019/10/21 14:25:31 1.1.1.1 +++ embedaddon/mtr/ui/report.c 2021/03/17 00:07:30 1.1.1.2 @@ -11,9 +11,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" @@ -26,6 +26,14 @@ #include #include #include +#ifdef HAVE_JANSSON +#include +#endif +#ifdef HAVE_ERROR_H +#include +#else +#include "portability/error.h" +#endif #include "mtr.h" #include "report.h" @@ -74,8 +82,8 @@ static void print_mpls( { int k; for (k = 0; k < mpls->labels; k++) - printf(" [MPLS: Lbl %lu Exp %u S %cu TTL %u]\n", - mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); + printf(" [MPLS: Lbl %lu TC %u S %cu TTL %u]\n", + mpls->label[k], mpls->tc[k], mpls->s[k], mpls->ttl[k]); } #endif @@ -176,15 +184,25 @@ void report_close( /* This feature shows 'loadbalances' on routes */ - /* z is starting at 1 because addrs[0] is the same that addr */ - for (z = 1; z < MAXPATH; z++) { + /* Print list of all hosts that have responded from ttl = at + 1 away */ + for (z = 0; z < MAX_PATH; z++) { int found = 0; addr2 = net_addrs(at, z); mplss = net_mplss(at, z); if ((addrcmp ((void *) &ctl->unspec_addr, (void *) addr2, - ctl->af)) == 0) + ctl->af)) == 0) { break; + } else if ((addrcmp + ((void *) addr, (void *) addr2, + ctl->af)) == 0) { + continue; /* Latest Host is already printed */ + } else { + snprint_addr(ctl, name, sizeof(name), addr2); + snprintf(fmt, sizeof(fmt), " %%-%zus", len_hosts); + snprintf(buf, sizeof(buf), fmt, name); + printf("%s\n", buf); + } for (w = 0; w < z; w++) /* Ok... checking if there are ips repeated on same hop */ if ((addrcmp @@ -210,8 +228,8 @@ void report_close( if (mpls->labels && z == 1 && ctl->enablempls) { for (k = 0; k < mpls->labels; k++) { printf - (" | |+-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", - mpls->label[k], mpls->exp[k], mpls->s[k], + (" | |+-- [MPLS: Lbl %lu TC %u S %u TTL %u]\n", + mpls->label[k], mpls->tc[k], mpls->s[k], mpls->ttl[k]); } } @@ -220,16 +238,16 @@ void report_close( printf(" | `|-- %s\n", strlongip(ctl, addr2)); for (k = 0; k < mplss->labels && ctl->enablempls; k++) { printf - (" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", - mplss->label[k], mplss->exp[k], mplss->s[k], + (" | +-- [MPLS: Lbl %lu TC %u S %u TTL %u]\n", + mplss->label[k], mplss->tc[k], mplss->s[k], mplss->ttl[k]); } } else { printf(" | |-- %s\n", strlongip(ctl, addr2)); for (k = 0; k < mplss->labels && ctl->enablempls; k++) { printf - (" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", - mplss->label[k], mplss->exp[k], mplss->s[k], + (" | +-- [MPLS: Lbl %lu TC %u S %u TTL %u]\n", + mplss->label[k], mplss->tc[k], mplss->s[k], mplss->ttl[k]); } } @@ -247,8 +265,8 @@ void report_close( if (mpls->labels && z == 1 && ctl->enablempls) { int k; for (k = 0; k < mpls->labels; k++) { - printf(" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", - mpls->label[k], mpls->exp[k], mpls->s[k], + printf(" | +-- [MPLS: Lbl %lu TC %u S %u TTL %u]\n", + mpls->label[k], mpls->tc[k], mpls->s[k], mpls->ttl[k]); } } @@ -269,110 +287,111 @@ void txt_close( report_close(ctl); } - +#ifdef HAVE_JANSSON void json_open( void) { } - -void json_close( - struct mtr_ctl *ctl) +void json_close(struct mtr_ctl *ctl) { - int i, j, at, first, max; + int i, j, at, max; + int ret; + char buf[128]; + json_t *jreport, *jmtr, *jhubs, *jh; ip_t *addr; char name[MAX_FORMAT_STR]; - printf("{\n"); - printf(" \"report\": {\n"); - printf(" \"mtr\": {\n"); - printf(" \"src\": \"%s\",\n", ctl->LocalHostname); - printf(" \"dst\": \"%s\",\n", ctl->Hostname); - printf(" \"tos\": \"0x%X\",\n", ctl->tos); + jmtr = json_pack("{ss ss si si}", + "src", ctl->LocalHostname, + "dst", ctl->Hostname, + "tos", ctl->tos, + "tests", ctl->MaxPing); + if (!jmtr) + goto on_error; + if (ctl->cpacketsize >= 0) { - printf(" \"psize\": \"%d\",\n", ctl->cpacketsize); + snprintf(buf, sizeof(buf), "%d", ctl->cpacketsize); } else { - printf(" \"psize\": \"rand(%d-%d)\",\n", MINPACKET, - -ctl->cpacketsize); + snprintf(buf, sizeof(buf), "rand(%d-%d)", MINPACKET, -ctl->cpacketsize); } + ret = json_object_set_new(jmtr, "psize", json_string(buf)); + if (ret == -1) + goto on_error; + if (ctl->bitpattern >= 0) { - printf(" \"bitpattern\": \"0x%02X\",\n", - (unsigned char) (ctl->bitpattern)); + snprintf(buf, sizeof(buf), "0x%02X", (unsigned char)(ctl->bitpattern)); } else { - printf(" \"bitpattern\": \"rand(0x00-FF)\",\n"); + snprintf(buf, sizeof(buf), "rand(0x00-FF)"); } - printf(" \"tests\": \"%d\"\n", ctl->MaxPing); - printf(" },\n"); - printf(" \"hubs\": ["); + ret = json_object_set_new(jmtr, "bitpattern", json_string(buf)); + if (ret == -1) + goto on_error; + jhubs = json_array(); + if (!jhubs) + goto on_error; + max = net_max(ctl); - at = first = net_min(ctl); + at = net_min(ctl); for (; at < max; at++) { addr = net_addr(at); snprint_addr(ctl, name, sizeof(name), addr); - if (at == first) { - printf("{\n"); - } else { - printf(" {\n"); - } - printf(" \"count\": \"%d\",\n", at + 1); - printf(" \"host\": \"%s\",\n", name); + jh = json_pack("{si ss}", "count", at + 1, "host", name); + if (!jh) + goto on_error; + #ifdef HAVE_IPINFO if(!ctl->ipinfo_no) { - char* fmtinfo = fmt_ipinfo(ctl, addr); - if (fmtinfo != NULL) fmtinfo = trim(fmtinfo, '\0'); - printf(" \"ASN\": \"%s\",\n", fmtinfo); + char* fmtinfo = fmt_ipinfo(ctl, addr); + if (fmtinfo != NULL) + fmtinfo = trim(fmtinfo, '\0'); + + ret = json_object_set_new(jh, "ASN", json_string(fmtinfo)); + if (ret == -1) + goto on_error; } #endif - for (i = 0; i < MAXFLD; i++) { - const char *format; + for (i = 0; i < MAXFLD; i++) { j = ctl->fld_index[ctl->fld_active[i]]; - /* Commas */ - if (i + 1 == MAXFLD) { - printf("\n"); - } else if (j > 0 && i != 0) { - printf(",\n"); - } - if (j <= 0) - continue; /* Field nr 0, " " shouldn't be printed in this method. */ + continue; /* Field nr 0, " " shouldn't be printed in this method. */ - /* Format value */ - format = data_fields[j].format; - if (strchr(format, 'f')) { - format = "%.2f"; - } else { - format = "%d"; - } - - /* Format json line */ - snprintf(name, sizeof(name), "%s%s", " \"%s\": ", format); - - /* Output json line */ if (strchr(data_fields[j].format, 'f')) { - /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */ - printf(name, - data_fields[j].title, - data_fields[j].net_xxx(at) / 1000.0); + ret = json_object_set_new( + jh, data_fields[j].title, + json_real(data_fields[j].net_xxx(at) / 1000.0)); } else { - printf(name, - data_fields[j].title, data_fields[j].net_xxx(at)); + ret = json_object_set_new( + jh, data_fields[j].title, + json_integer(data_fields[j].net_xxx(at))); } + if (ret == -1) + goto on_error; } - if (at + 1 == max) { - printf(" }]\n"); - } else { - printf(" },\n"); - } + + ret = json_array_append_new(jhubs, jh); + if (ret == -1) + goto on_error; } - printf(" }\n"); - printf("}\n"); -} + jreport = json_pack("{s{so so}}", "report", "mtr", jmtr, "hubs", jhubs); + + ret = json_dumpf(jreport, stdout, JSON_INDENT(4) | JSON_REAL_PRECISION(5)); + if (ret == -1) + goto on_error; + + printf("\n"); // bash promt should be on new line + json_decref(jreport); + return; +on_error: + error(EXIT_FAILURE, 0, "json_close failed"); +} +#endif void xml_open(