Annotation of embedaddon/mtr/mtr.c, revision 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>