From 433bf6c22ce90e25f3ffb0b4852631e5724ac608 Mon Sep 17 00:00:00 2001 From: Roger Wolff Date: Sat, 3 Apr 1999 00:00:00 +0000 Subject: [PATCH] mtr v0.34 - Added Matt's nifty "use the icmp unreachables to do the timing" patch. - Added Steve Kann's pause/resume patch. source: ftp://ftp.bitwizard.nl/mtr/mtr-0.34.tar.gz --- AUTHORS | 1 + Makefile.am | 1 + NEWS | 3 + TODO | 5 -- configure.in | 7 +- curses.c | 4 + display.c | 8 ++ display.h | 3 +- gtk.c | 1 + net.c | 216 ++++++++++++++++++--------------------------------- net.h | 1 + select.c | 14 +++- 12 files changed, 112 insertions(+), 152 deletions(-) diff --git a/AUTHORS b/AUTHORS index 531be36..f771b61 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,6 +24,7 @@ Adam Kramer (l3zqc@qcunix1.acc.qc.edu), Simon Kirby, Christophe Kalt, + Steve Kann (stevek@spheara.horizonlive.com), Mircea Damian, Brian Casey, diff --git a/Makefile.am b/Makefile.am index b6b3032..59cd031 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,6 +24,7 @@ mtr_LDFLAGS = $(GTK_OBJ) $(CURSES_OBJ) EXTRA_DIST = SECURITY mtr.8 Makefile Makefile.dist distclean-local: cp Makefile.dist Makefile + rm -f *.orig DISTCLEANFILES = *~ diff --git a/NEWS b/NEWS index c8150be..a357c7a 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ WHAT'S NEW? + v0.34 Added Matt's nifty "use the icmp unreachables to do the timing" patch. + Added Steve Kann's pause/resume patch. + v0.33 Fixed the Linux glibc resolver problems. Fixed the off-by-one problem with -c option. diff --git a/TODO b/TODO index e95455e..e7374f6 100644 --- a/TODO +++ b/TODO @@ -17,11 +17,6 @@ (Anybody have the statistics experience to tell me how to do the data analysis?) - - Allow MTR to keep on getting the icmp host unreachables, and - work through that. Some hosts don't answer PINGs. - - Auto-switch to that strategy if "host is known, but 10/10 - pings got lost" - - The "don't probe all hosts at once" strategy can be improved a bit. It should not probe more than 10 unknown hosts, but the counter need not be reset at the start of the "round". This way if you probe diff --git a/configure.in b/configure.in index 8b369a2..fe8e208 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ AC_INIT(mtr.c) -AM_INIT_AUTOMAKE(mtr, 0.33) +AM_INIT_AUTOMAKE(mtr, 0.34) AC_SUBST(GTK_OBJ) AC_SUBST(CURSES_OBJ) @@ -14,12 +14,17 @@ AC_CHECK_SIZEOF(unsigned short, 2) AC_CHECK_SIZEOF(unsigned int, 4) AC_CHECK_SIZEOF(unsigned long, 4) +# Some doc I found somewhere. :-) -- REW +# - Macro: AC_CHECK_FUNC (FUNCTION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +# - Macro: AC_CHECK_LIB (LIBRARY, FUNCTION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]]) + AC_CHECK_FUNC(initscr, , AC_CHECK_LIB(ncurses, initscr, , AC_CHECK_LIB(curses, initscr, , AC_MSG_WARN(Building without curses display support) AC_DEFINE(NO_CURSES) CURSES_OBJ=))) + AC_CHECK_HEADERS(ncurses.h ncurses/curses.h curses.h) AC_CHECK_HEADERS(sys/xti.h) diff --git a/curses.c b/curses.c index 930c66a..beb2620 100644 --- a/curses.c +++ b/curses.c @@ -63,6 +63,10 @@ int mtr_curses_keyaction() { return ActionQuit; if (c==12) return ActionClear; + if (c==19) + return ActionPause; + if (c==17) + return ActionResume; if(tolower(c) == 'r') return ActionReset; if (tolower(c) == 'd') diff --git a/display.c b/display.c index 9f18b4e..eea3269 100644 --- a/display.c +++ b/display.c @@ -31,6 +31,7 @@ extern int DisplayMode; #define mtr_curses_close() #define mtr_curses_redraw() #define mtr_curses_keyaction() +#define mtr_curses_clear() #endif #ifdef NO_GTK @@ -41,6 +42,13 @@ extern int DisplayMode; #define gtk_loop() #endif +#ifdef NO_SPLIT +#define split_open() +#define split_close() +#define split_redraw() +#define split_keyaction() 0 +#endif + void display_detect(int *argc, char ***argv) { DisplayMode = DisplayReport; diff --git a/display.h b/display.h index 3bd27f2..6b091d7 100644 --- a/display.h +++ b/display.h @@ -17,7 +17,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -enum { ActionNone, ActionQuit, ActionReset, ActionDisplay, ActionClear }; +enum { ActionNone, ActionQuit, ActionReset, ActionDisplay, ActionClear, + ActionPause, ActionResume }; enum { DisplayReport, DisplayCurses, DisplayGTK, DisplaySplit, DisplayRaw }; /* Prototypes for display.c */ diff --git a/gtk.c b/gtk.c index 3835395..f7cce58 100644 --- a/gtk.c +++ b/gtk.c @@ -258,6 +258,7 @@ void Window_fill(GtkWidget *Window) { GtkWidget *List; gtk_window_set_title(GTK_WINDOW(Window), "My traceroute [v" VERSION "]"); + gtk_window_set_wmclass(GTK_WINDOW(Window), "mtr", "Mtr"); gtk_widget_set_usize(Window, 540, 400); gtk_container_border_width(GTK_CONTAINER(Window), 10); VBox = gtk_vbox_new(FALSE, 10); diff --git a/net.c b/net.c index 52358dc..75c0c0d 100644 --- a/net.c +++ b/net.c @@ -78,16 +78,8 @@ struct IPHeader { #define SOL_IP 0 #endif -struct packetdata { - int index; - int ttl; - int sec; - int msec; - int seq; -}; - struct nethost { - int addr; + uint32 addr; int xmit; int returned; int total; @@ -97,7 +89,15 @@ struct nethost { int saved[SAVED_PINGS]; }; +struct sequence { + int index; + int transit; + int saved_seq; + struct timeval time; +}; + static struct nethost host[MaxHost]; +static struct sequence sequence[MaxSequence]; static struct timeval reset = { 0, 0 }; int sendsock; @@ -123,65 +123,31 @@ int checksum(void *data, int sz) { static int BSDfix = 0; -void net_send_ping(int index) { - char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader) - + sizeof(struct packetdata)]; - struct IPHeader *ip; - struct ICMPHeader *icmp; - struct packetdata *data; - int packetsize = sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + sizeof(struct packetdata); - struct sockaddr_in addr; - struct timeval now; +int new_sequence(int index) { + static int next_sequence = 0; + int seq; - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = host[index].addr; - host[index].xmit++; + seq = next_sequence++; + if(next_sequence >= MaxSequence) + next_sequence = 0; + + sequence[seq].index = index; + sequence[seq].transit = 1; + sequence[seq].saved_seq = ++host[index].xmit; + memset(&sequence[seq].time, 0, sizeof(sequence[seq].time)); + host[index].transit = 1; net_save_xmit(index); - - memset(packet, 0, packetsize); - - ip = (struct IPHeader *)packet; - icmp = (struct ICMPHeader *)(packet + sizeof(struct IPHeader)); - data = (struct packetdata *)(packet + sizeof(struct IPHeader) + sizeof(struct ICMPHeader)); - - ip->version = 0x45; - ip->tos = 0; - ip->len = BSDfix? packetsize: htons (packetsize); - ip->id = 0; - ip->frag = 0; - ip->ttl = 127; - ip->protocol = IPPROTO_ICMP; - ip->saddr = 0; - ip->daddr = host[index].addr; - icmp->type = timestamp?ICMP_TSTAMP:ICMP_ECHO; - icmp->id = getpid(); - icmp->sequence = 0; - - data->ttl = 0; - data->index = index; - data->seq = host[index].xmit; - - gettimeofday(&now, NULL); - data->sec = now.tv_sec; - data->msec = now.tv_usec / 1000; - - icmp->checksum = checksum(icmp, packetsize - sizeof(struct IPHeader)); - ip->check = checksum(ip, packetsize); - - sendto(sendsock, packet, packetsize, 0, - (struct sockaddr *)&addr, sizeof(addr)); + return seq; } /* Attempt to find the host at a particular number of hops away */ -void net_send_query(int hops) { - char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + sizeof(struct packetdata)]; +void net_send_query(int index) { + char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader)]; struct IPHeader *ip; struct ICMPHeader *icmp; - struct packetdata *data; - int packetsize = sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + sizeof(struct packetdata); + int packetsize = sizeof(struct IPHeader) + sizeof(struct ICMPHeader); int rv; static int first=1; @@ -189,33 +155,28 @@ void net_send_query(int hops) { ip = (struct IPHeader *)packet; icmp = (struct ICMPHeader *)(packet + sizeof(struct IPHeader)); - data = (struct packetdata *)(packet + sizeof(struct IPHeader) + sizeof(struct ICMPHeader)); ip->version = 0x45; ip->tos = 0; ip->len = BSDfix ? packetsize: htons (packetsize); ip->id = 0; ip->frag = 0; - ip->ttl = hops; + ip->ttl = index + 1; ip->protocol = IPPROTO_ICMP; ip->saddr = 0; ip->daddr = remoteaddress.sin_addr.s_addr; icmp->type = ICMP_ECHO; icmp->id = getpid(); - icmp->sequence = hops; - - data->ttl = hops; - data->index = -1; + icmp->sequence = new_sequence(index); icmp->checksum = checksum(icmp, packetsize - sizeof(struct IPHeader)); ip->check = checksum(ip, packetsize); - + gettimeofday(&sequence[icmp->sequence].time, NULL); rv = sendto(sendsock, packet, packetsize, 0, (struct sockaddr *)&remoteaddress, sizeof(remoteaddress)); if (first && (rv < 0) && (errno == EINVAL)) { - first = 0; ip->len = packetsize; rv = sendto(sendsock, packet, packetsize, 0, (struct sockaddr *)&remoteaddress, sizeof(remoteaddress)); @@ -224,54 +185,50 @@ void net_send_query(int hops) { BSDfix = 1; } } + first = 0; } -void net_process_ping(struct packetdata *data, struct sockaddr_in *addr) { - int at; - struct timeval now; +/* 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) { + int index; int totmsec; - if(data->index >= 0) { - gettimeofday(&now, NULL); - - if(data->sec < reset.tv_sec - || (data->sec == reset.tv_sec && (1000*data->msec) < reset.tv_usec)) - /* discard this data point, stats were reset after it was generated */ - return; - - if (net_duplicate(data->index, data->seq)) { - return; - } - - totmsec = (now.tv_sec - data->sec) * 1000 + - ((now.tv_usec/1000) - data->msec); + if(seq < 0 || seq >= MaxSequence) + return; - if(host[data->index].returned <= 0) { - host[data->index].best = host[data->index].worst = totmsec; - } + if(!sequence[seq].transit) + return; + sequence[seq].transit = 0; - if(totmsec < host[data->index].best) - host[data->index].best = totmsec; + index = sequence[seq].index; - if(totmsec > host[data->index].worst) - host[data->index].worst = totmsec; + totmsec = (now.tv_sec - sequence[seq].time.tv_sec) * 1000 + + ((now.tv_usec/1000) - (sequence[seq].time.tv_usec/1000)); - display_rawping (data->index, totmsec); + if(host[index].addr == 0) { + host[index].addr = addr; + display_rawhost(index, host[index].addr); + } + if(host[index].returned <= 0) { + host[index].best = host[index].worst = totmsec; + } + if(totmsec < host[index].best) + host[index].best = totmsec; + if(totmsec > host[index].worst) + host[index].worst = totmsec; - host[data->index].total += totmsec; - host[data->index].returned++; - host[data->index].transit = 0; - net_save_return(data->index, data->seq, totmsec); - } else { - at = data->ttl - 1; - if(at < 0 || at > MaxHost) - return; + host[index].total += totmsec; + host[index].returned++; + host[index].transit = 0; - host[at].addr = addr->sin_addr.s_addr; - display_rawhost (at, host[at].addr); - } + net_save_return(index, sequence[seq].saved_seq, totmsec); + display_rawping(index, totmsec); } +/* 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() { char packet[2048]; struct sockaddr_in fromaddr; @@ -279,12 +236,15 @@ void net_process_return() { int num; int at; struct ICMPHeader *header; + struct timeval now; + + gettimeofday(&now, NULL); fromaddrsize = sizeof(fromaddr); num = recvfrom(recvsock, packet, 2048, 0, (struct sockaddr *)&fromaddr, &fromaddrsize); - if(num < sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + sizeof(struct packetdata)) + if(num < sizeof(struct IPHeader) + sizeof(struct ICMPHeader)) return; header = (struct ICMPHeader *)(packet + sizeof(struct IPHeader)); @@ -292,9 +252,7 @@ void net_process_return() { if(header->id != getpid()) return; - net_process_ping((struct packetdata *)(packet + sizeof(struct IPHeader) + - sizeof(struct ICMPHeader)), - &fromaddr); + net_process_ping(header->sequence, fromaddr.sin_addr.s_addr, now); } else if(header->type == ICMP_TIME_EXCEEDED) { if(num < sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + sizeof(struct IPHeader) + sizeof(struct ICMPHeader)) @@ -304,13 +262,8 @@ void net_process_return() { sizeof(struct ICMPHeader) + sizeof(struct IPHeader)); if(header->id != getpid()) return; - - at = header->sequence - 1; - if(at < 0 || at > MaxHost) - return; - host[at].addr = fromaddr.sin_addr.s_addr; - display_rawhost (at, net_addr(at)); + net_process_ping(header->sequence, fromaddr.sin_addr.s_addr, now); } } @@ -382,11 +335,7 @@ int net_send_batch() { static int at; int n_unknown, i; - if(host[at].addr == 0) { - net_send_query(at + 1); - } else { - net_send_ping(at); - } + net_send_query(at); n_unknown = 0; @@ -463,7 +412,8 @@ void net_reset() { int i; for(at = 0; at < MaxHost; at++) { - host[at].xmit = host[at].transit; + host[at].xmit = 0; + host[at].transit = 0; host[at].returned = 0; host[at].total = 0; host[at].best = 0; @@ -472,6 +422,11 @@ void net_reset() { host[at].saved[i] = -2; /* unsent */ } } + + for(at = 0; at < MaxSequence; at++) { + sequence[at].transit = 0; + } + gettimeofday(&reset, NULL); } @@ -484,6 +439,7 @@ int net_waitfd() { return recvsock; } + int* net_saved_pings(int at) { return host[at].saved; } @@ -495,28 +451,6 @@ void net_save_xmit(int at) { host[at].saved[SAVED_PINGS-1] = -1; } -int net_duplicate(int at, int seq) { - int idx; - idx = SAVED_PINGS - (host[at].xmit - seq) - 1; - if (idx < 0) { - /* long in the past - assume received */ - return 2; - } - if (idx >= SAVED_PINGS) { - /* ehhhh - back to the future? */ - return 3; - } - if (host[at].saved[idx] == -2) { - /* say what? must be an old ping */ - return 4; - } - if (host[at].saved[idx] != -1) { - /* it's a dup */ - return 5; - } - return 0; -} - void net_save_return(int at, int seq, int ms) { int idx; idx = SAVED_PINGS - (host[at].xmit - seq) - 1; diff --git a/net.h b/net.h index a9fdecc..929a7a6 100644 --- a/net.h +++ b/net.h @@ -47,3 +47,4 @@ void net_save_return(int at, int seq, int ms); int net_duplicate(int at, int seq); #define MaxHost 256 +#define MaxSequence 65536 diff --git a/select.c b/select.c index 17d7601..39eaa3a 100644 --- a/select.c +++ b/select.c @@ -43,15 +43,15 @@ void select_loop() { int action, maxfd; int dnsfd, netfd; int NumPing; + int paused; struct timeval lasttime, thistime, selecttime; float wt; - /* This starts at -1, because the first packet sent is not counted - as a ping. That confuses people. */ - NumPing = -1; + NumPing = 0; anyset = 0; gettimeofday(&lasttime, NULL); DeltaTime = WaitTime/10; + paused=0; while(1) { intervaltime.tv_sec = DeltaTime; @@ -76,7 +76,7 @@ void select_loop() { if(netfd >= maxfd) maxfd = netfd + 1; - if(anyset) { + if(anyset || paused) { selecttime.tv_sec = 0; selecttime.tv_usec = 0; @@ -142,6 +142,12 @@ void select_loop() { if (action == ActionClear) display_clear(); + if (action == ActionPause) + paused=1; + + if (action == ActionResume) + paused=0; + anyset = 1; } -- 2.47.2