diff --git a/FORMATS b/FORMATS new file mode 100644 index 0000000..5404e87 --- /dev/null +++ b/FORMATS @@ -0,0 +1,31 @@ + +The "split" format is for a separating the gui from the main program. +The main program can be installed setuid, and you don't want to link a +gui-library with a setuid program. + + +The split format is: + + + + +The "raw" format is: + +hostline|pingline|dnsline|timestampline + +hostline: +h + +pingline: +p + +dnsline: +d + +timestampline: +t + + +Timestampline is not yet implemented. Need to find out how to do +ICMP timestamping first. :-) + diff --git a/Makefile.am b/Makefile.am index d5648d9..f7ee2b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,8 @@ install-exec-am: mtr_SOURCES = mtr.c \ net.c net.h \ dns.c dns.h \ + raw.c raw.h \ + split.c split.h \ display.c display.h \ report.c report.h \ getopt.c getopt1.c getopt.h \ diff --git a/NEWS b/NEWS index 2e58556..8d938db 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,20 @@ WHAT'S NEW? + + v0.25 + Included two "raw" formats. One for separating GUI from + the setuid program, and one suitable for later parsing and + displaying. Volunteers wanted to separate the GTK + backend. Thanks to Bertrand Leconte for contributing + the format that's now called "split". + + v0.24 + Fixed number of probes. Accidentally was counted per + packet sent instead of per round of packets. + + v0.23 + Fixed Sparc alignment problem with statmalloc + v0.22 Roger has take over maintenance. mtr now uses an "int" to pass options to the kernel. diff --git a/SECURITY b/SECURITY index a6b48dd..1ebf15c 100644 --- a/SECURITY +++ b/SECURITY @@ -1,5 +1,11 @@ SECURITY ISSUES RELATED TO MTR +You can limit mtr usage to the root user by not putting a setuid bit +on the mtr binary. In that case, the security implications are +minimal. + +Or you can make mtr setuid-root, and the following applies to you.... + Since mtr is installed as suid-root, some concern over security is justified. Since version 0.21 of mtr, does the following two things after it is launched: diff --git a/TODO b/TODO index 8e45c3c..1277e76 100644 --- a/TODO +++ b/TODO @@ -17,6 +17,15 @@ - 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 + slowly (relative to the RTT time to the end host), it can probe + all hosts in the first "round". + - Bugs to fix? - ? diff --git a/configure.in b/configure.in index db69ac2..8f9c701 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ AC_INIT(mtr.c) -AM_INIT_AUTOMAKE(mtr, 0.24) +AM_INIT_AUTOMAKE(mtr, 0.25) AC_SUBST(GTK_OBJ) AC_SUBST(CURSES_OBJ) diff --git a/display.c b/display.c index f140aa9..2200663 100644 --- a/display.c +++ b/display.c @@ -26,6 +26,21 @@ extern int DisplayMode; +#ifdef NO_CURSES +#define mtr_curses_open() +#define mtr_curses_close() +#define mtr_curses_redraw() +#define mtr_curses_keyaction() +#endif + +#ifdef NO_GTK +#define gtk_open() +#define gtk_close() +#define gtk_redraw() +#define gtk_keyaction() +#define gtk_loop() +#endif + void display_detect(int *argc, char ***argv) { DisplayMode = DisplayReport; @@ -46,17 +61,17 @@ void display_open() { report_open(); break; -#ifndef NO_CURSES case DisplayCurses: mtr_curses_open(); break; -#endif -#ifndef NO_GTK + case DisplaySplit: /* BL */ + split_open(); + break; + case DisplayGTK: gtk_open(); break; -#endif } } @@ -66,63 +81,92 @@ void display_close() { report_close(); break; -#ifndef NO_CURSES case DisplayCurses: mtr_curses_close(); break; -#endif -#ifndef NO_GTK + case DisplaySplit: /* BL */ + split_close(); + break; + case DisplayGTK: gtk_close(); break; -#endif } } void display_redraw() { switch(DisplayMode) { -#ifndef NO_CURSES + case DisplayCurses: mtr_curses_redraw(); break; -#endif -#ifndef NO_GTK + case DisplaySplit: /* BL */ + split_redraw(); + break; + case DisplayGTK: gtk_redraw(); break; -#endif } } int display_keyaction() { switch(DisplayMode) { -#ifndef NO_CURSES case DisplayCurses: return mtr_curses_keyaction(); -#endif -#ifndef NO_GTK + case DisplaySplit: /* BL */ + return split_keyaction(); + case DisplayGTK: return gtk_keyaction(); -#endif } return 0; } + +void display_rawping(int host, int msec) { + switch(DisplayMode) { + case DisplayReport: + case DisplaySplit: /* BL */ + case DisplayCurses: + case DisplayGTK: + break; + case DisplayRaw: + raw_rawping (host, msec); + break; + } +} + + +void display_rawhost(int host, int ip_addr) { + switch(DisplayMode) { + case DisplayReport: + case DisplaySplit: /* BL */ + case DisplayCurses: + case DisplayGTK: + break; + case DisplayRaw: + raw_rawhost (host, ip_addr); + break; + } +} + + void display_loop() { switch(DisplayMode) { case DisplayCurses: case DisplayReport: + case DisplaySplit: /* BL */ + case DisplayRaw: select_loop(); break; -#ifndef NO_GTK case DisplayGTK: gtk_loop(); break; -#endif } } diff --git a/display.h b/display.h index 9d89d56..7919bbf 100644 --- a/display.h +++ b/display.h @@ -18,12 +18,14 @@ */ enum { ActionNone, ActionQuit, ActionReset }; -enum { DisplayReport, DisplayCurses, DisplayGTK }; +enum { DisplayReport, DisplayCurses, DisplayGTK, DisplaySplit, DisplayRaw }; /* Prototypes for display.c */ void display_detect(int *argc, char ***argv); void display_open(); void display_close(); void display_redraw(); +void display_rawping(int hostnum, int msec); +void display_rawhost(int hostnum, int ip_addr); int display_keyaction(); void display_loop(); diff --git a/dns.c b/dns.c index 0637427..e41ad4a 100644 --- a/dns.c +++ b/dns.c @@ -1134,7 +1134,7 @@ void dns_events(double *sinterval){ (void)istime(expireresolves->expiretime,sinterval); } -char *dns_lookup(ip_t ip){ +char *dns_lookup2(ip_t ip){ struct resolve *rp; ip = htonl(ip); if ((rp = findip(ip))){ @@ -1152,10 +1152,10 @@ char *dns_lookup(ip_t ip){ strlongip(ip)); restell(tempstring); } - return strlongip(ip); + return NULL; } } - return strlongip(ip); + return NULL; } if (debug) fprintf(stderr,"Resolver: Added to new record.\n"); @@ -1167,5 +1167,13 @@ char *dns_lookup(ip_t ip){ rp->ip = ip; linkresolveip(rp); sendrequest(rp,T_PTR); - return strlongip(ip); + return NULL; +} + + +char *dns_lookup(ip_t ip){ + char *t; + + t = dns_lookup2 (ip); + return t?t:strlongip(ip); } diff --git a/dns.h b/dns.h index 2f4f35b..3af73e4 100644 --- a/dns.h +++ b/dns.h @@ -24,4 +24,5 @@ int dns_waitfd(); void dns_ack(); void dns_events(double *sinterval); char *dns_lookup(int address); +char *dns_lookup2(int address); int dns_forward(char *name); diff --git a/mtr.8 b/mtr.8 index ae209b0..0261293 100644 --- a/mtr.8 +++ b/mtr.8 @@ -26,6 +26,12 @@ mtr \- a network diagnostic tool .B \-\-curses\c ] [\c +.B \-\-split\c +] +[\c +.B \-\-raw\c +] +[\c .B \-\-gtk\c ] [\c @@ -131,6 +137,26 @@ was built for this to work. See the GTK+ web page at .B http://www.gimp.org/gtk/ for more information about GTK+. +.TP +.B \-s +.TP +.B \-\-split +.br +Use this option to set +.B mtr +to spit out a format that is suitable for a split-user interface. + +.TP +.B \-l +.TP +.B \-\-raw +.br +Use this option to tell +.B mtr +to use the raw output format. This format is better suited for +archival of the measurement results. It could be parsed to +be presented into any of the other display methods. + .TP .B \-i\ SECONDS .TP diff --git a/mtr.c b/mtr.c index cb1dc8e..1315f8e 100644 --- a/mtr.c +++ b/mtr.c @@ -48,12 +48,14 @@ void parse_arg(int argc, char **argv) { { "curses", 0, 0, 't' }, { "gtk", 0, 0, 'g' }, { "interval", 1, 0, 'i' }, + { "split", 0, 0, 's' }, /* BL */ + { "raw", 0, 0, 'l' }, { 0, 0, 0, 0 } }; opt = 0; while(1) { - opt = getopt_long(argc, argv, "hvrc:tli:", long_options, NULL); + opt = getopt_long(argc, argv, "hvrc:tklsi:", long_options, NULL); if(opt == -1) break; @@ -76,6 +78,12 @@ void parse_arg(int argc, char **argv) { case 'g': DisplayMode = DisplayGTK; break; + case 's': /* BL */ + DisplayMode = DisplaySplit; + break; + case 'l': + DisplayMode = DisplayRaw; + break; case 'i': WaitTime = atof(optarg); if (WaitTime <= 0.0) { @@ -127,8 +135,9 @@ int main(int argc, char **argv) { } if(Hostname == NULL || PrintHelp) { - printf("usage: %s [-hvrctli] [--help] [--version] [--report]\n" + printf("usage: %s [-hvrctlis] [--help] [--version] [--report]\n" "\t\t[--report-cycles=COUNT] [--curses] [--gtk]\n" + "\t\t[--raw] [--split]\n" /* BL */ "\t\t[--interval=SECONDS] HOSTNAME\n", argv[0]); exit(0); } diff --git a/net.c b/net.c index a090928..3d4c252 100644 --- a/net.c +++ b/net.c @@ -32,7 +32,6 @@ #include "net.h" -#define MaxHost 256 #define MaxTransit 4 /* We can't rely on header files to provide this information, because @@ -200,7 +199,6 @@ void net_process_ping(struct packetdata *data, struct sockaddr_in *addr) { int at; struct timeval now; int totmsec; - int msec; if(data->index >= 0) { gettimeofday(&now, NULL); @@ -210,12 +208,8 @@ void net_process_ping(struct packetdata *data, struct sockaddr_in *addr) { /* discard this data point, stats were reset after it was generated */ return; - totmsec = (now.tv_sec - data->sec) * 1000; - msec = now.tv_usec / 1000 - data->msec; - if(msec >= 0) - totmsec += msec; - else - totmsec = totmsec - 1000 + 1000 - data->msec + now.tv_usec / 1000; + totmsec = (now.tv_sec - data->sec) * 1000 + + ((now.tv_usec/1000) - data->msec); if(host[data->index].returned <= 0) { host[data->index].best = host[data->index].worst = totmsec; @@ -227,6 +221,8 @@ void net_process_ping(struct packetdata *data, struct sockaddr_in *addr) { if(totmsec > host[data->index].worst) host[data->index].worst = totmsec; + display_rawping (data->index, totmsec); + host[data->index].total += totmsec; host[data->index].returned++; host[data->index].transit = 0; @@ -236,6 +232,7 @@ void net_process_ping(struct packetdata *data, struct sockaddr_in *addr) { return; host[at].addr = addr->sin_addr.s_addr; + display_rawhost (at, host[at].addr); } } @@ -277,6 +274,7 @@ void net_process_return() { return; host[at].addr = fromaddr.sin_addr.s_addr; + display_rawhost (at, net_addr(at)); } } diff --git a/net.h b/net.h index a68677d..fd78670 100644 --- a/net.h +++ b/net.h @@ -41,3 +41,4 @@ int net_xmit(int at); int net_transit(int at); +#define MaxHost 256 diff --git a/raw.c b/raw.c new file mode 100644 index 0000000..42b3418 --- /dev/null +++ b/raw.c @@ -0,0 +1,68 @@ +/* + mtr -- a network diagnostic tool + Copyright (C) 1998 R.E.Wolff@BitWizard.nl + + raw.c -- raw output (for logging for later analysis) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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. +*/ + +#include +#include +#include + + +#include "raw.h" +#include "net.h" +#include "dns.h" + +static int havename[MaxHost]; + +static char *addr_to_str(int addr) +{ + static char buf[20]; + + sprintf (buf, "%d.%d.%d.%d", + (addr >> 0) & 0xff, + (addr >> 8) & 0xff, + (addr >> 16) & 0xff, + (addr >> 24) & 0xff); + return buf; +} + + +void raw_rawping (int host, int msec) +{ + char *name; + + if (!havename[host]) { + name = dns_lookup2(net_addr(host)); + if (name) { + havename[host]++; + printf ("d %d %s\n", host, name); + } + } + printf ("p %d %d\n", host, msec); +} + + +void raw_rawhost (int host, int ip_addr) +{ + printf ("h %d %s\n", host, addr_to_str (ip_addr)); +} + + + + diff --git a/raw.h b/raw.h new file mode 100644 index 0000000..710aabe --- /dev/null +++ b/raw.h @@ -0,0 +1,24 @@ +/* + mtr -- a network diagnostic tool + Copyright (C) 1998 R.E.Wolff@BitWizard.nl + + raw.h -- raw output (for logging for later analysis) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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. +*/ + +/* Prototypes for raw.c */ +void raw_rawping(int host, int msec); +void raw_rawhost(int host, int addr); diff --git a/split.c b/split.c new file mode 100644 index 0000000..a9bc2ff --- /dev/null +++ b/split.c @@ -0,0 +1,148 @@ +/* + mtr -- a network diagnostic tool + Copyright (C) 1997 Matt Kimball + + split.c -- raw output (for inclusion in KDE Network Utilities or others + GUI based tools) + Copyright (C) 1998 Bertrand Leconte + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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. +*/ + +#include +#include +#include + +#include "display.h" +#include "dns.h" +/* +#include "net.h" +#include "split.h" +*/ + + +extern char *Hostname; +extern int WaitTime; + +/* There is 256 hops max in the IP header (coded with a byte) */ +#define MAX_LINE_COUNT 256 +#define MAX_LINE_SIZE 256 + +char Lines[MAX_LINE_COUNT][MAX_LINE_SIZE]; +int LineCount; + + +#define DEBUG 0 + +void +split_redraw() { + int max; + int at; + int addr; + char *name; + char newLine[MAX_LINE_SIZE]; + int i; + +#if DEBUG + fprintf(stderr, "split_redraw()\n"); +#endif + + /* + * If there is less lines than last time, we delete them + * TEST THIS PLEASE + */ + max = net_max(); + for (i=LineCount; i>max; i--) { + printf("-%d\n", i); + LineCount--; + } + + /* + * For each line, we compute the new one and we compare it to the old one + */ + for(at = 0; at < max; at++) { + addr = net_addr(at); + + if(addr != 0) { + name = dns_lookup(addr); + 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)); + } 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)); + } + } else { + sprintf(newLine, "???"); + } + + if (strcmp(newLine, Lines[at]) == 0) { + /* The same, so do nothing */ +#if DEBUG + printf("SAME LINE\n"); +#endif + } else { + printf("%d %s\n", at+1, newLine); + fflush(stdout); + strcpy(Lines[at], newLine); + if (LineCount < (at+1)) { + LineCount = at+1; + } + } + } +} + +void +split_open() { + int i; +#if DEBUG + printf("split_open()\n"); +#endif + LineCount = -1; + for (i=0; i + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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. +*/ + +/* Prototypes for split.c */ +void split_open(); +void split_close(); +void split_redraw(); +int split_keyaction();