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>