File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / mtr.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:43:42 2013 UTC (10 years, 11 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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>