File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / mtr.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:44:48 2016 UTC (7 years, 7 months ago) by misho
Branches: mtr, elwix, MAIN
CVS tags: v0_86, HEAD
mtr 0.86

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

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