1998-10-17 00:00:00 +00:00
|
|
|
/*
|
|
|
|
mtr -- a network diagnostic tool
|
|
|
|
Copyright (C) 1997,1998 Matt Kimball
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
2017-06-02 06:30:58 +00:00
|
|
|
it under the terms of the GNU General Public License version 2 as
|
2010-05-31 00:00:00 +00:00
|
|
|
published by the Free Software Foundation.
|
1998-10-17 00:00:00 +00:00
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2013-10-26 17:13:48 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
1998-10-17 00:00:00 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <string.h>
|
2005-01-11 00:00:00 +00:00
|
|
|
#include <strings.h>
|
2013-02-05 12:42:37 +00:00
|
|
|
#include <time.h>
|
1998-10-17 00:00:00 +00:00
|
|
|
|
2005-01-11 00:00:00 +00:00
|
|
|
#include "mtr.h"
|
1998-10-17 00:00:00 +00:00
|
|
|
#include "report.h"
|
|
|
|
#include "net.h"
|
2005-01-11 00:00:00 +00:00
|
|
|
#include "dns.h"
|
2013-04-24 09:35:52 +00:00
|
|
|
#include "asn.h"
|
2016-08-29 18:45:36 +00:00
|
|
|
#include "utils.h"
|
1998-10-17 00:00:00 +00:00
|
|
|
|
2010-06-01 00:00:00 +00:00
|
|
|
#define MAXLOADBAL 5
|
2016-08-29 17:36:47 +00:00
|
|
|
#define MAX_FORMAT_STR 81
|
1998-11-02 00:00:00 +00:00
|
|
|
|
1998-10-17 00:00:00 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void report_open(
|
|
|
|
void)
|
2013-02-05 12:42:37 +00:00
|
|
|
{
|
2017-02-04 21:25:23 +00:00
|
|
|
const time_t now = time(NULL);
|
|
|
|
const char *t = iso_time(&now);
|
2016-08-16 12:40:19 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
printf("Start: %s\n", t);
|
2005-01-11 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
static size_t snprint_addr(
|
|
|
|
struct mtr_ctl *ctl,
|
|
|
|
char *dst,
|
|
|
|
size_t dst_len,
|
|
|
|
ip_t * addr)
|
2013-02-01 01:58:14 +00:00
|
|
|
{
|
2017-02-04 21:25:23 +00:00
|
|
|
if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
|
|
|
|
struct hostent *host =
|
|
|
|
ctl->dns ? addr2host((void *) addr, ctl->af) : NULL;
|
|
|
|
if (!host)
|
|
|
|
return snprintf(dst, dst_len, "%s", strlongip(ctl, addr));
|
|
|
|
else if (ctl->dns && ctl->show_ips)
|
|
|
|
return snprintf(dst, dst_len, "%s (%s)", host->h_name,
|
|
|
|
strlongip(ctl, addr));
|
|
|
|
else
|
|
|
|
return snprintf(dst, dst_len, "%s", host->h_name);
|
|
|
|
} else
|
|
|
|
return snprintf(dst, dst_len, "%s", "???");
|
2013-02-01 01:58:14 +00:00
|
|
|
}
|
|
|
|
|
2005-01-11 00:00:00 +00:00
|
|
|
|
2016-08-18 21:22:56 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
2017-02-04 21:25:23 +00:00
|
|
|
static void print_mpls(
|
|
|
|
struct mplslen *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]);
|
2013-04-24 09:35:52 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void report_close(
|
|
|
|
struct mtr_ctl *ctl)
|
2005-01-11 00:00:00 +00:00
|
|
|
{
|
2017-02-04 21:25:23 +00:00
|
|
|
int i, j, at, max, z, w;
|
|
|
|
struct mplslen *mpls, *mplss;
|
|
|
|
ip_t *addr;
|
|
|
|
ip_t *addr2 = NULL;
|
|
|
|
char name[MAX_FORMAT_STR];
|
|
|
|
char buf[1024];
|
|
|
|
char fmt[16];
|
|
|
|
size_t len = 0;
|
|
|
|
size_t len_hosts = 33;
|
2016-10-04 16:00:34 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
2017-02-04 21:25:23 +00:00
|
|
|
int len_tmp;
|
|
|
|
const size_t iiwidth_len = get_iiwidth_len();
|
2016-10-04 16:00:34 +00:00
|
|
|
#endif
|
1998-10-17 00:00:00 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
if (ctl->reportwide) {
|
|
|
|
/* get the longest hostname */
|
|
|
|
len_hosts = strlen(ctl->LocalHostname);
|
|
|
|
max = net_max(ctl);
|
|
|
|
at = net_min(ctl);
|
|
|
|
for (; at < max; at++) {
|
|
|
|
size_t nlen;
|
|
|
|
addr = net_addr(at);
|
|
|
|
if ((nlen = snprint_addr(ctl, name, sizeof(name), addr)))
|
|
|
|
if (len_hosts < nlen)
|
|
|
|
len_hosts = nlen;
|
|
|
|
}
|
2008-09-19 00:00:00 +00:00
|
|
|
}
|
2016-08-18 21:22:56 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
2017-02-04 21:25:23 +00:00
|
|
|
len_tmp = len_hosts;
|
|
|
|
if (ctl->ipinfo_no >= 0 && iiwidth_len) {
|
|
|
|
ctl->ipinfo_no %= iiwidth_len;
|
|
|
|
if (ctl->reportwide) {
|
|
|
|
len_hosts++; /* space */
|
|
|
|
len_tmp += get_iiwidth(ctl->ipinfo_no);
|
|
|
|
if (!ctl->ipinfo_no)
|
|
|
|
len_tmp += 2; /* align header: AS */
|
|
|
|
}
|
2013-04-24 09:35:52 +00:00
|
|
|
}
|
2017-02-04 21:25:23 +00:00
|
|
|
snprintf(fmt, sizeof(fmt), "HOST: %%-%ds", len_tmp);
|
2013-04-24 09:35:52 +00:00
|
|
|
#else
|
2017-02-04 21:25:23 +00:00
|
|
|
snprintf(fmt, sizeof(fmt), "HOST: %%-%zus", len_hosts);
|
2013-04-24 09:35:52 +00:00
|
|
|
#endif
|
2017-02-04 21:25:23 +00:00
|
|
|
snprintf(buf, sizeof(buf), fmt, ctl->LocalHostname);
|
|
|
|
len = ctl->reportwide ? strlen(buf) : len_hosts;
|
|
|
|
for (i = 0; i < MAXFLD; i++) {
|
|
|
|
j = ctl->fld_index[ctl->fld_active[i]];
|
|
|
|
if (j < 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
snprintf(fmt, sizeof(fmt), "%%%ds", data_fields[j].length);
|
|
|
|
snprintf(buf + len, sizeof(buf), fmt, data_fields[j].title);
|
|
|
|
len += data_fields[j].length;
|
|
|
|
}
|
|
|
|
printf("%s\n", buf);
|
|
|
|
|
|
|
|
max = net_max(ctl);
|
|
|
|
at = net_min(ctl);
|
|
|
|
for (; at < max; at++) {
|
|
|
|
addr = net_addr(at);
|
|
|
|
mpls = net_mpls(at);
|
|
|
|
snprint_addr(ctl, name, sizeof(name), addr);
|
1998-10-17 00:00:00 +00:00
|
|
|
|
2016-08-18 21:22:56 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
2017-02-04 21:25:23 +00:00
|
|
|
if (is_printii(ctl)) {
|
|
|
|
snprintf(fmt, sizeof(fmt), " %%2d. %%s%%-%zus", len_hosts);
|
|
|
|
snprintf(buf, sizeof(buf), fmt, at + 1, fmt_ipinfo(ctl, addr),
|
|
|
|
name);
|
|
|
|
} else {
|
2013-04-24 09:35:52 +00:00
|
|
|
#endif
|
2017-02-04 21:25:23 +00:00
|
|
|
snprintf(fmt, sizeof(fmt), " %%2d.|-- %%-%zus", len_hosts);
|
|
|
|
snprintf(buf, sizeof(buf), fmt, at + 1, name);
|
2016-08-18 21:22:56 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
2017-02-04 21:25:23 +00:00
|
|
|
}
|
2013-04-24 09:35:52 +00:00
|
|
|
#endif
|
2017-02-04 21:25:23 +00:00
|
|
|
len = ctl->reportwide ? strlen(buf) : len_hosts;
|
|
|
|
for (i = 0; i < MAXFLD; i++) {
|
|
|
|
j = ctl->fld_index[ctl->fld_active[i]];
|
|
|
|
if (j < 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
|
|
|
|
if (strchr(data_fields[j].format, 'f')) {
|
|
|
|
snprintf(buf + len, sizeof(buf), data_fields[j].format,
|
|
|
|
data_fields[j].net_xxx(at) / 1000.0);
|
|
|
|
} else {
|
|
|
|
snprintf(buf + len, sizeof(buf), data_fields[j].format,
|
|
|
|
data_fields[j].net_xxx(at));
|
|
|
|
}
|
|
|
|
len += data_fields[j].length;
|
|
|
|
}
|
|
|
|
printf("%s\n", buf);
|
|
|
|
|
|
|
|
/* 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++) {
|
|
|
|
int found = 0;
|
|
|
|
addr2 = net_addrs(at, z);
|
|
|
|
mplss = net_mplss(at, z);
|
|
|
|
if ((addrcmp
|
|
|
|
((void *) &ctl->unspec_addr, (void *) addr2,
|
|
|
|
ctl->af)) == 0)
|
|
|
|
break;
|
|
|
|
for (w = 0; w < z; w++)
|
|
|
|
/* Ok... checking if there are ips repeated on same hop */
|
|
|
|
if ((addrcmp
|
|
|
|
((void *) addr2, (void *) net_addrs(at, w),
|
|
|
|
ctl->af)) == 0) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
|
|
|
|
#ifdef HAVE_IPINFO
|
|
|
|
if (is_printii(ctl)) {
|
|
|
|
if (mpls->labels && z == 1 && ctl->enablempls)
|
|
|
|
print_mpls(mpls);
|
|
|
|
snprint_addr(ctl, name, sizeof(name), addr2);
|
|
|
|
printf(" %s%s\n", fmt_ipinfo(ctl, addr2), name);
|
|
|
|
if (ctl->enablempls)
|
|
|
|
print_mpls(mplss);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int k;
|
|
|
|
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->ttl[k]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (z == 1) {
|
|
|
|
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],
|
|
|
|
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],
|
|
|
|
mplss->ttl[k]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No multipath */
|
2016-08-18 21:22:56 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
2016-08-28 19:12:58 +00:00
|
|
|
if (is_printii(ctl)) {
|
2017-02-04 21:25:23 +00:00
|
|
|
if (mpls->labels && z == 1 && ctl->enablempls)
|
|
|
|
print_mpls(mpls);
|
2017-02-04 21:18:13 +00:00
|
|
|
}
|
2013-04-24 09:35:52 +00:00
|
|
|
#else
|
2016-08-28 09:51:33 +00:00
|
|
|
if (mpls->labels && z == 1 && ctl->enablempls) {
|
2017-02-04 21:25:23 +00:00
|
|
|
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],
|
|
|
|
mpls->ttl[k]);
|
|
|
|
}
|
2011-12-02 00:00:00 +00:00
|
|
|
}
|
2013-04-24 09:35:52 +00:00
|
|
|
#endif
|
2010-06-01 00:00:00 +00:00
|
|
|
}
|
2004-04-01 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void txt_open(
|
|
|
|
void)
|
2005-01-11 00:00:00 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void txt_close(
|
|
|
|
struct mtr_ctl *ctl)
|
2016-07-29 15:31:14 +00:00
|
|
|
{
|
2017-02-04 21:25:23 +00:00
|
|
|
report_close(ctl);
|
2005-01-11 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void json_open(
|
|
|
|
void)
|
2016-07-29 15:31:14 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void json_close(
|
|
|
|
struct mtr_ctl *ctl)
|
2016-07-29 15:31:14 +00:00
|
|
|
{
|
2017-02-04 21:25:23 +00:00
|
|
|
int i, j, at, first, max;
|
|
|
|
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);
|
|
|
|
if (ctl->cpacketsize >= 0) {
|
|
|
|
printf(" \"psize\": \"%d\",\n", ctl->cpacketsize);
|
|
|
|
} else {
|
|
|
|
printf(" \"psize\": \"rand(%d-%d)\",\n", MINPACKET,
|
|
|
|
-ctl->cpacketsize);
|
|
|
|
}
|
|
|
|
if (ctl->bitpattern >= 0) {
|
|
|
|
printf(" \"bitpattern\": \"0x%02X\",\n",
|
|
|
|
(unsigned char) (ctl->bitpattern));
|
2016-07-29 15:31:14 +00:00
|
|
|
} else {
|
2017-02-04 21:25:23 +00:00
|
|
|
printf(" \"bitpattern\": \"rand(0x00-FF)\",\n");
|
2016-07-29 15:31:14 +00:00
|
|
|
}
|
2017-02-04 21:25:23 +00:00
|
|
|
printf(" \"tests\": \"%d\"\n", ctl->MaxPing);
|
|
|
|
printf(" },\n");
|
2016-10-04 16:00:34 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
printf(" \"hubs\": [");
|
2016-07-29 15:31:14 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
max = net_max(ctl);
|
|
|
|
at = first = 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);
|
2017-06-02 06:30:58 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
|
|
|
if(!ctl->ipinfo_no) {
|
2017-06-02 08:52:58 +00:00
|
|
|
char* fmtinfo = fmt_ipinfo(ctl, addr);
|
|
|
|
if (fmtinfo != NULL) fmtinfo = trim(fmtinfo, '\0');
|
2017-06-02 06:30:58 +00:00
|
|
|
printf(" \"ASN\": \"%s\",\n", fmtinfo);
|
|
|
|
}
|
|
|
|
#endif
|
2017-02-04 21:25:23 +00:00
|
|
|
for (i = 0; i < MAXFLD; i++) {
|
|
|
|
const char *format;
|
|
|
|
|
|
|
|
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. */
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
} else {
|
|
|
|
printf(name,
|
|
|
|
data_fields[j].title, data_fields[j].net_xxx(at));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (at + 1 == max) {
|
|
|
|
printf(" }]\n");
|
|
|
|
} else {
|
|
|
|
printf(" },\n");
|
|
|
|
}
|
2016-07-29 15:31:14 +00:00
|
|
|
}
|
2017-02-04 21:25:23 +00:00
|
|
|
printf(" }\n");
|
|
|
|
printf("}\n");
|
2016-07-29 15:31:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-01-11 00:00:00 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void xml_open(
|
|
|
|
void)
|
2005-01-11 00:00:00 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2004-04-01 00:00:00 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void xml_close(
|
|
|
|
struct mtr_ctl *ctl)
|
2005-01-11 00:00:00 +00:00
|
|
|
{
|
2017-02-04 21:25:23 +00:00
|
|
|
int i, j, at, max;
|
|
|
|
ip_t *addr;
|
|
|
|
char name[MAX_FORMAT_STR];
|
|
|
|
|
|
|
|
printf("<?xml version=\"1.0\"?>\n");
|
|
|
|
printf("<MTR SRC=\"%s\" DST=\"%s\"", ctl->LocalHostname,
|
|
|
|
ctl->Hostname);
|
|
|
|
printf(" TOS=\"0x%X\"", ctl->tos);
|
|
|
|
if (ctl->cpacketsize >= 0) {
|
|
|
|
printf(" PSIZE=\"%d\"", ctl->cpacketsize);
|
|
|
|
} else {
|
|
|
|
printf(" PSIZE=\"rand(%d-%d)\"", MINPACKET, -ctl->cpacketsize);
|
|
|
|
}
|
|
|
|
if (ctl->bitpattern >= 0) {
|
|
|
|
printf(" BITPATTERN=\"0x%02X\"",
|
|
|
|
(unsigned char) (ctl->bitpattern));
|
|
|
|
} else {
|
|
|
|
printf(" BITPATTERN=\"rand(0x00-FF)\"");
|
2004-04-01 00:00:00 +00:00
|
|
|
}
|
2017-02-04 21:25:23 +00:00
|
|
|
printf(" TESTS=\"%d\">\n", ctl->MaxPing);
|
|
|
|
|
|
|
|
max = net_max(ctl);
|
|
|
|
at = net_min(ctl);
|
|
|
|
for (; at < max; at++) {
|
|
|
|
addr = net_addr(at);
|
|
|
|
snprint_addr(ctl, name, sizeof(name), addr);
|
|
|
|
|
|
|
|
printf(" <HUB COUNT=\"%d\" HOST=\"%s\">\n", at + 1, name);
|
|
|
|
for (i = 0; i < MAXFLD; i++) {
|
|
|
|
const char *title;
|
|
|
|
|
|
|
|
j = ctl->fld_index[ctl->fld_active[i]];
|
|
|
|
if (j <= 0)
|
|
|
|
continue; /* Field nr 0, " " shouldn't be printed in this method. */
|
|
|
|
|
|
|
|
snprintf(name, sizeof(name), "%s%s%s", " <%s>",
|
|
|
|
data_fields[j].format, "</%s>\n");
|
|
|
|
|
|
|
|
/* XML doesn't allow "%" in tag names, rename Loss% to just Loss */
|
|
|
|
title = data_fields[j].title;
|
|
|
|
if (strcmp(data_fields[j].title, "Loss%") == 0) {
|
|
|
|
title = "Loss";
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
|
|
|
|
if (strchr(data_fields[j].format, 'f')) {
|
|
|
|
printf(name,
|
|
|
|
title, data_fields[j].net_xxx(at) / 1000.0, title);
|
|
|
|
} else {
|
|
|
|
printf(name, title, data_fields[j].net_xxx(at), title);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf(" </HUB>\n");
|
|
|
|
}
|
|
|
|
printf("</MTR>\n");
|
1998-10-17 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2005-01-11 00:00:00 +00:00
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void csv_open(
|
|
|
|
void)
|
2005-01-11 00:00:00 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
void csv_close(
|
|
|
|
struct mtr_ctl *ctl,
|
|
|
|
time_t now)
|
2005-01-11 00:00:00 +00:00
|
|
|
{
|
2017-02-04 21:25:23 +00:00
|
|
|
int i, j, at, max;
|
|
|
|
ip_t *addr;
|
|
|
|
char name[MAX_FORMAT_STR];
|
|
|
|
|
|
|
|
for (i = 0; i < MAXFLD; i++) {
|
|
|
|
j = ctl->fld_index[ctl->fld_active[i]];
|
|
|
|
if (j < 0)
|
|
|
|
continue;
|
2015-12-25 11:57:32 +00:00
|
|
|
}
|
|
|
|
|
2017-02-04 21:25:23 +00:00
|
|
|
max = net_max(ctl);
|
|
|
|
at = net_min(ctl);
|
|
|
|
for (; at < max; at++) {
|
|
|
|
addr = net_addr(at);
|
|
|
|
snprint_addr(ctl, name, sizeof(name), addr);
|
|
|
|
|
|
|
|
if (at == net_min(ctl)) {
|
|
|
|
printf("Mtr_Version,Start_Time,Status,Host,Hop,Ip,");
|
2016-08-18 21:22:56 +00:00
|
|
|
#ifdef HAVE_IPINFO
|
2017-02-04 21:25:23 +00:00
|
|
|
if (!ctl->ipinfo_no) {
|
|
|
|
printf("Asn,");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
for (i = 0; i < MAXFLD; i++) {
|
|
|
|
j = ctl->fld_index[ctl->fld_active[i]];
|
|
|
|
if (j < 0)
|
|
|
|
continue;
|
|
|
|
printf("%s,", data_fields[j].title);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
#ifdef HAVE_IPINFO
|
|
|
|
if (!ctl->ipinfo_no) {
|
|
|
|
char *fmtinfo = fmt_ipinfo(ctl, addr);
|
|
|
|
fmtinfo = trim(fmtinfo, '\0');
|
|
|
|
printf("MTR.%s,%lld,%s,%s,%d,%s,%s", PACKAGE_VERSION,
|
|
|
|
(long long) now, "OK", ctl->Hostname, at + 1, name,
|
|
|
|
fmtinfo);
|
|
|
|
} else
|
2013-07-05 13:45:52 +00:00
|
|
|
#endif
|
2017-02-04 21:25:23 +00:00
|
|
|
printf("MTR.%s,%lld,%s,%s,%d,%s", PACKAGE_VERSION,
|
|
|
|
(long long) now, "OK", ctl->Hostname, at + 1, name);
|
|
|
|
|
|
|
|
for (i = 0; i < MAXFLD; i++) {
|
|
|
|
j = ctl->fld_index[ctl->fld_active[i]];
|
|
|
|
if (j < 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
|
|
|
|
if (strchr(data_fields[j].format, 'f')) {
|
|
|
|
printf(",%.2f",
|
|
|
|
(double) (data_fields[j].net_xxx(at) / 1000.0));
|
|
|
|
} else {
|
|
|
|
printf(",%d", data_fields[j].net_xxx(at));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n");
|
2004-04-01 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|