- Fixed some problems with HPUX and SunOS.
- Included Olav Kvittem's patch to do packetsize option.
- Made the timekeeping in micro seconds.
source: ftp://ftp.bitwizard.nl/mtr/mtr-0.40.tar.gz
Charles Levert (charles@comm.polymtl.ca),
Bertrand Leconte (B.Leconte@mail.dotcom.fr),
Anand Kumria,
+ Olav Kvittem (Olav.Kvittem@uninett.no),
Adam Kramer (l3zqc@qcunix1.acc.qc.edu),
Philip Kizer (pckizer@nostrum.com),
Simon Kirby,
WHAT'S NEW?
+ v0.40 Fixed some problems with HPUX and SunOS.
+ Included Olav Kvittem's patch to do packetsize option.
+ Made the timekeeping in micro seconds.
+
+ v0.39 Forgot the parentheses around the previous fix... :-(
+
+ v0.38 fixed some dubious code in dns.c (noted by someone's lint)
+
v0.37 Added Bill Bogstad's "show the local host & time" patch.
Added R. Sparks' show-last-ping patch, submitted by Philip Kizer.
+Hi everyone,
+
+This is the "todo" file for mtr. I just realized that some people
+might think that this is all in MY queue to implement. That is not
+true: This is the "for everybody" todo list. Feel free to pick a
+"project" and implement something off this list.
+
+Students: Feel free to take up one of these as a programming exercise
+for one of your courses.
+
+Everybody: If you want to start on something, contact me first, so
+that the effort isn't wasted by someone who finishes just a tad
+earlier. I'll happily provide "coaching" to anyone who wants to
+implement something on this list. That way we get the design of
+these things the way I like them. This should result in a better
+maintainable mtr.
+
+Oh, Feel free to provide suggestions for this list.
+
+
+-- REW
+
+----------------------------------------------------------------------
+
+
- Stuff to implement:
- Allow mtr to log the return packets, for later analysis.
- Done: 0.25 . Todo: allow the userinterface(s) to work while
+ Done: 0.25 . Todo: allow the user interface(s) to work while
still logging to a file. Write a "logfile displaying" mode to
mtr.
convert these measurements into one-way measurements, not just
round-trip.
- - Allow mtr to also send larger packets.
- This will enable us to get a feel for the speed of the links
- we're traversing. (Van Jacobson was working on this His tool
- was slow, mtr will rock with this feature.... :-)
- (Anybody have the statistics experience to tell me how
- to do the data analysis?)
-
- - 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
- slowly (relative to the RTT time to the end host), it can probe
- all hosts in the first "round".
- -- DONE.
-
- allow "keyboard navigation" in the GTK version.
- Allow a toggle between hostname/IP number display. (for example a
click on the hostname could revert to ip number display in gtk version.
- curses: "n" key toggles hostnames/ipnumbers?
+ curses: "n" key toggles hostnames/ipnumbers?)
+
+ - Implement rfc2317 mechanism to do reverse lookups for networks that
+ have DNS delegations on non-octet boundaries. -- Daniel Bergstrom
+ (noa@melody.se)
+
+------------------------------------------------------------------------
+Things that shouldn't be on the TODO list because they're done. ;-)
+
+ - Allow mtr to also send larger packets.
+ This will enable us to get a feel for the speed of the links
+ we're traversing. (Van Jacobson was working on this His tool
+ was slow, mtr will rock with this feature.... :-)
+ (Anybody have the statistics experience to tell me how
+ to do the data analysis?)
+ -- DONE. Thanks to Olav Kvittem ...
+
+ - 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
+ slowly (relative to the RTT time to the end host), it can probe
+ all hosts in the first "round".
+ -- DONE.
AC_INIT(mtr.c)
-AM_INIT_AUTOMAKE(mtr, 0.39)
+AM_INIT_AUTOMAKE(mtr, 0.40)
AC_SUBST(GTK_OBJ)
AC_SUBST(CURSES_OBJ)
# - 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]]])
+# We don't refer to any symbols in termcap, but -lcurses on SunOS does.
+# We have to trust the linker not to mess things up... (It should not
+# pull in anything if we don't refer to anything in the lib).
+AC_CHECK_LIB(termcap, tgetent)
+
AC_CHECK_FUNC(initscr, ,
AC_CHECK_LIB(ncurses, initscr, ,
AC_CHECK_LIB(curses, initscr, ,
+ AC_CHECK_LIB(cursesX, initscr, ,
AC_MSG_WARN(Building without curses display support)
AC_DEFINE(NO_CURSES)
- CURSES_OBJ=)))
+ CURSES_OBJ=))))
+
+AC_CHECK_FUNCS(attron)
-AC_CHECK_HEADERS(ncurses.h ncurses/curses.h curses.h)
+
+AC_CHECK_HEADERS(ncurses.h ncurses/curses.h curses.h cursesX.h sys/types.h)
AC_CHECK_HEADERS(sys/xti.h)
AC_CHECK_LIB(m, floor, , AC_MSG_ERROR(No math library found))
AC_CHECK_LIB(bind, res_init, ,
AC_CHECK_LIB(resolv, res_init, , AC_MSG_ERROR(No resolver library found))))
+AC_CHECK_FUNCS(seteuid)
+# AC_CHECK_FUNC(setuid, , AC_MSG_ERROR (I Need either seteuid or setuid))
+
AC_CHECK_FUNC(res_mkquery, ,
AC_CHECK_LIB(bind, res_init, ,
AC_CHECK_LIB(resolv, res_init, , AC_MSG_ERROR(No resolver library found))))
# include <ncurses/curses.h>
#elif defined(HAVE_CURSES_H)
# include <curses.h>
+#elif defined(HAVE_CURSESX_H)
+# include <cursesX.h>
#else
# error No curses header file available
#endif
+#if defined(HAVE_SYS_TYPES_H)
+#include <sys/types.h>
+#else
+/* If a system doesn't have sys/types.h, lets hope that time_t is an int */
+#define time_t int
+#endif
+
+#ifndef HAVE_ATTRON
+#define attron(x)
+#define attroff(x)
+#endif
+
#ifndef getmaxyx
# define getmaxyx(win,y,x) (y = (win)->_maxy + 1, x = (win)->_maxx + 1)
#endif
#endif
#include <time.h>
-extern LocalHostname[];
+extern char LocalHostname[];
void pwcenter(char *str) {
int maxx, maxy;
return ActionQuit;
if (c==12)
return ActionClear;
- if (c==19)
+ if ((c==19) || (tolower (c) == 'p'))
return ActionPause;
- if (c==17)
+ if ((c==17) || (c == ' '))
return ActionResume;
if(tolower(c) == 'r')
return ActionReset;
getyx(stdscr, y, x);
move(y, startstat);
+ /* net_xxx returns times in usecs. Just display millisecs */
printw(" %3d%% %4d %4d %4d %4d %4d %6d",
net_percent(at),
- net_returned(at), net_xmit(at),
- net_last(at),net_best(at), net_avg(at), net_worst(at));
+ net_returned(at), net_xmit(at),
+ net_last(at)/1000, net_best(at)/1000,
+ net_avg(at)/1000, net_worst(at)/1000);
} else {
rowstat = 5;
- attron(A_BOLD);
move(0, 0);
+ attron(A_BOLD);
pwcenter("Matt's traceroute [v" VERSION "]");
- printw("\n");
attroff(A_BOLD);
- printw(LocalHostname);
+
+ mvprintw(1,0, LocalHostname);
time(&t);
mvprintw(1, maxx-25, ctime(&t));
mvprintw(rowstat - 1, 0, "Hostname");
if (display_mode == 0) {
- startstat = maxx - 40;
+ startstat = maxx - 41;
/* Modified by Brian Casey December 1997 bcasey@imagiware.com */
mvprintw(rowstat - 2, startstat, " Packets Pings");
attroff(A_BOLD);
for (i = 0; i < 7; i++) {
- printw(" %c:%d ms", block_map[i], scale[i]);
+ printw(" %c:%d ms", block_map[i], scale[i]/1000);
}
}
struct resolve *previousip;
struct resolve *nexthost;
struct resolve *previoushost;
+ float expiretime; /* Fucking HPUX has a problem with "double" here. */
char *hostname;
- double expiretime;
ip_t ip;
word id;
byte state;
gtk_set_field_num(List, row, 2, "%d", net_returned(row));
gtk_set_field_num(List, row, 3, "%d", net_xmit(row));
- gtk_set_field_num(List, row, 4, "%d", net_best(row));
- gtk_set_field_num(List, row, 5, "%d", net_avg(row));
- gtk_set_field_num(List, row, 6, "%d", net_worst(row));
+ gtk_set_field_num(List, row, 4, "%d", net_best(row)/1000);
+ gtk_set_field_num(List, row, 5, "%d", net_avg(row)/1000);
+ gtk_set_field_num(List, row, 6, "%d", net_worst(row)/1000);
}
[\c
.B \-\-interval\ SECONDS\c
]
-.B HOSTNAME
+[\c
+.B \-\-psize\ BYTES | -p BYTES\c
+]
+.B HOSTNAME [PACKETSIZE]
.SH DESCRIPTION
.B -r
option.
+.TP
+.B \-p\ BYTES
+.TP
+.B \-\-psize\ BYTES
+.TP
+.B PACKETSIZE
+These options or a trailing PACKETSIZE on the commandline sets
+the packet size used for probing.
+It is in bytes inclusive IP and ICMP headers
.TP
.B \-t
.TP
#include "report.h"
#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 Interactive = 1;
int PrintVersion = 0;
char *Hostname = NULL;
char LocalHostname[128];
int dns = 1;
+int packetsize = 64;
void parse_arg(int argc, char **argv) {
int opt;
{ "curses", 0, 0, 't' },
{ "gtk", 0, 0, 'g' },
{ "interval", 1, 0, 'i' },
+ { "psize", 1, 0, 'p' },
{ "no-dns", 0, 0, 'n' },
{ "split", 0, 0, 's' }, /* BL */
{ "raw", 0, 0, 'l' },
opt = 0;
while(1) {
- opt = getopt_long(argc, argv, "hvrc:tklnsi:", long_options, NULL);
+ opt = getopt_long(argc, argv, "hvrc:tklnsi:p:", long_options, NULL);
if(opt == -1)
break;
DisplayMode = DisplayReport;
break;
case 'c':
- MaxPing = atoi(optarg);
+ MaxPing = atoi (optarg);
+ break;
+ case 'p':
+ packetsize = atoi (optarg);
break;
case 't':
DisplayMode = DisplayCurses;
dns = 0;
break;
case 'i':
- WaitTime = atof(optarg);
+ WaitTime = atof (optarg);
if (WaitTime <= 0.0) {
fprintf (stderr, "mtr: wait time must be positive\n");
exit (1);
}
+
int main(int argc, char **argv) {
int traddr;
struct hostent *host;
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ 1999-08-13 ok Olav@okvittem.priv.no added -psize
+
*/
#include <config.h>
#ifndef SOL_IP
#define SOL_IP 0
#endif
-
+
+
+
struct nethost {
uint32 addr;
int xmit;
int returned;
- int total;
+ long long total;
int last;
int best;
int worst;
static int batch_at = 0;
-
+extern int packetsize;
static int numhosts = 10;
/* return the number of microseconds to wait before sending the next
/* Attempt to find the host at a particular number of hops away */
void net_send_query(int index) {
- char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader)];
+ /*ok char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader)];*/
+ char packet[MAXPACKET];
struct IPHeader *ip;
struct ICMPHeader *icmp;
- int packetsize = sizeof(struct IPHeader) + sizeof(struct ICMPHeader);
+
+ /*ok int packetsize = sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + datasize;*/
int rv;
static int first=1;
+ if ( packetsize < MINPACKET ) packetsize = MINPACKET;
+ if ( packetsize > MAXPACKET ) packetsize = MAXPACKET;
memset(packet, 0, packetsize);
ip = (struct IPHeader *)packet;
time. */
void net_process_ping(int seq, uint32 addr, struct timeval now) {
int index;
- int totmsec;
+ int totusec;
if(seq < 0 || seq >= MaxSequence)
return;
index = sequence[seq].index;
- totmsec = (now.tv_sec - sequence[seq].time.tv_sec) * 1000 +
- ((now.tv_usec/1000) - (sequence[seq].time.tv_usec/1000));
+ totusec = (now.tv_sec - sequence[seq].time.tv_sec ) * 1000000 +
+ (now.tv_usec - sequence[seq].time.tv_usec);
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;
+ host[index].best = host[index].worst = totusec;
}
- host[index].last = totmsec;
- if(totmsec < host[index].best)
- host[index].best = totmsec;
- if(totmsec > host[index].worst)
- host[index].worst = totmsec;
+ host[index].last = totusec;
+ if(totusec < host[index].best)
+ host[index].best = totusec;
+ if(totusec > host[index].worst)
+ host[index].worst = totusec;
- host[index].total += totmsec;
+ host[index].total += totusec;
host[index].returned++;
host[index].transit = 0;
- net_save_return(index, sequence[seq].saved_seq, totmsec);
- display_rawping(index, totmsec);
+ net_save_return(index, sequence[seq].saved_seq, totusec);
+ display_rawping(index, totusec);
}
/* We know a packet has come in, because the main select loop has called us,
#define MaxHost 256
#define MaxSequence 65536
+
+#define MAXPACKET 4096
+#define MINPACKET 64
printf("%-40s%5d%%%6d%5d%6d%6d%6d\n", name,
net_percent(at),
net_returned(at), net_xmit(at),
- net_best(at), net_avg(at), net_worst(at));
+ net_best(at)/1000, net_avg(at)/1000, net_worst(at)/1000);
}
}
#include <config.h>
+#ifdef NO_CURSES
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#else
+/* Use the curses variant */
+
#if defined(HAVE_NCURSES_H)
# include <ncurses.h>
#elif defined(HAVE_NCURSES_CURSES_H)
# error No curses header file available
#endif
+#endif
extern char *Hostname;
if(name != NULL) {
/* May be we should test name's length */
sprintf(newLine, "%s %d %d %d %d %d %d", name,
- net_percent(at),
- net_returned(at), net_xmit(at),
- net_best(at), net_avg(at), net_worst(at));
+ net_percent(at),
+ net_returned(at), net_xmit(at),
+ net_best(at) /1000, net_avg(at)/1000,
+ net_worst(at)/1000);
} else {
sprintf(newLine, "%d.%d.%d.%d %d %d %d %d %d %d",
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff,
- net_percent(at),
- net_returned(at), net_xmit(at),
- net_best(at), net_avg(at), net_worst(at));
+ (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+ (addr >> 8) & 0xff, addr & 0xff,
+ net_percent(at),
+ net_returned(at), net_xmit(at),
+ net_best(at) /1000, net_avg(at)/1000,
+ net_worst(at)/1000);
}
} else {
sprintf(newLine, "???");
int
split_keyaction() {
+#ifdef NO_CURSES
+ fd_set readfds;
+ struct timeval tv;
+ char c;
+
+ FD_ZERO (&readfds);
+ FD_SET (0, &readfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ if (select (1, &readfds, NULL, NULL, &tv) > 0) {
+ read (0, &c, 1);
+ } else
+ return 0;
+#else
char c = getch();
+#endif
#if DEBUG
printf("split_keyaction()\n");