From: Roger Wolff Date: Wed, 11 Aug 2004 00:00:00 +0000 (+0000) Subject: mtr v0.61 X-Git-Tag: v0.61^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3adcb265b5652a6c77ed5353a62c3cee1bb66e54;p=thirdparty%2Fmtr.git mtr v0.61 - Attempt to get/print the local IP address. Now shows as 0.0.0.0 :-( Hints and tips appreciated! -- REW - Lots of blank space reformatting. - Moved the interface address setting to net.c (where it belongs). source: ftp://ftp.bitwizard.nl/mtr/mtr-0.61.tar.gz --- diff --git a/NEWS b/NEWS index 99485fc..d1b7159 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,10 @@ WHAT'S NEW? + v0.61 Attempt to get/print the local IP address. Now shows as + 0.0.0.0 :-( Hints and tips appreciated! -- REW + Lots of blank space reformatting. + moved the interface address setting to net.c (where it + belongs). + v0.60 John Thacker submitted a surprisingly simple patch to enable linking against GTK2. (up to 2.4.0) diff --git a/configure.in b/configure.in index 44a92ad..e80c131 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ AC_INIT(mtr.c) -AM_INIT_AUTOMAKE(mtr, 0.60) +AM_INIT_AUTOMAKE(mtr, 0.61) AC_SUBST(GTK_OBJ) diff --git a/curses.c b/curses.c index d9ef8fd..dff24fd 100644 --- a/curses.c +++ b/curses.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #if defined(HAVE_NCURSES_H) # include @@ -471,6 +474,7 @@ void mtr_curses_redraw() int hd_len = 0; char buf[1024]; char fmt[16]; + erase(); getmaxyx(stdscr, maxy, maxx); @@ -482,7 +486,7 @@ void mtr_curses_redraw() pwcenter("My traceroute [v" VERSION "]"); attroff(A_BOLD); - mvprintw(1, 0, "%s", LocalHostname); + mvprintw(1, 0, "%s (%s)", LocalHostname, inet_ntoa(*net_localaddr())); printw("(tos=0x%X ", tos); printw("psize=%d ", abs(packetsize) ); printw("bitpattern=0x%02X)", (unsigned char)(abs(bitpattern))); diff --git a/dns.c b/dns.c index fabab32..32a96b3 100644 --- a/dns.c +++ b/dns.c @@ -280,9 +280,10 @@ char stackstring[1024+1]; char nullstring[] = ""; -/* Code */ +int use_dns = 1; +/* Code */ #ifdef CorruptCheck #define TOT_SLACK 2 #define HEAD_SLACK 1 @@ -301,925 +302,982 @@ char nullstring[] = ""; void *statmalloc(size_t size) { - void *p; - size_t mallocsize; - mem+= size; - mallocsize = size + TOT_SLACK * sizeof(dword); - - p = malloc(mallocsize); - if (!p) { - fprintf(stderr,"malloc() of %u bytes failed: %s\n", (unsigned int)size, strerror(errno)); - exit(-1); - } - *((dword *)p) = (dword)size; + void *p; + size_t mallocsize; + + mem+= size; + mallocsize = size + TOT_SLACK * sizeof(dword); + + p = malloc(mallocsize); + if (!p) { + fprintf(stderr,"malloc() of %u bytes failed: %s\n", (unsigned int)size, strerror(errno)); + exit(-1); + } + *((dword *)p) = (dword)size; #ifdef CorruptCheck - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 0) = 0xde; - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 1) = 0xad; - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 2) = 0xbe; - *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 3) = 0xef; + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 0) = 0xde; + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 1) = 0xad; + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 2) = 0xbe; + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 3) = 0xef; #endif - p = (void *)((dword *)p + HEAD_SLACK); + p = (void *)((dword *)p + HEAD_SLACK); #ifdef WipeMallocs - memset(p,0xf0,size); + memset(p,0xf0,size); #endif - return p; + return p; } + void statfree(void *p) { - if (p) { - if (*((dword *)p - HEAD_SLACK) == 0) { - fprintf(stderr,"ERROR: Attempt to free pointer twice.\n"); - *(int*)0=0; - exit(-1); - } else { - if (*((dword *)p - HEAD_SLACK) > 8192) { - fprintf(stderr,"ERROR: Corrupted free() buffer. (header)\n"); - *(int*)0=0; - exit(-1); - } + if (p) { + if (*((dword *)p - HEAD_SLACK) == 0) { + fprintf(stderr,"ERROR: Attempt to free pointer twice.\n"); + *(int*)0=0; + exit(-1); + } else { + if (*((dword *)p - HEAD_SLACK) > 8192) { + fprintf (stderr,"ERROR: Corrupted free() buffer. (header)\n"); + *(int*)0=0; + exit(-1); + } #ifdef CorruptCheck - if ((*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 0) != 0xde) || - (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 1) != 0xad) || - (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 2) != 0xbe) || - (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 3) != 0xef)) { - fprintf(stderr,"ERROR: Corrupted free() buffer. (footer)\n"); - *(int*)0=0; - exit(-1); - } + if ((*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 0) != 0xde) || + (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 1) != 0xad) || + (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 2) != 0xbe) || + (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 3) != 0xef)) { + fprintf(stderr,"ERROR: Corrupted free() buffer. (footer)\n"); + *(int*)0=0; + exit(-1); + } #endif - mem-= *((dword *)p - HEAD_SLACK); + mem-= *((dword *)p - HEAD_SLACK); #ifdef WipeFrees - memset(p,0xfe,*((dword *)p - HEAD_SLACK)); - *((dword *)p - 1) = 0; + memset(p,0xfe,*((dword *)p - HEAD_SLACK)); + *((dword *)p - 1) = 0; #endif - free((dword *)p - HEAD_SLACK); - } - } + free((dword *)p - HEAD_SLACK); + } + } } + char *strtdiff(char *d,long signeddiff) { - dword diff; - dword seconds,minutes,hours; - long days; - if ((diff = labs(signeddiff))) { - seconds = diff % 60; diff/= 60; - minutes = diff % 60; diff/= 60; - hours = diff % 24; - days = signeddiff / (60 * 60 * 24); - if (days) - sprintf(d,"%lid",days); - else - *d = '\0'; - if (hours) - sprintf(d + strlen(d),"%luh",hours); - if (minutes) - sprintf(d + strlen(d),"%lum",minutes); - if (seconds) - sprintf(d + strlen(d),"%lus",seconds); - } else - sprintf(d,"0s"); - return d; + dword diff; + dword seconds,minutes,hours; + long days; + + if ((diff = labs(signeddiff))) { + seconds = diff % 60; diff/= 60; + minutes = diff % 60; diff/= 60; + hours = diff % 24; + days = signeddiff / (60 * 60 * 24); + if (days) + sprintf(d,"%lid",days); + else + *d = '\0'; + if (hours) + sprintf(d + strlen(d),"%luh",hours); + if (minutes) + sprintf(d + strlen(d),"%lum",minutes); + if (seconds) + sprintf(d + strlen(d),"%lus",seconds); + } else + sprintf(d,"0s"); + return d; } + int issetfd(fd_set *set,int fd) { - return (int)((FD_ISSET(fd,set)) && 1); + return (int)((FD_ISSET(fd,set)) && 1); } + void setfd(fd_set *set,int fd) { - FD_SET(fd,set); + FD_SET(fd,set); } + void clearfd(fd_set *set,int fd) { - FD_CLR(fd,set); + FD_CLR(fd,set); } + void clearset(fd_set *set) { - FD_ZERO(set); + FD_ZERO(set); } + char *strlongip(ip_t ip) { - struct in_addr a; - a.s_addr = htonl(ip); - return inet_ntoa(a); + struct in_addr a; + a.s_addr = htonl(ip); + return inet_ntoa(a); } + ip_t longipstr(char *s) { - return inet_addr(s); + return inet_addr(s); } + int dns_forward(char *name) { - struct hostent *host; - if ((host = gethostbyname(name))) - return *(int *)host->h_addr; - else - return 0; + struct hostent *host; + + if ((host = gethostbyname(name))) + return *(int *)host->h_addr; + else + return 0; } + int dns_waitfd(void) { - return resfd; + return resfd; } + void dns_open(void) { - int option,i; + int option,i; - res_init(); - if (!_res.nscount) { - fprintf(stderr,"No nameservers defined.\n"); - exit(-1); - } - _res.options|= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH; - for (i = 0;i < _res.nscount;i++) - _res.nsaddr_list[i].sin_family = AF_INET; - resfd = socket(AF_INET, SOCK_DGRAM, 0); - if (resfd == -1) { - fprintf(stderr,"Unable to allocate socket for nameserver communication: %s\n", - strerror(errno)); - exit(-1); - } - option = 1; - if (setsockopt(resfd,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) { - fprintf(stderr,"Unable to setsockopt() on nameserver communication socket: %s\n", - strerror(errno)); - exit(-1); - } - localhost = longipstr("127.0.0.1"); - aseed = time(NULL) ^ (time(NULL) << 3) ^ (dword)getpid(); - for (i = 0;i < BashSize;i++) { - idbash[i] = NULL; - hostbash[i] = NULL; - } + res_init(); + if (!_res.nscount) { + fprintf(stderr,"No nameservers defined.\n"); + exit(-1); + } + _res.options|= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH; + for (i = 0;i < _res.nscount;i++) + _res.nsaddr_list[i].sin_family = AF_INET; + resfd = socket(AF_INET, SOCK_DGRAM, 0); + if (resfd == -1) { + fprintf(stderr,"Unable to allocate socket for nameserver communication: %s\n", + strerror(errno)); + exit(-1); + } + option = 1; + if (setsockopt(resfd,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) { + fprintf(stderr,"Unable to setsockopt() on nameserver communication socket: %s\n", + strerror(errno)); + exit(-1); + } + localhost = longipstr("127.0.0.1"); + aseed = time(NULL) ^ (time(NULL) << 3) ^ (dword)getpid(); + for (i = 0;i < BashSize;i++) { + idbash[i] = NULL; + hostbash[i] = NULL; + } } + struct resolve *allocresolve(void) { - struct resolve *rp; - rp = (struct resolve *)statmalloc(sizeof(struct resolve)); - if (!rp) { - fprintf(stderr,"statmalloc() failed: %s\n",strerror(errno)); - exit(-1); - } - memset(rp,0, sizeof(struct resolve)); - return rp; + struct resolve *rp; + + rp = (struct resolve *)statmalloc(sizeof(struct resolve)); + if (!rp) { + fprintf(stderr,"statmalloc() failed: %s\n",strerror(errno)); + exit(-1); + } + memset(rp,0, sizeof(struct resolve)); + return rp; } + dword getidbash(word id) { - return (dword)BashModulo(id); + return (dword)BashModulo(id); } + dword getipbash(ip_t ip) { - return (dword)BashModulo(ip); + return (dword)BashModulo(ip); } + dword gethostbash(char *host) { - dword bashvalue = 0; - for (;*host;host++) { - bashvalue^= *host; - bashvalue+= (*host >> 1) + (bashvalue >> 1); - } - return BashModulo(bashvalue); + dword bashvalue = 0; + + for (;*host;host++) { + bashvalue^= *host; + bashvalue+= (*host >> 1) + (bashvalue >> 1); + } + return BashModulo(bashvalue); } + void linkresolveid(struct resolve *addrp) { - struct resolve *rp; - dword bashnum; - bashnum = getidbash(addrp->id); - rp = idbash[bashnum]; - if (rp) { - while ((rp->nextid) && (addrp->id > rp->nextid->id)) - rp = rp->nextid; - while ((rp->previousid) && (addrp->id < rp->previousid->id)) - rp = rp->previousid; - if (rp->id < addrp->id) { - addrp->previousid = rp; - addrp->nextid = rp->nextid; - if (rp->nextid) - rp->nextid->previousid = addrp; - rp->nextid = addrp; - } else { - addrp->previousid = rp->previousid; - addrp->nextid = rp; - if (rp->previousid) - rp->previousid->nextid = addrp; - rp->previousid = addrp; - } - } else - addrp->nextid = addrp->previousid = NULL; - idbash[bashnum] = addrp; + struct resolve *rp; + dword bashnum; + + bashnum = getidbash(addrp->id); + rp = idbash[bashnum]; + if (rp) { + while ((rp->nextid) && (addrp->id > rp->nextid->id)) + rp = rp->nextid; + while ((rp->previousid) && (addrp->id < rp->previousid->id)) + rp = rp->previousid; + if (rp->id < addrp->id) { + addrp->previousid = rp; + addrp->nextid = rp->nextid; + if (rp->nextid) + rp->nextid->previousid = addrp; + rp->nextid = addrp; + } else { + addrp->previousid = rp->previousid; + addrp->nextid = rp; + if (rp->previousid) + rp->previousid->nextid = addrp; + rp->previousid = addrp; + } + } else + addrp->nextid = addrp->previousid = NULL; + idbash[bashnum] = addrp; } + void unlinkresolveid(struct resolve *rp) { - dword bashnum; - bashnum = getidbash(rp->id); - if (idbash[bashnum] == rp) - idbash[bashnum] = (rp->previousid)? rp->previousid : rp->nextid; - if (rp->nextid) - rp->nextid->previousid = rp->previousid; - if (rp->previousid) - rp->previousid->nextid = rp->nextid; + dword bashnum; + + bashnum = getidbash(rp->id); + if (idbash[bashnum] == rp) + idbash[bashnum] = (rp->previousid)? rp->previousid : rp->nextid; + if (rp->nextid) + rp->nextid->previousid = rp->previousid; + if (rp->previousid) + rp->previousid->nextid = rp->nextid; } + void linkresolvehost(struct resolve *addrp) { - struct resolve *rp; - dword bashnum; - bashnum = gethostbash(addrp->hostname); - rp = hostbash[bashnum]; - if (rp) { - while ((rp->nexthost) && (strcasecmp(addrp->hostname,rp->nexthost->hostname) < 0)) - rp = rp->nexthost; - while ((rp->previoushost) && (strcasecmp(addrp->hostname,rp->previoushost->hostname) > 0)) - rp = rp->previoushost; - if (strcasecmp(addrp->hostname,rp->hostname) < 0) { - addrp->previoushost = rp; - addrp->nexthost = rp->nexthost; - if (rp->nexthost) - rp->nexthost->previoushost = addrp; - rp->nexthost = addrp; - } else { - addrp->previoushost = rp->previoushost; - addrp->nexthost = rp; - if (rp->previoushost) - rp->previoushost->nexthost = addrp; - rp->previoushost = addrp; - } - } else - addrp->nexthost = addrp->previoushost = NULL; - hostbash[bashnum] = addrp; + struct resolve *rp; + dword bashnum; + + bashnum = gethostbash(addrp->hostname); + rp = hostbash[bashnum]; + if (rp) { + while ((rp->nexthost) && (strcasecmp(addrp->hostname,rp->nexthost->hostname) < 0)) + rp = rp->nexthost; + while ((rp->previoushost) && (strcasecmp(addrp->hostname,rp->previoushost->hostname) > 0)) + rp = rp->previoushost; + if (strcasecmp(addrp->hostname,rp->hostname) < 0) { + addrp->previoushost = rp; + addrp->nexthost = rp->nexthost; + if (rp->nexthost) + rp->nexthost->previoushost = addrp; + rp->nexthost = addrp; + } else { + addrp->previoushost = rp->previoushost; + addrp->nexthost = rp; + if (rp->previoushost) + rp->previoushost->nexthost = addrp; + rp->previoushost = addrp; + } + } else + addrp->nexthost = addrp->previoushost = NULL; + hostbash[bashnum] = addrp; } + void unlinkresolvehost(struct resolve *rp) { - dword bashnum; - bashnum = gethostbash(rp->hostname); - if (hostbash[bashnum] == rp) - hostbash[bashnum] = (rp->previoushost)? rp->previoushost : rp->nexthost; - if (rp->nexthost) - rp->nexthost->previoushost = rp->previoushost; - if (rp->previoushost) - rp->previoushost->nexthost = rp->nexthost; - statfree(rp->hostname); + dword bashnum; + + bashnum = gethostbash(rp->hostname); + if (hostbash[bashnum] == rp) + hostbash[bashnum] = (rp->previoushost)? rp->previoushost : rp->nexthost; + if (rp->nexthost) + rp->nexthost->previoushost = rp->previoushost; + if (rp->previoushost) + rp->previoushost->nexthost = rp->nexthost; + statfree(rp->hostname); } + void linkresolveip(struct resolve *addrp) { - struct resolve *rp; - dword bashnum; - bashnum = getipbash(addrp->ip); - rp = ipbash[bashnum]; - if (rp) { - while ((rp->nextip) && (addrp->ip > rp->nextip->ip)) - rp = rp->nextip; - while ((rp->previousip) && (addrp->ip < rp->previousip->ip)) - rp = rp->previousip; - if (rp->ip < addrp->ip) { - addrp->previousip = rp; - addrp->nextip = rp->nextip; - if (rp->nextip) - rp->nextip->previousip = addrp; - rp->nextip = addrp; - } else { - addrp->previousip = rp->previousip; - addrp->nextip = rp; - if (rp->previousip) - rp->previousip->nextip = addrp; - rp->previousip = addrp; - } - } else - addrp->nextip = addrp->previousip = NULL; - ipbash[bashnum] = addrp; + struct resolve *rp; + dword bashnum; + + bashnum = getipbash(addrp->ip); + rp = ipbash[bashnum]; + if (rp) { + while ((rp->nextip) && (addrp->ip > rp->nextip->ip)) + rp = rp->nextip; + while ((rp->previousip) && (addrp->ip < rp->previousip->ip)) + rp = rp->previousip; + if (rp->ip < addrp->ip) { + addrp->previousip = rp; + addrp->nextip = rp->nextip; + if (rp->nextip) + rp->nextip->previousip = addrp; + rp->nextip = addrp; + } else { + addrp->previousip = rp->previousip; + addrp->nextip = rp; + if (rp->previousip) + rp->previousip->nextip = addrp; + rp->previousip = addrp; + } + } else + addrp->nextip = addrp->previousip = NULL; + ipbash[bashnum] = addrp; } + void unlinkresolveip(struct resolve *rp) { - dword bashnum; - bashnum = getipbash(rp->ip); - if (ipbash[bashnum] == rp) - ipbash[bashnum] = (rp->previousip)? rp->previousip : rp->nextip; - if (rp->nextip) - rp->nextip->previousip = rp->previousip; - if (rp->previousip) - rp->previousip->nextip = rp->nextip; + dword bashnum; + + bashnum = getipbash(rp->ip); + if (ipbash[bashnum] == rp) + ipbash[bashnum] = (rp->previousip)? rp->previousip : rp->nextip; + if (rp->nextip) + rp->nextip->previousip = rp->previousip; + if (rp->previousip) + rp->previousip->nextip = rp->nextip; } + void linkresolve(struct resolve *rp) { - struct resolve *irp; - if (expireresolves) { - irp = expireresolves; - while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; - if (rp->expiretime >= irp->expiretime) { - rp->next = NULL; - rp->previous = irp; - irp->next = rp; - lastresolve = rp; - } else { - rp->previous = irp->previous; - rp->next = irp; - if (irp->previous) - irp->previous->next = rp; - else - expireresolves = rp; - irp->previous = rp; - } - } else { + struct resolve *irp; + + if (expireresolves) { + irp = expireresolves; + while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; + if (rp->expiretime >= irp->expiretime) { rp->next = NULL; - rp->previous = NULL; - expireresolves = lastresolve = rp; - } - resolvecount++; + rp->previous = irp; + irp->next = rp; + lastresolve = rp; + } else { + rp->previous = irp->previous; + rp->next = irp; + if (irp->previous) + irp->previous->next = rp; + else + expireresolves = rp; + irp->previous = rp; + } + } else { + rp->next = NULL; + rp->previous = NULL; + expireresolves = lastresolve = rp; + } + resolvecount++; } + void lastlinkresolve(struct resolve *rp) { - struct resolve *irp; - if (lastresolve) { - irp = lastresolve; - while ((irp->previous) && (rp->expiretime < irp->expiretime)) irp = irp->previous; - while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; - if (rp->expiretime >= irp->expiretime) { - rp->next = NULL; - rp->previous = irp; - irp->next = rp; - lastresolve = rp; - } else { - rp->previous = irp->previous; - rp->next = irp; - if (irp->previous) - irp->previous->next = rp; - else - expireresolves = rp; - irp->previous = rp; - } - } else { + struct resolve *irp; + + if (lastresolve) { + irp = lastresolve; + while ((irp->previous) && (rp->expiretime < irp->expiretime)) irp = irp->previous; + while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; + if (rp->expiretime >= irp->expiretime) { rp->next = NULL; - rp->previous = NULL; - expireresolves = lastresolve = rp; - } - resolvecount++; + rp->previous = irp; + irp->next = rp; + lastresolve = rp; + } else { + rp->previous = irp->previous; + rp->next = irp; + if (irp->previous) + irp->previous->next = rp; + else + expireresolves = rp; + irp->previous = rp; + } + } else { + rp->next = NULL; + rp->previous = NULL; + expireresolves = lastresolve = rp; + } + resolvecount++; } + void untieresolve(struct resolve *rp) { - if (rp->previous) - rp->previous->next = rp->next; - else - expireresolves = rp->next; - if (rp->next) - rp->next->previous = rp->previous; - else - lastresolve = rp->previous; - resolvecount--; + if (rp->previous) + rp->previous->next = rp->next; + else + expireresolves = rp->next; + if (rp->next) + rp->next->previous = rp->previous; + else + lastresolve = rp->previous; + resolvecount--; } + void unlinkresolve(struct resolve *rp) { - untieresolve(rp); - unlinkresolveid(rp); - unlinkresolveip(rp); - if (rp->hostname) - unlinkresolvehost(rp); + untieresolve(rp); + unlinkresolveid(rp); + unlinkresolveip(rp); + if (rp->hostname) + unlinkresolvehost(rp); } + struct resolve *findid(word id) { - struct resolve *rp; - int bashnum; - bashnum = getidbash(id); - rp = idbash[bashnum]; - if (rp) { - while ((rp->nextid) && (id >= rp->nextid->id)) - rp = rp->nextid; - while ((rp->previousid) && (id <= rp->previousid->id)) - rp = rp->previousid; - if (id == rp->id) { - idbash[bashnum] = rp; - return rp; - } else - return NULL; - } - return rp; /* NULL */ + struct resolve *rp; + int bashnum; + + bashnum = getidbash(id); + rp = idbash[bashnum]; + if (rp) { + while ((rp->nextid) && (id >= rp->nextid->id)) + rp = rp->nextid; + while ((rp->previousid) && (id <= rp->previousid->id)) + rp = rp->previousid; + if (id == rp->id) { + idbash[bashnum] = rp; + return rp; + } else + return NULL; + } + return rp; /* NULL */ } + struct resolve *findhost(char *hostname) { - struct resolve *rp; - int bashnum; - bashnum = gethostbash(hostname); - rp = hostbash[bashnum]; - if (rp) { - while ((rp->nexthost) && (strcasecmp(hostname,rp->nexthost->hostname) >= 0)) - rp = rp->nexthost; - while ((rp->previoushost) && (strcasecmp(hostname,rp->nexthost->hostname) <= 0)) - rp = rp->previoushost; - if (strcasecmp(hostname,rp->hostname)) - return NULL; - else { - hostbash[bashnum] = rp; - return rp; - } - } - return rp; /* NULL */ + struct resolve *rp; + int bashnum; + + bashnum = gethostbash(hostname); + rp = hostbash[bashnum]; + if (rp) { + while ((rp->nexthost) && (strcasecmp(hostname,rp->nexthost->hostname) >= 0)) + rp = rp->nexthost; + while ((rp->previoushost) && (strcasecmp(hostname,rp->nexthost->hostname) <= 0)) + rp = rp->previoushost; + if (strcasecmp(hostname,rp->hostname)) + return NULL; + else { + hostbash[bashnum] = rp; + return rp; + } + } + return rp; /* NULL */ } + struct resolve *findip(ip_t ip) { - struct resolve *rp; - dword bashnum; - bashnum = getipbash(ip); - rp = ipbash[bashnum]; - if (rp) { - while ((rp->nextip) && (ip >= rp->nextip->ip)) - rp = rp->nextip; - while ((rp->previousip) && (ip <= rp->previousip->ip)) - rp = rp->previousip; - if (ip == rp->ip) { - ipbash[bashnum] = rp; - return rp; - } else - return NULL; - } - return rp; /* NULL */ + struct resolve *rp; + dword bashnum; + + bashnum = getipbash(ip); + rp = ipbash[bashnum]; + if (rp) { + while ((rp->nextip) && (ip >= rp->nextip->ip)) + rp = rp->nextip; + while ((rp->previousip) && (ip <= rp->previousip->ip)) + rp = rp->previousip; + if (ip == rp->ip) { + ipbash[bashnum] = rp; + return rp; + } else + return NULL; + } + return rp; /* NULL */ } + void restell(char *s) { - fputs(s,stderr); - fputs("\r",stderr); + fputs(s,stderr); + fputs("\r",stderr); } + void dorequest(char *s,int type,word id) { - packetheader *hp; - int r,i; - int buf[(MaxPacketsize/sizeof (int))+1]; - r = res_mkquery(QUERY,s,C_IN,type,NULL,0,NULL,(unsigned char*)buf,MaxPacketsize); - if (r == -1) { - restell("Resolver error: Query too large."); - return; - } - hp = (packetheader *)buf; - hp->id = id; /* htons() deliberately left out (redundant) */ - for (i = 0;i < _res.nscount;i++) - (void)sendto(resfd,buf,r,0,(struct sockaddr *)&_res.nsaddr_list[i], - sizeof(struct sockaddr)); + packetheader *hp; + int r,i; + int buf[(MaxPacketsize/sizeof (int))+1]; + + r = res_mkquery(QUERY,s,C_IN,type,NULL,0,NULL,(unsigned char*)buf,MaxPacketsize); + if (r == -1) { + restell("Resolver error: Query too large."); + return; + } + hp = (packetheader *)buf; + hp->id = id; /* htons() deliberately left out (redundant) */ + for (i = 0;i < _res.nscount;i++) + (void)sendto(resfd,buf,r,0,(struct sockaddr *)&_res.nsaddr_list[i], + sizeof(struct sockaddr)); } void resendrequest(struct resolve *rp,int type) { - if (type == T_A) { - dorequest(rp->hostname,type,rp->id); - if (debug) { - sprintf(tempstring,"Resolver: Sent reverse authentication request for \"%s\".", - rp->hostname); - restell(tempstring); - } - } else if (type == T_PTR) { - sprintf(tempstring,"%u.%u.%u.%u.in-addr.arpa", - ((byte *)&rp->ip)[3], - ((byte *)&rp->ip)[2], - ((byte *)&rp->ip)[1], - ((byte *)&rp->ip)[0]); - dorequest(tempstring,type,rp->id); - if (debug) { - sprintf(tempstring,"Resolver: Sent domain lookup request for \"%s\".", - strlongip(rp->ip)); - restell(tempstring); - } - } + if (type == T_A) { + dorequest(rp->hostname,type,rp->id); + if (debug) { + sprintf(tempstring,"Resolver: Sent reverse authentication request for \"%s\".", + rp->hostname); + restell(tempstring); + } + } else if (type == T_PTR) { + sprintf(tempstring,"%u.%u.%u.%u.in-addr.arpa", + ((byte *)&rp->ip)[3], + ((byte *)&rp->ip)[2], + ((byte *)&rp->ip)[1], + ((byte *)&rp->ip)[0]); + dorequest(tempstring,type,rp->id); + if (debug) { + sprintf(tempstring,"Resolver: Sent domain lookup request for \"%s\".", + strlongip(rp->ip)); + restell(tempstring); + } + } } void sendrequest(struct resolve *rp,int type) { - do { - idseed = (((idseed + idseed) | (long)time(NULL)) + idseed - 0x54bad4a) ^ aseed; - aseed^= idseed; - rp->id = (word)idseed; - } while (findid(rp->id)); - linkresolveid(rp); - resendrequest(rp,type); + do { + idseed = (((idseed + idseed) | (long)time(NULL)) + idseed - 0x54bad4a) ^ aseed; + aseed^= idseed; + rp->id = (word)idseed; + } while (findid(rp->id)); + linkresolveid(rp); + resendrequest(rp,type); } + void failrp(struct resolve *rp) { - if (rp->state == STATE_FINISHED) - return; - rp->state = STATE_FAILED; - untieresolve(rp); - if (debug) - restell("Resolver: Lookup failed.\n"); + if (rp->state == STATE_FINISHED) + return; + rp->state = STATE_FAILED; + untieresolve(rp); + if (debug) + restell("Resolver: Lookup failed.\n"); } + void passrp(struct resolve *rp,long ttl) { - rp->state = STATE_FINISHED; - rp->expiretime = sweeptime + (double)ttl; - untieresolve(rp); - if (debug) { - sprintf(tempstring,"Resolver: Lookup successful: %s\n",rp->hostname); - restell(tempstring); - } + rp->state = STATE_FINISHED; + rp->expiretime = sweeptime + (double)ttl; + untieresolve(rp); + if (debug) { + sprintf(tempstring,"Resolver: Lookup successful: %s\n",rp->hostname); + restell(tempstring); + } } + void parserespacket(byte *s,int l) { - struct resolve *rp; - packetheader *hp; - byte *eob; - byte *c; - long ttl; - int r,usefulanswer; - word rr,datatype,class,qdatatype,qclass; - byte rdatalength; - if (l < sizeof(packetheader)) { - restell("Resolver error: Packet smaller than standard header size."); - return; - } - if (l == sizeof(packetheader)) { - restell("Resolver error: Packet has empty body."); - return; - } - hp = (packetheader *)s; - /* Convert data to host byte order */ - /* hp->id does not need to be redundantly byte-order flipped, it is only echoed by nameserver */ - rp = findid(hp->id); - if (!rp) { - res_unknownid++; - return; - } - if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) - return; - hp->qdcount = ntohs(hp->qdcount); - hp->ancount = ntohs(hp->ancount); - hp->nscount = ntohs(hp->nscount); - hp->arcount = ntohs(hp->arcount); - if (getheader_tc(hp)) { /* Packet truncated */ - restell("Resolver error: Nameserver packet truncated."); - return; - } - if (!getheader_qr(hp)) { /* Not a reply */ - restell("Resolver error: Query packet received on nameserver communication socket."); - return; - } - if (getheader_opcode(hp)) { /* Not opcode 0 (standard query) */ - restell("Resolver error: Invalid opcode in response packet."); - return; - } - eob = s + l; - c = s + HFIXEDSZ; - switch (getheader_rcode(hp)) { - case NOERROR: - if (hp->ancount) { - if (debug) { - sprintf(tempstring,"Resolver: Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)", + struct resolve *rp; + packetheader *hp; + byte *eob; + byte *c; + long ttl; + int r,usefulanswer; + word rr,datatype,class,qdatatype,qclass; + byte rdatalength; + + if (l < sizeof(packetheader)) { + restell("Resolver error: Packet smaller than standard header size."); + return; + } + if (l == sizeof(packetheader)) { + restell("Resolver error: Packet has empty body."); + return; + } + hp = (packetheader *)s; + /* Convert data to host byte order */ + /* hp->id does not need to be redundantly byte-order flipped, it is only echoed by nameserver */ + rp = findid(hp->id); + if (!rp) { + res_unknownid++; + return; + } + if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) + return; + hp->qdcount = ntohs(hp->qdcount); + hp->ancount = ntohs(hp->ancount); + hp->nscount = ntohs(hp->nscount); + hp->arcount = ntohs(hp->arcount); + if (getheader_tc(hp)) { /* Packet truncated */ + restell("Resolver error: Nameserver packet truncated."); + return; + } + if (!getheader_qr(hp)) { /* Not a reply */ + restell("Resolver error: Query packet received on nameserver communication socket."); + return; + } + if (getheader_opcode(hp)) { /* Not opcode 0 (standard query) */ + restell("Resolver error: Invalid opcode in response packet."); + return; + } + eob = s + l; + c = s + HFIXEDSZ; + switch (getheader_rcode(hp)) { + case NOERROR: + if (hp->ancount) { + if (debug) { + sprintf(tempstring,"Resolver: Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)", hp->qdcount,hp->ancount,hp->nscount,hp->arcount); - restell(tempstring); - } - if (hp->qdcount != 1) { - restell("Resolver error: Reply does not contain one query."); - return; - } - if (c > eob) { - restell("Resolver error: Reply too short."); - return; - } - switch (rp->state) { /* Construct expected query reply */ - case STATE_PTRREQ1: - case STATE_PTRREQ2: - case STATE_PTRREQ3: - sprintf(stackstring,"%u.%u.%u.%u.in-addr.arpa", - ((byte *)&rp->ip)[3], - ((byte *)&rp->ip)[2], - ((byte *)&rp->ip)[1], - ((byte *)&rp->ip)[0]); - break; - } - *namestring = '\0'; - r = dn_expand(s,s + l,c,namestring,MAXDNAME); - if (r == -1) { - restell("Resolver error: dn_expand() failed while expanding query domain."); - return; - } - namestring[strlen(stackstring)] = '\0'; - if (strcasecmp(stackstring,namestring)) { - if (debug) { - sprintf(tempstring,"Resolver: Unknown query packet dropped. (\"%s\" does not match \"%s\")", - stackstring,namestring); - restell(tempstring); - } - return; - } - if (debug) { - sprintf(tempstring,"Resolver: Queried domain name: \"%s\"",namestring); - restell(tempstring); - } - c+= r; - if (c + 4 > eob) { - restell("Resolver error: Query resource record truncated."); - return; - } - qdatatype = sucknetword(c); - qclass = sucknetword(c); - if (qclass != C_IN) { - sprintf(tempstring,"Resolver error: Received unsupported query class: %u (%s)", + restell(tempstring); + } + if (hp->qdcount != 1) { + restell("Resolver error: Reply does not contain one query."); + return; + } + if (c > eob) { + restell("Resolver error: Reply too short."); + return; + } + switch (rp->state) { /* Construct expected query reply */ + case STATE_PTRREQ1: + case STATE_PTRREQ2: + case STATE_PTRREQ3: + sprintf(stackstring,"%u.%u.%u.%u.in-addr.arpa", + ((byte *)&rp->ip)[3], + ((byte *)&rp->ip)[2], + ((byte *)&rp->ip)[1], + ((byte *)&rp->ip)[0]); + break; + } + *namestring = '\0'; + r = dn_expand(s,s + l,c,namestring,MAXDNAME); + if (r == -1) { + restell("Resolver error: dn_expand() failed while expanding query domain."); + return; + } + namestring[strlen(stackstring)] = '\0'; + if (strcasecmp(stackstring,namestring)) { + if (debug) { + sprintf(tempstring,"Resolver: Unknown query packet dropped. (\"%s\" does not match \"%s\")", + stackstring,namestring); + restell(tempstring); + } + return; + } + if (debug) { + sprintf(tempstring,"Resolver: Queried domain name: \"%s\"",namestring); + restell(tempstring); + } + c+= r; + if (c + 4 > eob) { + restell("Resolver error: Query resource record truncated."); + return; + } + qdatatype = sucknetword(c); + qclass = sucknetword(c); + if (qclass != C_IN) { + sprintf(tempstring,"Resolver error: Received unsupported query class: %u (%s)", qclass,qclass < ClasstypeCount ? classtypes[qclass] : - classtypes[ClasstypeCount]); - restell(tempstring); - } - switch (qdatatype) { - case T_PTR: - if (!Is_PTR(rp)) - if (debug) { - restell("Resolver warning: Ignoring response with unexpected query type \"PTR\"."); - return; - } - break; - default: - sprintf(tempstring,"Resolver error: Received unimplemented query type: %u (%s)", - qdatatype,qdatatype < ResourcetypeCount ? - resourcetypes[qdatatype] : resourcetypes[ResourcetypeCount]); - restell(tempstring); - } - for (rr = hp->ancount + hp->nscount + hp->arcount;rr;rr--) { - if (c > eob) { - restell("Resolver error: Packet does not contain all specified resouce records."); - return; - } - *namestring = '\0'; - r = dn_expand(s,s + l,c,namestring,MAXDNAME); - if (r == -1) { - restell("Resolver error: dn_expand() failed while expanding answer domain."); - return; - } - namestring[strlen(stackstring)] = '\0'; - if (strcasecmp(stackstring,namestring)) - usefulanswer = 0; - else - usefulanswer = 1; - if (debug) { - sprintf(tempstring,"Resolver: answered domain query: \"%s\"",namestring); - restell(tempstring); - } - c+= r; - if (c + 10 > eob) { - restell("Resolver error: Resource record truncated."); - return; - } - datatype = sucknetword(c); - class = sucknetword(c); - ttl = sucknetlong(c); - rdatalength = sucknetword(c); - if (class != qclass) { - sprintf(tempstring,"query class: %u (%s)",qclass,qclass < ClasstypeCount ? - classtypes[qclass] : classtypes[ClasstypeCount]); - restell(tempstring); - sprintf(tempstring,"rr class: %u (%s)",class,class < ClasstypeCount ? - classtypes[class] : classtypes[ClasstypeCount]); - restell(tempstring); - restell("Resolver error: Answered class does not match queried class."); - return; - } - if (!rdatalength) { - restell("Resolver error: Zero size rdata."); - return; - } - if (c + rdatalength > eob) { - restell("Resolver error: Specified rdata length exceeds packet size."); - return; - } - if (datatype == qdatatype || datatype == T_CNAME) { - if (debug) { - sprintf(tempstring,"Resolver: TTL: %s",strtdiff(sendstring,ttl)); - restell(tempstring); - } - if (usefulanswer) - switch (datatype) { - case T_A: - if (rdatalength != 4) { - sprintf(tempstring,"Resolver error: Unsupported rdata format for \"A\" type. (%u bytes)", - rdatalength); - restell(tempstring); - return; - } - if (memcmp(&rp->ip,(ip_t *)c,sizeof(ip_t))) { - sprintf(tempstring,"Resolver: Reverse authentication failed: %s != ", - strlongip(rp->ip)); - memcpy(&alignedip,(ip_t *)c,sizeof(ip_t)); - strcat(tempstring,strlongip(alignedip)); - restell(tempstring); - res_hostipmismatch++; - failrp(rp); - } else { - sprintf(tempstring,"Resolver: Reverse authentication complete: %s == \"%s\".", - strlongip(rp->ip),nonull(rp->hostname)); - restell(tempstring); - res_reversesuccess++; - passrp(rp,ttl); - return; - } - break; - case T_PTR: - case T_CNAME: - *namestring = '\0'; - r = dn_expand(s,s + l,c,namestring,MAXDNAME); - if (r == -1) { - restell("Resolver error: dn_expand() failed while expanding domain in rdata."); - return; - } - if (debug) { - sprintf(tempstring,"Resolver: Answered domain: \"%s\"",namestring); - restell(tempstring); - } - if (r > HostnameLength) { - restell("Resolver error: Domain name too long."); - failrp(rp); - return; - } - if (datatype == T_CNAME) { - strcpy(stackstring,namestring); - break; - } - if (!rp->hostname) { - rp->hostname = (char *)statmalloc(strlen(namestring) + 1); - if (!rp->hostname) { - fprintf(stderr,"statmalloc() error: %s\n",strerror(errno)); - exit(-1); - } - strcpy(rp->hostname,namestring); - linkresolvehost(rp); - passrp(rp,ttl); - res_iplookupsuccess++; - } - break; - default: - sprintf(tempstring,"Resolver error: Received unimplemented data type: %u (%s)", - datatype,datatype < ResourcetypeCount ? - resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); - restell(tempstring); - } - } else { - if (debug) { - sprintf(tempstring,"Resolver: Ignoring resource type %u. (%s)", - datatype,datatype < ResourcetypeCount ? - resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); - restell(tempstring); - } - } - c+= rdatalength; - } - } else - restell("Resolver error: No error returned but no answers given."); - break; - case NXDOMAIN: - if (debug) - restell("Resolver: Host not found."); - res_nxdomain++; - failrp(rp); - break; + classtypes[ClasstypeCount]); + restell(tempstring); + } + switch (qdatatype) { + case T_PTR: + if (!Is_PTR(rp)) + if (debug) { + restell("Resolver warning: Ignoring response with unexpected query type \"PTR\"."); + return; + } + break; default: - sprintf(tempstring,"Resolver: Received error response %u. (%s)", - getheader_rcode(hp),getheader_rcode(hp) < ResponsecodeCount ? - responsecodes[getheader_rcode(hp)] : responsecodes[ResponsecodeCount]); - restell(tempstring); - res_nserror++; - } + sprintf(tempstring,"Resolver error: Received unimplemented query type: %u (%s)", + qdatatype,qdatatype < ResourcetypeCount ? + resourcetypes[qdatatype] : resourcetypes[ResourcetypeCount]); + restell(tempstring); + } + for (rr = hp->ancount + hp->nscount + hp->arcount;rr;rr--) { + if (c > eob) { + restell("Resolver error: Packet does not contain all specified resouce records."); + return; + } + *namestring = '\0'; + r = dn_expand(s,s + l,c,namestring,MAXDNAME); + if (r == -1) { + restell("Resolver error: dn_expand() failed while expanding answer domain."); + return; + } + namestring[strlen(stackstring)] = '\0'; + if (strcasecmp(stackstring,namestring)) + usefulanswer = 0; + else + usefulanswer = 1; + if (debug) { + sprintf(tempstring,"Resolver: answered domain query: \"%s\"",namestring); + restell(tempstring); + } + c+= r; + if (c + 10 > eob) { + restell("Resolver error: Resource record truncated."); + return; + } + datatype = sucknetword(c); + class = sucknetword(c); + ttl = sucknetlong(c); + rdatalength = sucknetword(c); + if (class != qclass) { + sprintf(tempstring,"query class: %u (%s)",qclass,qclass < ClasstypeCount ? + classtypes[qclass] : classtypes[ClasstypeCount]); + restell(tempstring); + sprintf(tempstring,"rr class: %u (%s)",class,class < ClasstypeCount ? + classtypes[class] : classtypes[ClasstypeCount]); + restell(tempstring); + restell("Resolver error: Answered class does not match queried class."); + return; + } + if (!rdatalength) { + restell("Resolver error: Zero size rdata."); + return; + } + if (c + rdatalength > eob) { + restell("Resolver error: Specified rdata length exceeds packet size."); + return; + } + if (datatype == qdatatype || datatype == T_CNAME) { + if (debug) { + sprintf(tempstring,"Resolver: TTL: %s",strtdiff(sendstring,ttl)); + restell(tempstring); + } + if (usefulanswer) + switch (datatype) { + case T_A: + if (rdatalength != 4) { + sprintf(tempstring,"Resolver error: Unsupported rdata format for \"A\" type. (%u bytes)", + rdatalength); + restell(tempstring); + return; + } + if (memcmp(&rp->ip,(ip_t *)c,sizeof(ip_t))) { + sprintf(tempstring,"Resolver: Reverse authentication failed: %s != ", + strlongip(rp->ip)); + memcpy(&alignedip,(ip_t *)c,sizeof(ip_t)); + strcat(tempstring,strlongip(alignedip)); + restell(tempstring); + res_hostipmismatch++; + failrp(rp); + } else { + sprintf(tempstring,"Resolver: Reverse authentication complete: %s == \"%s\".", + strlongip(rp->ip),nonull(rp->hostname)); + restell(tempstring); + res_reversesuccess++; + passrp(rp,ttl); + return; + } + break; + case T_PTR: + case T_CNAME: + *namestring = '\0'; + r = dn_expand(s,s + l,c,namestring,MAXDNAME); + if (r == -1) { + restell("Resolver error: dn_expand() failed while expanding domain in rdata."); + return; + } + if (debug) { + sprintf(tempstring,"Resolver: Answered domain: \"%s\"",namestring); + restell(tempstring); + } + if (r > HostnameLength) { + restell("Resolver error: Domain name too long."); + failrp(rp); + return; + } + if (datatype == T_CNAME) { + strcpy(stackstring,namestring); + break; + } + if (!rp->hostname) { + rp->hostname = (char *)statmalloc(strlen(namestring) + 1); + if (!rp->hostname) { + fprintf(stderr,"statmalloc() error: %s\n",strerror(errno)); + exit(-1); + } + strcpy(rp->hostname,namestring); + linkresolvehost(rp); + passrp(rp,ttl); + res_iplookupsuccess++; + } + break; + default: + sprintf(tempstring,"Resolver error: Received unimplemented data type: %u (%s)", + datatype,datatype < ResourcetypeCount ? + resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); + restell(tempstring); + } + } else { + if (debug) { + sprintf(tempstring,"Resolver: Ignoring resource type %u. (%s)", + datatype,datatype < ResourcetypeCount ? + resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); + restell(tempstring); + } + } + c+= rdatalength; + } + } else + restell("Resolver error: No error returned but no answers given."); + break; + case NXDOMAIN: + if (debug) + restell("Resolver: Host not found."); + res_nxdomain++; + failrp(rp); + break; + default: + sprintf(tempstring,"Resolver: Received error response %u. (%s)", + getheader_rcode(hp),getheader_rcode(hp) < ResponsecodeCount ? + responsecodes[getheader_rcode(hp)] : responsecodes[ResponsecodeCount]); + restell(tempstring); + res_nserror++; + } } + void dns_ack(void) { - int r,i; - r = recvfrom(resfd,(byte *)resrecvbuf,MaxPacketsize,0,(struct sockaddr *)&from,&fromlen); - if (r > 0) { - /* Check to see if this server is actually one we sent to */ - if (from.sin_addr.s_addr == localhost) { - for (i = 0;i < _res.nscount;i++) - if ((_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr) || - (!_res.nsaddr_list[i].sin_addr.s_addr)) /* 0.0.0.0 replies as 127.0.0.1 */ - break; - } else - for (i = 0;i < _res.nscount;i++) - if (_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr) - break; - if (i == _res.nscount) { - sprintf(tempstring,"Resolver error: Received reply from unknown source: %s", - inet_ntoa(from.sin_addr)); - restell(tempstring); - } else - parserespacket((byte *)resrecvbuf,r); - } else { - sprintf(tempstring,"Resolver: Socket error: %s",strerror(errno)); + int r,i; + + r = recvfrom(resfd,(byte *)resrecvbuf,MaxPacketsize,0,(struct sockaddr *)&from,&fromlen); + if (r > 0) { + /* Check to see if this server is actually one we sent to */ + if (from.sin_addr.s_addr == localhost) { + for (i = 0;i < _res.nscount;i++) + if ((_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr) || + (!_res.nsaddr_list[i].sin_addr.s_addr)) /* 0.0.0.0 replies as 127.0.0.1 */ + break; + } else + for (i = 0;i < _res.nscount;i++) + if (_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr) + break; + if (i == _res.nscount) { + sprintf(tempstring,"Resolver error: Received reply from unknown source: %s", + inet_ntoa(from.sin_addr)); restell(tempstring); - } + } else + parserespacket((byte *)resrecvbuf,r); + } else { + sprintf(tempstring,"Resolver: Socket error: %s",strerror(errno)); + restell(tempstring); + } } + int istime(double x,double *sinterval) { if (x) { - if (x > sweeptime) { - if (*sinterval > x - sweeptime) - *sinterval = x - sweeptime; - } else - return 1; + if (x > sweeptime) { + if (*sinterval > x - sweeptime) + *sinterval = x - sweeptime; + } else + return 1; } return 0; } + void dns_events(double *sinterval) { - struct resolve *rp,*nextrp; - for (rp = expireresolves;(rp) && (sweeptime >= rp->expiretime);rp = nextrp) { - nextrp = rp->next; - switch (rp->state) { - case STATE_FINISHED: /* TTL has expired */ - case STATE_FAILED: /* Fake TTL has expired */ - if (debug) { - sprintf(tempstring,"Resolver: Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %g, time: %g.", + struct resolve *rp,*nextrp; + + for (rp = expireresolves;(rp) && (sweeptime >= rp->expiretime);rp = nextrp) { + nextrp = rp->next; + switch (rp->state) { + case STATE_FINISHED: /* TTL has expired */ + case STATE_FAILED: /* Fake TTL has expired */ + if (debug) { + sprintf(tempstring,"Resolver: Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %g, time: %g.", nonull(rp->hostname),strlongip(rp->ip),rp->state,rp->expiretime,sweeptime); - restell(tempstring); - } - unlinkresolve(rp); - break; - case STATE_PTRREQ1: /* First T_PTR send timed out */ - resendrequest(rp,T_PTR); - restell("Resolver: Send #2 for \"PTR\" query..."); - rp->state++; - rp->expiretime = sweeptime + ResRetryDelay2; - (void)istime(rp->expiretime,sinterval); - res_resend++; - break; - case STATE_PTRREQ2: /* Second T_PTR send timed out */ - resendrequest(rp,T_PTR); - restell("Resolver: Send #3 for \"PTR\" query..."); - rp->state++; - rp->expiretime = sweeptime + ResRetryDelay3; - (void)istime(rp->expiretime,sinterval); - res_resend++; - break; - case STATE_PTRREQ3: /* Third T_PTR timed out */ - restell("Resolver: \"PTR\" query timed out."); - failrp(rp); - (void)istime(rp->expiretime,sinterval); - res_timeout++; - break; + restell(tempstring); } - } - if (expireresolves) - (void)istime(expireresolves->expiretime,sinterval); + unlinkresolve(rp); + break; + case STATE_PTRREQ1: /* First T_PTR send timed out */ + resendrequest(rp,T_PTR); + restell("Resolver: Send #2 for \"PTR\" query..."); + rp->state++; + rp->expiretime = sweeptime + ResRetryDelay2; + (void)istime(rp->expiretime,sinterval); + res_resend++; + break; + case STATE_PTRREQ2: /* Second T_PTR send timed out */ + resendrequest(rp,T_PTR); + restell("Resolver: Send #3 for \"PTR\" query..."); + rp->state++; + rp->expiretime = sweeptime + ResRetryDelay3; + (void)istime(rp->expiretime,sinterval); + res_resend++; + break; + case STATE_PTRREQ3: /* Third T_PTR timed out */ + restell("Resolver: \"PTR\" query timed out."); + failrp(rp); + (void)istime(rp->expiretime,sinterval); + res_timeout++; + break; + } + } + if (expireresolves) + (void)istime(expireresolves->expiretime,sinterval); } + char *dns_lookup2(ip_t ip) { - struct resolve *rp; - ip = htonl(ip); - if ((rp = findip(ip))) { - if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) { - if ((rp->state == STATE_FINISHED) && (rp->hostname)) { - if (debug) { - sprintf(tempstring,"Resolver: Used cached record: %s == \"%s\".\n", - strlongip(ip),rp->hostname); - restell(tempstring); - } - return rp->hostname; - } else { - if (debug) { - sprintf(tempstring,"Resolver: Used failed record: %s == ???\n", - strlongip(ip)); - restell(tempstring); - } - return NULL; - } + struct resolve *rp; + + ip = htonl(ip); + if ((rp = findip(ip))) { + if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) { + if ((rp->state == STATE_FINISHED) && (rp->hostname)) { + if (debug) { + sprintf(tempstring,"Resolver: Used cached record: %s == \"%s\".\n", + strlongip(ip),rp->hostname); + restell(tempstring); + } + return rp->hostname; + } else { + if (debug) { + sprintf(tempstring,"Resolver: Used failed record: %s == ???\n", + strlongip(ip)); + restell(tempstring); + } + return NULL; } - return NULL; - } - if (debug) - fprintf(stderr,"Resolver: Added to new record.\n"); - rp = allocresolve(); - rp->state = STATE_PTRREQ1; - rp->expiretime = sweeptime + ResRetryDelay1; - rp->ip = ip; - linkresolve(rp); - rp->ip = ip; - linkresolveip(rp); - sendrequest(rp,T_PTR); - return NULL; + } + return NULL; + } + if (debug) + fprintf(stderr,"Resolver: Added to new record.\n"); + rp = allocresolve(); + rp->state = STATE_PTRREQ1; + rp->expiretime = sweeptime + ResRetryDelay1; + rp->ip = ip; + linkresolve(rp); + rp->ip = ip; + linkresolveip(rp); + sendrequest(rp,T_PTR); + return NULL; } -int use_dns = 1; char *dns_lookup(ip_t ip) { diff --git a/mtr.c b/mtr.c index fccfeca..c8af062 100644 --- a/mtr.c +++ b/mtr.c @@ -35,32 +35,6 @@ #include "net.h" -#ifndef HAVE_SETEUID -/* HPUX doesn't have seteuid, but setuid works fine in that case for us */ -#define seteuid setuid -#endif - -int DisplayMode; -int display_mode; -int Interactive = 1; -int PrintVersion = 0; -int PrintHelp = 0; -int MaxPing = 10; -int ForceMaxPing = 0; -float WaitTime = 1.0; -char *Hostname = NULL; -char *InterfaceAddress = NULL; -char LocalHostname[128]; -int dns = 1; -int packetsize = 64; /* default packet size */ -int bitpattern = 0; -int tos = 0; -/* begin ttl windows addByMin */ -int fstTTL = 1; /* default start at first hop */ -//int maxTTL = MaxHost-1; /* max you can go is 255 hops */ -int maxTTL = 30; /* inline with traceroute */ -/* end ttl */ - #ifdef ENABLE_IPV6 #define DEFAULT_AF AF_UNSPEC #else @@ -69,35 +43,58 @@ int maxTTL = 30; /* inline with traceroute */ #ifdef NO_HERROR -#define herror(str) printf(str ": error looking up \"%s\"\n", Hostname); +#define herror(str) fprintf(stderr, str ": error looking up \"%s\"\n", Hostname); #endif + +int DisplayMode; +int display_mode; +int Interactive = 1; +int PrintVersion = 0; +int PrintHelp = 0; +int MaxPing = 10; +int ForceMaxPing = 0; +float WaitTime = 1.0; +char *Hostname = NULL; +char *InterfaceAddress = NULL; +char LocalHostname[128]; +int dns = 1; +int packetsize = 64; /* default packet size */ +int bitpattern = 0; +int tos = 0; int af = DEFAULT_AF; + /* begin ttl windows addByMin */ +int fstTTL = 1; /* default start at first hop */ +//int maxTTL = MaxHost-1; /* max you can go is 255 hops */ +int maxTTL = 30; /* inline with traceroute */ + /* end ttl window stuff. */ + + /* default display field(defined by key in net.h) and order */ unsigned char fld_active[2*MAXFLD] = "LS NABWV"; -char fld_index[256]; -char available_options[MAXFLD]; +char fld_index[256]; +char available_options[MAXFLD]; struct fields data_fields[MAXFLD] = { /* key, Remark, Header, Format, Width, CallBackFunc */ - {' ', ": Space between fields", " ", " ", 1, &net_drop }, /* 0 */ - {'L', "L: Loss Ratio", "Loss%", " %4.1f%%", 6, &net_loss }, /* 1 */ - {'D', "D: Dropped Packets", "Drop", " %4d", 5, &net_drop }, /* 2 */ - {'R', "R: Received Packets", "Rcv", " %5d", 6, &net_returned}, /* 3 */ - {'S', "S: Sent Packets", "Snt", " %5d", 6, &net_xmit }, /* 4 */ - {'N', "N: Newest RTT(ms)", "Last", " %5.1f", 6, &net_last }, /* 5 */ - {'B', "B: Min/Best RTT(ms)", "Best", " %5.1f", 6, &net_best }, /* 6 */ - {'A', "A: Average RTT(ms)", "Avg", " %5.1f", 6, &net_avg }, /* 7 */ - {'W', "W: Max/Worst RTT(ms)", "Wrst", " %5.1f", 6, &net_worst }, /* 8 */ - {'V', "V: Standard Deviation", "StDev", " %5.1f", 6, &net_stdev }, /* 9 */ - {'G', "G: Geometric Mean", "Gmean", " %5.1f", 6, &net_gmean }, /* 10 */ - {'J', "J: Current Jitter", "Jttr", " %4.1f", 5, &net_jitter}, /* 11 */ - {'M', "M: Jitter Mean/Avg.", "Javg", " %4.1f", 5, &net_javg }, /* 12 */ - {'X', "X: Worst Jitter", "Jmax", " %4.1f", 5, &net_jworst}, /* 13 */ - {'I', "I: Interarrival Jitter", "Jint", " %4.1f", 5, &net_jinta }, /* 14 */ - {'\0', 0, 0, 0, 0, 0 } + {' ', ": Space between fields", " ", " ", 1, &net_drop }, + {'L', "L: Loss Ratio", "Loss%", " %4.1f%%", 6, &net_loss }, + {'D', "D: Dropped Packets", "Drop", " %4d", 5, &net_drop }, + {'R', "R: Received Packets", "Rcv", " %5d", 6, &net_returned}, + {'S', "S: Sent Packets", "Snt", " %5d", 6, &net_xmit }, + {'N', "N: Newest RTT(ms)", "Last", " %5.1f", 6, &net_last }, + {'B', "B: Min/Best RTT(ms)", "Best", " %5.1f", 6, &net_best }, + {'A', "A: Average RTT(ms)", "Avg", " %5.1f", 6, &net_avg }, + {'W', "W: Max/Worst RTT(ms)", "Wrst", " %5.1f", 6, &net_worst }, + {'V', "V: Standard Deviation", "StDev", " %5.1f", 6, &net_stdev }, + {'G', "G: Geometric Mean", "Gmean", " %5.1f", 6, &net_gmean }, + {'J', "J: Current Jitter", "Jttr", " %4.1f", 5, &net_jitter}, + {'M', "M: Jitter Mean/Avg.", "Javg", " %4.1f", 5, &net_javg }, + {'X', "X: Worst Jitter", "Jmax", " %4.1f", 5, &net_jworst}, + {'I', "I: Interarrival Jitter", "Jint", " %4.1f", 5, &net_jinta }, + {'\0', NULL, NULL, NULL, 0, NULL} }; @@ -116,7 +113,7 @@ void init_fld_options (void) } -void parse_arg(int argc, char **argv) +void parse_arg (int argc, char **argv) { int opt; int i; @@ -188,9 +185,9 @@ void parse_arg(int argc, char **argv) break; case 's': packetsize = atoi (optarg); - if( packetsize >=0 ) { - if ( packetsize < MINPACKET ) packetsize = MINPACKET; - if ( packetsize > MAXPACKET ) packetsize = MAXPACKET; + if (packetsize >=0) { + if (packetsize < MINPACKET) packetsize = MINPACKET; + if (packetsize > MAXPACKET) packetsize = MAXPACKET; } break; case 'a': @@ -210,19 +207,19 @@ void parse_arg(int argc, char **argv) break; case 'f': fstTTL = atoi (optarg); - if( fstTTL > maxTTL ) { + if (fstTTL > maxTTL) { fstTTL = maxTTL; } - if( fstTTL < 1) { /* prevent 0 hop */ + if (fstTTL < 1) { /* prevent 0 hop */ fstTTL = 1; } break; case 'm': maxTTL = atoi (optarg); - if( maxTTL > (MaxHost - 1) ) { + if (maxTTL > (MaxHost - 1)) { maxTTL = MaxHost-1; } - if( maxTTL < 1) { /* prevent 0 hop */ + if (maxTTL < 1) { /* prevent 0 hop */ maxTTL = 1; } if (fstTTL > maxTTL) { /* don't know the pos of -m or -f */ @@ -236,7 +233,7 @@ void parse_arg(int argc, char **argv) exit (1); } for (i=0; optarg[i]; i++) { - if(!strchr(available_options, optarg[i])) { + if(!strchr (available_options, optarg[i])) { fprintf (stderr, "Unknown field identifier: %c\n", optarg[i]); exit (1); } @@ -245,12 +242,12 @@ void parse_arg(int argc, char **argv) break; case 'b': bitpattern = atoi (optarg); - if( bitpattern > 255 ) + if (bitpattern > 255) bitpattern = -1; break; case 'Q': tos = atoi (optarg); - if( tos > 255 || tos <0 ) { + if (tos > 255 || tos < 0) { /* error message, should do more checking for valid values, * details in rfc2474 */ tos = 0; @@ -258,24 +255,24 @@ void parse_arg(int argc, char **argv) break; } } - - if(DisplayMode == DisplayReport || - DisplayMode == DisplayTXT || - DisplayMode == DisplayXML || - DisplayMode == DisplayRaw || - DisplayMode == DisplayCSV ) + + if (DisplayMode == DisplayReport || + DisplayMode == DisplayTXT || + DisplayMode == DisplayXML || + DisplayMode == DisplayRaw || + DisplayMode == DisplayCSV) Interactive = 0; - if(optind > argc - 1) + if (optind > argc - 1) return; Hostname = argv[optind++]; if (argc > optind) { - packetsize = atoi(argv[optind]); - if( packetsize >=0 ) { - if ( packetsize < MINPACKET ) packetsize = MINPACKET; - if ( packetsize > MAXPACKET ) packetsize = MAXPACKET; + packetsize = atoi (argv[optind]); + if (packetsize >=0 ) { + if (packetsize < MINPACKET) packetsize = MINPACKET; + if (packetsize > MAXPACKET) packetsize = MAXPACKET; } } } @@ -304,7 +301,8 @@ void parse_mtr_options (char *string) } -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ int traddr; struct hostent * host = NULL; int net_preopen_result; @@ -314,19 +312,19 @@ int main(int argc, char **argv) { net_preopen_result = net_preopen (); /* Now drop to user permissions */ - if(setuid(getuid())) { - printf("mtr: Unable to drop permissions.\n"); + if (setuid(getuid())) { + fprintf (stderr, "mtr: Unable to drop permissions.\n"); exit(1); } /* Double check, just in case */ - if(geteuid() != getuid()) { - printf("mtr: Unable to drop permissions.\n"); + if (geteuid() != getuid()) { + fprintf (stderr, "mtr: Unable to drop permissions.\n"); exit(1); } /* reset the random seed */ - srand(getpid()); + srand (getpid()); display_detect(&argc, &argv); @@ -336,14 +334,14 @@ int main(int argc, char **argv) { parse_mtr_options (getenv ("MTR_OPTIONS")); - parse_arg(argc, argv); + parse_arg (argc, argv); - if(PrintVersion) { - printf("mtr " VERSION "\n"); + if (PrintVersion) { + printf ("mtr " VERSION "\n"); exit(0); } - if(PrintHelp) { + if (PrintHelp) { printf("usage: %s [-hvrctglsni] [--help] [--version] [--report]\n" "\t\t[--report-cycles=COUNT] [--curses] [--gtk]\n" "\t\t[--raw] [--split] [--no-dns] [--address interface]\n" /* BL */ @@ -351,44 +349,22 @@ int main(int argc, char **argv) { "\t\t[--interval=SECONDS] HOSTNAME [PACKETSIZE]\n", argv[0]); exit(0); } + if (Hostname == NULL) Hostname = "localhost"; - if(gethostname(LocalHostname, sizeof(LocalHostname))) { + if (gethostname(LocalHostname, sizeof(LocalHostname))) { strcpy(LocalHostname, "UNKNOWNHOST"); } - if(net_preopen_result != 0) { - printf("mtr: Unable to get raw socket. (Executable not suid?)\n"); + if (net_preopen_result != 0) { + fprintf(stderr, "mtr: Unable to get raw socket. (Executable not suid?)\n"); exit(1); } - - if (InterfaceAddress) { /* Mostly borrowed from ping(1) code */ - int i1, i2, i3, i4; - char dummy; - extern int sendsock; /* from net.c:118 */ - extern struct sockaddr_in sourceaddress; /* from net.c:120 */ - - sourceaddress.sin_family = AF_INET; - sourceaddress.sin_port = 0; - sourceaddress.sin_addr.s_addr = 0; - - if(sscanf(InterfaceAddress, "%u.%u.%u.%u%c", &i1, &i2, &i3, &i4, &dummy) != 4) { - printf("mtr: bad interface address: %s\n", InterfaceAddress); - exit(1); - } else { - unsigned char *ptr; - ptr = (unsigned char*)&sourceaddress.sin_addr; - ptr[0] = i1; - ptr[1] = i2; - ptr[2] = i3; - ptr[3] = i4; - } - - if(bind(sendsock, (struct sockaddr*)&sourceaddress, sizeof(sourceaddress)) == -1) { - perror("mtr: failed to bind to interface"); - exit(1); - } + + if (net_set_interfaceaddress (InterfaceAddress) != 0) { + fprintf (stderr, "mtr: Couldn't set interface addres.\n"); + exit (1); } #ifdef ENABLE_IPV6 @@ -403,24 +379,17 @@ int main(int argc, char **argv) { host = gethostbyname2(Hostname, af); } - if(host == NULL) { + if (host == NULL) { herror("mtr"); exit(1); } - traddr = *(int *)host->h_addr; - - if(net_open(traddr) != 0) { - printf("mtr: Unable to get raw socket. (Executable not suid?)\n"); - exit(1); - } - switch (af) { case AF_INET: traddr = *(int *)host->h_addr; - if(net_open(traddr) != 0) { - printf("mtr: Unable to get raw socket. (Executable not suid?)\n"); + if (net_open(traddr) != 0) { + fprintf(stderr, "mtr: Unable to start net module.\n"); exit(1); } break; diff --git a/net.c b/net.c index f7f5380..6abbde1 100644 --- a/net.c +++ b/net.c @@ -41,8 +41,6 @@ #include "display.h" -#define MaxTransit 4 - /* We can't rely on header files to provide this information, because the fields have different names between, for instance, Linux and Solaris */ @@ -54,6 +52,7 @@ struct ICMPHeader { uint16 sequence; }; + /* Structure of an IP header. */ struct IPHeader { uint8 version; @@ -68,6 +67,7 @@ struct IPHeader { uint32 daddr; }; + #define ICMP_ECHO 8 #define ICMP_ECHOREPLY 0 @@ -80,8 +80,6 @@ struct IPHeader { #define SOL_IP 0 #endif -#define saddr_correction(addr) BSDfix ? addr : 0 - struct nethost { uint32 addr; uint32 addrs[MAXPATH]; /* for multi paths byMin */ @@ -105,32 +103,41 @@ struct nethost { int saved_seq_offset; }; + struct sequence { - int index; - int transit; - int saved_seq; - struct timeval time; + int index; + int transit; + int saved_seq; + struct timeval time; }; /* Configuration parameter: How many queries to unknown hosts do we send? (This limits the amount of traffic generated if a host is not - reachable) */ + reachable) -- REW */ #define MAX_UNKNOWN_HOSTS 5 +/* There is something stupid with BSD. We now detect this automatically */ +static int BSDfix = 0; +#define saddr_correction(addr) BSDfix ? addr : 0 + static struct nethost host[MaxHost]; static struct sequence sequence[MaxSequence]; static struct timeval reset = { 0, 0 }; -int timestamp; -int sendsock; -int recvsock; +int timestamp; +int sendsock; +int recvsock; struct sockaddr_in sourceaddress; struct sockaddr_in remoteaddress; +/* XXX How do I code this to be IPV6 compatible??? -- REW */ +struct in_addr localaddr; + static int batch_at = 0; static int numhosts = 10; + extern int fstTTL; /* initial hub(ttl) to ping byMin */ extern int maxTTL; /* last hub to ping byMin*/ extern int packetsize; /* packet size used by ping */ @@ -138,6 +145,7 @@ extern int bitpattern; /* packet bit pattern used by ping */ extern int tos; /* type of service set in ping packet*/ + /* return the number of microseconds to wait before sending the next ping */ int calc_deltatime (float waittime) @@ -149,14 +157,15 @@ int calc_deltatime (float waittime) /* This doesn't work for odd sz. I don't know enough about this to say that this is wrong. It doesn't seem to cripple mtr though. -- REW */ -int checksum(void *data, int sz) { +int checksum(void *data, int sz) +{ unsigned short *ch; unsigned int sum; sum = 0; ch = data; sz = sz / 2; - while(sz--) { + while (sz--) { sum += *(ch++); } @@ -166,14 +175,13 @@ int checksum(void *data, int sz) { } -static int BSDfix = 0; - -int new_sequence(int index) { +int new_sequence(int index) +{ static int next_sequence = 0; int seq; seq = next_sequence++; - if(next_sequence >= MaxSequence) + if (next_sequence >= MaxSequence) next_sequence = 0; sequence[seq].index = index; @@ -190,6 +198,7 @@ int new_sequence(int index) { return seq; } + /* Attempt to find the host at a particular number of hops away */ void net_send_query(int index) { @@ -247,19 +256,21 @@ void net_send_query(int index) first = 0; } + /* We got a return on something we sent out. Record the address and time. */ -void net_process_ping(int seq, uint32 addr, struct timeval now) { +void net_process_ping(int seq, uint32 addr, struct timeval now) +{ int index; int totusec; int oldavg; /* usedByMin */ int oldjavg; /* usedByMin */ int i; /* usedByMin */ - if(seq < 0 || seq >= MaxSequence) + if (seq < 0 || seq >= MaxSequence) return; - if(!sequence[seq].transit) + if (!sequence[seq].transit) return; sequence[seq].transit = 0; @@ -269,7 +280,7 @@ void net_process_ping(int seq, uint32 addr, struct timeval now) { (now.tv_usec - sequence[seq].time.tv_usec); /* impossible? if( totusec < 0 ) totusec = 0 */; - if(host[index].addr == 0) { + if (host[index].addr == 0) { host[index].addr = addr; // should be out of if as addr can change display_rawhost(index, host[index].addr); @@ -287,10 +298,10 @@ void net_process_ping(int seq, uint32 addr, struct timeval now) { } host[index].jitter = totusec - host[index].last; - if( host[index].jitter < 0 ) host[index].jitter = - host[index].jitter; + if (host[index].jitter < 0 ) host[index].jitter = - host[index].jitter; host[index].last = totusec; - if(host[index].returned < 1) { + if (host[index].returned < 1) { host[index].best = host[index].worst = host[index].gmean = totusec; host[index].avg = host[index].var = 0; @@ -302,17 +313,17 @@ void net_process_ping(int seq, uint32 addr, struct timeval now) { * safe guard 1) best[index]>=best[index-1] if index>0 * 2) best >= average-20,000 usec (good number?) * Min - if( index > 0 ) { - if(totusec < host[index].best && - totusec>= host[index-1].best ) host[index].best = totusec; + if (index > 0) { + if (totusec < host[index].best && + totusec>= host[index-1].best) host[index].best = totusec; } else { - if(totusec < host[index].best ) host[index].best = totusec; + if(totusec < host[index].best) host[index].best = totusec; } */ - if(totusec < host[index].best ) host[index].best = totusec; - if(totusec > host[index].worst) host[index].worst = totusec; + if (totusec < host[index].best ) host[index].best = totusec; + if (totusec > host[index].worst) host[index].worst = totusec; - if(host[index].jitter > host[index].jworst) + if (host[index].jitter > host[index].jworst) host[index].jworst = host[index].jitter; host[index].returned++; @@ -338,10 +349,12 @@ void net_process_ping(int seq, uint32 addr, struct timeval now) { display_rawping(index, totusec); } + /* We know a packet has come in, because the main select loop has called us, now we just need to read it, see if it is for us, and if it is a reply to something we sent, then call net_process_ping() */ -void net_process_return() { +void net_process_return() +{ char packet[MAXPACKET]; struct sockaddr_in fromaddr; int fromaddrsize; @@ -378,9 +391,12 @@ void net_process_return() { } } + int net_addr(int at) { return ntohl(host[at].addr); } + + int net_addrs(int at, int i) { return ntohl(host[at].addrs[i]); } @@ -389,39 +405,49 @@ int net_addrs(int at, int i) { int net_loss(int at) { - if((host[at].xmit - host[at].transit) == 0) return 0; + if ((host[at].xmit - host[at].transit) == 0) + return 0; /* times extra 1000 */ return 1000*(100 - (100.0 * host[at].returned / (host[at].xmit - host[at].transit)) ); } + int net_drop(int at) { return (host[at].xmit - host[at].transit) - host[at].returned; } + int net_last(int at) { return (host[at].last); } + int net_best(int at) { return (host[at].best); } + int net_worst(int at) { return (host[at].worst); } + int net_avg(int at) { return (host[at].avg); } + + int net_gmean(int at) { return (host[at].gmean); } + + int net_stdev(int at) { if( host[at].returned > 1 ) { @@ -430,11 +456,31 @@ int net_stdev(int at) return( 0 ); } } + + /* jitter stuff */ -int net_jitter(int at) { return (host[at].jitter); } -int net_jworst(int at) { return (host[at].jworst); } -int net_javg(int at) { return (host[at].javg); } -int net_jinta(int at) { return (host[at].jinta); } +int net_jitter(int at) +{ + return (host[at].jitter); +} + + +int net_jworst(int at) +{ + return (host[at].jworst); +} + + +int net_javg(int at) +{ + return (host[at].javg); +} + + +int net_jinta(int at) +{ + return (host[at].jinta); +} /* end jitter */ @@ -457,6 +503,7 @@ int net_max() return max; } + /* add by Min (wonder its named net_min;-)) because of ttl stuff */ int net_min () { @@ -469,21 +516,32 @@ int net_returned(int at) { return host[at].returned; } + + int net_xmit(int at) { return host[at].xmit; } + int net_transit(int at) { return host[at].transit; } + int net_up(int at) { return host[at].up; } + +struct in_addr *net_localaddr (void) +{ + return &localaddr; +} + + void net_end_transit() { int at; @@ -494,7 +552,6 @@ void net_end_transit() } - int net_send_batch() { int n_unknown=0, i; @@ -542,36 +599,47 @@ int net_preopen() int trueopt = 1; sendsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - if(sendsock < 0) + if (sendsock < 0) return -1; #ifdef IP_HDRINCL /* FreeBSD wants this to avoid sending out packets with protocol type RAW to the network. */ - if(setsockopt(sendsock, SOL_IP, IP_HDRINCL, &trueopt, sizeof(trueopt))) - { + if (setsockopt(sendsock, SOL_IP, IP_HDRINCL, &trueopt, sizeof(trueopt))) { perror("setsockopt(IP_HDRINCL,1)"); return -1; } #endif recvsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); - if(recvsock < 0) + if (recvsock < 0) return -1; return 0; } + int net_open(int addr) { + struct sockaddr_in name; + int len; + net_reset(); remoteaddress.sin_family = AF_INET; remoteaddress.sin_addr.s_addr = addr; + len = sizeof (name); + getsockname (recvsock, (struct sockaddr *)&name, &len); + localaddr = name.sin_addr; +#if 0 + printf ("got localaddr: %x\n", *(int *)&localaddr); +#endif + return 0; } + void net_reopen(int addr) { int at; @@ -587,6 +655,7 @@ void net_reopen(int addr) net_send_batch(); } + void net_reset() { int at; @@ -595,7 +664,7 @@ void net_reset() batch_at = fstTTL - 1; /* above replacedByMin */ numhosts = 10; - for(at = 0; at < MaxHost; at++) { + for (at = 0; at < MaxHost; at++) { host[at].xmit = 0; host[at].transit = 0; host[at].returned = 0; @@ -617,19 +686,51 @@ void net_reset() host[at].saved_seq_offset = -SAVED_PINGS+2; } - for(at = 0; at < MaxSequence; at++) { + for (at = 0; at < MaxSequence; at++) { sequence[at].transit = 0; } gettimeofday(&reset, NULL); } + +int net_set_interfaceaddress (char *InterfaceAddress) +{ + int i1, i2, i3, i4; + char dummy; + + if (!InterfaceAddress) return 0; + + sourceaddress.sin_family = AF_INET; + sourceaddress.sin_port = 0; + sourceaddress.sin_addr.s_addr = 0; + + if(sscanf(InterfaceAddress, "%u.%u.%u.%u%c", &i1, &i2, &i3, &i4, &dummy) != 4) { + printf("mtr: bad interface address: %s\n", InterfaceAddress); + exit(1); + } + + ((unsigned char*)&sourceaddress.sin_addr)[0] = i1; + ((unsigned char*)&sourceaddress.sin_addr)[1] = i2; + ((unsigned char*)&sourceaddress.sin_addr)[2] = i3; + ((unsigned char*)&sourceaddress.sin_addr)[3] = i4; + + if(bind(sendsock, (struct sockaddr*)&sourceaddress, sizeof(sourceaddress)) == -1) { + perror("mtr: failed to bind to interface"); + exit(1); + } + return 0; +} + + + void net_close() { close(sendsock); close(recvsock); } + int net_waitfd() { return recvsock; @@ -641,6 +742,7 @@ int* net_saved_pings(int at) return host[at].saved; } + void net_save_increment() { int at; @@ -651,6 +753,7 @@ void net_save_increment() } } + void net_save_xmit(int at) { if (host[at].saved[SAVED_PINGS-1] != -2) @@ -658,6 +761,7 @@ void net_save_xmit(int at) host[at].saved[SAVED_PINGS-1] = -1; } + void net_save_return(int at, int seq, int ms) { int idx; diff --git a/net.h b/net.h index f4a0060..621b06a 100644 --- a/net.h +++ b/net.h @@ -22,6 +22,7 @@ int net_preopen(); int net_open(int address); void net_reopen(int address); +int net_set_interfaceaddress (char *InterfaceAddress); void net_reset(); void net_close(); int net_waitfd(); @@ -44,7 +45,7 @@ int net_jworst(int at); int net_javg(int at); int net_jinta(int at); int net_addrs(int at, int i); - +struct in_addr *net_localaddr(void); int net_send_batch(); void net_end_transit();