]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
mtr v0.68 v0.68
authorRoger Wolff <r.e.wolff@bitwizard.nl>
Tue, 11 Jan 2005 00:00:00 +0000 (00:00 +0000)
committerTravis Cross <tc@traviscross.com>
Sun, 3 Feb 2013 20:45:38 +0000 (20:45 +0000)
 - included some old patches.
 - included patch from Antonio Querubin for better IPV6 support
   restructured some more whitespace.
 - added mtr.h where "global" things should go. Not finished moving
   things around, but now that the infrastructure is there, it should
   be easy.

source: ftp://ftp.bitwizard.nl/mtr/mtr-0.68.tar.gz

26 files changed:
AUTHORS
Makefile.am
NEWS
configure.in
curses.c
display.c
display.h
dns.c
dns.h
getopt.h
gtk.c
mtr-curses.h
mtr-gtk.h
mtr.8
mtr.c
mtr.h [new file with mode: 0644]
net.c
net.h
raw.c
raw.h
report.c
report.h
select.c
select.h
split.c
split.h

diff --git a/AUTHORS b/AUTHORS
index 629f1ed1b4664de0168b187592fe3762bf4bc847..18d452c7ae174a5ccd32b37d804f3500a585ccf8 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -25,6 +25,7 @@
         Mike Simons (msimons@moria.simons-clan.com)
         Aaron Scarisbrick,
         Craig Milo Rogers (Rogers@ISI.EDU)
+        Antonio Querubin <tony@aloha.net>
         Russell Nelson (rn-mtr@crynwr.com)
         Davin Milun (milun@acm.org)
         Josh Martin (jmartin@columbiaservices.net)
index ac610ac42763d1d15c8c073ea3b4bc8fc2807dbf..d02920fdafa6e0928c9aec43962b2ab1069d6dc1 100644 (file)
@@ -2,7 +2,7 @@ SUBDIRS = img
 
 sbin_PROGRAMS = mtr
 man_MANS = mtr.8
-install-exec-am
+install-exec-hook
        chmod u+s $(DESTDIR)$(sbindir)/mtr
 
 mtr_SOURCES = mtr.c \
diff --git a/NEWS b/NEWS
index 9b4e31c14d18b6ddfd68d8fe9241691a322678a0..529ffd71bcd597273042b119533b01740fe517ee 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,10 @@
 WHAT'S NEW?
+  v0.68 included some old patches.
+        included patch from Antonio Querubin for better IPV6 support
+        restructured some more whitespace. 
+        added mtr.h where "global" things should go. Not finished
+        moving things around, but now that the infrastructure is there, 
+        it should be easy. 
   v0.67 Bad keyboarding by REW caused this one out the door. Sorry. 
         No changes. 
   v0.66 Through the Debian bugtracking system a bug report and
index 473339025759efefe0240024ce136f43dc2ec0ba..9e52a31db9afe2775f2a04e7ec0104fd75f3f5aa 100644 (file)
@@ -1,5 +1,5 @@
 AC_INIT(mtr.c)
-AM_INIT_AUTOMAKE(mtr, 0.67)
+AM_INIT_AUTOMAKE(mtr, 0.68)
 
 
 AC_SUBST(GTK_OBJ)
@@ -49,6 +49,10 @@ AC_ARG_ENABLE(gtk2,
 [  --enable-gtk2           Compile against GTK2 instead of GTK+],
 WANTS_GTK2=$enableval, WANTS_GTK2=no)
    
+AC_ARG_ENABLE(ipv6,
+[  --disable-ipv6          Do not enable IPv6],
+WANTS_IPV6=$enableval, WANTS_IPV6=yes)
+   
 if test "x$WANTS_GTK" = "xyes"; then
        if test "x$WANTS_GTK2" = "xyes"; then
                 AM_PATH_GTK_2_0(2.0.0, CFLAGS="$CFLAGS $GTK_CFLAGS"
@@ -88,6 +92,10 @@ AC_CHECK_FUNC(res_mkquery, ,
 AC_CHECK_FUNC(herror, , AC_DEFINE(NO_HERROR))
 AC_CHECK_FUNC(strerror, , AC_DEFINE(NO_STRERROR))
 
+AC_CHECK_FUNC(getaddrinfo,
+[if test "$WANTS_IPV6" = "yes"; then
+       AC_DEFINE([ENABLE_IPV6], [], [Define to enable IPv6])
+fi])
 
 dnl Add C flags to display more warnings
 AC_MSG_CHECKING(for C flags to get more warnings)
index 414f5f20d75bee5604ff32a51aaf783071fa8739..f7f5fa18fc8c32a3c5b328ec7a230ccb6e378e6f 100644 (file)
--- a/curses.c
+++ b/curses.c
@@ -18,6 +18,7 @@
 */
 
 #include <config.h>
+#include <strings.h>
 
 #ifndef NO_CURSES
 #include <ctype.h>
@@ -57,6 +58,7 @@
 #  define getmaxyx(win,y,x)    ((y) = (win)->_maxy + 1, (x) = (win)->_maxx + 1)
 #endif
 
+#include "mtr.h"
 #include "mtr-curses.h"
 #include "display.h"
 #include "net.h"
@@ -72,7 +74,7 @@ extern int packetsize;
 extern int bitpattern;
 extern int tos;
 extern float WaitTime;
-
+extern int af;
 
 void pwcenter(char *str) 
 {
@@ -86,7 +88,8 @@ void pwcenter(char *str)
   printw(str);
 }
 
-int mtr_curses_keyaction() 
+
+int mtr_curses_keyaction(void)
 {
   int c = getch();
   int i=0;
@@ -119,7 +122,7 @@ int mtr_curses_keyaction()
     mvprintw(3, 0, "Size Range: %d-%d, <0 random.\n", MINPACKET, MAXPACKET);
     move(2,20);
     refresh();
-    while ( (c=getch ()) != '\n' && i<MAXFLD ) {
+    while ( (c=getch ()) != '\n' && i < MAXFLD ) {
       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh ();
       buf[i++] = c;   /* need more checking on 'c' */
     }
@@ -140,7 +143,7 @@ int mtr_curses_keyaction()
     mvprintw(3, 0, "Pattern Range: 0(0x00)-255(0xff), <0 random.\n");
     move(2,18);
     refresh();
-    while ( (c=getch ()) != '\n' && i<MAXFLD ) {
+    while ( (c=getch ()) != '\n' && i < MAXFLD ) {
       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh ();
       buf[i++] = c;   /* need more checking on 'c' */
     }
@@ -154,7 +157,7 @@ int mtr_curses_keyaction()
     mvprintw(3, 0, "default 0x00, min cost 0x02, rel 0x04,, thr 0x08, low del 0x10...\n");
     move(2,22);
     refresh();
-    while ( (c=getch ()) != '\n' && i<MAXFLD ) {
+    while ( (c=getch ()) != '\n' && i < MAXFLD ) {
       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
       buf[i++] = c;   /* need more checking on 'c' */
     }
@@ -169,7 +172,7 @@ int mtr_curses_keyaction()
     mvprintw(2, 0, "Interval : %0.0f\n\n", WaitTime );
     move(2,11);
     refresh();
-    while ( (c=getch ()) != '\n' && i<MAXFLD ) {
+    while ( (c=getch ()) != '\n' && i < MAXFLD ) {
       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
       buf[i++] = c;   /* need more checking on 'c' */
     }
@@ -185,7 +188,7 @@ int mtr_curses_keyaction()
     mvprintw(2, 0, "First TTL: %d\n\n", fstTTL );
     move(2,11);
     refresh();
-    while ( (c=getch ()) != '\n' && i<MAXFLD ) {
+    while ( (c=getch ()) != '\n' && i < MAXFLD ) {
       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
       buf[i++] = c;   /* need more checking on 'c' */
     }
@@ -201,7 +204,7 @@ int mtr_curses_keyaction()
     mvprintw(2, 0, "Max TTL: %d\n\n", maxTTL );
     move(2,9);
     refresh();
-    while ( (c=getch ()) != '\n' && i<MAXFLD ) {
+    while ( (c=getch ()) != '\n' && i < MAXFLD ) {
       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
       buf[i++] = c;   /* need more checking on 'c' */
     }
@@ -271,11 +274,12 @@ int mtr_curses_keyaction()
   return ActionNone;          /* ignore unknown input */
 }
 
+
 void mtr_curses_hosts(int startstat) 
 {
   int max;
   int at;
-  int addr, addrs;
+  ip_t *addr, *addrs;
   int y, x;
   char *name;
 
@@ -289,15 +293,14 @@ void mtr_curses_hosts(int startstat)
     printw("%2d. ", at + 1);
     addr = net_addr(at);
 
-    if(addr != 0) {
+    if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) {
       name = dns_lookup(addr);
       if (! net_up(at))
        attron(A_BOLD);
       if(name != NULL) {
        printw("%s", name);
       } else {
-       printw("%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, 
-              (addr >> 8) & 0xff, addr & 0xff);
+       printw("%s", strlongip( addr ) );
       }
       attroff(A_BOLD);
 
@@ -330,17 +333,15 @@ void mtr_curses_hosts(int startstat)
       /* Multi path by Min */
       for (i=0; i < MAXPATH; i++ ) {
         addrs = net_addrs(at, i);
-       if (addrs == addr) continue;
-       if (addrs == 0) break;
+       if ( addrcmp( (void *) addrs, (void *) addr, af ) == 0 ) continue;
+       if ( addrcmp( (void *) addrs, (void *) &unspec_addr, af ) == 0 ) break;
 
         name = dns_lookup(addrs);
         if (! net_up(at)) attron(A_BOLD);
         if (name != NULL) {
          printw("\n    %s", name);
         } else {
-         printw("\n    %d.%d.%d.%d",
-               (addrs >> 24) & 0xff, (addrs >> 16) & 0xff, 
-               (addrs >> 8) & 0xff, addrs & 0xff);
+         printw("\n    %s", strlongip( addrs ) );
         }
         attroff(A_BOLD);
       }
@@ -354,6 +355,7 @@ void mtr_curses_hosts(int startstat)
   move(2, 0);
 }
 
+
 static double factors[] = { 0.02, 0.05, 0.08, 0.15, 0.33, 0.50, 0.80, 1.00 };
 static int scale[8];
 static int low_ms, high_ms;
@@ -388,6 +390,7 @@ void mtr_gen_scale(void)
        }
 }
 
+
 static const char* block_map = ".123abc>";
 
 void mtr_print_scaled(int ms) 
@@ -403,6 +406,7 @@ void mtr_print_scaled(int ms)
        printw(">");
 }
 
+
 void mtr_fill_graph(int at, int cols) 
 {
        int* saved;
@@ -430,9 +434,11 @@ void mtr_fill_graph(int at, int cols)
        }
 }
 
+
 void mtr_curses_graph(int startstat, int cols) 
 {
-       int max, at, addr, y, x;
+       int max, at, y, x;
+       ip_t * addr;
        char* name;
 
        max = net_max();
@@ -452,7 +458,7 @@ void mtr_curses_graph(int startstat, int cols)
                if (name) {
                        printw("%s", name);
                } else {
-                       printw("%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) && 0xff, (addr >> 8) & 0xff, addr & 0xff);
+                       printw("%s", strlongip( addr ) );
                }
                attroff(A_BOLD);
 
@@ -465,7 +471,8 @@ void mtr_curses_graph(int startstat, int cols)
        }
 }
 
-void mtr_curses_redraw() 
+
+void mtr_curses_redraw(void)
 {
   int maxx, maxy;
   int startstat;
@@ -488,7 +495,7 @@ void mtr_curses_redraw()
   pwcenter("My traceroute  [v" VERSION "]");
   attroff(A_BOLD);
 
-  mvprintw(1, 0, "%s (%s)", LocalHostname, inet_ntoa(*net_localaddr()));
+  mvprintw(1, 0, "%s (%s)", LocalHostname, net_localaddr());
   printw("(tos=0x%X ", tos);
   printw("psize=%d ", abs(packetsize) );
   printw("bitpattern=0x%02X)", (unsigned char)(abs(bitpattern)));
@@ -562,7 +569,7 @@ void mtr_curses_redraw()
 }
 
 
-void mtr_curses_open(
+void mtr_curses_open(void)
 {
   initscr();
   raw();
@@ -572,14 +579,14 @@ void mtr_curses_open()
 }
 
 
-void mtr_curses_close(
+void mtr_curses_close(void)
 {  
   printw("\n");
   endwin();
 }
 
 
-void mtr_curses_clear(
+void mtr_curses_clear(void)
 {
   mtr_curses_close();
   mtr_curses_open();
index b9502ce1687965cd20751f883bae026cda20801c..e18374f363d207fb77fee6baaf2a1037b6fc3e8c 100644 (file)
--- a/display.c
+++ b/display.c
 
 #include <config.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "mtr.h"
 #include "display.h"
 #include "mtr-curses.h"
 #include "mtr-gtk.h"
 #include "report.h"
 #include "select.h"
 #include "raw.h"
+#include "dns.h"
 
 extern int DisplayMode;
 
@@ -71,7 +76,9 @@ void display_detect(int *argc, char ***argv) {
 #endif
 }
 
-void display_open() {
+
+void display_open(void)
+{
   switch(DisplayMode) {
 
   case DisplayReport:
@@ -98,7 +105,9 @@ void display_open() {
   }
 }
 
-void display_close() {
+
+void display_close(void)
+{
   switch(DisplayMode) {
   case DisplayReport:
     report_close();
@@ -124,7 +133,9 @@ void display_close() {
   }
 }
 
-void display_redraw() {
+
+void display_redraw(void)
+{
   switch(DisplayMode) {
 
   case DisplayCurses:
@@ -141,7 +152,9 @@ void display_redraw() {
   }
 }
 
-int display_keyaction() {
+
+int display_keyaction(void)
+{
   switch(DisplayMode) {
   case DisplayCurses:
     return mtr_curses_keyaction();
@@ -156,7 +169,8 @@ int display_keyaction() {
 }
 
 
-void display_rawping(int host, int msec) {
+void display_rawping(int host, int msec) 
+{
   switch(DisplayMode) {
   case DisplayReport:
   case DisplayTXT:
@@ -173,7 +187,8 @@ void display_rawping(int host, int msec) {
 }
 
 
-void display_rawhost(int host, int ip_addr) {
+void display_rawhost(int host, ip_t *ip_addr) 
+{
   switch(DisplayMode) {
   case DisplayReport:
   case DisplayTXT:
@@ -190,7 +205,8 @@ void display_rawhost(int host, int ip_addr) {
 }
 
 
-void display_loop() {
+void display_loop(void)
+{
   switch(DisplayMode) {
   case DisplayReport:
   case DisplayTXT:
@@ -208,7 +224,8 @@ void display_loop() {
 }
 
 
-void display_clear() {
+void display_clear(void)
+{
   switch(DisplayMode) {
   case DisplayCurses:
     mtr_curses_clear();
index 648e5b194d813a862cc927271a3e57b1a6719563..d75c27b6601787c28abb63f6cd069587c7e777b7 100644 (file)
--- a/display.h
+++ b/display.h
@@ -17,6 +17,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <netinet/in.h>
+
 enum { ActionNone,  ActionQuit,  ActionReset,  ActionDisplay, 
        ActionClear, ActionPause, ActionResume, ActionDNS, 
        ActionScrollDown, ActionScrollUp,  };
@@ -25,16 +27,14 @@ enum { DisplayReport, DisplayCurses, DisplayGTK, DisplaySplit,
 
 /*  Prototypes for display.c  */
 void display_detect(int *argc, char ***argv);
-void display_open();
-void display_close();
-void display_redraw();
+void display_open(void);
+void display_close(void);
+void display_redraw(void);
 void display_rawping(int hostnum, int msec);
-void display_rawhost(int hostnum, int ip_addr);
-int display_keyaction();
-void display_loop();
-void display_clear();
+void display_rawhost(int hostnum, ip_t *ip_addr);
+int display_keyaction(void);
+void display_loop(void);
+void display_clear(void);
 
 extern int display_mode;
-extern int use_dns;
-extern int dns;
 extern int display_offset; /* only used in text mode */
diff --git a/dns.c b/dns.c
index 32a96b35c7fdddfdaacdb9109f50d8fcd23b3d69..2b746b63929418cebdcd0d6b7ac4d7310c67dde4 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -44,7 +44,9 @@
 #include <errno.h>
 #include <time.h>
 
+#include "mtr.h"
 #include "dns.h"
+#include "net.h"
 
 #ifdef NO_STRERROR
 extern int sys_nerr;
@@ -55,6 +57,8 @@ extern char *sys_errlist[];
 /*  Hmm, it seems Irix requires this  */
 extern int errno;
 
+extern int af;
+
 /* Defines */
 
 #undef Debug
@@ -268,10 +272,18 @@ dword resolvecount = 0;
 long idseed = 0xdeadbeef;
 long aseed;
 
-struct sockaddr_in from;
+#ifdef ENABLE_IPV6
+struct sockaddr_storage from_sastruct;
+struct sockaddr_in6 * from6 = (struct sockaddr_in6 *) &from_sastruct;
+#else
+struct sockaddr_in from_sastruct;
+#endif
+
+struct sockaddr_in * from4 = (struct sockaddr_in *) &from_sastruct;
+struct sockaddr * from = (struct sockaddr *) &from_sastruct;
 
 int resfd;
-int fromlen = sizeof(struct sockaddr_in);
+int fromlen = sizeof from_sastruct;
 
 char tempstring[16384+1+1];
 char sendstring[1024+1];
@@ -413,28 +425,36 @@ void clearset(fd_set *set)
 }
 
 
-char *strlongip(ip_t ip)
+char *strlongip(ip_t ip)
 {
-  struct in_addr a;
-  a.s_addr = htonl(ip);
-  return inet_ntoa(a);
+#ifdef ENABLE_IPV6
+  static char buf[INET6_ADDRSTRLEN];
+
+  return (char *) inet_ntop( af, ip, buf, sizeof buf );
+#else
+  return inet_ntoa( *ip );
+#endif
 }
 
 
-ip_t longipstr(char *s)
+int longipstr(char *s, ip_t *dst)
 {
-  return inet_addr(s);
+#ifdef ENABLE_IPV6
+  return inet_pton( af, s, dst );
+#else
+  return inet_aton( s, dst );
+#endif
 }
 
 
-int dns_forward(char *name)
+struct hostent * dns_forward(char *name)
 {
   struct hostent *host;
 
   if ((host = gethostbyname(name)))
-    return *(int *)host->h_addr;
+    return host;
   else
-    return 0;
+    return NULL;
 }
 
 
@@ -468,7 +488,7 @@ void dns_open(void)
            strerror(errno));
     exit(-1);
   }
-  localhost = longipstr("127.0.0.1");
+  longipstr( "127.0.0.1", &localhost );
   aseed = time(NULL) ^ (time(NULL) << 3) ^ (dword)getpid();
   for (i = 0;i < BashSize;i++) {
     idbash[i] = NULL;
@@ -497,9 +517,27 @@ dword getidbash(word id)
 }
 
 
-dword getipbash(ip_t ip)
+dword getipbash(ip_t ip)
 {
-  return (dword)BashModulo(ip);
+  char *p = (char *) ip;
+  int i, len = 0;
+  dword bashvalue = 0;
+
+  switch ( af ) {
+  case AF_INET:
+    len = sizeof (struct in_addr);
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    len = sizeof (struct in6_addr);
+    break;
+#endif
+  }
+  for (i = 0; i < len; i++, p++) {
+    bashvalue^= *p;
+    bashvalue+= (*p >> 1) + (bashvalue >> 1);
+  }
+  return BashModulo(bashvalue);
 }
 
 
@@ -611,14 +649,18 @@ void linkresolveip(struct resolve *addrp)
   struct resolve *rp;
   dword bashnum;
 
-  bashnum = getipbash(addrp->ip);
+  bashnum = getipbash( &(addrp->ip) );
   rp = ipbash[bashnum];
   if (rp) {
-    while ((rp->nextip) && (addrp->ip > rp->nextip->ip))
+    while ((rp->nextip) &&
+          ( addrcmp( (void *) &(addrp->ip),
+                     (void *) &(rp->nextip->ip), af ) > 0 ))
       rp = rp->nextip;
-    while ((rp->previousip) && (addrp->ip < rp->previousip->ip))
+    while ((rp->previousip) &&
+          ( addrcmp( (void *) &(addrp->ip),
+                     (void *) &(rp->previousip->ip), af ) < 0 ))
       rp = rp->previousip;
-    if (rp->ip < addrp->ip) {
+    if ( addrcmp( (void *) &(rp->ip), (void *) &(addrp->ip), af ) < 0 ) {
       addrp->previousip = rp;
       addrp->nextip = rp->nextip;
       if (rp->nextip)
@@ -641,7 +683,7 @@ void unlinkresolveip(struct resolve *rp)
 {
   dword bashnum;
 
-  bashnum = getipbash(rp->ip);
+  bashnum = getipbash( &(rp->ip) );
   if (ipbash[bashnum] == rp)
     ipbash[bashnum] = (rp->previousip)? rp->previousip : rp->nextip;
   if (rp->nextip)
@@ -781,7 +823,7 @@ struct resolve *findhost(char *hostname)
 }
 
 
-struct resolve *findip(ip_t ip)
+struct resolve *findip(ip_t ip)
 {
   struct resolve *rp;
   dword bashnum;
@@ -789,11 +831,13 @@ struct resolve *findip(ip_t ip)
   bashnum = getipbash(ip);
   rp = ipbash[bashnum];
   if (rp) {
-    while ((rp->nextip) && (ip >= rp->nextip->ip))
+    while ((rp->nextip) &&
+          ( addrcmp( (void *) ip, (void *) &(rp->nextip->ip), af ) >= 0 ))
       rp = rp->nextip;
-    while ((rp->previousip) && (ip <= rp->previousip->ip))
+    while ((rp->previousip) &&
+           ( addrcmp( (void *) ip, (void *) &(rp->previousip->ip), af ) <= 0 ))
       rp = rp->previousip;
-    if (ip == rp->ip) {
+    if ( addrcmp( (void *) ip, (void *) &(rp->ip), af ) == 0 ) {
       ipbash[bashnum] = rp;
       return rp;
     } else
@@ -838,15 +882,24 @@ void resendrequest(struct resolve *rp,int type)
       restell(tempstring);
     }
   } else if (type == T_PTR) {
+    switch ( af ) {
+    case AF_INET:
     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]);
+      break;
+#ifdef ENABLE_IPV6
+    case AF_INET6:
+      addr2ip6arpa( &(rp->ip), tempstring );
+      break;
+#endif
+    }
     dorequest(tempstring,type,rp->id);
     if (debug) {
       sprintf(tempstring,"Resolver: Sent domain lookup request for \"%s\".",
-             strlongip(rp->ip));
+             strlongip( &(rp->ip) ));
       restell(tempstring);
     }
   }
@@ -887,7 +940,7 @@ void passrp(struct resolve *rp,long ttl)
 }
 
 
-void parserespacket(byte *s,int l)
+void parserespacket(byte *s, int l)
 {
   struct resolve *rp;
   packetheader *hp;
@@ -898,11 +951,11 @@ void parserespacket(byte *s,int l)
   word rr,datatype,class,qdatatype,qclass;
   byte rdatalength;
 
-  if (l < sizeof(packetheader)) {
+  if (l < (int) sizeof(packetheader)) {
     restell("Resolver error: Packet smaller than standard header size.");
     return;
   }
-  if (l == sizeof(packetheader)) {
+  if (l == (int) sizeof(packetheader)) {
     restell("Resolver error: Packet has empty body.");
     return;
   }
@@ -954,12 +1007,20 @@ void parserespacket(byte *s,int l)
       case STATE_PTRREQ1:
       case STATE_PTRREQ2:
       case STATE_PTRREQ3:
+        switch ( af ) {
+        case AF_INET:
        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;
+#ifdef ENABLE_IPV6
+        case AF_INET6:
+          addr2ip6arpa( &(rp->ip), stackstring );
+          break;
+#endif
+        }
       }
       *namestring = '\0';
       r = dn_expand(s,s + l,c,namestring,MAXDNAME);
@@ -1068,17 +1129,17 @@ void parserespacket(byte *s,int l)
                restell(tempstring);
                return;
              }
-             if (memcmp(&rp->ip,(ip_t *)c,sizeof(ip_t))) {
+             if ( addrcmp( (void *) &(rp->ip), (void *) c, af ) == 0 ) {
                sprintf(tempstring,"Resolver: Reverse authentication failed: %s != ",
-                       strlongip(rp->ip));
-               memcpy(&alignedip,(ip_t *)c,sizeof(ip_t));
-               strcat(tempstring,strlongip(alignedip));
+                       strlongip( &(rp->ip) ));
+               addrcpy( (void *) &alignedip, (void *) c, af );
+               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));
+                       strlongip( &(rp->ip) ),nonull(rp->hostname));
                restell(tempstring);
                res_reversesuccess++;
                passrp(rp,ttl);
@@ -1157,21 +1218,26 @@ void dns_ack(void)
 {
   int r,i;
 
-  r = recvfrom(resfd,(byte *)resrecvbuf,MaxPacketsize,0,(struct sockaddr *)&from,&fromlen);
+  r = recvfrom(resfd,(byte *)resrecvbuf,MaxPacketsize,0,
+               from, &fromlen);
   if (r > 0) {
     /* Check to see if this server is actually one we sent to */
-    if (from.sin_addr.s_addr == localhost) {
+    if ( addrcmp( (void *) &(from4->sin_addr), (void *) &localhost,
+                  (int) AF_INET ) == 0 ) {
       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 */
+       if ( addrcmp( (void *) &(_res.nsaddr_list[i].sin_addr),
+                     (void *) &(from4->sin_addr), (int) AF_INET ) == 0 ||
+            addrcmp( (void *) &(_res.nsaddr_list[i].sin_addr),
+                     (void *) &unspec_addr, (int) AF_INET ) != 0 )     /* 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)
+       if ( addrcmp( (void *) &(_res.nsaddr_list[i].sin_addr),
+                     (void *) &(from4->sin_addr), AF_INET ) == 0 )
          break;
     if (i == _res.nscount) {
       sprintf(tempstring,"Resolver error: Received reply from unknown source: %s",
-             inet_ntoa(from.sin_addr));
+             inet_ntoa(from4->sin_addr ));
       restell(tempstring);
     } else
       parserespacket((byte *)resrecvbuf,r);
@@ -1206,7 +1272,8 @@ void dns_events(double *sinterval)
     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);
+                nonull(rp->hostname), strlongip( &(rp->ip) ), 
+               rp->state, rp->expiretime, sweeptime);
        restell(tempstring);
       }
       unlinkresolve(rp);
@@ -1240,11 +1307,10 @@ void dns_events(double *sinterval)
 }
 
 
-char *dns_lookup2(ip_t ip)
+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)) {
@@ -1270,16 +1336,16 @@ char *dns_lookup2(ip_t ip)
   rp = allocresolve();
   rp->state = STATE_PTRREQ1;
   rp->expiretime = sweeptime + ResRetryDelay1;
-  rp->ip = ip;
+  addrcpy( (void *) &(rp->ip), (void *) ip, af );
   linkresolve(rp);
-  rp->ip = ip;
+  addrcpy( (void *) &(rp->ip), (void *) ip, af );
   linkresolveip(rp);
   sendrequest(rp,T_PTR);
   return NULL;
 }
 
 
-char *dns_lookup(ip_t ip)
+char *dns_lookup(ip_t ip)
 {
   char *t;
 
@@ -1287,3 +1353,19 @@ char *dns_lookup(ip_t ip)
   t = dns_lookup2 (ip);
   return (t&&use_dns)?t:strlongip(ip);
 }
+
+#ifdef ENABLE_IPV6
+/* Returns an ip6.arpa character string. */
+void addr2ip6arpa( ip_t * ip, char * buf ) {
+  unsigned char * p = (char *) ip;
+  unsigned char * b = buf;
+  int i;
+
+  for ( i = sizeof (struct in6_addr) - 1; i >= 0; i-- ) {
+        sprintf( b, "%x.%x.", p[i] % 16, p[i] >> 4 );
+        b += 4;
+  }
+  sprintf( b, "ip6.arpa" );
+  return;
+}
+#endif
diff --git a/dns.h b/dns.h
index 8daccb7e4c0fab2eab794c519741bae440e5b09b..cbf0006dec2387b61a4da7598e392646a1ead831 100644 (file)
--- a/dns.h
+++ b/dns.h
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* Typedefs */
-
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long dword;
-
-typedef unsigned int ip_t;
-
+#include <netinet/in.h>
 
 
 /*  Prototypes for dns.c  */
 
-void dns_open();
-int dns_waitfd();
-void dns_ack();
+void dns_open(void);
+int dns_waitfd(void);
+void dns_ack(void);
 void dns_events(double *sinterval);
-char *dns_lookup(ip_t address);
-char *dns_lookup2(ip_t address);
-int dns_forward(char *name);
-char *strlongip(ip_t ip);
+char *dns_lookup(ip_t * address);
+char *dns_lookup2(ip_t * address);
+struct hostent * dns_forward(char *name);
+char *strlongip(ip_t * ip);
+
+void addr2ip6arpa( ip_t * ip, char * buf );
 
-extern int dns;
index 4ac33b71824d389cbc70c9eb0f5e0b2073b28567..2f2689397a29ce61646d00f40c497cd73f13726e 100644 (file)
--- a/getopt.h
+++ b/getopt.h
@@ -101,7 +101,7 @@ struct option
    errors, only prototype getopt for the GNU C library.  */
 extern int getopt (int argc, char *const *argv, const char *shortopts);
 #else /* not __GNU_LIBRARY__ */
-extern int getopt ();
+extern int getopt (void);
 #endif /* __GNU_LIBRARY__ */
 extern int getopt_long (int argc, char *const *argv, const char *shortopts,
                        const struct option *longopts, int *longind);
@@ -115,11 +115,11 @@ extern int _getopt_internal (int argc, char *const *argv,
                             const struct option *longopts, int *longind,
                             int long_only);
 #else /* not __STDC__ */
-extern int getopt ();
-extern int getopt_long ();
-extern int getopt_long_only ();
+extern int getopt (void);
+extern int getopt_long (void);
+extern int getopt_long_only (void);
 
-extern int _getopt_internal ();
+extern int _getopt_internal (void);
 #endif /* __STDC__ */
 
 #ifdef __cplusplus
diff --git a/gtk.c b/gtk.c
index 2d72a29432432778b3cb4e805042fd2634e2a910..63e43e583e447bcd305cbac15529fef4baafbf8e 100644 (file)
--- a/gtk.c
+++ b/gtk.c
 #include <sys/types.h>
 
 #ifndef NO_GTK
+#include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
 #include <gtk/gtk.h>
 
+#include "mtr.h"
 #include "net.h"
 #include "dns.h"
 #include "mtr-gtk.h"
 #include "img/mtr_icon.xpm"
 #endif
 
-
 gint gtk_ping(gpointer data);
 
 
 extern char *Hostname;
 extern float WaitTime;
+extern int af;
 static int tag;
 static GtkWidget *Pause_Button;
 
@@ -67,7 +71,8 @@ void gtk_do_init(int *argc, char ***argv)
   }
 }
 
-int gtk_detect(int *argc, char ***argv) 
+
+int gtk_detect(UNUSED int *argc, UNUSED char ***argv) 
 {
   if(getenv("DISPLAY") != NULL) {
     /* If we do this here, gtk_init exits on an error. This happens
@@ -79,14 +84,16 @@ int gtk_detect(int *argc, char ***argv)
   }
 }
 
-gint Window_destroy(GtkWidget *Window, gpointer data) 
+
+gint Window_destroy(UNUSED GtkWidget *Window, UNUSED gpointer data) 
 {
   gtk_main_quit();
 
   return FALSE;
 }
 
-gint Restart_clicked(GtkWidget *Button, gpointer data) 
+
+gint Restart_clicked(UNUSED GtkWidget *Button, UNUSED gpointer data) 
 {
   net_reset();
   gtk_redraw();
@@ -95,7 +102,7 @@ gint Restart_clicked(GtkWidget *Button, gpointer data)
 }
 
 
-gint Pause_clicked(GtkWidget *Button, gpointer data) 
+gint Pause_clicked(UNUSED GtkWidget *Button, UNUSED gpointer data) 
 {
   static int paused = 0;
 
@@ -110,6 +117,7 @@ gint Pause_clicked(GtkWidget *Button, gpointer data)
   return FALSE;
 }
 
+
 /*
  * There is a small problem with the following code:
  * The timeout is canceled and removed in order to ensure that
@@ -119,7 +127,7 @@ gint Pause_clicked(GtkWidget *Button, gpointer data)
  * What's the problem with this? (-> "I don't think so)  -- REW
  */
 
-gint WaitTime_changed(GtkAdjustment *Adj, GtkWidget *Button) 
+gint WaitTime_changed(UNUSED GtkAdjustment *Adj, UNUSED GtkWidget *Button) 
 {
   WaitTime = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(Button));
   gtk_timeout_remove (tag);
@@ -129,9 +137,10 @@ gint WaitTime_changed(GtkAdjustment *Adj, GtkWidget *Button)
   return FALSE;
 }
 
-gint Host_activate(GtkWidget *Entry, gpointer data) 
+
+gint Host_activate(GtkWidget *Entry, UNUSED gpointer data) 
 {
-  int addr;
+  struct hostent * addr;
 
   addr = dns_forward(gtk_entry_get_text(GTK_ENTRY(Entry)));
   if(addr) {
@@ -147,6 +156,7 @@ gint Host_activate(GtkWidget *Entry, gpointer data)
   return FALSE;
 }
 
+
 GdkPixmap *gtk_load_pixmap(char **pixmap) 
 {
   return gdk_pixmap_colormap_create_from_xpm_d(NULL, 
@@ -154,6 +164,7 @@ GdkPixmap *gtk_load_pixmap(char **pixmap)
                                               NULL, NULL, pixmap);
 }
 
+
 void Toolbar_fill(GtkWidget *Toolbar) 
 {
   GtkWidget *Button;
@@ -207,6 +218,7 @@ void Toolbar_fill(GtkWidget *Toolbar)
   gtk_widget_show(Entry);
 }
 
+
 char *Report_Text[] = { "Hostname", "Loss", "Rcv", "Snt", "Last", "Best", "Avg", "Worst", "StDev", NULL };
 int Report_Positions[] = { 10, 200, 240, 280, 320, 360, 400, 440, 480, 0 };
 GtkWidget *Report;
@@ -214,7 +226,7 @@ GtkWidget *ReportBody;
 
 GtkWidget *GetRow(int index) 
 {
-  int addr;
+  ip_t * addr;
   char *name;
   GtkWidget *Row, *Label;
 
@@ -222,7 +234,7 @@ GtkWidget *GetRow(int index)
   
   addr = net_addr(index);
   name = "???";
-  if(addr != 0) {
+  if ( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) {
     name = dns_lookup(addr);
     if(!name) {
       /* Actually this is not neccesary: 
@@ -238,7 +250,8 @@ GtkWidget *GetRow(int index)
   return Row;
 }
 
-GtkWidget *Scrollarea_create() 
+
+GtkWidget *Scrollarea_create(void)
 {
   GtkWidget *List;
   GtkWidget *scroll;
@@ -265,6 +278,7 @@ GtkWidget *Scrollarea_create()
   return scroll;
 }
 
+
 void gtk_add_row(GtkWidget *List) 
 {
   int at;
@@ -286,10 +300,12 @@ void gtk_add_row(GtkWidget *List)
   gtk_widget_show(Row);
 }
 
+
 void gtk_set_field(GtkCList *List, int row, int ix, char *str) {
   gtk_clist_set_text(List, row, ix, str);
 }
 
+
 //void gtk_set_field_num(GtkCList *List, int row, int ix, char *format, int num) {
 // changed int to dobule byMin
 void gtk_set_field_num(GtkCList *List, int row, int ix, char *format, double num) 
@@ -300,20 +316,20 @@ void gtk_set_field_num(GtkCList *List, int row, int ix, char *format, double num
   gtk_set_field(List, row, ix, str);
 }
 
+
 void gtk_update_row(GtkCList *List, int row) 
 {
-  int addr;
+  ip_t *addr;
   char str[256], *name;
   GdkColor color;
   GdkColormap *cmap;
 
   addr = net_addr(row);
   name = "???";
-  if(addr != 0) {
+  if ( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) {
     name = dns_lookup(addr);
     if(!name) {
-      sprintf(str, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, 
-             (addr >> 8) & 0xff, addr & 0xff);
+      sprintf(str, "%s", strlongip( addr ));
       name = str;
     }
   }
@@ -333,7 +349,7 @@ void gtk_update_row(GtkCList *List, int row)
   /* the row - net_min() is kind of not clean, need some more work */
   gtk_set_field(List, row - net_min(), 0, name);
 
-  gtk_set_field_num(List, row - net_min(), 1, "%.0f%%", net_loss(row)/1000.0);
+  gtk_set_field_num(List, row - net_min(), 1, "%.1f%%", net_loss(row)/1000.0);
   gtk_set_field_num(List, row - net_min(), 2, "%.0f", net_returned(row));  
   gtk_set_field_num(List, row - net_min(), 3, "%.0f", net_xmit(row));
   
@@ -342,10 +358,10 @@ void gtk_update_row(GtkCList *List, int row)
   gtk_set_field_num(List, row - net_min(), 6, "%.0f", net_avg(row)/1000.0);  
   gtk_set_field_num(List, row - net_min(), 7, "%.0f", net_worst(row)/1000.0);
   gtk_set_field_num(List, row - net_min(), 8, "%.2f", net_stdev(row)/1000.0);
-  
 }
 
-void gtk_redraw() 
+
+void gtk_redraw(void)
 {
   int at  = net_min(); // changed from 0 to net_min for TTL stuff byMin
   int max = net_max();
@@ -368,6 +384,7 @@ void gtk_redraw()
   gtk_clist_thaw(GTK_CLIST(ReportBody));
 }
 
+
 void Window_fill(GtkWidget *Window) 
 {
   GtkWidget *VBox;
@@ -393,7 +410,8 @@ void Window_fill(GtkWidget *Window)
   gtk_widget_show(VBox);
 }
 
-void gtk_open() 
+
+void gtk_open(void)
 {
   GtkWidget *Window;
   GdkPixmap *icon;
@@ -423,16 +441,19 @@ void gtk_open()
   gdk_window_set_icon_name(Window->window, "mtr");
 }
 
-void gtk_close() 
+
+void gtk_close(void)
 {
 }
 
-int gtk_keyaction() 
+
+int gtk_keyaction(void)
 {
   return 0;
 }
 
-gint gtk_ping(gpointer data) 
+
+gint gtk_ping(UNUSED gpointer data) 
 {
   gtk_redraw();
   net_send_batch();
@@ -441,20 +462,21 @@ gint gtk_ping(gpointer data)
   return TRUE;
 }
 
-void gtk_net_data(gpointer data, gint fd, GdkInputCondition cond) 
+
+void gtk_net_data(UNUSED gpointer data, UNUSED gint fd, UNUSED GdkInputCondition cond) 
 {
   net_process_return();
 }
 
-void gtk_dns_data(gpointer data, gint fd, GdkInputCondition cond) 
+
+void gtk_dns_data(UNUSED gpointer data, UNUSED gint fd, UNUSED GdkInputCondition cond) 
 {
   dns_ack();
-
   gtk_redraw();
 }
 
 
-void gtk_loop() 
+void gtk_loop(void
 {
   gtk_add_ping_timeout ();
   gdk_input_add(net_waitfd(), GDK_INPUT_READ, gtk_net_data, NULL);
@@ -462,3 +484,5 @@ void gtk_loop()
 
   gtk_main();
 }
+
+
index d12d878c1c168ac7b73567a19b6915ebac7bc4f2..732a71a6faffa5b127c9b2000837b8111aa93de2 100644 (file)
@@ -18,8 +18,8 @@
 */
 
 /*  Prototypes for curses.c  */
-void mtr_curses_open();
-void mtr_curses_close();
-void mtr_curses_redraw();
-int mtr_curses_keyaction();
-void mtr_curses_clear();
+void mtr_curses_open(void);
+void mtr_curses_close(void);
+void mtr_curses_redraw(void);
+int mtr_curses_keyaction(void);
+void mtr_curses_clear(void);
index fe87bb3c07c661e7312b0832a43d2910cd065585..01bc03d91312896f973e03a311e7e4b0ab194dc5 100644 (file)
--- a/mtr-gtk.h
+++ b/mtr-gtk.h
@@ -19,8 +19,8 @@
 
 /*  Prototypes for gtk.c  */
 int gtk_detect(int *argc, char ***argv);
-void gtk_open();
-void gtk_close();
-void gtk_redraw();
-int gtk_keyaction();
-void gtk_loop();
+void gtk_open(void);
+void gtk_close(void);
+void gtk_redraw(void);
+int gtk_keyaction(void);
+void gtk_loop(void);
diff --git a/mtr.8 b/mtr.8
index 89ac76c32661855c7526b9a8ca145a4833a96745..d6708590410958e42c8dc8873d06282f4ba9445e 100644 (file)
--- a/mtr.8
+++ b/mtr.8
@@ -8,7 +8,7 @@ mtr \- a network diagnostic tool
 .SH SYNOPSIS
 .B mtr 
 [\c
-.B \-hvrctglsni\c
+.B \-hvrctglsni46\c
 ]
 [\c
 .B \-\-help\c
@@ -204,6 +204,16 @@ what you want).
 Use this option to specify the positive number of seconds between ICMP
 ECHO requests.  The default value for this parameter is one second.
 
+.TP
+.B \-4
+.br
+Use IPv4 only.
+
+.TP
+.B \-6
+.br
+Use IPv6 only.
+
 .SH BUGS
 
 Some modern routers give a lower priority to ICMP ECHO packets than 
diff --git a/mtr.c b/mtr.c
index fc52824d6510b58c5b1b997f9df0645cd296ae6a..7cb02f4deef4201ac3a3c0c312254d66c990ea7d 100644 (file)
--- a/mtr.c
+++ b/mtr.c
@@ -26,7 +26,9 @@
 #include <netinet/in.h>
 #include <sys/socket.h> 
 #include <unistd.h>
+#include <strings.h>
 
+#include "mtr.h"
 #include "mtr-curses.h"
 #include "getopt.h"
 #include "display.h"
@@ -141,6 +143,8 @@ void parse_arg (int argc, char **argv)
     { "address", 1, 0, 'a' },
     { "first-ttl", 1, 0, 'f' },        /* -f & -m are borrowed from traceroute */
     { "max-ttl", 1, 0, 'm' },
+    { "inet", 0, 0, '4' },     /* IPv4 only */
+    { "inet6", 0, 0, '6' },    /* IPv6 only */
     { 0, 0, 0, 0 }
   };
 
@@ -148,7 +152,7 @@ void parse_arg (int argc, char **argv)
   while(1) {
     /* added f:m:o: byMin */
     opt = getopt_long(argc, argv,
-                     "vhrxtglpo:i:c:s:b:Q:na:f:m:", long_options, NULL);
+                     "vhrxtglpo:i:c:s:b:Q:na:f:m:46", long_options, NULL);
     if(opt == -1)
       break;
 
@@ -253,6 +257,17 @@ void parse_arg (int argc, char **argv)
        tos = 0;
       }
       break;
+    case '4':
+      af = AF_INET;
+      break;
+    case '6':
+#ifdef ENABLE_IPV6
+      af = AF_INET6;
+      break;
+#else
+      fprintf( stderr, "IPv6 not enabled.\n" );
+      break;
+#endif
     }
   }
 
@@ -288,11 +303,11 @@ void parse_mtr_options (char *string)
   argv[0] = "mtr";
   argc = 1;
   p = strtok (string, " \t");
-  while (p && (argc < (sizeof(argv)/sizeof(argv[0])))) {
+  while (p != NULL && ((size_t) argc < (sizeof(argv)/sizeof(argv[0])))) {
     argv[argc++] = p;
     p = strtok (NULL, " \t");
   }
-  if (p) {
+  if (p != NULL) {
     fprintf (stderr, "Warning: extra arguments ignored: %s", p);
   }
 
@@ -303,13 +318,24 @@ void parse_mtr_options (char *string)
 
 int main(int argc, char **argv) 
 {
-  int               traddr;
+  ip_t *            traddr;
   struct hostent *  host                = NULL;
   int               net_preopen_result;
+#ifdef ENABLE_IPV6
+  struct addrinfo       hints, *res;
+  int                   error;
+  struct hostent        trhost;
+  char *                alptr[2];
+  struct sockaddr_in *  sa4;
+  struct sockaddr_in6 * sa6;
+#endif
 
   /*  Get the raw sockets first thing, so we can drop to user euid immediately  */
 
-  net_preopen_result = net_preopen ();
+  if ( ( net_preopen_result = net_preopen () ) ) {
+    fprintf( stderr, "mtr: unable to get raw sockets.\n" );
+    exit( EXIT_FAILURE );
+  }
 
   /*  Now drop to user permissions  */
   if (setuid(getuid())) {
@@ -342,7 +368,7 @@ int main(int argc, char **argv)
   }
 
   if (PrintHelp) {
-    printf("usage: %s [-hvrctglsni] [--help] [--version] [--report]\n"
+    printf("usage: %s [-hvrctglsni46] [--help] [--version] [--report]\n"
           "\t\t[--report-cycles=COUNT] [--curses] [--gtk]\n"
            "\t\t[--raw] [--split] [--no-dns] [--address interface]\n" /* BL */
            "\t\t[--psize=bytes/-p=bytes]\n"            /* ok */
@@ -368,40 +394,53 @@ int main(int argc, char **argv)
   }
 
 #ifdef ENABLE_IPV6
-  if (af == AF_UNSPEC) {
-    af = AF_INET6;
-    host = gethostbyname2(Hostname, af);
-    if (host == NULL) af = AF_INET;
+  /* gethostbyname2() is deprecated so we'll use getaddrinfo() instead. */
+  bzero( &hints, sizeof hints );
+  hints.ai_family = af;
+  hints.ai_socktype = SOCK_DGRAM;
+  error = getaddrinfo( Hostname, "0", &hints, &res );
+  if ( error ) {
+    perror( gai_strerror(error) );
+    exit( EXIT_FAILURE );
   }
-#endif
-   
-  if (host == NULL) {
-    host = gethostbyname(Hostname);
+  /* Convert the first addrinfo into a hostent. */
+  host = &trhost;
+  bzero( host, sizeof trhost );
+  host->h_name = res->ai_canonname;
+  host->h_aliases = NULL;
+  host->h_addrtype = res->ai_family;
+  af = res->ai_family;
+  host->h_length = res->ai_addrlen;
+  host->h_addr_list = alptr;
+  switch ( af ) {
+  case AF_INET:
+    sa4 = (struct sockaddr_in *) res->ai_addr;
+    alptr[0] = (void *) &(sa4->sin_addr);
+    break;
+  case AF_INET6:
+    sa6 = (struct sockaddr_in6 *) res->ai_addr;
+    alptr[0] = (void *) &(sa6->sin6_addr);
+    break;
+  default:
+    fprintf( stderr, "mtr unknown address type\n" );
+    exit( EXIT_FAILURE );
   }
-  
+  alptr[1] = NULL;
+#else
+    host = gethostbyname(Hostname);
   if (host == NULL) {
-    herror("mtr");
+    herror("mtr gethostbyname");
     exit(1);
   }
+  af = host->h_addrtype;
+#endif
 
-  switch (af) {
-    case AF_INET:
-      traddr = *(int *)host->h_addr;
+  traddr = (ip_t *) host->h_addr;
   
-      if (net_open(traddr) != 0) {
+  if (net_open(host) != 0) {
        fprintf(stderr, "mtr: Unable to start net module.\n");
         exit(1);
       }
-      break;
-#ifdef ENABLE_IPV6
-     case AF_INET6:
-       if(net6_open((struct in6_addr *)host->h_addr) != 0) {
-         printf("mtr: Unable to get raw socket.  (Executable not suid?)\n");
-         exit(1);
-       }
-       break;
-#endif
-  }
 
   display_open();
   dns_open();
diff --git a/mtr.h b/mtr.h
new file mode 100644 (file)
index 0000000..5fecd2f
--- /dev/null
+++ b/mtr.h
@@ -0,0 +1,41 @@
+/*
+    mtr  --  a network diagnostic tool
+    Copyright (C) 1997,1998  Matt Kimball
+    Copyright (C) 2005 R.E.Wolff@BitWizard.nl
+
+    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.
+*/
+
+/* Typedefs */
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+#ifdef ENABLE_IPV6
+typedef struct in6_addr ip_t;
+#else
+typedef struct in_addr ip_t;
+#endif
+
+extern int dns;
+extern int use_dns;
+
+#ifdef __GNUC__
+#define UNUSED __attribute__((__unused__))
+#else
+#define UNUSED
+#endif
+
diff --git a/net.c b/net.c
index 0ed228e54eff435e1e7e2ec5802f46d702fa6132..22861a742d808cac956c2d97fa169886442b1bb7 100644 (file)
--- a/net.c
+++ b/net.c
 #include <stdlib.h>
 #include <math.h>
 #include <errno.h>
+#include <string.h>
 
+#include "mtr.h"
 #include "net.h"
 #include "display.h"
-
+#include "dns.h"
 
 /*  We can't rely on header files to provide this information, because
     the fields have different names between, for instance, Linux and 
@@ -81,8 +83,8 @@ struct IPHeader {
 #endif
 
 struct nethost {
-  uint32 addr;
-  uint32 addrs[MAXPATH];       /* for multi paths byMin */
+  ip_t addr;
+  ip_t addrs[MAXPATH]; /* for multi paths byMin */
   int xmit;
   int returned;
   int sent;
@@ -127,13 +129,40 @@ static struct sequence sequence[MaxSequence];
 static struct timeval reset = { 0, 0 };
 
 int    timestamp;
+int    sendsock4;
+int    recvsock4;
+int    sendsock6;
+int    recvsock6;
 int    sendsock;
 int    recvsock;
-struct sockaddr_in sourceaddress;
-struct sockaddr_in remoteaddress;
+
+#ifdef ENABLE_IPV6
+struct sockaddr_storage sourcesockaddr_struct;
+struct sockaddr_storage remotesockaddr_struct;
+struct sockaddr_in6 * ssa6 = (struct sockaddr_in6 *) &sourcesockaddr_struct;
+struct sockaddr_in6 * rsa6 = (struct sockaddr_in6 *) &remotesockaddr_struct;
+#else
+struct sockaddr_in sourcesockaddr_struct;
+struct sockaddr_in remotesockaddr_struct;
+#endif
+
+struct sockaddr * sourcesockaddr = (struct sockaddr *) &sourcesockaddr_struct;
+struct sockaddr * remotesockaddr = (struct sockaddr *) &remotesockaddr_struct;
+struct sockaddr_in * ssa4 = (struct sockaddr_in *) &sourcesockaddr_struct;
+struct sockaddr_in * rsa4 = (struct sockaddr_in *) &remotesockaddr_struct;
+
+ip_t * sourceaddress;
+ip_t * remoteaddress;
 
 /* XXX How do I code this to be IPV6 compatible??? -- REW */
-struct in_addr localaddr;
+#ifdef ENABLE_IPV6
+char localaddr[INET6_ADDRSTRLEN];
+#else
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#endif
+char localaddr[INET_ADDRSTRLEN];
+#endif
 
 static int batch_at = 0;
 static int numhosts = 10;
@@ -143,7 +172,7 @@ extern int maxTTL;          /* last hub to ping byMin*/
 extern int packetsize;         /* packet size used by ping */
 extern int bitpattern;         /* packet bit pattern used by ping */
 extern int tos;                        /* type of service set in ping packet*/
-
+extern int af;                 /* address family of remote target */
 
 
 /* return the number of microseconds to wait before sending the next
@@ -204,50 +233,77 @@ void net_send_query(int index)
 {
   /*ok  char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader)];*/
   char packet[MAXPACKET];
-  struct IPHeader *ip;
+  struct IPHeader *ip = (struct IPHeader *) packet;
   struct ICMPHeader *icmp;
 
   /*ok  int packetsize = sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + datasize;*/
   int rv;
   static int first=1;
+  int ttl, iphsize = 0, echotype = 0, salen = 0;
+
+  ttl = index + 1;
 
   if ( packetsize < MINPACKET ) packetsize = MINPACKET;
   if ( packetsize > MAXPACKET ) packetsize = MAXPACKET;
 
   memset(packet, (unsigned char) abs(bitpattern), abs(packetsize));
 
-  ip = (struct IPHeader *)packet;
-  icmp = (struct ICMPHeader *)(packet + sizeof(struct IPHeader));
+  switch ( af ) {
+  case AF_INET:
+    iphsize = sizeof (struct IPHeader);
 
   ip->version = 0x45;
   ip->tos = tos;
   ip->len = BSDfix ? abs(packetsize): htons (abs(packetsize));
   ip->id = 0;
   ip->frag = 0;    /* 1, if want to find mtu size? Min */
-  ip->ttl = index + 1;
+    ip->ttl = ttl;
   ip->protocol = IPPROTO_ICMP;
   ip->check = 0;
 
   /* BSD needs the source address here, Linux & others do not... */
-  ip->saddr = saddr_correction(sourceaddress.sin_addr.s_addr);
-  ip->daddr = remoteaddress.sin_addr.s_addr;
+    addrcpy( (void *) &(ip->saddr), (void *) &(ssa4->sin_addr), AF_INET );
+    addrcpy( (void *) &(ip->daddr), (void *) remoteaddress, AF_INET );
+
+    echotype = ICMP_ECHO;
+    salen = sizeof (struct sockaddr_in);
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    iphsize = 0;
+    if ( setsockopt( sendsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+                     &ttl, sizeof ttl ) ) {
+      perror( "setsockopt IPV6_UNICAST_HOPS" );
+      exit( EXIT_FAILURE);
+    }
+    echotype = ICMP6_ECHO_REQUEST;
+    salen = sizeof (struct sockaddr_storage);
+    break;
+#endif
+  }
 
-  icmp->type     = ICMP_ECHO;
+  icmp = (struct ICMPHeader *)(packet + iphsize);
+  icmp->type     = echotype;
   icmp->code     = 0;
   icmp->checksum = 0;
   icmp->id       = getpid();
   icmp->sequence = new_sequence(index);
+  icmp->checksum = checksum(icmp, abs(packetsize) - iphsize);
 
-  icmp->checksum = checksum(icmp, abs(packetsize) - sizeof(struct IPHeader));
-  ip->check = checksum(ip, abs(packetsize));
+  switch ( af ) {
+  case AF_INET:
+    ip->check = checksum(packet, abs(packetsize));
+    break;
+  }
 
   gettimeofday(&sequence[icmp->sequence].time, NULL);
+
   rv = sendto(sendsock, packet, abs(packetsize), 0, 
-             (struct sockaddr *)&remoteaddress, sizeof(remoteaddress));
+             remotesockaddr, salen);
   if (first && (rv < 0) && (errno == EINVAL)) {
     ip->len = abs (packetsize);
     rv = sendto(sendsock, packet, abs(packetsize), 0, 
-               (struct sockaddr *)&remoteaddress, sizeof(remoteaddress));
+               remotesockaddr, salen);
     if (rv >= 0) {
       fprintf (stderr, "You've got a broken (FreeBSD?) system\n");
       BSDfix = 1;
@@ -259,7 +315,7 @@ void net_send_query(int index)
 
 /*   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, void * addr, struct timeval now) 
 {
   int index;
   int totusec;
@@ -280,19 +336,25 @@ 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) {
-    host[index].addr = addr;   // should be out of if as addr can change
-    display_rawhost(index, host[index].addr);
+  if ( addrcmp( (void *) &(host[index].addr),
+               (void *) &unspec_addr, af ) == 0 ) {
+    // should be out of if as addr can change
+    addrcpy( (void *) &(host[index].addr), addr, af );
+    display_rawhost(index, (void *) &(host[index].addr));
 
   /* multi paths by Min */
-    host[index].addrs[0] = addr;
+    addrcpy( (void *) &(host[index].addrs[0]), addr, af );
   } else {
     for( i=0; i<MAXPATH; ) {
-      if( host[index].addrs[i] == addr || host[index].addrs[i] == 0 ) break;
+      if( addrcmp( (void *) &(host[index].addrs[i]), (void *) &addr,
+                   af ) == 0 ||
+          addrcmp( (void *) &(host[index].addrs[i]),
+                  (void *) &unspec_addr, af ) == 0 ) break;
       i++;
     }
-    if( host[index].addrs[i] != addr && i<MAXPATH ) {
-      host[index].addrs[i] = addr;
+    if( addrcmp( (void *) &(host[index].addrs[i]), addr, af ) != 0 && 
+        i<MAXPATH ) {
+      addrcpy( (void *) &(host[index].addrs[i]), addr, af );
     }
   /* end multi paths */
   }
@@ -353,56 +415,110 @@ void net_process_ping(int seq, uint32 addr, struct timeval now)
 /*  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(void
 {
   char packet[MAXPACKET];
-  struct sockaddr_in fromaddr;
-  int fromaddrsize;
+#ifdef ENABLE_IPV6
+  struct sockaddr_storage fromsockaddr_struct;
+  struct sockaddr_in6 * fsa6 = (struct sockaddr_in6 *) &fromsockaddr_struct;
+#else
+  struct sockaddr_in fromsockaddr_struct;
+#endif
+  struct sockaddr * fromsockaddr = (struct sockaddr *) &fromsockaddr_struct;
+  struct sockaddr_in * fsa4 = (struct sockaddr_in *) &fromsockaddr_struct;
+  int fromsockaddrsize;
   int num;
-  struct ICMPHeader *header;
+  struct ICMPHeader *header = NULL;
   struct timeval now;
+  ip_t * fromaddress = NULL;
+  int echoreplytype = 0, timeexceededtype = 0;
 
   gettimeofday(&now, NULL);
+  switch ( af ) {
+  case AF_INET:
+    fromsockaddrsize = sizeof (struct sockaddr_in);
+    fromaddress = (ip_t *) &(fsa4->sin_addr);
+    echoreplytype = ICMP_ECHOREPLY;
+    timeexceededtype = ICMP_TIME_EXCEEDED;
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    fromsockaddrsize = sizeof (struct sockaddr_storage);
+    fromaddress = (ip_t *) &(fsa6->sin6_addr);
+    echoreplytype = ICMP6_ECHO_REPLY;
+    timeexceededtype = ICMP6_TIME_EXCEEDED;
+    break;
+#endif
+  }
 
-  fromaddrsize = sizeof(fromaddr);
   num = recvfrom(recvsock, packet, MAXPACKET, 0, 
-                (struct sockaddr *)&fromaddr, &fromaddrsize);
+                fromsockaddr, &fromsockaddrsize);
 
-  if(num < sizeof(struct IPHeader) + sizeof(struct ICMPHeader))
-    return;
+  switch ( af ) {
+  case AF_INET:
+    if((size_t) num < sizeof(struct IPHeader) + sizeof(struct ICMPHeader))
+      return;
+    header = (struct ICMPHeader *)(packet + sizeof(struct IPHeader));
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    if(num < sizeof(struct ICMPHeader))
+      return;
 
-  header = (struct ICMPHeader *)(packet + sizeof(struct IPHeader));
-  if(header->type == ICMP_ECHOREPLY) {
+    header = (struct ICMPHeader *) packet;
+    break;
+#endif
+  }
+  if (header->type == echoreplytype) {
     if(header->id != (uint16)getpid())
       return;
 
-    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))
-      return;
-    
-    header = (struct ICMPHeader *)(packet + sizeof(struct IPHeader) + 
-                               sizeof(struct ICMPHeader) + sizeof(struct IPHeader));
-    if(header->id != (uint16)getpid())
+    net_process_ping (header->sequence, (void *) fromaddress, now);
+  } else if (header->type == timeexceededtype) {
+    switch ( af ) {
+    case AF_INET:
+
+      if ((size_t) num < sizeof(struct IPHeader) + 
+                         sizeof(struct ICMPHeader) + 
+                         sizeof (struct IPHeader) + 
+                         sizeof (struct ICMPHeader))
+        return;
+      header = (struct ICMPHeader *)(packet + sizeof (struct IPHeader) + 
+                                              sizeof (struct ICMPHeader) + 
+                                              sizeof (struct IPHeader));
+    break;
+#ifdef ENABLE_IPV6
+    case AF_INET6:
+      if ( num < sizeof (struct ICMPHeader) + 
+                 sizeof (struct ip6_hdr) + sizeof (struct ICMPHeader) )
+        return;
+      header = (struct ICMPHeader *) ( packet + 
+                                       sizeof (struct ICMPHeader) +
+                                       sizeof (struct ip6_hdr) );
+      break;
+#endif
+    }
+
+    if (header->id != (uint16)getpid())
       return;
 
-    net_process_ping(header->sequence, fromaddr.sin_addr.s_addr, now);
+    net_process_ping(header->sequence, (void *)fromaddress, now);
   }
 }
 
 
-int net_addr(int at) {
-  return ntohl(host[at].addr);
+ip_t *net_addr(int at) 
+{
+  return (ip_t *)&(host[at].addr);
 }
 
 
-int net_addrs(int at, int i) {
-  return ntohl(host[at].addrs[i]);
+ip_t *net_addrs(int at, int i) 
+{
+  return (ip_t *)&(host[at].addrs[i]);
 }
 
 
-
 int net_loss(int at) 
 {
   if ((host[at].xmit - host[at].transit) == 0) 
@@ -484,7 +600,7 @@ int net_jinta(int at)
 /* end jitter */
 
 
-int net_max() 
+int net_max(void
 {
   int at;
   int max;
@@ -493,9 +609,11 @@ int net_max()
   // replacedByMin
   // for(at = 0; at < MaxHost-2; at++) {
   for(at = 0; at < maxTTL-1; at++) {
-    if(host[at].addr == remoteaddress.sin_addr.s_addr) {
+    if ( addrcmp( (void *) &(host[at].addr),
+                  (void *) remoteaddress, af ) == 0 ) {
       return at + 1;
-    } else if(host[at].addr != 0) {
+    } else if ( addrcmp( (void *) &(host[at].addr),
+                        (void *) &unspec_addr, af ) != 0 ) {
       max = at + 2;
     }
   }
@@ -505,7 +623,7 @@ int net_max()
 
 
 /* add by Min (wonder its named net_min;-)) because of ttl stuff */
-int net_min () 
+int net_min (void
 {
   return ( fstTTL - 1 );
 }
@@ -536,13 +654,13 @@ int net_up(int at)
 }
 
 
-struct in_addr *net_localaddr (void)
+char * net_localaddr (void)
 {
-  return &localaddr;
+  return localaddr;
 }
 
 
-void net_end_transit() 
+void net_end_transit(void
 {
   int at;
   
@@ -551,7 +669,7 @@ void net_end_transit()
   }
 }
 
-int net_send_batch() 
+int net_send_batch(void
 {
   int n_unknown=0, i;
 
@@ -571,7 +689,7 @@ int net_send_batch()
   net_send_query(batch_at);
 
   for (i=fstTTL-1;i<batch_at;i++) {
-    if (host[i].addr == 0)
+    if ( addrcmp( (void *) &(host[i].addr), (void *) &unspec_addr, af ) == 0 )
       n_unknown++;
 
     /* The second condition in the next "if" statement was added in mtr-0.56, 
@@ -579,13 +697,15 @@ int net_send_batch()
        hosts. Removed in 0.65. 
        If the line proves neccesary, it should at least NOT trigger that line 
        when host[i].addr == 0 -- REW */
-    if ((host[i].addr == remoteaddress.sin_addr.s_addr) 
+    if ( ( addrcmp( (void *) &(host[i].addr),
+                    (void *) remoteaddress, af ) == 0 )
        /* || (host[i].addr == host[batch_at].addr)  */)
       n_unknown = MaxHost; /* Make sure we drop into "we should restart" */
   }
 
   if ( // success in reaching target
-      (host[batch_at].addr == remoteaddress.sin_addr.s_addr) ||
+     ( addrcmp( (void *) &(host[batch_at].addr),
+                (void *) remoteaddress, af ) == 0 ) ||
       // fail in consecuitive MAX_UNKNOWN_HOSTS (firewall?)
       (n_unknown > MAX_UNKNOWN_HOSTS) ||
       // or reach limit 
@@ -600,53 +720,89 @@ int net_send_batch()
 }
 
 
-int net_preopen() 
+int net_preopen(void
 {
   int trueopt = 1;
 
-  sendsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
-  if (sendsock < 0)
+  sendsock4 = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+  if (sendsock4 < 0) 
+    return -1;
+#ifdef ENABLE_IPV6
+  sendsock6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+  if (sendsock6 < 0)
     return -1;
+#endif
 
 #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(sendsock4, SOL_IP, IP_HDRINCL, &trueopt, sizeof(trueopt))) {
     perror("setsockopt(IP_HDRINCL,1)");
     return -1;
   }
-#endif
+#endif /* IP_HDRINCL */
 
-  recvsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
-  if (recvsock < 0)
+  recvsock4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+  if (recvsock4 < 0)
     return -1;
+#ifdef ENABLE_IPV6
+  recvsock6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+  if (recvsock6 < 0)
+    return -1;
+#endif
 
   return 0;
 }
 
  
-int net_open(int addr
+int net_open(struct hostent * host
 {
-  struct sockaddr_in name; 
+#ifdef ENABLE_IPV6
+  struct sockaddr_storage name_struct;
+#else
+  struct sockaddr_in name_struct; 
+#endif
+  struct sockaddr * name = (struct sockaddr *) &name_struct;
   int len; 
 
   net_reset();
 
-  remoteaddress.sin_family = AF_INET;
-  remoteaddress.sin_addr.s_addr = addr;
+  remotesockaddr->sa_family = host->h_addrtype;
+
+  switch ( host->h_addrtype ) {
+  case AF_INET:
+    sendsock = sendsock4;
+    recvsock = recvsock4;
+    addrcpy( (void *) &(rsa4->sin_addr), host->h_addr, AF_INET );
+    sourceaddress = (ip_t *) &(ssa4->sin_addr);
+    remoteaddress = (ip_t *) &(rsa4->sin_addr);
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    sendsock = sendsock6;
+    recvsock = recvsock6;
+    addrcpy( (void *) &(rsa6->sin6_addr), host->h_addr, AF_INET6 );
+    sourceaddress = (ip_t *) &(ssa6->sin6_addr);
+    remoteaddress = (ip_t *) &(rsa6->sin6_addr);
+    break;
+#endif
+  default:
+    fprintf( stderr, "net_open bad address type\n" );
+    exit( EXIT_FAILURE );
+  }
 
-  len = sizeof (name)
-  getsockname (recvsock, (struct sockaddr *)&name, &len);
-  localaddr = name.sin_addr;
+  len = sizeof name_struct
+  getsockname (recvsock, name, &len);
+  sockaddrtop( name, localaddr, sizeof localaddr );
 #if 0
-  printf ("got localaddr: %x\n", *(int *)&localaddr); 
+  printf ("got localaddr: %s\n", localaddr); 
 #endif
 
   return 0;
 }
 
 
-void net_reopen(int addr) 
+void net_reopen(struct hostent * addr) 
 {
   int at;
 
@@ -654,15 +810,28 @@ void net_reopen(int addr)
     memset(&host[at], 0, sizeof(host[at]));
   }
 
-  remoteaddress.sin_family = AF_INET;
-  remoteaddress.sin_addr.s_addr = addr;
+  remotesockaddr->sa_family = addr->h_addrtype;
+
+  switch ( addr->h_addrtype ) {
+  case AF_INET:
+    addrcpy( (void *) remoteaddress, addr->h_addr, AF_INET );
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    addrcpy( (void *) &(rsa6->sin6_addr), addr->h_addr, AF_INET6 );
+    break;
+#endif
+  default:
+    fprintf( stderr, "net_reopen bad address type\n" );
+    exit( EXIT_FAILURE );
+  }
 
   net_reset ();
   net_send_batch();
 }
 
 
-void net_reset() 
+void net_reset(void
 {
   int at;
   int i;
@@ -707,21 +876,31 @@ int net_set_interfaceaddress (char *InterfaceAddress)
 
   if (!InterfaceAddress) return 0; 
 
-  sourceaddress.sin_family = AF_INET;
-  sourceaddress.sin_port = 0;
-  sourceaddress.sin_addr.s_addr = 0;
+  sourcesockaddr->sa_family = af;
+  switch ( af ) {
+  case AF_INET:
+    ssa4->sin_port = 0;
+    ssa4->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;
+    ((unsigned char*)&ssa4->sin_addr)[0] = i1;
+    ((unsigned char*)&ssa4->sin_addr)[1] = i2;
+    ((unsigned char*)&ssa4->sin_addr)[2] = i3;
+    ((unsigned char*)&ssa4->sin_addr)[3] = i4;
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    ssa6->sin6_port = 0;
+    inet_pton( af, InterfaceAddress, &(ssa6->sin6_addr) );
+    break;
+#endif
+  }
 
-  if(bind(sendsock, (struct sockaddr*)&sourceaddress, sizeof(sourceaddress)) == -1) {
+  if (bind(sendsock, sourcesockaddr, sizeof sourcesockaddr_struct) == -1) {
     perror("mtr: failed to bind to interface");
     exit(1);
   }
@@ -730,26 +909,26 @@ int net_set_interfaceaddress (char *InterfaceAddress)
 
 
 
-void net_close(
+void net_close(void)
 {
   close(sendsock);
   close(recvsock);
 }
 
 
-int net_waitfd(
+int net_waitfd(void)
 {
   return recvsock;
 }
 
 
-int* net_saved_pings(int at) 
+int* net_saved_pings(int at)
 {
   return host[at].saved;
 }
 
 
-void net_save_increment(
+void net_save_increment(void)
 {
   int at;
   for (at = 0; at < MaxHost; at++) {
@@ -760,7 +939,7 @@ void net_save_increment()
 }
 
 
-void net_save_xmit(int at) 
+void net_save_xmit(int at)
 {
   if (host[at].saved[SAVED_PINGS-1] != -2) 
     net_save_increment();
@@ -768,7 +947,7 @@ void net_save_xmit(int at)
 }
 
 
-void net_save_return(int at, int seq, int ms) 
+void net_save_return(int at, int seq, int ms)
 {
   int idx;
   idx = seq - host[at].saved_seq_offset;
@@ -777,3 +956,61 @@ void net_save_return(int at, int seq, int ms)
   }
   host[at].saved[idx] = ms;
 }
+
+/* Similar to inet_ntop but uses a sockaddr as it's argument. */
+void sockaddrtop( struct sockaddr * saddr, char * strptr, size_t len ) {
+  struct sockaddr_in *  sa4;
+#ifdef ENABLE_IPV6
+  struct sockaddr_in6 * sa6;
+#endif
+
+  switch ( saddr->sa_family ) {
+  case AF_INET:
+    sa4 = (struct sockaddr_in *) saddr;
+    strncpy( strptr, inet_ntoa( (struct in_addr) sa4->sin_addr ), len );
+    return;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    sa6 = (struct sockaddr_in6 *) saddr;
+    inet_ntop( sa6->sin6_family, &(sa6->sin6_addr), strptr, len );
+    return;
+#endif
+  default:
+    fprintf( stderr, "sockaddrtop unknown address type\n" );
+    strptr[0] = '\0';
+    return;
+  }
+}
+
+/* Address comparison. */
+int addrcmp( char * a, char * b, int af ) {
+  int rc = -1;
+
+  switch ( af ) {
+  case AF_INET:
+    rc = memcmp( a, b, sizeof (struct in_addr) );
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    rc = memcmp( a, b, sizeof (struct in6_addr) );
+    break;
+#endif
+  }
+
+  return rc;
+}
+
+/* Address copy. */
+void addrcpy( char * a, char * b, int af ) {
+
+  switch ( af ) {
+  case AF_INET:
+    memcpy( a, b, sizeof (struct in_addr) );
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    memcpy( a, b, sizeof (struct in6_addr) );
+    break;
+#endif
+  }
+}
diff --git a/net.h b/net.h
index 3042f3788ca3ae00a36864a41c43924ad9ed43a4..db43973367e4f3ec517765569523d840874358f9 100644 (file)
--- a/net.h
+++ b/net.h
 */
 
 /*  Prototypes for functions in net.c  */
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#ifdef ENABLE_IPV6
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#endif
 
-int net_preopen();
-int net_open(int address);
-void net_reopen(int address);
+int net_preopen(void);
+int net_open(struct hostent *host);
+void net_reopen(struct hostent *address);
 int net_set_interfaceaddress (char *InterfaceAddress); 
-void net_reset();
-void net_close();
-int net_waitfd();
-void net_process_return();
+void net_reset(void);
+void net_close(void);
+int net_waitfd(void);
+void net_process_return(void);
 
 int net_max(void);
 int net_min(void);
 int net_last(int at);
-int net_addr(int at);
+#ifdef ENABLE_IPV6
+struct in6_addr * net_addr(int at);
+#else
+struct in_addr * net_addr(int at);
+#endif
 int net_loss(int at);
 int net_drop(int at);
 int net_last(int at);
@@ -44,11 +56,15 @@ int net_jitter(int at);
 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); 
+#ifdef ENABLE_IPV6
+struct in6_addr * net_addrs(int at, int i);
+#else
+struct in_addr * net_addrs(int at, int i);
+#endif
+char *net_localaddr(void); 
 
-int net_send_batch();
-void net_end_transit();
+int net_send_batch(void);
+void net_end_transit(void);
 
 int calc_deltatime (float WaitTime);
 
@@ -66,6 +82,10 @@ void net_save_xmit(int at);
 void net_save_return(int at, int seq, int ms);
 int net_duplicate(int at, int seq);
 
+void sockaddrtop( struct sockaddr * saddr, char * strptr, size_t len );
+int addrcmp( char * a, char * b, int af );
+void addrcpy( char * a, char * b, int af );
+
 #define MAXPATH 8
 #define MaxHost 256
 #define MaxSequence 65536
@@ -104,3 +124,8 @@ extern int fld_index[];
 extern unsigned char fld_active[];
 extern char available_options[];
 
+#ifdef ENABLE_IPV6
+struct in6_addr unspec_addr;
+#else
+struct in_addr unspec_addr;
+#endif
diff --git a/raw.c b/raw.c
index 65c1129f4d89c2b4d769756c5d5681a48532c8f9..16741674dcb0d8417931f45da385e87093510870 100644 (file)
--- a/raw.c
+++ b/raw.c
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <config.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 
+#include "mtr.h"
 #include "raw.h"
 #include "net.h"
 #include "dns.h"
 
 static int havename[MaxHost];
 
+extern int af;
+
 #if 0
-static char *addr_to_str(int addr)
+static char *addr_to_str(ip_t addr)
 {
   static char buf[20];
 
-  sprintf (buf, "%d.%d.%d.%d", 
-          (addr >> 0)  & 0xff, 
-          (addr >> 8)  & 0xff, 
-          (addr >> 16) & 0xff, 
-          (addr >> 24) & 0xff);
+  sprintf (buf, "%s", strlongip( &addr ));
   return buf;
 }
 #endif
@@ -63,17 +64,8 @@ void raw_rawping (int host, int msec)
 }
 
 
-void raw_rawhost (int host, int ip_addr)
+void raw_rawhost (int host, ip_t * ip_addr)
 {
-  struct in_addr in;
-
-  in.s_addr = ip_addr;
-
-  printf ("h %d %s\n", 
-         host, inet_ntoa(in));
+  printf ("h %d %s\n", host, strlongip( ip_addr ));
   fflush (stdout); 
 }
-
-
-
-
diff --git a/raw.h b/raw.h
index 710aabe556a4a13c139aa3c682dba38f76fadee0..4020e5aa1a751261f8ce208155e79f7a6324d71d 100644 (file)
--- a/raw.h
+++ b/raw.h
@@ -21,4 +21,8 @@
 
 /*  Prototypes for raw.c  */
 void raw_rawping(int host, int msec);
-void raw_rawhost(int host, int addr);
+#ifdef ENABLE_IPV6
+void raw_rawhost(int host, struct in6_addr * addr);
+#else
+void raw_rawhost(int host, struct in_addr * addr);
+#endif
index b979650607b3a2376bd4624acb69231a26c5e921..41208b930347c823163fa23df0af4b65841691ca 100644 (file)
--- a/report.c
+++ b/report.c
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <string.h>
+#include <strings.h>
 
+#include "mtr.h"
 #include "report.h"
 #include "net.h"
+#include "dns.h"
 
 extern int dns;
 extern char LocalHostname[];
@@ -37,12 +40,18 @@ extern int packetsize;
 extern int bitpattern;
 extern int tos;
 extern int MaxPing;
+extern int af;
 
 
-void report_open() {}
-void report_close() {
-  int i, j, at, max, addr;
-  int haddr;
+void report_open(void) 
+{
+}
+
+
+void report_close(void) 
+{
+  int i, j, at, max;
+  ip_t *addr;
   char name[81];
   char buf[1024];
   char fmt[16];
@@ -65,18 +74,16 @@ void report_close() {
   for(; at < max; at++) {
     addr = net_addr(at);
     
-    if(addr == 0) {
+    if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) == 0 ) {
       sprintf(name, "???");
     } else {
-      haddr = htonl(addr);
-      host = dns?gethostbyaddr((char *)&haddr, sizeof(int), AF_INET):NULL;
+      host = dns?gethostbyaddr( (void *) addr, sizeof(int), AF_INET):NULL;
 
       if (host != NULL) {
         strncpy(name, host->h_name, 80);
         name[80] = 0;
       } else {
-       sprintf(name, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, 
-               (addr >> 8) & 0xff, addr & 0xff);
+       sprintf(name, "%s", strlongip( addr ) );
       }
     }
 
@@ -99,15 +106,29 @@ void report_close() {
     printf("%s\n",buf);
   }
 }
-void txt_open() {}
-void txt_close() { report_close(); }
 
 
+void txt_open(void)
+{
+}
+
+
+void txt_close(void)
+{ 
+  report_close();
+}
+
+
+
+void xml_open(void)
+{
+}
+
 
-void xml_open() {}
-void xml_close() {
-  int i, j, at, max, addr;
-  int haddr;
+void xml_close(void)
+{
+  int i, j, at, max;
+  ip_t *addr;
   char name[81];
   struct hostent *host;
 
@@ -130,18 +151,16 @@ void xml_close() {
   for(; at < max; at++) {
     addr = net_addr(at);
     
-    if(addr == 0) {
+    if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) == 0 ) {
       sprintf(name, "???");
     } else {
-      haddr = htonl(addr);
-      host = dns?gethostbyaddr((char *)&haddr, sizeof(int), AF_INET):NULL;
+      host = dns?gethostbyaddr( (void *) addr, sizeof(int), AF_INET):NULL;
 
       if (host != NULL) {
         strncpy(name, host->h_name, 80);
         name[80] = 0;
       } else {
-       sprintf(name, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, 
-               (addr >> 8) & 0xff, addr & 0xff);
+       sprintf(name, "%s", strlongip( addr ) );
       }
     }
 
@@ -171,10 +190,16 @@ void xml_close() {
   printf("</MTR>\n");
 }
 
-void csv_open() {}
-void csv_close() {
-  int i, j, at, max, addr;
-  int haddr;
+
+void csv_open(void)
+{
+}
+
+
+void csv_close(void)
+{
+  int i, j, at, max;
+  ip_t *addr;
   char name[81];
   struct hostent *host;
 
@@ -208,18 +233,16 @@ void csv_close() {
   for(; at < max; at++) {
     addr = net_addr(at);
     
-    if(addr == 0) {
+    if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) == 0 ) {
       sprintf(name, "???");
     } else {
-      haddr = htonl(addr);
-      host = dns?gethostbyaddr((char *)&haddr, sizeof(int), AF_INET):NULL;
+      host = dns?gethostbyaddr( (void *) addr, sizeof(int), AF_INET):NULL;
 
       if (host != NULL) {
         strncpy(name, host->h_name, 80);
         name[80] = 0;
       } else {
-       sprintf(name, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, 
-               (addr >> 8) & 0xff, addr & 0xff);
+       sprintf(name, "%s", strlongip( addr ) );
       }
     }
 
index b402f9bd7d60bab73fac1af81b7f4601c2e60b35..4e8fd1c29a99fe79e5bd92220d441cb7bfa5c060 100644 (file)
--- a/report.h
+++ b/report.h
 
 /*  Prototypes for report.h  */
 
-void report_open();
-void report_close();
-void txt_open();
-void txt_close();
-void xml_open();
-void xml_close();
-void csv_open();
-void csv_close();
+void report_open(void);
+void report_close(void);
+void txt_open(void);
+void txt_close(void);
+void xml_open(void);
+void xml_close(void);
+void csv_open(void);
+void csv_close(void);
index 7136582e5ac0e01ac75e0312102818db452d3650..3577c9c152d7bd4f460ed93caf98215a881cfec0 100644 (file)
--- a/select.c
+++ b/select.c
@@ -29,6 +29,7 @@
 #include <math.h>
 #include <errno.h>
 
+#include "mtr.h"
 #include "display.h"
 #include "dns.h"
 #include "net.h"
@@ -43,7 +44,7 @@ static struct timeval intervaltime;
 int display_offset = 0;
 
 
-void select_loop() {
+void select_loop(void) {
   fd_set readfd;
   int anyset = 0;
   int maxfd = 0;
@@ -116,11 +117,13 @@ void select_loop() {
          selecttime.tv_usec += 1000000;
        }
 
-       if ((selecttime.tv_sec > (time_t)dnsinterval) ||
-           ((selecttime.tv_sec == (time_t)dnsinterval) &&
-            (selecttime.tv_usec > ((time_t)(dnsinterval * 1000000) % 1000000)))) {
-         selecttime.tv_sec = (time_t)dnsinterval;
-         selecttime.tv_usec = (time_t)(dnsinterval * 1000000) % 1000000;
+       if (dns) {
+         if ((selecttime.tv_sec > (time_t)dnsinterval) ||
+             ((selecttime.tv_sec == (time_t)dnsinterval) &&
+              (selecttime.tv_usec > ((time_t)(dnsinterval * 1000000) % 1000000)))) {
+           selecttime.tv_sec = (time_t)dnsinterval;
+           selecttime.tv_usec = (time_t)(dnsinterval * 1000000) % 1000000;
+         }
        }
 
        rv = select(maxfd, (void *)&readfd, NULL, NULL, &selecttime);
index 33a9a96dbda9ec72ce5f704610d1e68daea23573..03876e5616057479a77e8bcce3f917d32047de2a 100644 (file)
--- a/select.h
+++ b/select.h
@@ -17,4 +17,4 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-void select_loop();
+void select_loop(void);
diff --git a/split.c b/split.c
index 7e0112450723f23e871ddc4cb3792168c7b4db82..e49bc6b58321930e82129143bea6b28bc503bceb 100644 (file)
--- a/split.c
+++ b/split.c
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <config.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/types.h>
 
+#include "mtr.h"
 #include "display.h"
 #include "dns.h"
 
 #include "net.h"
 #include "split.h"
 
-
-#include <config.h>
-
 #ifdef NO_CURSES
 #include <sys/time.h>
 #include <sys/types.h>
@@ -57,6 +57,7 @@
 
 extern char *Hostname;
 extern int WaitTime;
+extern int af;
 
 /* There is 256 hops max in the IP header (coded with a byte) */
 #define MAX_LINE_COUNT 256
@@ -68,11 +69,12 @@ int  LineCount;
 
 #define DEBUG 0
 
-void 
-split_redraw() {
+
+void split_redraw(void) 
+{
   int   max;
   int   at;
-  int   addr;
+  ip_t *addr;
   char *name;
   char  newLine[MAX_LINE_SIZE];
   int   i;
@@ -97,7 +99,7 @@ split_redraw() {
   for(at = 0; at < max; at++) {
     addr = net_addr(at);
     
-    if(addr != 0) {
+    if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) {
       name = dns_lookup(addr);
       if(name != NULL) {
        /* May be we should test name's length */
@@ -107,9 +109,8 @@ split_redraw() {
                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,
+       sprintf(newLine, "%s %d %d %d %d %d %d", 
+               strlongip( addr ),
                net_loss(at),
                net_returned(at), net_xmit(at),
                net_best(at) /1000, net_avg(at)/1000, 
@@ -135,8 +136,9 @@ split_redraw() {
   }
 }
 
-void 
-split_open() {
+
+void split_open(void)
+{
   int i;
 #if DEBUG
   printf("split_open()\n");
@@ -147,15 +149,17 @@ split_open() {
   }
 }
 
-void 
-split_close() {
+
+void split_close(void)
+{
 #if DEBUG
   printf("split_close()\n");
 #endif
 }
 
-int 
-split_keyaction() {
+
+int split_keyaction(void) 
+{
 #ifdef NO_CURSES
   fd_set readfds;
   struct timeval tv;
diff --git a/split.h b/split.h
index ad4f31856a70dbe64f6ac442e200fd9c47273e73..2a19eb99fddc2bc1c768fa7add07023e07875064 100644 (file)
--- a/split.h
+++ b/split.h
@@ -20,7 +20,7 @@
 */
 
 /*  Prototypes for split.c  */
-void split_open();
-void split_close();
-void split_redraw();
-int split_keyaction();
+void split_open(void);
+void split_close(void);
+void split_redraw(void);
+int split_keyaction(void);