Annotation of embedaddon/mtr/ui/report.c, revision 1.1.1.1
1.1 misho 1: /*
2: mtr -- a network diagnostic tool
3: Copyright (C) 1997,1998 Matt Kimball
4:
5: This program is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License version 2 as
7: published by the Free Software Foundation.
8:
9: This program is distributed in the hope that it will be useful,
10: but WITHOUT ANY WARRANTY; without even the implied warranty of
11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: GNU General Public License for more details.
13:
14: You should have received a copy of the GNU General Public License
15: along with this program; if not, write to the Free Software
16: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: #include "config.h"
20:
21: #include <sys/types.h>
22: #include <stdio.h>
23: #include <netdb.h>
24: #include <netinet/in.h>
25: #include <sys/socket.h>
26: #include <string.h>
27: #include <strings.h>
28: #include <time.h>
29:
30: #include "mtr.h"
31: #include "report.h"
32: #include "net.h"
33: #include "dns.h"
34: #include "asn.h"
35: #include "utils.h"
36:
37: #define MAXLOADBAL 5
38: #define MAX_FORMAT_STR 81
39:
40:
41: void report_open(
42: void)
43: {
44: const time_t now = time(NULL);
45: const char *t = iso_time(&now);
46:
47: printf("Start: %s\n", t);
48: }
49:
50: static size_t snprint_addr(
51: struct mtr_ctl *ctl,
52: char *dst,
53: size_t dst_len,
54: ip_t * addr)
55: {
56: if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
57: struct hostent *host =
58: ctl->dns ? addr2host((void *) addr, ctl->af) : NULL;
59: if (!host)
60: return snprintf(dst, dst_len, "%s", strlongip(ctl, addr));
61: else if (ctl->dns && ctl->show_ips)
62: return snprintf(dst, dst_len, "%s (%s)", host->h_name,
63: strlongip(ctl, addr));
64: else
65: return snprintf(dst, dst_len, "%s", host->h_name);
66: } else
67: return snprintf(dst, dst_len, "%s", "???");
68: }
69:
70:
71: #ifdef HAVE_IPINFO
72: static void print_mpls(
73: struct mplslen *mpls)
74: {
75: int k;
76: for (k = 0; k < mpls->labels; k++)
77: printf(" [MPLS: Lbl %lu Exp %u S %cu TTL %u]\n",
78: mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]);
79: }
80: #endif
81:
82: void report_close(
83: struct mtr_ctl *ctl)
84: {
85: int i, j, at, max, z, w;
86: struct mplslen *mpls, *mplss;
87: ip_t *addr;
88: ip_t *addr2 = NULL;
89: char name[MAX_FORMAT_STR];
90: char buf[1024];
91: char fmt[16];
92: size_t len = 0;
93: size_t len_hosts = 33;
94: #ifdef HAVE_IPINFO
95: int len_tmp;
96: const size_t iiwidth_len = get_iiwidth_len();
97: #endif
98:
99: if (ctl->reportwide) {
100: /* get the longest hostname */
101: len_hosts = strlen(ctl->LocalHostname);
102: max = net_max(ctl);
103: at = net_min(ctl);
104: for (; at < max; at++) {
105: size_t nlen;
106: addr = net_addr(at);
107: if ((nlen = snprint_addr(ctl, name, sizeof(name), addr)))
108: if (len_hosts < nlen)
109: len_hosts = nlen;
110: }
111: }
112: #ifdef HAVE_IPINFO
113: len_tmp = len_hosts;
114: if (ctl->ipinfo_no >= 0 && iiwidth_len) {
115: ctl->ipinfo_no %= iiwidth_len;
116: if (ctl->reportwide) {
117: len_hosts++; /* space */
118: len_tmp += get_iiwidth(ctl->ipinfo_no);
119: if (!ctl->ipinfo_no)
120: len_tmp += 2; /* align header: AS */
121: }
122: }
123: snprintf(fmt, sizeof(fmt), "HOST: %%-%ds", len_tmp);
124: #else
125: snprintf(fmt, sizeof(fmt), "HOST: %%-%zus", len_hosts);
126: #endif
127: snprintf(buf, sizeof(buf), fmt, ctl->LocalHostname);
128: len = ctl->reportwide ? strlen(buf) : len_hosts;
129: for (i = 0; i < MAXFLD; i++) {
130: j = ctl->fld_index[ctl->fld_active[i]];
131: if (j < 0)
132: continue;
133:
134: snprintf(fmt, sizeof(fmt), "%%%ds", data_fields[j].length);
135: snprintf(buf + len, sizeof(buf), fmt, data_fields[j].title);
136: len += data_fields[j].length;
137: }
138: printf("%s\n", buf);
139:
140: max = net_max(ctl);
141: at = net_min(ctl);
142: for (; at < max; at++) {
143: addr = net_addr(at);
144: mpls = net_mpls(at);
145: snprint_addr(ctl, name, sizeof(name), addr);
146:
147: #ifdef HAVE_IPINFO
148: if (is_printii(ctl)) {
149: snprintf(fmt, sizeof(fmt), " %%2d. %%s%%-%zus", len_hosts);
150: snprintf(buf, sizeof(buf), fmt, at + 1, fmt_ipinfo(ctl, addr),
151: name);
152: } else {
153: #endif
154: snprintf(fmt, sizeof(fmt), " %%2d.|-- %%-%zus", len_hosts);
155: snprintf(buf, sizeof(buf), fmt, at + 1, name);
156: #ifdef HAVE_IPINFO
157: }
158: #endif
159: len = ctl->reportwide ? strlen(buf) : len_hosts;
160: for (i = 0; i < MAXFLD; i++) {
161: j = ctl->fld_index[ctl->fld_active[i]];
162: if (j < 0)
163: continue;
164:
165: /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
166: if (strchr(data_fields[j].format, 'f')) {
167: snprintf(buf + len, sizeof(buf), data_fields[j].format,
168: data_fields[j].net_xxx(at) / 1000.0);
169: } else {
170: snprintf(buf + len, sizeof(buf), data_fields[j].format,
171: data_fields[j].net_xxx(at));
172: }
173: len += data_fields[j].length;
174: }
175: printf("%s\n", buf);
176:
177: /* This feature shows 'loadbalances' on routes */
178:
179: /* z is starting at 1 because addrs[0] is the same that addr */
180: for (z = 1; z < MAXPATH; z++) {
181: int found = 0;
182: addr2 = net_addrs(at, z);
183: mplss = net_mplss(at, z);
184: if ((addrcmp
185: ((void *) &ctl->unspec_addr, (void *) addr2,
186: ctl->af)) == 0)
187: break;
188: for (w = 0; w < z; w++)
189: /* Ok... checking if there are ips repeated on same hop */
190: if ((addrcmp
191: ((void *) addr2, (void *) net_addrs(at, w),
192: ctl->af)) == 0) {
193: found = 1;
194: break;
195: }
196:
197: if (!found) {
198:
199: #ifdef HAVE_IPINFO
200: if (is_printii(ctl)) {
201: if (mpls->labels && z == 1 && ctl->enablempls)
202: print_mpls(mpls);
203: snprint_addr(ctl, name, sizeof(name), addr2);
204: printf(" %s%s\n", fmt_ipinfo(ctl, addr2), name);
205: if (ctl->enablempls)
206: print_mpls(mplss);
207: }
208: #else
209: int k;
210: if (mpls->labels && z == 1 && ctl->enablempls) {
211: for (k = 0; k < mpls->labels; k++) {
212: printf
213: (" | |+-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n",
214: mpls->label[k], mpls->exp[k], mpls->s[k],
215: mpls->ttl[k]);
216: }
217: }
218:
219: if (z == 1) {
220: printf(" | `|-- %s\n", strlongip(ctl, addr2));
221: for (k = 0; k < mplss->labels && ctl->enablempls; k++) {
222: printf
223: (" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n",
224: mplss->label[k], mplss->exp[k], mplss->s[k],
225: mplss->ttl[k]);
226: }
227: } else {
228: printf(" | |-- %s\n", strlongip(ctl, addr2));
229: for (k = 0; k < mplss->labels && ctl->enablempls; k++) {
230: printf
231: (" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n",
232: mplss->label[k], mplss->exp[k], mplss->s[k],
233: mplss->ttl[k]);
234: }
235: }
236: #endif
237: }
238: }
239:
240: /* No multipath */
241: #ifdef HAVE_IPINFO
242: if (is_printii(ctl)) {
243: if (mpls->labels && z == 1 && ctl->enablempls)
244: print_mpls(mpls);
245: }
246: #else
247: if (mpls->labels && z == 1 && ctl->enablempls) {
248: int k;
249: for (k = 0; k < mpls->labels; k++) {
250: printf(" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n",
251: mpls->label[k], mpls->exp[k], mpls->s[k],
252: mpls->ttl[k]);
253: }
254: }
255: #endif
256: }
257: }
258:
259:
260: void txt_open(
261: void)
262: {
263: }
264:
265:
266: void txt_close(
267: struct mtr_ctl *ctl)
268: {
269: report_close(ctl);
270: }
271:
272:
273: void json_open(
274: void)
275: {
276: }
277:
278:
279: void json_close(
280: struct mtr_ctl *ctl)
281: {
282: int i, j, at, first, max;
283: ip_t *addr;
284: char name[MAX_FORMAT_STR];
285:
286: printf("{\n");
287: printf(" \"report\": {\n");
288: printf(" \"mtr\": {\n");
289: printf(" \"src\": \"%s\",\n", ctl->LocalHostname);
290: printf(" \"dst\": \"%s\",\n", ctl->Hostname);
291: printf(" \"tos\": \"0x%X\",\n", ctl->tos);
292: if (ctl->cpacketsize >= 0) {
293: printf(" \"psize\": \"%d\",\n", ctl->cpacketsize);
294: } else {
295: printf(" \"psize\": \"rand(%d-%d)\",\n", MINPACKET,
296: -ctl->cpacketsize);
297: }
298: if (ctl->bitpattern >= 0) {
299: printf(" \"bitpattern\": \"0x%02X\",\n",
300: (unsigned char) (ctl->bitpattern));
301: } else {
302: printf(" \"bitpattern\": \"rand(0x00-FF)\",\n");
303: }
304: printf(" \"tests\": \"%d\"\n", ctl->MaxPing);
305: printf(" },\n");
306:
307: printf(" \"hubs\": [");
308:
309: max = net_max(ctl);
310: at = first = net_min(ctl);
311: for (; at < max; at++) {
312: addr = net_addr(at);
313: snprint_addr(ctl, name, sizeof(name), addr);
314:
315: if (at == first) {
316: printf("{\n");
317: } else {
318: printf(" {\n");
319: }
320: printf(" \"count\": \"%d\",\n", at + 1);
321: printf(" \"host\": \"%s\",\n", name);
322: #ifdef HAVE_IPINFO
323: if(!ctl->ipinfo_no) {
324: char* fmtinfo = fmt_ipinfo(ctl, addr);
325: if (fmtinfo != NULL) fmtinfo = trim(fmtinfo, '\0');
326: printf(" \"ASN\": \"%s\",\n", fmtinfo);
327: }
328: #endif
329: for (i = 0; i < MAXFLD; i++) {
330: const char *format;
331:
332: j = ctl->fld_index[ctl->fld_active[i]];
333:
334: /* Commas */
335: if (i + 1 == MAXFLD) {
336: printf("\n");
337: } else if (j > 0 && i != 0) {
338: printf(",\n");
339: }
340:
341: if (j <= 0)
342: continue; /* Field nr 0, " " shouldn't be printed in this method. */
343:
344: /* Format value */
345: format = data_fields[j].format;
346: if (strchr(format, 'f')) {
347: format = "%.2f";
348: } else {
349: format = "%d";
350: }
351:
352: /* Format json line */
353: snprintf(name, sizeof(name), "%s%s", " \"%s\": ", format);
354:
355: /* Output json line */
356: if (strchr(data_fields[j].format, 'f')) {
357: /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
358: printf(name,
359: data_fields[j].title,
360: data_fields[j].net_xxx(at) / 1000.0);
361: } else {
362: printf(name,
363: data_fields[j].title, data_fields[j].net_xxx(at));
364: }
365: }
366: if (at + 1 == max) {
367: printf(" }]\n");
368: } else {
369: printf(" },\n");
370: }
371: }
372: printf(" }\n");
373: printf("}\n");
374: }
375:
376:
377:
378: void xml_open(
379: void)
380: {
381: }
382:
383:
384: void xml_close(
385: struct mtr_ctl *ctl)
386: {
387: int i, j, at, max;
388: ip_t *addr;
389: char name[MAX_FORMAT_STR];
390:
391: printf("<?xml version=\"1.0\"?>\n");
392: printf("<MTR SRC=\"%s\" DST=\"%s\"", ctl->LocalHostname,
393: ctl->Hostname);
394: printf(" TOS=\"0x%X\"", ctl->tos);
395: if (ctl->cpacketsize >= 0) {
396: printf(" PSIZE=\"%d\"", ctl->cpacketsize);
397: } else {
398: printf(" PSIZE=\"rand(%d-%d)\"", MINPACKET, -ctl->cpacketsize);
399: }
400: if (ctl->bitpattern >= 0) {
401: printf(" BITPATTERN=\"0x%02X\"",
402: (unsigned char) (ctl->bitpattern));
403: } else {
404: printf(" BITPATTERN=\"rand(0x00-FF)\"");
405: }
406: printf(" TESTS=\"%d\">\n", ctl->MaxPing);
407:
408: max = net_max(ctl);
409: at = net_min(ctl);
410: for (; at < max; at++) {
411: addr = net_addr(at);
412: snprint_addr(ctl, name, sizeof(name), addr);
413:
414: printf(" <HUB COUNT=\"%d\" HOST=\"%s\">\n", at + 1, name);
415: for (i = 0; i < MAXFLD; i++) {
416: const char *title;
417:
418: j = ctl->fld_index[ctl->fld_active[i]];
419: if (j <= 0)
420: continue; /* Field nr 0, " " shouldn't be printed in this method. */
421:
422: snprintf(name, sizeof(name), "%s%s%s", " <%s>",
423: data_fields[j].format, "</%s>\n");
424:
425: /* XML doesn't allow "%" in tag names, rename Loss% to just Loss */
426: title = data_fields[j].title;
427: if (strcmp(data_fields[j].title, "Loss%") == 0) {
428: title = "Loss";
429: }
430:
431: /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
432: if (strchr(data_fields[j].format, 'f')) {
433: printf(name,
434: title, data_fields[j].net_xxx(at) / 1000.0, title);
435: } else {
436: printf(name, title, data_fields[j].net_xxx(at), title);
437: }
438: }
439: printf(" </HUB>\n");
440: }
441: printf("</MTR>\n");
442: }
443:
444:
445: void csv_open(
446: void)
447: {
448: }
449:
450: void csv_close(
451: struct mtr_ctl *ctl,
452: time_t now)
453: {
454: int i, j, at, max;
455: ip_t *addr;
456: char name[MAX_FORMAT_STR];
457:
458: for (i = 0; i < MAXFLD; i++) {
459: j = ctl->fld_index[ctl->fld_active[i]];
460: if (j < 0)
461: continue;
462: }
463:
464: max = net_max(ctl);
465: at = net_min(ctl);
466: for (; at < max; at++) {
467: addr = net_addr(at);
468: snprint_addr(ctl, name, sizeof(name), addr);
469:
470: if (at == net_min(ctl)) {
471: printf("Mtr_Version,Start_Time,Status,Host,Hop,Ip,");
472: #ifdef HAVE_IPINFO
473: if (!ctl->ipinfo_no) {
474: printf("Asn,");
475: }
476: #endif
477: for (i = 0; i < MAXFLD; i++) {
478: j = ctl->fld_index[ctl->fld_active[i]];
479: if (j < 0)
480: continue;
481: printf("%s,", data_fields[j].title);
482: }
483: printf("\n");
484: }
485: #ifdef HAVE_IPINFO
486: if (!ctl->ipinfo_no) {
487: char *fmtinfo = fmt_ipinfo(ctl, addr);
488: fmtinfo = trim(fmtinfo, '\0');
489: printf("MTR.%s,%lld,%s,%s,%d,%s,%s", PACKAGE_VERSION,
490: (long long) now, "OK", ctl->Hostname, at + 1, name,
491: fmtinfo);
492: } else
493: #endif
494: printf("MTR.%s,%lld,%s,%s,%d,%s", PACKAGE_VERSION,
495: (long long) now, "OK", ctl->Hostname, at + 1, name);
496:
497: for (i = 0; i < MAXFLD; i++) {
498: j = ctl->fld_index[ctl->fld_active[i]];
499: if (j < 0)
500: continue;
501:
502: /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
503: if (strchr(data_fields[j].format, 'f')) {
504: printf(",%.2f",
505: (double) (data_fields[j].net_xxx(at) / 1000.0));
506: } else {
507: printf(",%d", data_fields[j].net_xxx(at));
508: }
509: }
510: printf("\n");
511: }
512: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>