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
This commit is contained in:
Roger Wolff 2004-08-11 00:00:00 +00:00 committed by Travis Cross
parent 5536e69f6f
commit 3adcb265b5
7 changed files with 1050 additions and 908 deletions

6
NEWS
View File

@ -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)

View File

@ -1,5 +1,5 @@
AC_INIT(mtr.c)
AM_INIT_AUTOMAKE(mtr, 0.60)
AM_INIT_AUTOMAKE(mtr, 0.61)
AC_SUBST(GTK_OBJ)

View File

@ -23,6 +23,9 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#if defined(HAVE_NCURSES_H)
# include <ncurses.h>
@ -472,6 +475,7 @@ void mtr_curses_redraw()
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)));

66
dns.c
View File

@ -280,9 +280,10 @@ char stackstring[1024+1];
char nullstring[] = "";
int use_dns = 1;
/* Code */
#ifdef CorruptCheck
#define TOT_SLACK 2
#define HEAD_SLACK 1
@ -303,6 +304,7 @@ void *statmalloc(size_t size)
{
void *p;
size_t mallocsize;
mem+= size;
mallocsize = size + TOT_SLACK * sizeof(dword);
@ -325,6 +327,7 @@ void *statmalloc(size_t size)
return p;
}
void statfree(void *p)
{
if (p) {
@ -334,7 +337,7 @@ void statfree(void *p)
exit(-1);
} else {
if (*((dword *)p - HEAD_SLACK) > 8192) {
fprintf(stderr,"ERROR: Corrupted free() buffer. (header)\n");
fprintf (stderr,"ERROR: Corrupted free() buffer. (header)\n");
*(int*)0=0;
exit(-1);
}
@ -358,11 +361,13 @@ void statfree(void *p)
}
}
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;
@ -383,26 +388,31 @@ char *strtdiff(char *d,long signeddiff)
return d;
}
int issetfd(fd_set *set,int fd)
{
return (int)((FD_ISSET(fd,set)) && 1);
}
void setfd(fd_set *set,int fd)
{
FD_SET(fd,set);
}
void clearfd(fd_set *set,int fd)
{
FD_CLR(fd,set);
}
void clearset(fd_set *set)
{
FD_ZERO(set);
}
char *strlongip(ip_t ip)
{
struct in_addr a;
@ -410,25 +420,30 @@ char *strlongip(ip_t ip)
return inet_ntoa(a);
}
ip_t longipstr(char *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;
}
int dns_waitfd(void)
{
return resfd;
}
void dns_open(void)
{
int option,i;
@ -461,9 +476,11 @@ void dns_open(void)
}
}
struct resolve *allocresolve(void)
{
struct resolve *rp;
rp = (struct resolve *)statmalloc(sizeof(struct resolve));
if (!rp) {
fprintf(stderr,"statmalloc() failed: %s\n",strerror(errno));
@ -473,19 +490,23 @@ struct resolve *allocresolve(void)
return rp;
}
dword getidbash(word id)
{
return (dword)BashModulo(id);
}
dword getipbash(ip_t ip)
{
return (dword)BashModulo(ip);
}
dword gethostbash(char *host)
{
dword bashvalue = 0;
for (;*host;host++) {
bashvalue^= *host;
bashvalue+= (*host >> 1) + (bashvalue >> 1);
@ -493,10 +514,12 @@ dword gethostbash(char *host)
return BashModulo(bashvalue);
}
void linkresolveid(struct resolve *addrp)
{
struct resolve *rp;
dword bashnum;
bashnum = getidbash(addrp->id);
rp = idbash[bashnum];
if (rp) {
@ -522,9 +545,11 @@ void linkresolveid(struct resolve *addrp)
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;
@ -534,10 +559,12 @@ void unlinkresolveid(struct resolve *rp)
rp->previousid->nextid = rp->nextid;
}
void linkresolvehost(struct resolve *addrp)
{
struct resolve *rp;
dword bashnum;
bashnum = gethostbash(addrp->hostname);
rp = hostbash[bashnum];
if (rp) {
@ -563,9 +590,11 @@ void linkresolvehost(struct resolve *addrp)
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;
@ -576,10 +605,12 @@ void unlinkresolvehost(struct resolve *rp)
statfree(rp->hostname);
}
void linkresolveip(struct resolve *addrp)
{
struct resolve *rp;
dword bashnum;
bashnum = getipbash(addrp->ip);
rp = ipbash[bashnum];
if (rp) {
@ -605,9 +636,11 @@ void linkresolveip(struct resolve *addrp)
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;
@ -617,9 +650,11 @@ void unlinkresolveip(struct resolve *rp)
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;
@ -645,9 +680,11 @@ void linkresolve(struct resolve *rp)
resolvecount++;
}
void lastlinkresolve(struct resolve *rp)
{
struct resolve *irp;
if (lastresolve) {
irp = lastresolve;
while ((irp->previous) && (rp->expiretime < irp->expiretime)) irp = irp->previous;
@ -674,6 +711,7 @@ void lastlinkresolve(struct resolve *rp)
resolvecount++;
}
void untieresolve(struct resolve *rp)
{
if (rp->previous)
@ -687,6 +725,7 @@ void untieresolve(struct resolve *rp)
resolvecount--;
}
void unlinkresolve(struct resolve *rp)
{
untieresolve(rp);
@ -696,10 +735,12 @@ void unlinkresolve(struct resolve *rp)
unlinkresolvehost(rp);
}
struct resolve *findid(word id)
{
struct resolve *rp;
int bashnum;
bashnum = getidbash(id);
rp = idbash[bashnum];
if (rp) {
@ -716,10 +757,12 @@ struct resolve *findid(word id)
return rp; /* NULL */
}
struct resolve *findhost(char *hostname)
{
struct resolve *rp;
int bashnum;
bashnum = gethostbash(hostname);
rp = hostbash[bashnum];
if (rp) {
@ -737,10 +780,12 @@ struct resolve *findhost(char *hostname)
return rp; /* NULL */
}
struct resolve *findip(ip_t ip)
{
struct resolve *rp;
dword bashnum;
bashnum = getipbash(ip);
rp = ipbash[bashnum];
if (rp) {
@ -757,17 +802,20 @@ struct resolve *findip(ip_t ip)
return rp; /* NULL */
}
void restell(char *s)
{
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.");
@ -815,6 +863,7 @@ void sendrequest(struct resolve *rp,int type)
resendrequest(rp,type);
}
void failrp(struct resolve *rp)
{
if (rp->state == STATE_FINISHED)
@ -825,6 +874,7 @@ void failrp(struct resolve *rp)
restell("Resolver: Lookup failed.\n");
}
void passrp(struct resolve *rp,long ttl)
{
rp->state = STATE_FINISHED;
@ -836,6 +886,7 @@ void passrp(struct resolve *rp,long ttl)
}
}
void parserespacket(byte *s,int l)
{
struct resolve *rp;
@ -846,6 +897,7 @@ void parserespacket(byte *s,int l)
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;
@ -1100,9 +1152,11 @@ void parserespacket(byte *s,int l)
}
}
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 */
@ -1127,6 +1181,7 @@ void dns_ack(void)
}
}
int istime(double x,double *sinterval)
{
if (x) {
@ -1139,9 +1194,11 @@ int istime(double x,double *sinterval)
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) {
@ -1182,9 +1239,11 @@ void dns_events(double *sinterval)
(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)) {
@ -1219,7 +1278,6 @@ char *dns_lookup2(ip_t ip)
return NULL;
}
int use_dns = 1;
char *dns_lookup(ip_t ip)
{

169
mtr.c
View File

@ -35,11 +35,18 @@
#include "net.h"
#ifndef HAVE_SETEUID
/* HPUX doesn't have seteuid, but setuid works fine in that case for us */
#define seteuid setuid
#ifdef ENABLE_IPV6
#define DEFAULT_AF AF_UNSPEC
#else
#define DEFAULT_AF AF_INET
#endif
#ifdef NO_HERROR
#define herror(str) fprintf(stderr, str ": error looking up \"%s\"\n", Hostname);
#endif
int DisplayMode;
int display_mode;
int Interactive = 1;
@ -55,24 +62,14 @@ int dns = 1;
int packetsize = 64; /* default packet size */
int bitpattern = 0;
int tos = 0;
/* begin ttl windows addByMin */
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 */
/* end ttl window stuff. */
#ifdef ENABLE_IPV6
#define DEFAULT_AF AF_UNSPEC
#else
#define DEFAULT_AF AF_INET
#endif
#ifdef NO_HERROR
#define herror(str) printf(str ": error looking up \"%s\"\n", Hostname);
#endif
int af = DEFAULT_AF;
/* default display field(defined by key in net.h) and order */
unsigned char fld_active[2*MAXFLD] = "LS NABWV";
@ -82,22 +79,22 @@ char available_options[MAXFLD];
struct fields data_fields[MAXFLD] = {
/* key, Remark, Header, Format, Width, CallBackFunc */
{' ', "<sp>: 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 }
{' ', "<sp>: 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;
@ -259,23 +256,23 @@ void parse_arg(int argc, char **argv)
}
}
if(DisplayMode == DisplayReport ||
if (DisplayMode == DisplayReport ||
DisplayMode == DisplayTXT ||
DisplayMode == DisplayXML ||
DisplayMode == DisplayRaw ||
DisplayMode == DisplayCSV )
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;

178
net.c
View File

@ -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,6 +103,7 @@ struct nethost {
int saved_seq_offset;
};
struct sequence {
int index;
int transit;
@ -115,10 +114,14 @@ struct sequence {
/* 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 };
@ -129,8 +132,12 @@ 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;

3
net.h
View File

@ -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();