Annotation of embedaddon/mtr/mtr.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 <sys/types.h>
                     20: #include <config.h>
                     21: #include <netdb.h>
                     22: #include <stdio.h>
                     23: #include <stdlib.h>
                     24: #include <string.h>
                     25: #include <netinet/in.h>
                     26: #include <sys/socket.h>
                     27: #include <unistd.h>
                     28: #include <strings.h>
                     29: #include <time.h>
                     30: #include <errno.h>
                     31: #include <string.h>
                     32: #include <ctype.h>
                     33: #include <assert.h>
                     34: #include <fcntl.h>
                     35: #include <sys/stat.h>
                     36: 
                     37: #include "mtr.h"
                     38: #include "mtr-curses.h"
                     39: #include "getopt.h"
                     40: #include "display.h"
                     41: #include "dns.h"
                     42: #include "report.h"
                     43: #include "net.h"
                     44: #ifndef NO_IPINFO
                     45: #include "asn.h"
                     46: #endif
                     47: #include "version.h"
                     48: 
                     49: 
                     50: #ifdef ENABLE_IPV6
                     51: #define DEFAULT_AF AF_UNSPEC
                     52: #else
                     53: #define DEFAULT_AF AF_INET
                     54: #endif
                     55: 
                     56: 
                     57: #ifdef NO_HERROR
                     58: #define herror(str) fprintf(stderr, str ": error looking up \"%s\"\n", Hostname);
                     59: #endif
                     60: 
                     61: 
                     62: int   DisplayMode;
                     63: int   display_mode;
                     64: int   Interactive = 1;
                     65: int   PrintVersion = 0;
                     66: int   PrintHelp = 0;
                     67: int   MaxPing = 10;
                     68: int   ForceMaxPing = 0;
                     69: float WaitTime = 1.0;
                     70: char *Hostname = NULL;
                     71: char *InterfaceAddress = NULL;
                     72: char  LocalHostname[128];
                     73: int   dns = 1;
                     74: int   show_ips = 0;
                     75: int   enablempls = 0;
                     76: int   cpacketsize = 64;          /* default packet size */
                     77: int   bitpattern = 0;
                     78: int   tos = 0;
                     79: int   reportwide = 0;
                     80: int af = DEFAULT_AF;
                     81: int mtrtype = IPPROTO_ICMP;     /* Use ICMP as default packet type */
                     82: 
                     83:                                 /* begin ttl windows addByMin */
                     84: int  fstTTL = 1;                /* default start at first hop */
                     85: /*int maxTTL = MaxHost-1;  */     /* max you can go is 255 hops */
                     86: int   maxTTL = 30;              /* inline with traceroute */
                     87:                                 /* end ttl window stuff. */
                     88: int remoteport = 80;            /* for TCP tracing */
                     89: int timeout = 10 * 1000000;     /* for TCP tracing */
                     90: 
                     91: 
                     92: /* default display field(defined by key in net.h) and order */
                     93: unsigned char fld_active[2*MAXFLD] = "LS NABWV";
                     94: int           fld_index[256];
                     95: char          available_options[MAXFLD];
                     96: 
                     97: 
                     98: struct fields data_fields[MAXFLD] = {
                     99:   /* key, Remark, Header, Format, Width, CallBackFunc */
                    100:   {' ', "<sp>: Space between fields", " ",  " ",        1, &net_drop  },
                    101:   {'L', "L: Loss Ratio",          "Loss%",  " %4.1f%%", 6, &net_loss  },
                    102:   {'D', "D: Dropped Packets",     "Drop",   " %4d",     5, &net_drop  },
                    103:   {'R', "R: Received Packets",    "Rcv",    " %5d",     6, &net_returned},
                    104:   {'S', "S: Sent Packets",        "Snt",    " %5d",     6, &net_xmit  },
                    105:   {'N', "N: Newest RTT(ms)",      "Last",   " %5.1f",   6, &net_last  },
                    106:   {'B', "B: Min/Best RTT(ms)",    "Best",   " %5.1f",   6, &net_best  },
                    107:   {'A', "A: Average RTT(ms)",     "Avg",    " %5.1f",   6, &net_avg   },
                    108:   {'W', "W: Max/Worst RTT(ms)",   "Wrst",   " %5.1f",   6, &net_worst },
                    109:   {'V', "V: Standard Deviation",  "StDev",  " %5.1f",   6, &net_stdev },
                    110:   {'G', "G: Geometric Mean",      "Gmean",  " %5.1f",   6, &net_gmean },
                    111:   {'J', "J: Current Jitter",      "Jttr",   " %4.1f",   5, &net_jitter},
                    112:   {'M', "M: Jitter Mean/Avg.",    "Javg",   " %4.1f",   5, &net_javg  },
                    113:   {'X', "X: Worst Jitter",        "Jmax",   " %4.1f",   5, &net_jworst},
                    114:   {'I', "I: Interarrival Jitter", "Jint",   " %4.1f",   5, &net_jinta },
                    115:   {'\0', NULL, NULL, NULL, 0, NULL}
                    116: };
                    117: 
                    118: typedef struct names {
                    119:   char*                 name;
                    120:   struct names*         next;
                    121: } names_t;
                    122: static names_t *names = NULL;
                    123: 
                    124: char *
                    125: trim(char * s) {
                    126: 
                    127:   char * p = s;
                    128:   int l = strlen(p);
                    129: 
                    130:   while(isspace(p[l-1]) && l) p[--l] = 0;
                    131:   while(*p && isspace(*p) && l) ++p, --l;
                    132: 
                    133:   return p;
                    134: }
                    135: 
                    136: static void
                    137: append_to_names(const char* progname, const char* item) {
                    138: 
                    139:   names_t* name = calloc(1, sizeof(names_t));
                    140:   if (name == NULL) {
                    141:     fprintf(stderr, "%s: memory allocation failure\n", progname);
                    142:     exit(EXIT_FAILURE);
                    143:   }
                    144:   name->name = strdup(item);
                    145:   name->next = names;
                    146:   names = name;
                    147: }
                    148: 
                    149: static void
                    150: read_from_file(const char* progname, const char *filename) {
                    151: 
                    152:   FILE *in;
                    153:   char line[512];
                    154: 
                    155:   if (! filename || strcmp(filename, "-") == 0) {
                    156:     clearerr(stdin);
                    157:     in = stdin;
                    158:   } else {
                    159:     in = fopen(filename, "r");
                    160:     if (! in) {
                    161:       fprintf(stderr, "%s: fopen: %s\n", progname, strerror(errno));
                    162:       exit(EXIT_FAILURE);
                    163:     }
                    164:   }
                    165: 
                    166:   while (fgets(line, sizeof(line), in)) {
                    167:     char* name = trim(line);
                    168:     append_to_names(progname, name);
                    169:   }
                    170: 
                    171:   if (ferror(in)) {
                    172:     fprintf(stderr, "%s: ferror: %s\n", progname, strerror(errno));
                    173:     exit(EXIT_FAILURE);
                    174:   }
                    175: 
                    176:   if (in != stdin) fclose(in);
                    177: }
                    178: 
                    179: /*
                    180:  * If the file stream is associated with a regular file, lock the file
                    181:  * in order coordinate writes to a common file from multiple mtr
                    182:  * instances. This is useful if, for example, multiple mtr instances
                    183:  * try to append results to a common file.
                    184:  */
                    185: 
                    186: static void
                    187: lock(const char* progname, FILE *f) {
                    188:     int fd;
                    189:     struct stat buf;
                    190:     static struct flock lock;
                    191: 
                    192:     assert(f);
                    193: 
                    194:     lock.l_type = F_WRLCK;
                    195:     lock.l_start = 0;
                    196:     lock.l_whence = SEEK_END;
                    197:     lock.l_len = 0;
                    198:     lock.l_pid = getpid();
                    199: 
                    200:     fd = fileno(f);
                    201:     if ((fstat(fd, &buf) == 0) && S_ISREG(buf.st_mode)) {
                    202:       if (fcntl(fd, F_SETLKW, &lock) == -1) {
                    203:           fprintf(stderr, "%s: fcntl: %s (ignored)\n",
                    204:             progname, strerror(errno));
                    205:       }
                    206:     }
                    207: }
                    208: 
                    209: /*
                    210:  * If the file stream is associated with a regular file, unlock the
                    211:  * file (which presumably has previously been locked).
                    212:  */
                    213: 
                    214: static void
                    215: unlock(const char* progname, FILE *f) {
                    216:     int fd;
                    217:     struct stat buf;
                    218:     static struct flock lock;
                    219: 
                    220:     assert(f);
                    221: 
                    222:     lock.l_type = F_UNLCK;
                    223:     lock.l_start = 0;
                    224:     lock.l_whence = SEEK_END;
                    225:     lock.l_len = 0;
                    226:     lock.l_pid = getpid();
                    227: 
                    228:     fd = fileno(f);
                    229:     if ((fstat(fd, &buf) == 0) && S_ISREG(buf.st_mode)) {
                    230:       if (fcntl(fd, F_SETLKW, &lock) == -1) {
                    231:           fprintf(stderr, "%s: fcntl: %s (ignored)\n",
                    232:             progname, strerror(errno));
                    233:       }
                    234:     }
                    235: }
                    236: 
                    237: 
                    238: void init_fld_options (void)
                    239: {
                    240:   int i;
                    241: 
                    242:   for (i=0;i < 256;i++)
                    243:     fld_index[i] = -1;
                    244: 
                    245:   for (i=0;data_fields[i].key != 0;i++) {
                    246:     available_options[i] = data_fields[i].key;
                    247:     fld_index[data_fields[i].key] = i;
                    248:   }
                    249:   available_options[i] = 0;
                    250: }
                    251: 
                    252: 
                    253: void parse_arg (int argc, char **argv)
                    254: {
                    255:   int opt;
                    256:   int i;
                    257:   static struct option long_options[] = {
                    258:     { "version", 0, 0, 'v' },
                    259:     { "help", 0, 0, 'h' },
                    260: 
                    261:     { "report", 0, 0, 'r' },
                    262:     { "report-wide", 0, 0, 'w' },
                    263:     { "xml", 0, 0, 'x' },
                    264:     { "curses", 0, 0, 't' },
                    265:     { "gtk", 0, 0, 'g' },
                    266:     { "raw", 0, 0, 'l' },
                    267:     { "csv", 0, 0, 'C' },
                    268:     { "split", 0, 0, 'p' },     /* BL */
                    269:                                /* maybe above should change to -d 'x' */
                    270: 
                    271:     { "order", 1, 0, 'o' },    /* fileds to display & their order */
                    272: 
                    273:     { "interval", 1, 0, 'i' },
                    274:     { "report-cycles", 1, 0, 'c' },
                    275:     { "psize", 1, 0, 's' },    /* changed 'p' to 's' to match ping option
                    276:                                   overload psize<0, ->rand(min,max) */
                    277:     { "bitpattern", 1, 0, 'B' },/* overload b>255, ->rand(0,255) */
                    278:     { "tos", 1, 0, 'Q' },      /* typeof service (0,255) */
                    279:     { "mpls", 0, 0, 'e' },
                    280:     { "no-dns", 0, 0, 'n' },
                    281:     { "show-ips", 0, 0, 'b' },
                    282:     { "address", 1, 0, 'a' },
                    283:     { "first-ttl", 1, 0, 'f' },        /* -f & -m are borrowed from traceroute */
                    284:     { "filename", 1, 0, 'F' },
                    285:     { "max-ttl", 1, 0, 'm' },
                    286:     { "udp", 0, 0, 'u' },      /* UDP (default is ICMP) */
                    287:     { "tcp", 0, 0, 'T' },      /* TCP (default is ICMP) */
                    288:     { "port", 1, 0, 'P' },      /* target port number for TCP */
                    289:     { "timeout", 1, 0, 'Z' },   /* timeout for TCP sockets */
                    290:     { "inet", 0, 0, '4' },     /* IPv4 only */
                    291:     { "inet6", 0, 0, '6' },    /* IPv6 only */
                    292: #ifndef NO_IPINFO
                    293:     { "ipinfo", 1, 0, 'y' },    /* IP info lookup */
                    294:     { "aslookup", 0, 0, 'z' },  /* Do AS lookup (--ipinfo 0) */
                    295: #endif
                    296:     { 0, 0, 0, 0 }
                    297:   };
                    298: 
                    299:   opt = 0;
                    300:   while(1) {
                    301:     /* added f:m:o: byMin */
                    302:     opt = getopt_long(argc, argv,
                    303:                      "vhrwxtglCpo:B:i:c:s:Q:ena:f:m:uTP:Zby:z46", long_options, NULL);
                    304:     if(opt == -1)
                    305:       break;
                    306: 
                    307:     switch(opt) {
                    308:     case 'v':
                    309:       PrintVersion = 1;
                    310:       break;
                    311:     case 'h':
                    312:       PrintHelp = 1;
                    313:       break;
                    314: 
                    315:     case 'r':
                    316:       DisplayMode = DisplayReport;
                    317:       break;
                    318:     case 'w':
                    319:       reportwide = 1;
                    320:       DisplayMode = DisplayReport;
                    321:       break;
                    322:     case 't':
                    323:       DisplayMode = DisplayCurses;
                    324:       break;
                    325:     case 'g':
                    326:       DisplayMode = DisplayGTK;
                    327:       break;
                    328:     case 'p':                 /* BL */
                    329:       DisplayMode = DisplaySplit;
                    330:       break;
                    331:     case 'l':
                    332:       DisplayMode = DisplayRaw;
                    333:       break;
                    334:     case 'C':
                    335:       DisplayMode = DisplayCSV;
                    336:       break;
                    337:     case 'x':
                    338:       DisplayMode = DisplayXML;
                    339:       break;
                    340: 
                    341:     case 'c':
                    342:       MaxPing = atoi (optarg);
                    343:       ForceMaxPing = 1;
                    344:       break;
                    345:     case 's':
                    346:       cpacketsize = atoi (optarg);
                    347:       break;
                    348:     case 'a':
                    349:       InterfaceAddress = optarg;
                    350:       break;
                    351:     case 'e':
                    352:       enablempls = 1;
                    353:       break;
                    354:     case 'n':
                    355:       dns = 0;
                    356:       break;
                    357:     case 'i':
                    358:       WaitTime = atof (optarg);
                    359:       if (WaitTime <= 0.0) {
                    360:        fprintf (stderr, "mtr: wait time must be positive\n");
                    361:        exit (1);
                    362:       }
                    363:       if (getuid() != 0 && WaitTime < 1.0) {
                    364:         fprintf (stderr, "non-root users cannot request an interval < 1.0 seconds\r\n");
                    365:        exit (1);
                    366:       }
                    367:       break;
                    368:     case 'f':
                    369:       fstTTL = atoi (optarg);
                    370:       if (fstTTL > maxTTL) {
                    371:        fstTTL = maxTTL;
                    372:       }
                    373:       if (fstTTL < 1) {                       /* prevent 0 hop */
                    374:        fstTTL = 1;
                    375:       }
                    376:       break;
                    377:     case 'F':
                    378:       read_from_file(argv[0], optarg);
                    379:       break;
                    380:     case 'm':
                    381:       maxTTL = atoi (optarg);
                    382:       if (maxTTL > (MaxHost - 1)) {
                    383:        maxTTL = MaxHost-1;
                    384:       }
                    385:       if (maxTTL < 1) {                       /* prevent 0 hop */
                    386:        maxTTL = 1;
                    387:       }
                    388:       if (fstTTL > maxTTL) {         /* don't know the pos of -m or -f */
                    389:        fstTTL = maxTTL;
                    390:       }
                    391:       break;
                    392:     case 'o':
                    393:       /* Check option before passing it on to fld_active. */
                    394:       if (strlen (optarg) > MAXFLD) {
                    395:        fprintf (stderr, "Too many fields: %s\n", optarg);
                    396:         exit (1);
                    397:       }
                    398:       for (i=0; optarg[i]; i++) {
                    399:         if(!strchr (available_options, optarg[i])) {
                    400:           fprintf (stderr, "Unknown field identifier: %c\n", optarg[i]);
                    401:           exit (1);
                    402:         }
                    403:       }
                    404:       strcpy ((char*)fld_active, optarg);
                    405:       break;
                    406:     case 'B':
                    407:       bitpattern = atoi (optarg);
                    408:       if (bitpattern > 255)
                    409:        bitpattern = -1;
                    410:       break;
                    411:     case 'Q':
                    412:       tos = atoi (optarg);
                    413:       if (tos > 255 || tos < 0) {
                    414:        /* error message, should do more checking for valid values,
                    415:         * details in rfc2474 */
                    416:        tos = 0;
                    417:       }
                    418:       break;
                    419:     case 'u':
                    420:       if (mtrtype != IPPROTO_ICMP) {
                    421:         fprintf(stderr, "-u and -T are mutually exclusive.\n");
                    422:         exit(EXIT_FAILURE);
                    423:       }
                    424:       mtrtype = IPPROTO_UDP;
                    425:       break;
                    426:     case 'T':
                    427:       if (mtrtype != IPPROTO_ICMP) {
                    428:         fprintf(stderr, "-u and -T are mutually exclusive.\n");
                    429:         exit(EXIT_FAILURE);
                    430:       }
                    431:       mtrtype = IPPROTO_TCP;
                    432:       break;
                    433:     case 'b':
                    434:       show_ips = 1;
                    435:       break;
                    436:     case 'P':
                    437:       remoteport = atoi(optarg);
                    438:       if (remoteport > 65535 || remoteport < 1) {
                    439:         fprintf(stderr, "Illegal port number.\n");
                    440:         exit(EXIT_FAILURE);
                    441:       }
                    442:       break;
                    443:     case 'Z':
                    444:       timeout = atoi(optarg);
                    445:       timeout *= 1000000;
                    446:       break;
                    447:     case '4':
                    448:       af = AF_INET;
                    449:       break;
                    450:     case '6':
                    451: #ifdef ENABLE_IPV6
                    452:       af = AF_INET6;
                    453:       break;
                    454: #else
                    455:       fprintf( stderr, "IPv6 not enabled.\n" );
                    456:       break;
                    457: #endif
                    458: #ifndef NO_IPINFO
                    459:     case 'y':
                    460:       ipinfo_no = atoi (optarg);
                    461:       if (ipinfo_no < 0)
                    462:         ipinfo_no = 0;
                    463:       break;
                    464:     case 'z':
                    465:       ipinfo_no = 0;
                    466:       break;
                    467: #endif
                    468:     }
                    469:   }
                    470: 
                    471:   if (DisplayMode == DisplayReport ||
                    472:       DisplayMode == DisplayTXT ||
                    473:       DisplayMode == DisplayXML ||
                    474:       DisplayMode == DisplayRaw ||
                    475:       DisplayMode == DisplayCSV)
                    476:     Interactive = 0;
                    477: 
                    478:   if (optind > argc - 1)
                    479:     return;
                    480: 
                    481: }
                    482: 
                    483: 
                    484: void parse_mtr_options (char *string)
                    485: {
                    486:   int argc;
                    487:   char *argv[128], *p;
                    488: 
                    489:   if (!string) return;
                    490: 
                    491:   argv[0] = "mtr";
                    492:   argc = 1;
                    493:   p = strtok (string, " \t");
                    494:   while (p != NULL && ((size_t) argc < (sizeof(argv)/sizeof(argv[0])))) {
                    495:     argv[argc++] = p;
                    496:     p = strtok (NULL, " \t");
                    497:   }
                    498:   if (p != NULL) {
                    499:     fprintf (stderr, "Warning: extra arguments ignored: %s", p);
                    500:   }
                    501: 
                    502:   parse_arg (argc, argv);
                    503:   optind = 0;
                    504: }
                    505: 
                    506: 
                    507: int main(int argc, char **argv)
                    508: {
                    509:   struct hostent *  host                = NULL;
                    510:   int               net_preopen_result;
                    511: #ifdef ENABLE_IPV6
                    512:   struct addrinfo       hints, *res;
                    513:   int                   error;
                    514:   struct hostent        trhost;
                    515:   char *                alptr[2];
                    516:   struct sockaddr_in *  sa4;
                    517:   struct sockaddr_in6 * sa6;
                    518: #endif
                    519: 
                    520:   /*  Get the raw sockets first thing, so we can drop to user euid immediately  */
                    521: 
                    522:   if ( ( net_preopen_result = net_preopen () ) ) {
                    523:     fprintf( stderr, "mtr: unable to get raw sockets.\n" );
                    524:     exit( EXIT_FAILURE );
                    525:   }
                    526: 
                    527:   /*  Now drop to user permissions  */
                    528:   if (setgid(getgid()) || setuid(getuid())) {
                    529:     fprintf (stderr, "mtr: Unable to drop permissions.\n");
                    530:     exit(1);
                    531:   }
                    532: 
                    533:   /*  Double check, just in case  */
                    534:   if ((geteuid() != getuid()) || (getegid() != getgid())) {
                    535:     fprintf (stderr, "mtr: Unable to drop permissions.\n");
                    536:     exit(1);
                    537:   }
                    538: 
                    539:   /* reset the random seed */
                    540:   srand (getpid());
                    541: 
                    542:   display_detect(&argc, &argv);
                    543: 
                    544:   /* The field options are now in a static array all together,
                    545:      but that requires a run-time initialization. */
                    546:   init_fld_options ();
                    547: 
                    548:   parse_mtr_options (getenv ("MTR_OPTIONS"));
                    549: 
                    550:   parse_arg (argc, argv);
                    551: 
                    552:   while (optind < argc) {
                    553:     char* name = argv[optind++];
                    554:     append_to_names(argv[0], name);
                    555:   }
                    556: 
                    557:   /* Now that we know mtrtype we can select which socket to use */
                    558:   if (net_selectsocket() != 0) {
                    559:     fprintf( stderr, "mtr: Couldn't determine raw socket type.\n" );
                    560:     exit( EXIT_FAILURE );
                    561:   }
                    562: 
                    563:   if (PrintVersion) {
                    564:     printf ("mtr " MTR_VERSION "\n");
                    565:     exit(0);
                    566:   }
                    567: 
                    568:   if (PrintHelp) {
                    569:     printf("usage: %s [-hvrwctglspniuT46] [--help] [--version] [--report]\n"
                    570:           "\t\t[--report-wide] [--report-cycles=COUNT] [--curses] [--gtk]\n"
                    571:            "\t\t[--csv|-C] [--raw] [--split] [--mpls] [--no-dns] [--show-ips]\n"
                    572:            "\t\t[--address interface] [--filename=FILE|-F]\n" /* BL */
                    573: #ifndef NO_IPINFO
                    574:            "\t\t[--ipinfo=item_no|-y item_no]\n"
                    575:            "\t\t[--aslookup|-z]\n"
                    576: #endif
                    577:            "\t\t[--psize=bytes/-s bytes]\n"            /* ok */
                    578:            "\t\t[--report-wide|-w] [-u|-T] [--port=PORT] [--timeout=SECONDS]\n"            /* rew */
                    579:           "\t\t[--interval=SECONDS] HOSTNAME\n", argv[0]);
                    580:     exit(0);
                    581:   }
                    582: 
                    583:   time_t now = time(NULL);
                    584:   names_t* head = names;
                    585:   while (names != NULL) {
                    586: 
                    587:     Hostname = names->name;
                    588:     if (Hostname == NULL) Hostname = "localhost";
                    589:     if (gethostname(LocalHostname, sizeof(LocalHostname))) {
                    590:     strcpy(LocalHostname, "UNKNOWNHOST");
                    591:     }
                    592: 
                    593:     if (net_preopen_result != 0) {
                    594:       fprintf(stderr, "mtr: Unable to get raw socket.  (Executable not suid?)\n");
                    595:       if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
                    596:       else {
                    597:         names = names->next;
                    598:         continue;
                    599:       }
                    600:     }
                    601: 
                    602: #ifdef ENABLE_IPV6
                    603:     /* gethostbyname2() is deprecated so we'll use getaddrinfo() instead. */
                    604:     bzero( &hints, sizeof hints );
                    605:     hints.ai_family = af;
                    606:     hints.ai_socktype = SOCK_DGRAM;
                    607:     error = getaddrinfo( Hostname, NULL, &hints, &res );
                    608:     if ( error ) {
                    609:       if (error == EAI_SYSTEM)
                    610:          perror ("Failed to resolve host");
                    611:       else
                    612:          fprintf (stderr, "Failed to resolve host: %s\n", gai_strerror(error));
                    613: 
                    614:       if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
                    615:       else {
                    616:         names = names->next;
                    617:         continue;
                    618:       }
                    619:     }
                    620:     /* Convert the first addrinfo into a hostent. */
                    621:     host = &trhost;
                    622:     bzero( host, sizeof trhost );
                    623:     host->h_name = res->ai_canonname;
                    624:     host->h_aliases = NULL;
                    625:     host->h_addrtype = res->ai_family;
                    626:     af = res->ai_family;
                    627:     host->h_length = res->ai_addrlen;
                    628:     host->h_addr_list = alptr;
                    629:     switch ( af ) {
                    630:     case AF_INET:
                    631:       sa4 = (struct sockaddr_in *) res->ai_addr;
                    632:       alptr[0] = (void *) &(sa4->sin_addr);
                    633:       break;
                    634:     case AF_INET6:
                    635:       sa6 = (struct sockaddr_in6 *) res->ai_addr;
                    636:       alptr[0] = (void *) &(sa6->sin6_addr);
                    637:       break;
                    638:     default:
                    639:       fprintf( stderr, "mtr unknown address type\n" );
                    640:       if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
                    641:       else {
                    642:         names = names->next;
                    643:         continue;
                    644:       }
                    645:     }
                    646:     alptr[1] = NULL;
                    647: #else
                    648:       host = gethostbyname(Hostname);
                    649:     if (host == NULL) {
                    650:       herror("mtr gethostbyname");
                    651:       if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
                    652:       else {
                    653:         names = names->next;
                    654:         continue;
                    655:       }
                    656:     }
                    657:     af = host->h_addrtype;
                    658: #endif
                    659: 
                    660:     if (net_open(host) != 0) {
                    661:       fprintf(stderr, "mtr: Unable to start net module.\n");
                    662:       if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
                    663:       else {
                    664:         names = names->next;
                    665:         continue;
                    666:       }
                    667:     }
                    668: 
                    669:     if (net_set_interfaceaddress (InterfaceAddress) != 0) {
                    670:       fprintf( stderr, "mtr: Couldn't set interface address.\n" );
                    671:       if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
                    672:       else {
                    673:         names = names->next;
                    674:         continue;
                    675:       }
                    676:     }
                    677: 
                    678:     lock(argv[0], stdout);
                    679:       display_open();
                    680:       dns_open();
                    681: 
                    682:       display_mode = 0;
                    683:       display_loop();
                    684: 
                    685:       net_end_transit();
                    686:       display_close(now);
                    687:     unlock(argv[0], stdout);
                    688: 
                    689:     if ( DisplayMode != DisplayCSV ) break;
                    690:     else names = names->next;
                    691: 
                    692:   }
                    693: 
                    694:   net_close();
                    695: 
                    696:   while (head != NULL) {
                    697:     names_t* item = head;
                    698:     free(item->name); item->name = NULL;
                    699:     head = head->next;
                    700:     free(item); item = NULL;
                    701:   }
                    702:   head=NULL;
                    703: 
                    704:   return 0;
                    705: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>