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>