diff --git a/AUTHORS b/AUTHORS
index ccff487..c3ec5af 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -25,9 +25,9 @@
         Mike Simons <msimons@moria.simons-clan.com>
         Aaron Scarisbrick
         Craig Milo Rogers <Rogers@ISI.EDU>
-        Antonio Querubin <tony@aloha.net>
+        Antonio Querubin <tony@lavanauts.org>
         Russell Nelson <rn-mtr@crynwr.com>
-        Davin Milun <milun@acm.org>
+        Davin Milun
         Josh Martin <jmartin@columbiaservices.net>
         Alexander V. Lukyanov <lav@yars.free.net>
         Charles Levert <charles@comm.polymtl.ca> 
@@ -46,12 +46,19 @@
         Mircea Damian
         Cougar <cougar@random.ee>
         Travis Cross <tc@traviscross.com>
-        Brian Casey
+        Brian Casey <bcasey@imagiware.com>
         Andrew Brown <atatat@atatdot.net>
         Bill Bogstad <bogstad@pobox.com> 
         Marc Bejarano <marc.bejarano@openwave.com>
         Moritz Barsnick <barsnick@gmx.net>
         Thomas Klausner <wiz@NetBSD.org>
+        Roderick Groesbeek <mtr@roderick.triple-it.nl>
+        Kyle J. McKay <mackyle@gmail.com>
+        Joseph Carter
+        Thales <thales@paponline.net>
+        "Min"
+        Vaibhav Bajpai <contact@vaibhavbajpai.com>
+        Jürgen Schönwälder <j.schoenwaelder@jacobs-university.de>
 
         and anyone who has slipped through the cracks of my mail file.
 
diff --git a/Makefile.am b/Makefile.am
index 4a767fa..ed06db8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,7 +6,6 @@ install-exec-hook:
 	chmod u+s $(DESTDIR)$(sbindir)/mtr
 
 mtr_SOURCES = mtr.c \
-              asn.c asn.h \
               net.c net.h \
               dns.c dns.h \
               raw.c raw.h \
@@ -17,12 +16,18 @@ mtr_SOURCES = mtr.c \
               select.c select.h \
               mtr-curses.h \
               mtr-gtk.h
+
+if IPINFO
+mtr_SOURCES += asn.c asn.h
+endif
+
 nodist_mtr_SOURCES = version.h
 EXTRA_mtr_SOURCES = curses.c \
                     gtk.c
 DEFAULT_INCLUDES= $(GLIB_CFLAGS) -I.
 mtr_DEPENDENCIES = $(GTK_OBJ) $(CURSES_OBJ)
-mtr_LDFLAGS = $(GTK_OBJ) $(CURSES_OBJ) $(GLIB_LIBS)
+mtr_LDFLAGS = $(GTK_OBJ) $(CURSES_OBJ)
+mtr_LDADD = $(GLIB_LIBS) $(RESOLV_LIBS)
 
 CLEANFILES = version.h
 BUILT_SOURCES = version.h
diff --git a/NEWS b/NEWS
index ae64755..9d27366 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,22 @@
 WHAT'S NEW?
 
+V0.86 Fixed default hostname logic. 
+      Fix for NetBSD: 64bit time_t -- Thomas Klausner
+      Fix unnecessary runtime dependency on glib from VSYakovetsky through 
+           Thomas
+      Inverted IPINFO define in the code. Removes double negatives. 
+         -- Vladimir Yakovetsky, REW.
+      Fixed failure on IPv4 only systems when IPv6 was available at
+         compile time. -- REW.
+      Fixed (longstanding) bug that mtr used 100% cpu when paused. 
+      Cosmetic changes from Richard Hartman. 
+
+V0.85 Fixed asn support. (better compile time detection of required features)
+      support for multiple hostnames. (fixed in 0.86)
+      support for TCP probes
+
+V0.84 Fix some glib things by Thomas. 
+
 V0.83 Move to github. Mostly done by Travis.
 
 Author: Travis Cross <tc@traviscross.com>
diff --git a/README b/README
index c7588d0..f2f6538 100644
--- a/README
+++ b/README
@@ -10,7 +10,7 @@ WHAT IS MTR?
   quality of the link to each machine.  As it does this, it prints
   running statistics about each machine.
 
-  mtr is distributed under the GNU General Public License. 
+  mtr is distributed under the GNU General Public License version 2.
   See the COPYING file for details.  
 
 INSTALLING
diff --git a/SECURITY b/SECURITY
index 6cfc40b..4ff73a9 100644
--- a/SECURITY
+++ b/SECURITY
@@ -7,15 +7,16 @@ 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
+justified.  Since version 0.21, mtr does the following two things
 after it is launched:
 
 *  mtr requests a pair of raw sockets from the kernel.  
-*  mtr sets the effective uid to match the real uid.
+*  mtr drops root privileges by setting the effective uid to match
+   uid or the user calling mtr.
 
 See main() in mtr.c and net_preopen() in net.c for the details of this
-process.  Note that no code from GTK+ or curses is executed before the
-drop in permissions.
+process.  Note that no code from GTK+ or curses is executed before
+dropping root privileges.
 
 This should severely limit the possibilities of using mtr to breach
 system security.  This means the worst case scenerio is as follows:
@@ -24,10 +25,10 @@ Due to some oversight in the mtr code, a malicious user is able to
 overrun one of mtr's internal buffers with binary code that is
 eventually executed.  The malicious user is still not able to read
 from or write to any system files which they wouldn't normally have
-permission to write to.  The only priveledge gained is access to the
-raw socket descriptors, which would allow the malicious user to listen
-to all ICMP packets arriving at the system, and send forged packets
-with arbitrary contents.
+permission to read or write to, repectively.  The only privilege
+gained is access to the raw socket descriptors, which would allow
+the malicious user to listen to all ICMP packets arriving at the
+system, and to send forged packets with arbitrary contents.
 
 The mtr-code does its best to prevent calling of external library
 code before dropping privileges. It seems that C++ library code has 
@@ -36,7 +37,7 @@ loader/linker.  That would mean that we're still vulnerable to
 errors in that code. This is why I would prefer to drop the backends, 
 have mtr-core always run in "raw" mode, and have the backends interpret
 the output from the mtr-core. Maybe a nice project for a college-level
-student. 
+student.
 
 If you have further questions or comments about security issues,
 please direct them to the mtr mailing list.  See README for details.
diff --git a/asn.c b/asn.c
index f9484a8..33622ca 100644
--- a/asn.c
+++ b/asn.c
@@ -16,33 +16,60 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/*
-    Copyright (C) 2010 by Roderick Groesbeek <mtr@roderick.triple-it.nl>
-    Released under GPL, as above.
-*/
-
-#include <config.h>
+#include "config.h"
 
 #include <unistd.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
 
+#ifdef __APPLE__
+#define BIND_8_COMPAT
+#endif
 #include <arpa/nameser.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
 #include <netdb.h>
 #include <netinet/in.h>
 #include <resolv.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <search.h>
+
+#include "mtr.h"
+#include "asn.h"
+
+/*
+#ifndef IIDEBUG
+#define IIDEBUG
+#include <syslog.h>
+#endif
+*/
+
+#define IIHASH_HI	128
+#define ITEMSMAX	15
+#define ITEMSEP	'|'
+#define NAMELEN	127
+#define UNKN	"???"
 
+int  ipinfo_no = -1;
+int  ipinfo_max = -1;
+int  iihash = 0;
+char fmtinfo[32];
+extern int af;                  /* address family of remote target */
 
-#include <glib.h>
+// items width: ASN, Route, Country, Registry, Allocated 
+int iiwidth[] = { 6, 19, 4, 8, 11};	// item len + space
+int iiwidth_len = sizeof(iiwidth)/sizeof((iiwidth)[0]);
 
+typedef char* items_t[ITEMSMAX + 1];
+items_t items_a;		// without hash: items
+char txtrec[NAMELEN + 1];	// without hash: txtrec
+items_t* items = &items_a;
 
-int  PrintAS = 0;
-GHashTable * ashash = NULL;
 
-char *asn_lookup(const char *domain)
-{
+char *ipinfo_lookup(const char *domain) {
     unsigned char answer[PACKETSZ],  *pt;
     char host[128];
     char *txt;
@@ -56,7 +83,11 @@ char *asn_lookup(const char *domain)
 
     memset(answer, 0, PACKETSZ);
     if((len = res_query(domain, C_IN, T_TXT, answer, PACKETSZ)) < 0) {
-        return "-1";
+#ifdef IIDEBUG
+        if (iihash)
+            syslog(LOG_INFO, "Malloc-txt: %s", UNKN);
+#endif
+        return (iihash)?strdup(UNKN):UNKN;
     }
 
     pt = answer + sizeof(HEADER);
@@ -85,6 +116,7 @@ char *asn_lookup(const char *domain)
     }
 
     pt += INT16SZ; /* class */
+    pt += INT32SZ; /* ttl */
     GETSHORT(size, pt);
     txtlen = *pt;
 
@@ -93,16 +125,186 @@ char *asn_lookup(const char *domain)
         printf("@Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size); return NULL;
     }
 
-    if(!(txt = malloc(txtlen + 1)))
-        return NULL;
+    if (txtlen > NAMELEN)
+        txtlen = NAMELEN;
+
+    if (iihash) {
+        if (!(txt = malloc(txtlen + 1)))
+            return NULL;
+    } else
+        txt = (char*)txtrec;
 
     pt++;
     strncpy(txt, (char*) pt, txtlen);
     txt[txtlen] = 0;
 
+#ifdef IIDEBUG
+    if (iihash)
+        syslog(LOG_INFO, "Malloc-txt(%p): %s", txt, txt);
+#endif
+
     return txt;
 }
 
+char* trimsep(char *s) {
+    int l;
+    char *p = s;
+    while (*p == ' ' || *p == ITEMSEP)
+        *p++ = '\0';
+    for (l = strlen(p)-1; p[l] == ' ' || p[l] == ITEMSEP; l--)
+        p[l] = '\0';
+    return p;
+}
+
+// originX.asn.cymru.com txtrec:    ASN | Route | Country | Registry | Allocated
+char* split_txtrec(char *txtrec) {
+    if (!txtrec)
+	return NULL;
+    if (iihash) {
+#ifdef IIDEBUG
+        syslog(LOG_INFO, "Malloc-tbl: %s", txtrec);
+#endif
+        if (!(items = malloc(sizeof(*items)))) {
+#ifdef IIDEBUG
+            syslog(LOG_INFO, "Free-txt(%p)", txtrec);
+#endif
+            free(txtrec);
+            return NULL;
+        }
+    }
+
+    char* prev = (*items)[0] = trimsep(txtrec);
+    char* next;
+    int i = 0, j;
+
+    while ((next = strchr(prev, ITEMSEP)) && (i < ITEMSMAX)) {
+        *next++ = '\0';
+        (*items)[i++] = trimsep(prev);
+        (*items)[i] = prev = trimsep(next);
+    }
+    if (i < ITEMSMAX)
+        i++;
+    for (j = i;  j <= ITEMSMAX; j++)
+        (*items)[j] = NULL;
+
+    if (i > ipinfo_max)
+        ipinfo_max = i;
+    if (ipinfo_no >= i) {
+        if (ipinfo_no >= ipinfo_max)
+            ipinfo_no = 0;
+	return (*items)[0];
+    } else
+	return (*items)[ipinfo_no];
+}
+
+#ifdef ENABLE_IPV6
+// from dns.c:addr2ip6arpa()
+void reverse_host6(struct in6_addr *addr, char *buff) {
+    int i;
+    char *b = buff;
+    for (i=(sizeof(*addr)/2-1); i>=0; i--, b+=4) // 64b portion
+        sprintf(b, "%x.%x.", addr->s6_addr[i] & 0xf, addr->s6_addr[i] >> 4);
+    buff[strlen(buff) - 1] = '\0';
+}
+#endif
+
+char *get_ipinfo(ip_t *addr) {
+    if (!addr)
+        return NULL;
+
+    char key[NAMELEN];
+    char lookup_key[NAMELEN];
+
+    if (af == AF_INET6) {
+#ifdef ENABLE_IPV6
+        reverse_host6(addr, key);
+        if (snprintf(lookup_key, NAMELEN, "%s.origin6.asn.cymru.com", key) >= NAMELEN)
+            return NULL;
+#else
+	return NULL;
+#endif
+    } else {
+        unsigned char buff[4];
+        memcpy(buff, addr, 4);
+        if (snprintf(key, NAMELEN, "%d.%d.%d.%d", buff[3], buff[2], buff[1], buff[0]) >= NAMELEN)
+            return NULL;
+        if (snprintf(lookup_key, NAMELEN, "%s.origin.asn.cymru.com", key) >= NAMELEN)
+            return NULL;
+    }
+
+    char *val = NULL;
+    ENTRY item;
+
+    if (iihash) {
+#ifdef IIDEBUG
+        syslog(LOG_INFO, ">> Search: %s", key);
+#endif
+        item.key = key;;
+        ENTRY *found_item;
+        if ((found_item = hsearch(item, FIND))) {
+            if (!(val = (*((items_t*)found_item->data))[ipinfo_no]))
+                val = (*((items_t*)found_item->data))[0];
+#ifdef IIDEBUG
+        syslog(LOG_INFO, "Found (hashed): %s", val);
+#endif
+        }
+    }
+
+    if (!val) {
+#ifdef IIDEBUG
+        syslog(LOG_INFO, "Lookup: %s", key);
+#endif
+        if ((val = split_txtrec(ipinfo_lookup(lookup_key)))) {
+#ifdef IIDEBUG
+            syslog(LOG_INFO, "Looked up: %s", key);
+#endif
+            if (iihash)
+                if ((item.key = strdup(key))) {
+                    item.data = items;
+                    hsearch(item, ENTER);
+#ifdef IIDEBUG
+                    syslog(LOG_INFO, "Insert into hash: %s", key);
+#endif
+                }
+        }
+    }
+
+    return val;
+}
+
+int get_iiwidth(void) {
+    return (ipinfo_no < iiwidth_len) ? iiwidth[ipinfo_no] : iiwidth[ipinfo_no % iiwidth_len];
+}
+
+char *fmt_ipinfo(ip_t *addr) {
+    char *ipinfo = get_ipinfo(addr);
+    char fmt[8];
+    snprintf(fmt, sizeof(fmt), "%s%%-%ds", ipinfo_no?"":"AS", get_iiwidth());
+    snprintf(fmtinfo, sizeof(fmtinfo), fmt, ipinfo?ipinfo:UNKN);
+    return fmtinfo;
+}
+
+int is_printii(void) {
+    return ((ipinfo_no >= 0) && (ipinfo_no != ipinfo_max));
+}
 
+void asn_open(void) {
+    if (ipinfo_no >= 0) {
+#ifdef IIDEBUG
+        syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
+#endif
+        if (!(iihash = hcreate(IIHASH_HI)))
+            perror("ipinfo hash");
+    }
+}
 
+void asn_close(void) {
+    if (iihash) {
+#ifdef IIDEBUG
+        syslog(LOG_INFO, "hdestroy()");
+#endif
+        hdestroy();
+        iihash = 0;
+    }
+}
 
diff --git a/asn.h b/asn.h
index fde9af2..dd2d440 100644
--- a/asn.h
+++ b/asn.h
@@ -16,12 +16,26 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <glib.h>
-
-
-/*  Prototypes for asn.c  */
-
-extern int PrintAS;
-extern GHashTable * ashash;
-char *asn_lookup(const char *domain);
-
+// The autoconf system provides us with the NO_IPINFO define. 
+// Littering the code with #ifndef NO_IPINFO (double negative)
+// does not benefit readabilty. So here we invert the sense of the
+// define. 
+//
+// Similarly, this include file should be included unconditially. 
+// It will evaluate to nothing if we don't need it. 
+
+#ifndef NO_IPINFO
+#define IPINFO
+
+
+extern int ipinfo_no;
+extern int ipinfo_max;
+extern int iiwidth_len;
+extern int iihash;
+void asn_open();
+void asn_close();
+char *fmt_ipinfo(ip_t *addr);
+int get_iiwidth(void);
+int is_printii(void);
+
+#endif
diff --git a/configure.ac b/configure.ac
index 8f1d319..d50c253 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([mtr], [0.83])
+AC_INIT([mtr], [0.85])
 AC_CONFIG_SRCDIR([mtr.c])
 AM_INIT_AUTOMAKE([foreign])
 
@@ -18,16 +18,13 @@ AC_CHECK_SIZEOF(unsigned int, 4)
 AC_CHECK_SIZEOF(unsigned long, 4)
 
 AC_CHECK_HEADERS(ncurses.h ncurses/curses.h curses.h cursesX.h sys/types.h fcntl.h)
-AC_CHECK_HEADERS(socket.h sys/socket.h sys/xti.h)
-
-# Some doc I found somewhere. :-) -- REW
-# - Macro: AC_CHECK_FUNC (FUNCTION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
-# - Macro: AC_CHECK_LIB (LIBRARY, FUNCTION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
+AC_CHECK_HEADERS(socket.h sys/socket.h sys/xti.h arpa/nameser_compat.h)
 
 # 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_LIB(tinfo, tgetent)
 
 AC_CHECK_FUNC(initscr, , 
   AC_CHECK_LIB(ncurses, initscr, , 
@@ -41,14 +38,26 @@ AC_CHECK_FUNCS(attron fcntl)
 
 AC_CHECK_LIB(m, floor, , AC_MSG_ERROR(No math library found))
 
-dnl Added ability to cleanly disable GTK+      (12 Jan 2000, Joseph Carter)
 AC_ARG_WITH(gtk,
 [  --without-gtk           Do not try to use GTK+ at all],
 WANTS_GTK=$withval, WANTS_GTK=yes)
 
+AC_ARG_WITH([ipinfo],
+[  --without-ipinfo        Do not try to use ipinfo lookup at all],
+[ipinfo="${withval}"], [ipinfo=yes])
+AM_CONDITIONAL([IPINFO], [test x$ipinfo = xyes])
+
 AC_ARG_ENABLE(ipv6,
 [  --disable-ipv6          Do not enable IPv6],
 WANTS_IPV6=$enableval, WANTS_IPV6=yes)
+
+m4_ifndef([AM_PATH_GTK_2_0], [m4_defun([AM_PATH_GTK_2_0], [AC_MSG_ERROR([
+  Could not locate the gtk2 automake macros, these are usually located in
+    .../share/aclocal/gtk-2.0.m4
+  Before running bootstrap try setting the environment variable
+    ACLOCAL_PATH="/own/dir"
+  or configure --without-gtk.
+])])])
    
 if test "x$WANTS_GTK" = "xyes"; then
         AM_PATH_GTK_2_0(2.6.0, CFLAGS="$CFLAGS $GTK_CFLAGS"
@@ -59,7 +68,10 @@ if test "x$WANTS_GTK" = "xyes"; then
 else
 	AC_DEFINE(NO_GTK)
 	GTK_OBJ=""
-	PKG_CHECK_MODULES([GLIB], [glib-2.0])
+fi
+
+if test "x$ipinfo" = "xno"; then
+	AC_DEFINE([NO_IPINFO], [1], [Define to disable ipinfo lookup])
 fi
 
 AC_CHECK_FUNC(socket, , 
@@ -75,24 +87,109 @@ AC_CHECK_FUNC(gethostbyname, ,
 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_mkquery, , 
-   AC_CHECK_LIB(resolv, res_mkquery, ,
-     AC_CHECK_LIB(resolv, __res_mkquery, , AC_MSG_ERROR(No resolver library found)))))
-# This next line would override the just detected-or-not -lresolv. 
-# This apparently hurts BSD. And it's bad practise. So it should go. 
-# However, it probably didn't get added for nothing..... Holler if
-# removing it hurts your OS.... -- REW
-#LIBS="$LIBS -lresolv"
+#AC_CHECK_FUNC(res_mkquery, ,
+#  AC_CHECK_LIB(bind, res_mkquery, ,
+#   AC_CHECK_LIB(resolv, res_mkquery, ,
+#     AC_CHECK_LIB(resolv, __res_mkquery, , AC_MSG_ERROR(No resolver library found)))))
+
+# See if a library is needed for res_mkquery and if so put it in RESOLV_LIBS
+RESOLV_LIBS=
+AC_SUBST(RESOLV_LIBS)
+AC_DEFUN([LIBRESOLVTEST_SRC], [
+AC_LANG_PROGRAM([[
+#include <netinet/in.h>
+#include <resolv.h>
+]], [[
+int (*res_mkquery_func)(int,...) = (int (*)(int,...))res_mkquery;
+(void)(*res_mkquery_func)(0);
+]])])
+AC_MSG_CHECKING([whether library required for res_mkquery])
+RESOLV_LIB_NONE=
+AC_LINK_IFELSE([LIBRESOLVTEST_SRC],
+	[AC_MSG_RESULT([no])
+	RESOLV_LIB_NONE=yes],
+	[AC_MSG_RESULT([yes])])
+if test "x$RESOLV_LIB_NONE" = "x"; then
+	AC_MSG_CHECKING([for res_mkquery in -lbind])
+	STASH_LIBS="$LIBS"
+	LIBS="$STASH_LIBS -lbind"
+	AC_LINK_IFELSE([LIBRESOLVTEST_SRC],
+		[AC_MSG_RESULT([yes])
+		RESOLV_LIBS=-lbind],
+		[AC_MSG_RESULT([no])])
+	if test "x$RESOLV_LIBS" = "x"; then
+		AC_MSG_CHECKING([for res_mkquery in -lresolv])
+		LIBS="$STASH_LIBS -lresolv"
+		AC_LINK_IFELSE([LIBRESOLVTEST_SRC],
+			[AC_MSG_RESULT([yes])
+			RESOLV_LIBS=-lresolv],
+			[AC_MSG_RESULT([no])
+                        AC_MSG_ERROR(No resolver library found)])
+	fi
+	LIBS="$STASH_LIBS"
+fi
 
 AC_CHECK_FUNC(herror, , AC_DEFINE(NO_HERROR, 1, [Define if you don't have the herror() function available.]))
 AC_CHECK_FUNC(strerror, , AC_DEFINE(NO_STRERROR, 1, [Define if you don't have the strerror() function available.]))
 
+USES_IPV6=
 AC_CHECK_FUNC(getaddrinfo,
 [if test "$WANTS_IPV6" = "yes"; then
 	AC_DEFINE([ENABLE_IPV6], [], [Define to enable IPv6])
+	USES_IPV6=yes
 fi])
 
+AC_DEFUN([NEED_RES_STATE_EXT_TEST_SRC], [
+AC_LANG_PROGRAM([[
+#include <netinet/in.h>
+#include <resolv.h>
+#ifdef __GLIBC__
+#define RESEXTIN6(r,i) (*(r._u._ext.nsaddrs[i]))
+#else
+#define RESEXTIN6(r,i) (r._u._ext.ext->nsaddrs[i].sin6)
+#endif
+]], [[
+struct __res_state res;
+return RESEXTIN6(res,0).sin6_addr.s6_addr[0];
+]])])
+AC_DEFUN([DEFINE_RES_STATE_EXT_TEST_SRC], [
+AC_LANG_PROGRAM([[
+#include <netinet/in.h>
+#include <resolv.h>
+#ifdef __GLIBC__
+#define RESEXTIN6(r,i) (*(r._u._ext.nsaddrs[i]))
+#else
+#define RESEXTIN6(r,i) (r._u._ext.ext->nsaddrs[i].sin6)
+struct __res_state_ext {
+	union res_sockaddr_union nsaddrs[MAXNS];
+	struct sort_list {
+		int     af;
+		union {
+			struct in_addr  ina;
+			struct in6_addr in6a;
+		} addr, mask;
+	} sort_list[MAXRESOLVSORT];
+	char nsuffix[64];
+	char nsuffix2[64];
+};
+#endif
+]], [[
+struct __res_state res;
+return RESEXTIN6(res,0).sin6_addr.s6_addr[0];
+]])])
+if test "x$USES_IPV6" = "xyes"; then
+	AC_MSG_CHECKING([whether __res_state_ext needs to be defined])
+	AC_COMPILE_IFELSE([NEED_RES_STATE_EXT_TEST_SRC],
+		[AC_MSG_RESULT([no])],
+		[AC_MSG_RESULT([yes])
+		AC_MSG_CHECKING([whether provided __res_state_ext definition can be compiled])
+		AC_COMPILE_IFELSE([DEFINE_RES_STATE_EXT_TEST_SRC],
+			[AC_MSG_RESULT([yes])
+			AC_DEFINE(NEED_RES_STATE_EXT, 1, [Define if struct __res_state_ext needs to be defined.])],
+			[AC_MSG_RESULT([no])
+			AC_MSG_ERROR(Need definition for struct __res_state_ext but unable to define it.)])])
+fi
+
 AC_CHECK_DECLS(errno, , , [[
 #include <errno.h>
 #include <sys/errno.h>
diff --git a/curses.c b/curses.c
index dad7117..f4b8365 100644
--- a/curses.c
+++ b/curses.c
@@ -16,7 +16,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <config.h>
+#include "config.h"
+
 #include <strings.h>
 #include <unistd.h>
 
@@ -25,7 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-/* Philippe tells me MacOSX needs this before scoket.h... -- REW */
+/* MacOSX may need this before scoket.h...*/
 #if defined(HAVE_SYS_TYPES_H)
 #include <sys/types.h>
 #else
@@ -60,12 +61,12 @@
 
 #include "mtr.h"
 #include "mtr-curses.h"
-#include "display.h"
 #include "net.h"
 #include "dns.h"
 #include "asn.h"
+#include "display.h"
+
 #include "version.h"
-#include <glib.h>
 #endif
 
 #include <time.h>
@@ -120,12 +121,17 @@ int mtr_curses_keyaction(void)
     return ActionMPLS;
   if (tolower(c) == 'n')
     return ActionDNS;
+#ifdef IPINFO
+  if (tolower(c) == 'y')
+    return ActionII;
+  if (tolower(c) == 'z')
+    return ActionAS;
+#endif
   if (c == '+')
     return ActionScrollDown;
   if (c == '-')
     return ActionScrollUp;
 
-  /* more stuffs added by Min */
   if (tolower(c) == 's') {
     mvprintw(2, 0, "Change Packet Size: %d\n", cpacketsize );
     mvprintw(3, 0, "Size Range: %d-%d, < 0:random.\n", MINPACKET, MAXPACKET);
@@ -220,7 +226,7 @@ int mtr_curses_keyaction(void)
 
     return ActionNone;
   }
-  /* fields to display & their ordering -Min */
+  /* fields to display & their ordering */
   if (tolower(c) == 'o') {
     mvprintw(2, 0, "Fields: %s\n\n", fld_active );
 
@@ -257,6 +263,7 @@ int mtr_curses_keyaction(void)
   if (tolower(c) == 'u') {
     switch ( mtrtype ) {
     case IPPROTO_ICMP:
+    case IPPROTO_TCP:
       mtrtype = IPPROTO_UDP;
       break;
     case IPPROTO_UDP:
@@ -265,8 +272,21 @@ int mtr_curses_keyaction(void)
     }
     return ActionNone;
   }
+  if (tolower(c) == 't') {
+    switch ( mtrtype ) {
+    case IPPROTO_ICMP:
+    case IPPROTO_UDP:
+      mtrtype = IPPROTO_TCP;
+      break;
+    case IPPROTO_TCP:
+      mtrtype = IPPROTO_ICMP;
+      break;
+    }
+    return ActionNone;
+  }
   /* reserve to display help message -Min */
   if (tolower(c) == '?'|| tolower(c) == 'h') {
+    int pressanykey_row = 20;
     mvprintw(2, 0, "Command:\n" );
     printw("  ?|h     help\n" );
     printw("  p       pause (SPACE to resume)\n" );
@@ -283,8 +303,14 @@ int mtr_curses_keyaction(void)
     printw("  s <n>   set the packet size to n or random(n<0)\n" );
     printw("  b <c>   set ping bit pattern to c(0..255) or random(c<0)\n" );
     printw("  Q <t>   set ping packet's TOS to t\n" );
-    printw("  u       switch between ICMP ECHO and UDP datagrams\n\n" );
-    mvprintw(16, 0, " press any key to go back..." );
+    printw("  u       switch between ICMP ECHO and UDP datagrams\n" );
+#ifdef IPINFO
+    printw("  y       switching IP info\n");
+    printw("  z       toggle ASN info on/off\n");
+    pressanykey_row += 2;
+#endif
+    printw("\n");
+    mvprintw(pressanykey_row, 0, " press any key to go back..." );
 
     getch();                  /* get any key */
     return ActionNone;
@@ -315,47 +341,13 @@ void mtr_curses_hosts(int startstat)
     mpls = net_mpls(at);
 
     if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) {
-      struct in6_addr addr6 = *addr;
-
-      if (PrintAS) {
-              u_char ipv4[4];
-              ipv4[0] = addr6.s6_addr[0];
-              ipv4[1] = addr6.s6_addr[1];
-              ipv4[2] = addr6.s6_addr[2];
-              ipv4[3] = addr6.s6_addr[3];
-
-#define NAMELEN 127
-              char ipv4_buf[NAMELEN];
-              char* chip = (char*) &ipv4_buf;
-              char* chas = NULL;
-              char** key_ptr = &chip;
-              char** value_ptr = &chas;
-
-
-              if (snprintf(ipv4_buf, NAMELEN, "%d.%d.%d.%d.asn.routeviews.org", ipv4[3],
-                                      ipv4[2], ipv4[1], ipv4[0]) >= NAMELEN) {
-                      return;
-              }
-
-
-
-              gboolean result =
-                      g_hash_table_lookup_extended
-                      (ashash, ipv4_buf, (gpointer*)key_ptr, (gpointer*)value_ptr);
-              if (!result) {
-                      char* as = asn_lookup(ipv4_buf);
-                      chip = (char*) strdup(ipv4_buf);
-                      chas = (char*) as;
-                      g_hash_table_insert(ashash, chip, chas);
-              }
-              //g_hash_table_destroy(hash);
-
-
-              printw("[AS%s] ", chas);
-      }
       name = dns_lookup(addr);
       if (! net_up(at))
 	attron(A_BOLD);
+#ifdef IPINFO
+      if (is_printii())
+        printw(fmt_ipinfo(addr));
+#endif
       if(name != NULL) {
         if (show_ips) printw("%s (%s)", name, strlongip(addr));
         else printw("%s", name);
@@ -368,7 +360,6 @@ void mtr_curses_hosts(int startstat)
       move(y, startstat);
 
       /* net_xxx returns times in usecs. Just display millisecs */
-      /* changedByMin */
       hd_len = 0;
       for( i=0; i<MAXFLD; i++ ) {
 	/* Ignore options that don't exist */
@@ -400,7 +391,7 @@ void mtr_curses_hosts(int startstat)
         }
       }
 
-      /* Multi path by Min */
+      /* Multi path */
       for (i=0; i < MAXPATH; i++ ) {
         addrs = net_addrs(at, i);
         mplss = net_mplss(at, i);
@@ -409,11 +400,16 @@ void mtr_curses_hosts(int startstat)
 
         name = dns_lookup(addrs);
         if (! net_up(at)) attron(A_BOLD);
+        printw("\n    ");
+#ifdef IPINFO
+        if (is_printii())
+          printw(fmt_ipinfo(addrs));
+#endif
         if (name != NULL) {
-	  if (show_ips) printw("\n    %s (%s)", name, strlongip(addrs));
-	  else printw("\n    %s", name);
+	  if (show_ips) printw("%s (%s)", name, strlongip(addrs));
+	  else printw("%s", name);
         } else {
-	  printw("\n    %s", strlongip( addrs ) );
+	  printw("%s", strlongip( addrs ) );
         }
         for (k=0; k < mplss->labels && enablempls; k++) {
           printw("\n    [MPLS: Lbl %lu Exp %u S %u TTL %u]", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]);
@@ -430,9 +426,9 @@ 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];
+#define NUM_FACTORS 8
+static double factors[NUM_FACTORS];
+static int scale[NUM_FACTORS];
 static int low_ms, high_ms;
 
 void mtr_gen_scale(void) 
@@ -443,7 +439,7 @@ void mtr_gen_scale(void)
 	low_ms = 1000000;
 	high_ms = -1;
 
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < NUM_FACTORS; i++) {
 		scale[i] = 0;
 	}
 	max = net_max();
@@ -460,21 +456,62 @@ void mtr_gen_scale(void)
 		}
 	}
 	range = high_ms - low_ms;
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < NUM_FACTORS; i++) {
 		scale[i] = low_ms + ((double)range * factors[i]);
 	}
 }
 
 
-static const char* block_map = ".123abc>";
+static char block_map[NUM_FACTORS];
+
+void mtr_curses_init() {
+	int i;
+	int block_split;
+
+	/* Initialize factors to a log scale. */
+	for (i = 0; i < NUM_FACTORS; i++) {
+		factors[i] = ((double)1 / NUM_FACTORS) * (i + 1);
+		factors[i] *= factors[i]; /* Squared. */
+	}
+
+	/* Initialize block_map. */
+	block_split = (NUM_FACTORS - 2) / 2;
+	if (block_split > 9) {
+		block_split = 9;
+	}
+	for (i = 1; i <= block_split; i++) {
+		block_map[i] = '0' + i;
+	}
+	for (i = block_split+1; i < NUM_FACTORS-1; i++) {
+		block_map[i] = 'a' + i - block_split - 1;
+	}
+	block_map[0] = '.';
+	block_map[NUM_FACTORS-1] = '>';
+}
+
+
+static int block_col[NUM_FACTORS+1] =
+{	// 1:black 2:red 3:green 4:brown/yellow 5:blue 6:magenta 7:cyan 8:white
+        COLOR_PAIR(2)|A_BOLD,
+	A_NORMAL,
+	COLOR_PAIR(3),
+	COLOR_PAIR(3)|A_BOLD,
+	COLOR_PAIR(4)|A_BOLD,
+	COLOR_PAIR(6)|A_BOLD,
+	COLOR_PAIR(6),
+	COLOR_PAIR(2),
+	COLOR_PAIR(2)|A_BOLD
+};
 
 void mtr_print_scaled(int ms) 
 {
 	int i;
 
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < NUM_FACTORS; i++) {
 		if (ms <= scale[i]) {
+			attrset(block_col[i+1]);
 			printw("%c", block_map[i]);
+			attrset(A_NORMAL);
 			return;
 		}
 	}
@@ -492,13 +529,13 @@ void mtr_fill_graph(int at, int cols)
 		if (saved[i] == -2) {
 			printw(" ");
 		} else if (saved[i] == -1) {
-			attron(A_BOLD);
-			printw("?");
-			attroff(A_BOLD);
+		        attrset(block_col[0]);
+			printw("%c", '?');
+			attrset(A_NORMAL);
 		} else {
 			if (display_mode == 1) {
 				if (saved[i] > scale[6]) {
-					printw("%c", block_map[7]);
+					printw("%c", block_map[NUM_FACTORS-1]);
 				} else {
 					printw(".");
 				}
@@ -529,12 +566,15 @@ void mtr_curses_graph(int startstat, int cols)
 
 		if (! net_up(at))
 			attron(A_BOLD);
-		name = dns_lookup(addr);
-		if (name) {
-			printw("%s", name);
-		} else {
-			printw("%s", strlongip( addr ) );
-		}
+		if (addrcmp((void *) addr, (void *) &unspec_addr, af)) {
+#ifdef IPINFO
+			if (is_printii())
+				printw(fmt_ipinfo(addr));
+#endif
+			name = dns_lookup(addr);
+			printw("%s", name?name:strlongip(addr));
+		} else
+			printw("???");
 		attroff(A_BOLD);
 
 		getyx(stdscr, y, __unused_int);
@@ -597,7 +637,6 @@ void mtr_curses_redraw(void)
   attron(A_BOLD); printw("q"); attroff(A_BOLD); printw("uit\n");
   
   if (display_mode == 0) {
-    /* changedByMin */
     for (i=0; i < MAXFLD; i++ ) {
 	j = fld_index[fld_active[i]];
 	if (j < 0) continue;
@@ -616,10 +655,14 @@ void mtr_curses_redraw(void)
     mtr_curses_hosts(maxx-hd_len-1);
 
   } else {
-    /* David Sward, Jan 1999 */
     char msg[80];
-    int max_cols = maxx<=SAVED_PINGS+30 ? maxx-30 : SAVED_PINGS;
-    startstat = 28;
+    int padding = 30;
+#ifdef IPINFO
+    if (is_printii())
+      padding += get_iiwidth();
+#endif
+    int max_cols = maxx<=SAVED_PINGS+padding ? maxx-padding : SAVED_PINGS;
+    startstat = padding - 2;
 
     sprintf(msg, " Last %3d pings", max_cols);
     mvprintw(rowstat - 1, startstat, msg);
@@ -635,9 +678,17 @@ void mtr_curses_redraw(void)
     printw("Scale:");
     attroff(A_BOLD);
     
-    for (i = 0; i < 7; i++) {
-      printw("  %c:%d ms", block_map[i], scale[i]/1000);
+    for (i = 0; i < NUM_FACTORS-1; i++) {
+      printw("  ");
+      attrset(block_col[i+1]);
+      printw("%c", block_map[i]);
+      attrset(A_NORMAL);
+      printw(":%d ms", block_map[i], scale[i]/1000);
     }
+    printw("  ");
+    attrset(block_col[NUM_FACTORS]);
+    printw("%c", block_map[NUM_FACTORS-1]);
+    attrset(A_NORMAL);
   }
 
   refresh();
@@ -646,11 +697,15 @@ void mtr_curses_redraw(void)
 
 void mtr_curses_open(void)
 {
-  ashash = g_hash_table_new(g_str_hash, g_str_equal);
   initscr();
   raw();
   noecho(); 
+  start_color();
+  int i;
+  for (i = 0; i < 8; i++)
+      init_pair(i+1, i, 0);
 
+  mtr_curses_init();
   mtr_curses_redraw();
 }
 
diff --git a/display.c b/display.c
index f27cd7c..3545467 100644
--- a/display.c
+++ b/display.c
@@ -16,7 +16,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <config.h>
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -29,6 +30,7 @@
 #include "select.h"
 #include "raw.h"
 #include "dns.h"
+#include "asn.h"
 
 extern int DisplayMode;
 
@@ -94,8 +96,12 @@ void display_open(void)
     break;
   case DisplayCurses:
     mtr_curses_open();  
+#ifdef IPINFO
+    if (ipinfo_no >= 0)
+        asn_open();
+#endif
     break;
-  case DisplaySplit:            /* BL */
+  case DisplaySplit:
     split_open();
     break;
   case DisplayGTK:
@@ -105,7 +111,7 @@ void display_open(void)
 }
 
 
-void display_close(void)
+void display_close(time_t now)
 {
   switch(DisplayMode) {
   case DisplayReport:
@@ -118,12 +124,16 @@ void display_close(void)
     xml_close();
     break;
   case DisplayCSV:
-    csv_close();
+    csv_close(now);
     break;
   case DisplayCurses:
+#ifdef IPINFO
+    if (ipinfo_no >= 0)
+        asn_close();
+#endif
     mtr_curses_close();
     break;
-  case DisplaySplit:            /* BL */
+  case DisplaySplit:
     split_close();
     break;
   case DisplayGTK:
@@ -141,7 +151,7 @@ void display_redraw(void)
     mtr_curses_redraw();
     break;
 
-  case DisplaySplit:            /* BL */
+  case DisplaySplit:
     split_redraw();
     break;
 
@@ -158,7 +168,7 @@ int display_keyaction(void)
   case DisplayCurses:
     return mtr_curses_keyaction();
 
-  case DisplaySplit:		/* BL */
+  case DisplaySplit:
     return split_keyaction();
 
   case DisplayGTK:
@@ -175,7 +185,7 @@ void display_rawping(int host, int msec)
   case DisplayTXT:
   case DisplayXML:
   case DisplayCSV:
-  case DisplaySplit:            /* BL */
+  case DisplaySplit:
   case DisplayCurses:
   case DisplayGTK:
     break;
@@ -193,7 +203,7 @@ void display_rawhost(int host, ip_t *ip_addr)
   case DisplayTXT:
   case DisplayXML:
   case DisplayCSV:
-  case DisplaySplit:            /* BL */
+  case DisplaySplit:
   case DisplayCurses:
   case DisplayGTK:
     break;
@@ -211,7 +221,7 @@ void display_loop(void)
   case DisplayTXT:
   case DisplayXML:
   case DisplayCSV:
-  case DisplaySplit:            /* BL */
+  case DisplaySplit:
   case DisplayCurses:
   case DisplayRaw:
     select_loop();
@@ -233,7 +243,7 @@ void display_clear(void)
   case DisplayTXT:
   case DisplayXML:
   case DisplayCSV:
-  case DisplaySplit:            /* BL */
+  case DisplaySplit:
   case DisplayRaw:
     break;
 
diff --git a/display.h b/display.h
index 91f863d..6168914 100644
--- a/display.h
+++ b/display.h
@@ -19,9 +19,12 @@
 #include <netinet/in.h>
 
 /* Don't put a trailing comma in enumeration lists. Some compilers 
-   (notably the one on Irix 5.2) do not like that. -- REW */ 
+   (notably the one on Irix 5.2) do not like that. */ 
 enum { ActionNone,  ActionQuit,  ActionReset,  ActionDisplay, 
        ActionClear, ActionPause, ActionResume, ActionMPLS, ActionDNS, 
+#ifdef IPINFO
+       ActionII, ActionAS,
+#endif
        ActionScrollDown, ActionScrollUp  };
 enum { DisplayReport, DisplayCurses, DisplayGTK, DisplaySplit, 
        DisplayRaw,    DisplayXML,    DisplayCSV, DisplayTXT};
@@ -29,7 +32,7 @@ enum { DisplayReport, DisplayCurses, DisplayGTK, DisplaySplit,
 /*  Prototypes for display.c  */
 void display_detect(int *argc, char ***argv);
 void display_open(void);
-void display_close(void);
+void display_close(time_t now);
 void display_redraw(void);
 void display_rawping(int hostnum, int msec);
 void display_rawhost(int hostnum, ip_t *ip_addr);
diff --git a/dns.c b/dns.c
index 5d10d1c..32b83c2 100644
--- a/dns.c
+++ b/dns.c
@@ -22,7 +22,8 @@
     Released under GPL, as above.
 */
 
-#include <config.h>
+#include "config.h"
+
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/select.h>
@@ -32,8 +33,13 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#ifndef __APPLE__
 #define BIND_8_COMPAT
+#endif
 #include <arpa/nameser.h>
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+#include <arpa/nameser_compat.h>
+#endif
 #include <netdb.h>
 #include <resolv.h>
 #include <unistd.h>
@@ -51,22 +57,12 @@
 
 #ifdef ENABLE_IPV6
 #ifdef __GLIBC__
-#define NSCOUNT6 myres._u._ext.nscount6
 #define NSSOCKADDR6(i) (myres._u._ext.nsaddrs[i])
 #else
-#define NSCOUNT6 myres.nscount
 #define NSSOCKADDR6(i) (&(myres._u._ext.ext->nsaddrs[i].sin6))
 #endif
 #endif
 
-/* OSX  Needs this. I don't know how to enable this for them automatically. 
- * Should be easy with autoconf. Please submit a patch if you know 
- * autoconf.... -- REW
- */
-#if 0 
-#include "nameser8_compat.h"
-#endif
-
 
 #ifdef NO_STRERROR
 extern int sys_nerr;
@@ -184,7 +180,7 @@ char *rrtypes[] = {
 
 
 /* Please don't use a trailing comma in enumerations: It doesn't
-   work on all compilers -- REW */
+   work on all compilers */
 enum {
    RR_UNKNOWN,
    RR_QUERY,
@@ -233,8 +229,7 @@ typedef struct {
 #if 0
 
 /* The execution order inside an expression is undefined! That means that
-   this might work, but then again, it might not... Sun Lint pointed this 
-   one out...*/
+   this might work, but then again, it might not... */
 
 #define sucknetword(x) (((word)*(x) << 8) | (((x)+= 2)[-1]))
 #define sucknetshort(x) (((short)*(x) << 8) | (((x)+= 2)[-1]))
@@ -533,10 +528,12 @@ void dns_open(void)
 #ifdef ENABLE_IPV6
   resfd6 = socket(AF_INET6, SOCK_DGRAM, 0);
   if (resfd6 == -1) {
+    // consider making removing this warning. For now leave it in to see 
+    // new code activated. -- REW
     fprintf(stderr,
             "Unable to allocate IPv6 socket for nameserver communication: %s\n",
 	    strerror(errno));
-    exit(-1);
+    //    exit(-1);
   }
 #endif
   option = 1;
@@ -547,11 +544,13 @@ void dns_open(void)
     exit(-1);
   }
 #ifdef ENABLE_IPV6
-  if (setsockopt(resfd6,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) {
-    fprintf(stderr,
-            "Unable to setsockopt() on IPv6 nameserver communication socket: %s\n",
-	    strerror(errno));
-    exit(-1);
+  if (resfd6 > 0) {
+    if (setsockopt(resfd6,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) {
+      fprintf(stderr,
+	      "Unable to setsockopt() on IPv6 nameserver communication socket: %s\n",
+	      strerror(errno));
+      exit(-1);
+    }
   }
 #endif
   longipstr( "127.0.0.1", &localhost, AF_INET );
@@ -936,17 +935,19 @@ void dorequest(char *s,int type,word id)
   }
   hp = (packetheader *)buf;
   hp->id = id;	/* htons() deliberately left out (redundant) */
-#ifdef ENABLE_IPV6
-  for (i = 0;i < NSCOUNT6;i++) {
-    if (NSSOCKADDR6(i)->sin6_family == AF_INET6)
-      (void)sendto(resfd6,buf,r,0,(struct sockaddr *) NSSOCKADDR6(i),
-		   sizeof(struct sockaddr_in6));
-  }
-#endif
   for (i = 0;i < myres.nscount;i++)
     if (myres.nsaddr_list[i].sin_family == AF_INET)
       (void)sendto(resfd,buf,r,0,(struct sockaddr *)&myres.nsaddr_list[i],
 		   sizeof(struct sockaddr));
+#ifdef ENABLE_IPV6
+    else if (resfd6 > 0) {
+      if (!NSSOCKADDR6(i))
+	continue;
+      if (NSSOCKADDR6(i)->sin6_family == AF_INET6)
+	(void)sendto(resfd6,buf,r,0,(struct sockaddr *) NSSOCKADDR6(i),
+		     sizeof(struct sockaddr_in6));
+    }
+#endif
 }
 
 void resendrequest(struct resolve *rp,int type)
@@ -1329,13 +1330,19 @@ void dns_ack6(void)
   int r,i;
   static char addrstr[INET6_ADDRSTRLEN];
 
+  // Probably not necessary. -- REW
+  if (resfd6 < 0) return; 
+
   r = recvfrom(resfd6,(byte *)resrecvbuf,MaxPacketsize,0,
                from, &fromlen);
   if (r > 0) {
     /* Check to see if this server is actually one we sent to */
     if ( addrcmp( (void *) &(from6->sin6_addr), (void *) &localhost6,
                   (int) AF_INET6 ) == 0 ) {
-      for (i = 0;i < NSCOUNT6;i++) {
+      for (i = 0;i < myres.nscount;i++) {
+        if (!NSSOCKADDR6(i))
+          continue;
+
 	if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr),
 		      (void *) &(from6->sin6_addr), (int) AF_INET6 ) == 0 ||
 	     addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr),
@@ -1343,12 +1350,14 @@ void dns_ack6(void)
 	  break;
       }
     } else
-      for (i = 0;i < NSCOUNT6;i++) {
+      for (i = 0;i < myres.nscount;i++) {
+        if (!NSSOCKADDR6(i))
+          continue;
 	if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr),
 		      (void *) &(from6->sin6_addr), AF_INET6 ) == 0 )
 	  break;
       }
-    if (i == NSCOUNT6) {
+    if (i == myres.nscount) {
       snprintf(tempstring, sizeof(tempstring), 
 	       "Resolver error: Received reply from unknown source: %s",
 	       inet_ntop( AF_INET6, &(from6->sin6_addr), addrstr,
diff --git a/dns.h b/dns.h
index 4bf3fc1..79e91f4 100644
--- a/dns.h
+++ b/dns.h
@@ -16,8 +16,9 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <config.h>
 #include <netinet/in.h>
-
+#include <resolv.h>
 
 /*  Prototypes for dns.c  */
 
@@ -27,10 +28,8 @@ void dns_ack(void);
 #ifdef ENABLE_IPV6
 int dns_waitfd6(void);
 void dns_ack6(void);
-#ifdef BSD
-/* __res_state_ext is missing on many (most?) BSD systems
-   - this should probably be handled by autoconf */
-#ifndef __res_state_ext
+#ifdef NEED_RES_STATE_EXT
+/* __res_state_ext is missing on many (most?) BSD systems */
 struct __res_state_ext {
 	union res_sockaddr_union nsaddrs[MAXNS];
 	struct sort_list {
@@ -45,7 +44,6 @@ struct __res_state_ext {
 };
 #endif
 #endif
-#endif
 
 void dns_events(double *sinterval);
 char *dns_lookup(ip_t * address);
diff --git a/getopt.c b/getopt.c
index 3d43e26..e2f8758 100644
--- a/getopt.c
+++ b/getopt.c
@@ -27,7 +27,7 @@
 #endif
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #if !defined (__STDC__) || !__STDC__
diff --git a/getopt1.c b/getopt1.c
index bccf8b2..0a2d405 100644
--- a/getopt1.c
+++ b/getopt1.c
@@ -16,7 +16,7 @@
    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
 #endif
 
 #include "getopt.h"
diff --git a/gtk.c b/gtk.c
index b45ac81..7faa132 100644
--- a/gtk.c
+++ b/gtk.c
@@ -17,7 +17,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <config.h>
+#include "config.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -191,9 +191,9 @@ gint About_clicked(UNUSED GtkWidget *Button, UNUSED gpointer data)
  * There is a small problem with the following code:
  * The timeout is canceled and removed in order to ensure that
  * it takes effect (consider what happens if you set the timeout to 999,
- * then try to undo the change); is a better approach possible? -- CMR
+ * then try to undo the change); is a better approach possible?
  *
- * What's the problem with this? (-> "I don't think so)  -- REW
+ * What's the problem with this? (-> "I don't think so)
  */
 
 gint WaitTime_changed(UNUSED GtkAdjustment *Adj, UNUSED GtkWidget *Button) 
@@ -215,7 +215,7 @@ gint Host_activate(GtkWidget *Entry, UNUSED gpointer data)
   if(addr) {
     net_reopen(addr);
     /* If we are "Paused" at this point it is usually because someone
-       entered a non-existing host. Therefore do the go-ahead... --REW */
+       entered a non-existing host. Therefore do the go-ahead... */
     gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( Pause_Button ) , 0);
   } else {
     int pos = strlen(gtk_entry_get_text( GTK_ENTRY(Entry)));
@@ -310,7 +310,7 @@ enum {
 // architectures, the pointer is 64 bits and the integer only 32. 
 // The compiler warns us of loss of precision. However we know we
 // casted a normal 32-bit integer into this pointer a few microseconds
-// earlier, so it is ok. Nothing to worry about.... -- REW.
+// earlier, so it is ok. Nothing to worry about....
 #define POINTER_TO_INT(p) ((int)(long)(p))
 
 void  float_formatter(GtkTreeViewColumn *tree_column,
@@ -576,6 +576,7 @@ gint gtk_ping(UNUSED gpointer data)
 {
   gtk_redraw();
   net_send_batch();
+  net_harvest_fds();
   g_source_remove (tag);
   gtk_add_ping_timeout ();
   return TRUE;
@@ -614,8 +615,10 @@ void gtk_loop(void)
   net_iochannel = g_io_channel_unix_new(net_waitfd());
   g_io_add_watch(net_iochannel, G_IO_IN, gtk_net_data, NULL);
 #ifdef ENABLE_IPV6
-  dns_iochannel = g_io_channel_unix_new(dns_waitfd6());
-  g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data6, NULL);
+  if (dns_waitfd6() > 0) {
+    dns_iochannel = g_io_channel_unix_new(dns_waitfd6());
+    g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data6, NULL);
+  }
 #endif
   dns_iochannel = g_io_channel_unix_new(dns_waitfd());
   g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data, NULL);
diff --git a/mtr.8 b/mtr.8
index 81e1926..16770c5 100644
--- a/mtr.8
+++ b/mtr.8
@@ -1,20 +1,14 @@
-.TH MTR 8 "March 4, 1999" "mtr" "mtr"
-
-
+.TH MTR 8 "July 12, 2014" "mtr" "mtr"
 .SH NAME
 mtr \- a network diagnostic tool
-
-
 .SH SYNOPSIS
-.B mtr 
-[\c
-.B \-hvrctglspeniu46\c
-]
+.B mtr
 [\c
-.B \-\-help\c
+.BR \-4 |\c
+.B \-6\c
 ]
 [\c
-.B \-\-version\c
+.BI \-F \ FILENAME\c
 ]
 [\c
 .B \-\-report\c
@@ -23,19 +17,22 @@ mtr \- a network diagnostic tool
 .B \-\-report-wide\c
 ]
 [\c
-.B \-\-report\-cycles\ COUNT\c
+.B \-\-xml\c
 ]
 [\c
-.B \-\-curses\c
+.B \-\-gtk\c
 ]
 [\c
-.B \-\-split\c
+.B \-\-curses\c
 ]
 [\c
 .B \-\-raw\c
 ]
 [\c
-.B \-\-mpls\c
+.B \-\-csv\c
+]
+[\c
+.B \-\-split\c
 ]
 [\c
 .B \-\-no-dns\c
@@ -44,37 +41,72 @@ mtr \- a network diagnostic tool
 .B \-\-show-ips\c
 ]
 [\c
-.B \-\-gtk\c
+.BI \-o \ FIELDS\c
 ]
 [\c
-.B \-\-address\ IP.ADD.RE.SS\c
+.BI \-y \ IPINFO\c
 ]
 [\c
-.B \-\-interval\ SECONDS\c
+.B \-\-aslookup\c
 ]
 [\c
-.B \-\-psize\ BYTES | -s BYTES\c
+.BI \-i \ INTERVAL\c
 ]
-.B HOSTNAME [PACKETSIZE]
-
-
+[\c
+.BI \-c \ COUNT\c
+]
+[\c
+.BI \-s \ PACKETSIZE\c
+]
+[\c
+.BI \-B \ BITPATTERN\c
+]
+[\c
+.BI \-Q \ TOS\c
+]
+[\c
+.B \-\-mpls\c
+]
+[\c
+.BI \-a \ ADDRESS\c
+]
+[\c
+.BI \-f \ FIRST\-TTL\c
+]
+[\c
+.BI \-m \ MAX\-TTL\c
+]
+[\c
+.B \-\-udp\c
+]
+[\c
+.B \-\-tcp\c
+]
+[\c
+.BI \-P \ PORT\c
+]
+[\c
+.BI \-Z \ TIMEOUT\c
+]
+[\c
+.BI \-M \ MARK\c
+]
+.I HOSTNAME
 .SH DESCRIPTION
-
 .B mtr 
 combines the functionality of the 
 .B traceroute
 and 
 .B ping
 programs in a single network diagnostic tool.
-
 .PP
 As 
 .B mtr 
 starts, it investigates the network connection between the host 
 .B mtr
 runs on and 
-.BR HOSTNAME . 
-by sending packets with purposely low TTLs. It continues to send
+.BR HOSTNAME
+by sending packets with purposely low TTLs.  It continues to send
 packets with low TTL, noting the response time of the intervening
 routers.  This allows 
 .B mtr 
@@ -83,32 +115,27 @@ route to
 .BR HOSTNAME . 
 A sudden increase in packet loss or response time is often an indication
 of a bad (or simply overloaded) link. 
-
 .PP
 The results are usually reported as round-trip-response times in miliseconds 
 and the percentage of packetloss. 
-
 .SH OPTIONS
-
-.TP
-.B \-h
 .TP
-.B \-\-help
-.br
+.B \-h\fR, \fB\-\-help
 Print the summary of command line argument options.
-
-.TP
-.B \-v
 .TP
-.B \-\-version
-.br
+.B \-v\fR, \fB\-\-version
 Print the installed version of mtr.  
-
 .TP
-.B \-r
+.B \-4
+Use IPv4 only.
 .TP
-.B \-\-report
-.br
+.B \-6
+Use IPv6 only.  (IPV4 may be used for DNS lookups). 
+.TP
+.B \-F \fIFILENAME\fR, \fB\-\-filename \fIFILENAME
+MISSING
+.TP
+.B \-r\fR, \fB\-\-report
 This option puts 
 .B mtr
 into 
@@ -127,12 +154,8 @@ generates a significant amount of network traffic.  Using
 .B mtr
 to measure the quality of your network may result in decreased
 network performance.  
-
-.TP
-.B \-w
 .TP
-.B \-\-report-wide
-.br
+.B \-w\fR, \fB\-\-report\-wide
 This option puts 
 .B mtr
 into 
@@ -140,75 +163,61 @@ into
 mode.  When in this mode,
 .B mtr
 will not cut hostnames in the report. 
-
-.TP
-.B \-c\ COUNT
-.TP
-.B \-\-report\-cycles\ COUNT
-Use this option to set the number of pings sent to determine
-both the machines on the network and the reliability of 
-those machines.  Each cycle lasts one second.
-
-.TP
-.B \-s\ BYTES
-.TP
-.B \-\-psize\ BYTES
-.TP
-.B PACKETSIZE
-These options or a trailing PACKETSIZE on the command line sets 
-the packet size used for probing.
-It is in bytes inclusive IP and ICMP headers
-
-If set to a negative number, every iteration will use a different, random
-packet size upto that number. 
 .TP
-.B \-t
+.B \-x\fR, \fB\-\-xml
+Use this option to tell
+.B mtr
+to use the xml output format.  This format is better suited for
+automated processing of the measurement results.
 .TP
-.B \-\-curses
-.br
+.B \-t\fR, \fB\-\-curses
 Use this option to force 
 .B mtr 
 to use the curses based terminal
 interface (if available).
-
 .TP
-.B \-e
-.TP
-.B \-\-mpls
-.br
-Use this option to tell 
+.B \-g\fR, \fB\-\-gtk
+Use this option to force
 .B mtr 
-to display information from ICMP extensions for MPLS (RFC 4950)
-that are encoded in the response packets.
-
+to use the GTK+ based X11 window interface (if available).  
+GTK+ must have been available on the system when 
+.B mtr 
+was built for this to work.  See the GTK+ web page at 
+.B http://www.gtk.org/
+for more information about GTK+.
+.TP
+.B \-l\fR, \fB\-\-raw
+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 \-n
+.B \-C\fR, \fB\-\-csv
+MISSING
 .TP
-.B \-\-no-dns
-.br
+.B \-p\fR, \fB\-\-split
+Use this option to set
+.B mtr 
+to spit out a format that is suitable for a split-user interface.
+.TP
+.B \-n\fR, \fB\-\-no\-dns
 Use this option to force 
 .B mtr 
 to display numeric IP numbers and not try to resolve the
 host names. 
-
-.TP
-.B \-b
 .TP
-.B \-\-show-ips
-.br
+.B \-b\fR, \fB\-\-show\-ips
 Use this option to tell
 .B mtr
 to display both the host names and numeric IP numbers.  In split mode
-this adds an extra field to the output. In report mode, there is usually
-too little space to add the IPs, and they will be truncated. Use the 
+this adds an extra field to the output.  In report mode, there is usually
+too little space to add the IPs, and they will be truncated.  Use the
 wide report (-w) mode to see the IPs in report mode. 
-
-.TP
-.B \-o\ fields\ order
 .TP
-.B \-\-order\ fields\ order
-.br
-Use this option to specify the fields and their order when loading mtr.
+.B \-o \fIFIELDS\fR, \fB\-\-order \fIFIELDS
+Use this option to specify which fields to display and in which order.
+You may use one or more space characters to separate fields.
 .br
 Available fields:
 .TS
@@ -232,99 +241,129 @@ I%Interarrival Jitter
 .br
 
 Example:
--o "LSD NBAW"
+-o "LSD NBAW  X"
 .TP
-.B \-g
+.B \-y \fIn\fR, \fB\-\-ipinfo \fIn
+MISSING
 .TP
-.B \-\-gtk
-.br
-Use this option to force
-.B mtr 
-to use the GTK+ based X11 window interface (if available).  
-GTK+ must have been available on the system when 
-.B mtr 
-was built for this to work.  See the GTK+ web page at 
-.B http://www.gtk.org/
-for more information about GTK+.
-
+.B \-z\fR, \fB\-\-aslookup
+MISSING
 .TP
-.B \-p
+.B \-i \fISECONDS\fR, \fB\-\-interval \fISECONDS
+Use this option to specify the positive number of seconds between ICMP
+ECHO requests.  The default value for this parameter is one second.  The
+root user may choose values between zero and one.
 .TP
-.B \-\-split
-.br
-Use this option to set
-.B mtr 
-to spit out a format that is suitable for a split-user interface.
+.B \-c \fICOUNT\fR, \fB\-\-report\-cycles \fICOUNT
+Use this option to set the number of pings sent to determine
+both the machines on the network and the reliability of 
+those machines.  Each cycle lasts one second.
+.TP
+.B \-s \fIPACKETSIZE\fR, \fB\-\-psize \fIPACKETSIZE
+This option sets the packet size used for probing.  It is in bytes,
+inclusive IP and ICMP headers.
 
+If set to a negative number, every iteration will use a different, random
+packet size up to that number.
 .TP
-.B \-l
+.B \-B \fINUM\fR, \fB\-\-bitpattern \fINUM
+Specifies bit pattern to use in payload.  Should be within range 0 - 255.  If
+.I NUM
+is greater than 255, a random pattern is used.
 .TP
-.B \-\-raw
-.br
+.B \-Q \fINUM\fR, \fB\-\-tos \fINUM
+Specifies value for type of service field in IP header.  Should be within range 0
+- 255.
+.TP
+.B \-e\fR, \fB\-\-mpls
 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 \-a\ IP.ADD.RE.SS
+to display information from ICMP extensions for MPLS (RFC 4950)
+that are encoded in the response packets.
 .TP
-.B \-\-address\ IP.ADD.RE.SS
-.br
-Use this option to bind outgoing packets' socket to specific interface,
-so that any packet will be sent through this interface. NOTE that this
-option doesn't apply to DNS requests (which could be and could not be 
-what you want).
-
+.B \-a \fIADDRESS\fR, \fB\-\-address \fIADDRESS
+Use this option to bind the outgoing socket to
+.IR ADDRESS ,
+so that all packets will be sent with
+.I ADDRESS
+as source address.  NOTE that this option doesn't apply to DNS requests
+(which could be and could not be what you want).
 .TP
-.B \-i\ SECONDS
+.B \-f \fINUM\fR, \fB\-\-first-ttl \fINUM
+Specifies with what TTL to start.  Defaults to 1.
 .TP
-.B \-\-interval\ SECONDS
-.br
-Use this option to specify the positive number of seconds between ICMP
-ECHO requests.  The default value for this parameter is one second.
-
+.B \-m \fINUM\fR, \fB\-\-max-ttl \fINUM
+Specifies the maximum number of hops (max time-to-live value) traceroute will
+probe.  Default is 30.
 .TP
-.B \-u
-.br
+.B \-u\fR, \fB\-\-udp
 Use UDP datagrams instead of ICMP ECHO.
-
 .TP
-.B \-4
-.br
-Use IPv4 only.
-
+.B \-T\fR, \fB\-\-tcp
+Use TCP SYN packets instead of ICMP ECHO.
+.I PACKETSIZE
+is ignored, since SYN packets can not contain data.
 .TP
-.B \-6
-.br
-Use IPv6 only.
+.B \-P \fIPORT\fR, \fB\-\-port \fIPORT
+The target port number for TCP traces.
+.TP
+.B \-Z \fISECONDS\fR, \fB\-\-timeout \fISECONDS
+The number of seconds to keep the TCP socket open before giving up on
+the connection.  This will only affect the final hop.  Using large values
+for this, especially combined with a short interval, will use up a lot
+of file descriptors.
+.TP
+.B \-M \fIMARK\fR, \fB\-\-mark \fIMARK
+MISSING
+.SH ENVIRONMENT
+.B mtr
+recognizes a few environment variables.
+.TP
+.B MTR_OPTIONS
+This environment variable allows to specify options, as if they were
+passed on the command line.  It is parsed before reading the actual
+command line options, so that options specified in
+.B MTR_OPTIONS
+are overriden by command-line options.
 
-.SH BUGS
+Example:
 
+.BI MTR_OPTIONS ="-4\ -c\ 1"
+.B mtr
+.I \-6\ localhost
+
+would send one probe (because of
+.I -c\ 1\c
+) towards
+.B ::1
+(because of
+.IR -6 ,
+which overrides the
+.I -4
+passed in
+.B MTR_OPTIONS\c
+).
+.TP
+.B DISPLAY
+Used for the GTK+ frontend.
+.SH BUGS
 Some modern routers give a lower priority to ICMP ECHO packets than 
 to other network traffic.  Consequently, the reliability of these
 routers reported by 
 .B mtr
 will be significantly lower than the actual reliability of 
 these routers.  
-
-
 .SH CONTACT INFORMATION
-
 .PP
 For the latest version, see the mtr web page at 
 .BR http://www.bitwizard.nl/mtr/ .
-
 .PP
 The mtr mailinglist was little used and is no longer active. 
-
 .PP
-Bug reports and feature requests should be submitted to the
-launchpad mtr bugtracker. 
-
+For patches, bug reports, or feature requests, please open an issue on
+GitHub at:
+.BR https://github.com/traviscross/mtr .
 .SH "SEE ALSO"
-
 traceroute(8),
 ping(8)
 TCP/IP Illustrated (Stevens, ISBN 0201633469).
diff --git a/mtr.c b/mtr.c
index 9246bb1..417caf6 100644
--- a/mtr.c
+++ b/mtr.c
@@ -3,7 +3,7 @@
     Copyright (C) 1997,1998  Matt Kimball
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License version 2 as 
+    it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.
 
     This program is distributed in the hope that it will be useful,
@@ -16,17 +16,26 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "config.h"
+
 #include <sys/types.h>
-#include <config.h>
-#include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <netinet/in.h>
-#include <sys/socket.h> 
 #include <unistd.h>
+#include <errno.h>
+#include <string.h>
 #include <strings.h>
 
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <ctype.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
 #include "mtr.h"
 #include "mtr-curses.h"
 #include "getopt.h"
@@ -67,6 +76,9 @@ int   enablempls = 0;
 int   cpacketsize = 64;          /* default packet size */
 int   bitpattern = 0;
 int   tos = 0;
+#ifdef SO_MARK
+int   mark = -1;
+#endif
 int   reportwide = 0;
 int af = DEFAULT_AF;
 int mtrtype = IPPROTO_ICMP;     /* Use ICMP as default packet type */
@@ -76,6 +88,8 @@ int  fstTTL = 1;                /* default start at first hop */
 /*int maxTTL = MaxHost-1;  */     /* max you can go is 255 hops */
 int   maxTTL = 30;              /* inline with traceroute */
                                 /* end ttl window stuff. */
+int remoteport = 80;            /* for TCP tracing */
+int timeout = 10 * 1000000;     /* for TCP tracing */
 
 
 /* default display field(defined by key in net.h) and order */
@@ -104,6 +118,125 @@ struct fields data_fields[MAXFLD] = {
   {'\0', NULL, NULL, NULL, 0, NULL}
 };
 
+typedef struct names {
+  char*                 name;
+  struct names*         next;
+} names_t;
+static names_t *names = NULL;
+
+char *
+trim(char * s) {
+
+  char * p = s;
+  int l = strlen(p);
+
+  while(isspace(p[l-1]) && l) p[--l] = 0;
+  while(*p && isspace(*p) && l) ++p, --l;
+
+  return p;
+}
+
+static void
+append_to_names(const char* progname, const char* item) {
+
+  names_t* name = calloc(1, sizeof(names_t));
+  if (name == NULL) {
+    fprintf(stderr, "%s: memory allocation failure\n", progname);
+    exit(EXIT_FAILURE);
+  }
+  name->name = strdup(item);
+  name->next = names;
+  names = name;
+}
+
+static void
+read_from_file(const char* progname, const char *filename) {
+
+  FILE *in;
+  char line[512];
+
+  if (! filename || strcmp(filename, "-") == 0) {
+    clearerr(stdin);
+    in = stdin;
+  } else {
+    in = fopen(filename, "r");
+    if (! in) {
+      fprintf(stderr, "%s: fopen: %s\n", progname, strerror(errno));
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  while (fgets(line, sizeof(line), in)) {
+    char* name = trim(line);
+    append_to_names(progname, name);
+  }
+
+  if (ferror(in)) {
+    fprintf(stderr, "%s: ferror: %s\n", progname, strerror(errno));
+    exit(EXIT_FAILURE);
+  }
+
+  if (in != stdin) fclose(in);
+}
+
+/*
+ * If the file stream is associated with a regular file, lock the file
+ * in order coordinate writes to a common file from multiple mtr
+ * instances. This is useful if, for example, multiple mtr instances
+ * try to append results to a common file.
+ */
+
+static void
+lock(const char* progname, FILE *f) {
+    int fd;
+    struct stat buf;
+    static struct flock lock;
+
+    assert(f);
+
+    lock.l_type = F_WRLCK;
+    lock.l_start = 0;
+    lock.l_whence = SEEK_END;
+    lock.l_len = 0;
+    lock.l_pid = getpid();
+
+    fd = fileno(f);
+    if ((fstat(fd, &buf) == 0) && S_ISREG(buf.st_mode)) {
+      if (fcntl(fd, F_SETLKW, &lock) == -1) {
+          fprintf(stderr, "%s: fcntl: %s (ignored)\n",
+            progname, strerror(errno));
+      }
+    }
+}
+
+/*
+ * If the file stream is associated with a regular file, unlock the
+ * file (which presumably has previously been locked).
+ */
+
+static void
+unlock(const char* progname, FILE *f) {
+    int fd;
+    struct stat buf;
+    static struct flock lock;
+
+    assert(f);
+
+    lock.l_type = F_UNLCK;
+    lock.l_start = 0;
+    lock.l_whence = SEEK_END;
+    lock.l_len = 0;
+    lock.l_pid = getpid();
+
+    fd = fileno(f);
+    if ((fstat(fd, &buf) == 0) && S_ISREG(buf.st_mode)) {
+      if (fcntl(fd, F_SETLKW, &lock) == -1) {
+          fprintf(stderr, "%s: fcntl: %s (ignored)\n",
+            progname, strerror(errno));
+      }
+    }
+}
+
 
 void init_fld_options (void)
 {
@@ -120,13 +253,24 @@ void init_fld_options (void)
 }
 
 
-void parse_arg (int argc, char **argv) 
+void parse_arg (int argc, char **argv)
 {
   int opt;
   int i;
+  /* IMPORTANT: when adding or modifying an option:
+       1/ mind the order of options, there is some logic;
+       2/ update the getopt_long call below;
+       3/ update the man page (use the same order);
+       4/ update the help message showed when using --help.
+   */
   static struct option long_options[] = {
-    { "version", 0, 0, 'v' },
     { "help", 0, 0, 'h' },
+    { "version", 0, 0, 'v' },
+
+    { "inet", 0, 0, '4' },	/* IPv4 only */
+    { "inet6", 0, 0, '6' },	/* IPv6 only */
+
+    { "filename", 1, 0, 'F' },
 
     { "report", 0, 0, 'r' },
     { "report-wide", 0, 0, 'w' },
@@ -134,10 +278,17 @@ void parse_arg (int argc, char **argv)
     { "curses", 0, 0, 't' },
     { "gtk", 0, 0, 'g' },
     { "raw", 0, 0, 'l' },
+    { "csv", 0, 0, 'C' },
     { "split", 0, 0, 'p' },     /* BL */
     				/* maybe above should change to -d 'x' */
 
-    { "order", 1, 0, 'o' },	/* fileds to display & their order */
+    { "no-dns", 0, 0, 'n' },
+    { "show-ips", 0, 0, 'b' },
+    { "order", 1, 0, 'o' },	/* fields to display & their order */
+#ifdef IPINFO
+    { "ipinfo", 1, 0, 'y' },    /* IP info lookup */
+    { "aslookup", 0, 0, 'z' },  /* Do AS lookup (--ipinfo 0) */
+#endif
 
     { "interval", 1, 0, 'i' },
     { "report-cycles", 1, 0, 'c' },
@@ -146,23 +297,23 @@ void parse_arg (int argc, char **argv)
     { "bitpattern", 1, 0, 'B' },/* overload b>255, ->rand(0,255) */
     { "tos", 1, 0, 'Q' },	/* typeof service (0,255) */
     { "mpls", 0, 0, 'e' },
-    { "no-dns", 0, 0, 'n' },
-    { "show-ips", 0, 0, 'b' },
     { "address", 1, 0, 'a' },
     { "first-ttl", 1, 0, 'f' },	/* -f & -m are borrowed from traceroute */
     { "max-ttl", 1, 0, 'm' },
     { "udp", 0, 0, 'u' },	/* UDP (default is ICMP) */
-    { "inet", 0, 0, '4' },	/* IPv4 only */
-    { "inet6", 0, 0, '6' },	/* IPv6 only */
-    { "aslookup", 0, 0, 'z' },  /* Do AS lookup */
+    { "tcp", 0, 0, 'T' },	/* TCP (default is ICMP) */
+    { "port", 1, 0, 'P' },      /* target port number for TCP */
+    { "timeout", 1, 0, 'Z' },   /* timeout for TCP sockets */
+#ifdef SO_MARK
+    { "mark", 1, 0, 'M' },      /* use SO_MARK */
+#endif
     { 0, 0, 0, 0 }
   };
 
   opt = 0;
   while(1) {
-    /* added f:m:o: byMin */
     opt = getopt_long(argc, argv,
-		      "vhrwxtglpo:B:i:c:s:Q:ena:f:m:ubz46", long_options, NULL);
+		      "hv46F:rwxtglCpnbo:y:zi:c:s:B:Q:ea:f:m:uTP:Z:M:", long_options, NULL);
     if(opt == -1)
       break;
 
@@ -193,6 +344,9 @@ void parse_arg (int argc, char **argv)
     case 'l':
       DisplayMode = DisplayRaw;
       break;
+    case 'C':
+      DisplayMode = DisplayCSV;
+      break;
     case 'x':
       DisplayMode = DisplayXML;
       break;
@@ -233,6 +387,9 @@ void parse_arg (int argc, char **argv)
 	fstTTL = 1;
       }
       break;
+    case 'F':
+      read_from_file(argv[0], optarg);
+      break;
     case 'm':
       maxTTL = atoi (optarg);
       if (maxTTL > (MaxHost - 1)) {
@@ -273,11 +430,33 @@ void parse_arg (int argc, char **argv)
       }
       break;
     case 'u':
+      if (mtrtype != IPPROTO_ICMP) {
+        fprintf(stderr, "-u and -T are mutually exclusive.\n");
+        exit(EXIT_FAILURE);
+      }
       mtrtype = IPPROTO_UDP;
       break;
+    case 'T':
+      if (mtrtype != IPPROTO_ICMP) {
+        fprintf(stderr, "-u and -T are mutually exclusive.\n");
+        exit(EXIT_FAILURE);
+      }
+      mtrtype = IPPROTO_TCP;
+      break;
     case 'b':
       show_ips = 1;
       break;
+    case 'P':
+      remoteport = atoi(optarg);
+      if (remoteport > 65535 || remoteport < 1) {
+        fprintf(stderr, "Illegal port number.\n");
+        exit(EXIT_FAILURE);
+      }
+      break;
+    case 'Z':
+      timeout = atoi(optarg);
+      timeout *= 1000000;
+      break;
     case '4':
       af = AF_INET;
       break;
@@ -289,9 +468,34 @@ void parse_arg (int argc, char **argv)
       fprintf( stderr, "IPv6 not enabled.\n" );
       break;
 #endif
+#ifdef IPINFO
+    case 'y':
+      ipinfo_no = atoi (optarg);
+      if (ipinfo_no < 0)
+        ipinfo_no = 0;
+      break;
     case 'z':
-      PrintAS = 1;
+      ipinfo_no = 0;
+      break;
+#else
+    case 'y':
+    case 'z':
+      fprintf( stderr, "IPINFO not enabled.\n" );
+      break;
+#endif
+#ifdef SO_MARK
+    case 'M':
+      mark = atoi (optarg);
+      if (mark < 0) {
+        fprintf( stderr, "SO_MARK must be positive.\n" );
+        exit(EXIT_FAILURE);
+      }
+      break;
+#else
+    case 'M':
+      fprintf( stderr, "SO_MARK not enabled.\n" );
       break;
+#endif
     }
   }
 
@@ -305,11 +509,6 @@ void parse_arg (int argc, char **argv)
   if (optind > argc - 1)
     return;
 
-  Hostname = argv[optind++];
-
-  if (argc > optind) {
-    cpacketsize = atoi (argv[optind]);
-  }
 }
 
 
@@ -336,7 +535,7 @@ void parse_mtr_options (char *string)
 }
 
 
-int main(int argc, char **argv) 
+int main(int argc, char **argv)
 {
   struct hostent *  host                = NULL;
   int               net_preopen_result;
@@ -370,17 +569,22 @@ int main(int argc, char **argv)
 
   /* reset the random seed */
   srand (getpid());
-  
+
   display_detect(&argc, &argv);
 
-  /* The field options are now in a static array all together, 
-     but that requires a run-time initialization. -- REW */
+  /* The field options are now in a static array all together,
+     but that requires a run-time initialization. */
   init_fld_options ();
 
   parse_mtr_options (getenv ("MTR_OPTIONS"));
 
   parse_arg (argc, argv);
 
+  while (optind < argc) {
+    char* name = argv[optind++];
+    append_to_names(argv[0], name);
+  }
+
   /* Now that we know mtrtype we can select which socket to use */
   if (net_selectsocket() != 0) {
     fprintf( stderr, "mtr: Couldn't determine raw socket type.\n" );
@@ -393,93 +597,142 @@ int main(int argc, char **argv)
   }
 
   if (PrintHelp) {
-    printf("usage: %s [-hvrwctglspniu46] [--help] [--version] [--report]\n"
-	   "\t\t[--report-wide] [--report-cycles=COUNT] [--curses] [--gtk]\n"
-           "\t\t[--raw] [--split] [--mpls] [--no-dns] [--show-ips]\n"
-           "\t\t[--address interface]  [--aslookup]\n" /* BL */
-           "\t\t[--psize=bytes/-s bytes]\n"            /* ok */
-           "\t\t[--report-wide|-w] [-u]\n"            /* rew */
-	   "\t\t[--interval=SECONDS] HOSTNAME [PACKETSIZE]\n", argv[0]);
+       printf("usage: %s [--help] [--version] [-4|-6] [-F FILENAME]\n"
+              "\t\t[--report] [--report-wide]\n"
+              "\t\t[--xml] [--gtk] [--curses] [--raw] [--csv] [--split]\n"
+              "\t\t[--no-dns] [--show-ips] [-o FIELDS] [-y IPINFO] [--aslookup]\n"
+              "\t\t[-i INTERVAL] [-c COUNT] [-s PACKETSIZE] [-B BITPATTERN]\n"
+              "\t\t[-Q TOS] [--mpls]\n"
+              "\t\t[-a ADDRESS] [-f FIRST-TTL] [-m MAX-TTL]\n"
+              "\t\t[--udp] [--tcp] [-P PORT] [-Z TIMEOUT]\n"
+              "\t\t[-M MARK] HOSTNAME\n", argv[0]);
+       printf("See the man page for details.\n");
     exit(0);
   }
 
-  if (Hostname == NULL) Hostname = "localhost";
+  time_t now = time(NULL);
 
-  if (gethostname(LocalHostname, sizeof(LocalHostname))) {
-	strcpy(LocalHostname, "UNKNOWNHOST");
-  }
+  if (!names) append_to_names (argv[0], "localhost"); // default: localhost. 
 
-  if (net_preopen_result != 0) {
-    fprintf(stderr, "mtr: Unable to get raw socket.  (Executable not suid?)\n");
-    exit(1);
-  }
+  names_t* head = names;
+  while (names != NULL) {
+
+    Hostname = names->name;
+    //  if (Hostname == NULL) Hostname = "localhost"; // no longer necessary.
+    if (gethostname(LocalHostname, sizeof(LocalHostname))) {
+      strcpy(LocalHostname, "UNKNOWNHOST");
+    }
+
+    if (net_preopen_result != 0) {
+      fprintf(stderr, "mtr: Unable to get raw socket.  (Executable not suid?)\n");
+      if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
+      else {
+        names = names->next;
+        continue;
+      }
+    }
 
 #ifdef ENABLE_IPV6
-  /* 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, NULL, &hints, &res );
-  if ( error ) {
-    if (error == EAI_SYSTEM)
-       perror ("Failed to resolve host");
-    else
-       fprintf (stderr, "Failed to resolve host: %s\n", gai_strerror(error));
-    exit( EXIT_FAILURE );
-  }
-  /* 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;
+    /* 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, NULL, &hints, &res );
+    if ( error ) {
+      if (error == EAI_SYSTEM)
+         perror ("Failed to resolve host");
+      else
+         fprintf (stderr, "Failed to resolve host: %s\n", gai_strerror(error));
+
+      if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
+      else {
+        names = names->next;
+        continue;
+      }
+    }
+    /* 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" );
+      if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
+      else {
+        names = names->next;
+        continue;
+      }
+    }
+    alptr[1] = NULL;
 #else
-    host = gethostbyname(Hostname);
-  if (host == NULL) {
-    herror("mtr gethostbyname");
-    exit(1);
-  }
-  af = host->h_addrtype;
+      host = gethostbyname(Hostname);
+    if (host == NULL) {
+      herror("mtr gethostbyname");
+      if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
+      else {
+        names = names->next;
+        continue;
+      }
+    }
+    af = host->h_addrtype;
 #endif
 
-  if (net_open(host) != 0) {
-	fprintf(stderr, "mtr: Unable to start net module.\n");
-        exit(1);
+    if (net_open(host) != 0) {
+      fprintf(stderr, "mtr: Unable to start net module.\n");
+      if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
+      else {
+        names = names->next;
+        continue;
       }
+    }
 
-  if (net_set_interfaceaddress (InterfaceAddress) != 0) {
-    fprintf( stderr, "mtr: Couldn't set interface address.\n" ); 
-    exit( EXIT_FAILURE ); 
-  }
+    if (net_set_interfaceaddress (InterfaceAddress) != 0) {
+      fprintf( stderr, "mtr: Couldn't set interface address.\n" );
+      if ( DisplayMode != DisplayCSV ) exit(EXIT_FAILURE);
+      else {
+        names = names->next;
+        continue;
+      }
+    }
+
+    lock(argv[0], stdout);
+      display_open();
+      dns_open();
+
+      display_mode = 0;
+      display_loop();
 
-  display_open();
-  dns_open();
+      net_end_transit();
+      display_close(now);
+    unlock(argv[0], stdout);
 
-  display_mode = 0;
-  display_loop();
+    if ( DisplayMode != DisplayCSV ) break;
+    else names = names->next;
+
+  }
 
-  net_end_transit();
-  display_close();
   net_close();
 
+  while (head != NULL) {
+    names_t* item = head;
+    free(item->name); item->name = NULL;
+    head = head->next;
+    free(item); item = NULL;
+  }
+  head=NULL;
+
   return 0;
 }
-
-
diff --git a/mtr.h b/mtr.h
index ec76190..047d31d 100644
--- a/mtr.h
+++ b/mtr.h
@@ -72,3 +72,6 @@ extern int use_dns;
 #ifndef HAVE_SOCKLEN_T
 typedef int socklen_t; 
 #endif
+
+char *
+trim(char * s);
diff --git a/net.c b/net.c
index 431ad1e..d43054b 100644
--- a/net.c
+++ b/net.c
@@ -14,12 +14,9 @@
     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>
+#include "config.h"
 
 #if defined(HAVE_SYS_XTI_H)
 #include <sys/xti.h>
@@ -28,6 +25,8 @@
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
 #include <netinet/in.h>
 #include <memory.h>
 #include <unistd.h>
@@ -64,6 +63,13 @@ struct UDPHeader {
   uint16 checksum;
 };
 
+/* Structure of an TCP header, as far as we need it.  */
+struct TCPHeader {
+  uint16 srcport;
+  uint16 dstport;
+  uint32 seq;
+};
+
 /* Structure of an IPv4 UDP pseudoheader.  */
 struct UDPv4PHeader {
   uint32 saddr;
@@ -132,12 +138,13 @@ struct sequence {
   int transit;
   int saved_seq;
   struct timeval time;
+  int socket;
 };
 
 
 /* Configuration parameter: How many queries to unknown hosts do we
    send? (This limits the amount of traffic generated if a host is not
-   reachable) -- REW */
+   reachable) */
 #define MAX_UNKNOWN_HOSTS 5
 
 
@@ -180,7 +187,7 @@ 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 */
+/* XXX How do I code this to be IPV6 compatible??? */
 #ifdef ENABLE_IPV6
 char localaddr[INET6_ADDRSTRLEN];
 #else
@@ -201,6 +208,11 @@ 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 */
 extern int mtrtype;		/* type of query packet used */
+extern int remoteport;          /* target port for TCP tracing */
+extern int timeout;             /* timeout for TCP connections */
+#ifdef SO_MARK
+extern int mark;		/* SO_MARK to set for ping packet*/
+#endif
 
 /* return the number of microseconds to wait before sending the next
    ping */
@@ -257,15 +269,8 @@ int udp_checksum(void *pheader, void *udata, int psize, int dsize)
 }
 
 
-int new_sequence(int index) 
+void save_sequence(int index, int seq)
 {
-  static int next_sequence = MinSequence;
-  int seq;
-
-  seq = next_sequence++;
-  if (next_sequence >= MaxSequence)
-    next_sequence = MinSequence;
-
   sequence[seq].index = index;
   sequence[seq].transit = 1;
   sequence[seq].saved_seq = ++host[index].xmit;
@@ -276,14 +281,147 @@ int new_sequence(int index)
     host[index].up = 0;
   host[index].sent = 1;
   net_save_xmit(index);
-  
+}
+
+int new_sequence(int index)
+{
+  static int next_sequence = MinSequence;
+  int seq;
+
+  seq = next_sequence++;
+  if (next_sequence >= MaxSequence)
+    next_sequence = MinSequence;
+
+  save_sequence(index, seq);
+
   return seq;
 }
 
+/*  Attempt to connect to a TCP port with a TTL */
+void net_send_tcp(int index)
+{
+  int ttl, s;
+  int opt = 1;
+  int port;
+  struct sockaddr_storage local;
+  struct sockaddr_storage remote;
+  struct sockaddr_in *local4 = (struct sockaddr_in *) &local;
+  struct sockaddr_in6 *local6 = (struct sockaddr_in6 *) &local;
+  struct sockaddr_in *remote4 = (struct sockaddr_in *) &remote;
+  struct sockaddr_in6 *remote6 = (struct sockaddr_in6 *) &remote;
+  socklen_t len;
+
+  ttl = index + 1;
+
+  s = socket(af, SOCK_STREAM, 0);
+  if (s < 0) {
+    display_clear();
+    perror("socket()");
+    exit(EXIT_FAILURE);
+  }
+
+  memset(&local, 0, sizeof (local));
+  memset(&remote, 0, sizeof (remote));
+  local.ss_family = af;
+  remote.ss_family = af;
+
+  switch (af) {
+  case AF_INET:
+    addrcpy((void *) &local4->sin_addr, (void *) &ssa4->sin_addr, af);
+    addrcpy((void *) &remote4->sin_addr, (void *) remoteaddress, af);
+    remote4->sin_port = htons(remoteport);
+    len = sizeof (struct sockaddr_in);
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    addrcpy((void *) &local6->sin6_addr, (void *) &ssa6->sin6_addr, af);
+    addrcpy((void *) &remote6->sin6_addr, (void *) remoteaddress, af);
+    remote6->sin6_port = htons(remoteport);
+    len = sizeof (struct sockaddr_in6);
+    break;
+#endif
+  }
+
+  if (bind(s, (struct sockaddr *) &local, len)) {
+    display_clear();
+    perror("bind()");
+    exit(EXIT_FAILURE);
+  }
+
+  if (getsockname(s, (struct sockaddr *) &local, &len)) {
+    display_clear();
+    perror("getsockname()");
+    exit(EXIT_FAILURE);
+  }
+
+  opt = 1;
+  if (ioctl(s, FIONBIO, &opt)) {
+    display_clear();
+    perror("ioctl FIONBIO");
+    exit(EXIT_FAILURE);
+  }
+
+  switch (af) {
+  case AF_INET:
+    if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl))) {
+      display_clear();
+      perror("setsockopt IP_TTL");
+      exit(EXIT_FAILURE);
+    }
+    if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof (tos))) {
+      display_clear();
+      perror("setsockopt IP_TOS");
+      exit(EXIT_FAILURE);
+    }
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl))) {
+      display_clear();
+      perror("setsockopt IP_TTL");
+      exit(EXIT_FAILURE);
+    }
+    break;
+#endif
+  }
+
+#ifdef SO_MARK
+    if (mark >= 0 && setsockopt( s, SOL_SOCKET, SO_MARK, &mark, sizeof mark ) ) {
+      perror( "setsockopt SO_MARK" );
+      exit( EXIT_FAILURE );
+    }
+#endif
+
+  switch (local.ss_family) {
+  case AF_INET:
+    port = ntohs(local4->sin_port);
+    break;
+#ifdef ENABLE_IPV6
+  case AF_INET6:
+    port = ntohs(local6->sin6_port);
+    break;
+#endif
+  default:
+    display_clear();
+    perror("unknown AF?");
+    exit(EXIT_FAILURE);
+  }
+
+  save_sequence(index, port);
+  gettimeofday(&sequence[port].time, NULL);
+  sequence[port].socket = s;
+
+  connect(s, (struct sockaddr *) &remote, len);
+}
 
 /*  Attempt to find the host at a particular number of hops away  */
 void net_send_query(int index) 
 {
+  if (mtrtype == IPPROTO_TCP) {
+    net_send_tcp(index);
+    return;
+  }
+
   /*ok  char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader)];*/
   char packet[MAXPACKET];
   struct IPHeader *ip = (struct IPHeader *) packet;
@@ -354,6 +492,13 @@ void net_send_query(int index)
 #endif
   }
 
+#ifdef SO_MARK
+    if (mark >= 0 && setsockopt( sendsock, SOL_SOCKET, SO_MARK, &mark, sizeof mark ) ) {
+      perror( "setsockopt SO_MARK" );
+      exit( EXIT_FAILURE );
+    }
+#endif
+
   switch ( mtrtype ) {
   case IPPROTO_ICMP:
     icmp = (struct ICMPHeader *)(packet + iphsize);
@@ -458,6 +603,11 @@ void net_process_ping(int seq, struct mplslen mpls, void * addr, struct timeval
     return;
   sequence[seq].transit = 0;
 
+  if (sequence[seq].socket > 0) {
+    close(sequence[seq].socket);
+    sequence[seq].socket = 0;
+  }
+
   index = sequence[seq].index;
 
   totusec = (now.tv_sec  - sequence[seq].time.tv_sec ) * 1000000 +
@@ -471,7 +621,7 @@ void net_process_ping(int seq, struct mplslen mpls, void * addr, struct timeval
     host[index].mpls = mpls;
     display_rawhost(index, (void *) &(host[index].addr));
 
-  /* multi paths by Min */
+  /* multi paths */
     addrcpy( (void *) &(host[index].addrs[0]), addrcopy, af );
     host[index].mplss[0] = mpls;
   } else {
@@ -486,11 +636,8 @@ void net_process_ping(int seq, struct mplslen mpls, void * addr, struct timeval
         i<MAXPATH ) {
       addrcpy( (void *) &(host[index].addrs[i]), addrcopy, af );
       host[index].mplss[i] = mpls;
-      
-      /* rafaelmartins: multi path support to '--raw' */
       display_rawhost(index, (void *) &(host[index].addrs[i]));
     }
-  /* end multi paths */
   }
 
   host[index].jitter = totusec - host[index].last;
@@ -508,7 +655,6 @@ void net_process_ping(int seq, struct mplslen mpls, void * addr, struct timeval
    * at least in linux 2.4.x.
    *  safe guard 1) best[index]>=best[index-1] if index>0
    *             2) best >= average-20,000 usec (good number?)
-   *  Min
   if (index > 0) {
     if (totusec < host[index].best &&
        totusec>= host[index-1].best) host[index].best  = totusec;
@@ -523,7 +669,6 @@ void net_process_ping(int seq, struct mplslen mpls, void * addr, struct timeval
 	host[index].jworst = host[index].jitter;
 
   host[index].returned++;
-  /* begin addByMin do more stats */
   oldavg = host[index].avg;
   host[index].avg += (totusec - oldavg +.0) / host[index].returned;
   host[index].var += (totusec - oldavg +.0) * (totusec - host[index].avg) / 1000000;
@@ -536,7 +681,6 @@ void net_process_ping(int seq, struct mplslen mpls, void * addr, struct timeval
   if ( host[index].returned > 1 )
   host[index].gmean = pow( (double) host[index].gmean, (host[index].returned-1.0)/host[index].returned )
 			* pow( (double) totusec, 1.0/host[index].returned );
-  /* end addByMin*/
   host[index].sent = 0;
   host[index].up = 1;
   host[index].transit = 0;
@@ -564,6 +708,7 @@ void net_process_return(void)
   int num;
   struct ICMPHeader *header = NULL;
   struct UDPHeader *udpheader = NULL;
+  struct TCPHeader *tcpheader = NULL;
   struct timeval now;
   ip_t * fromaddress = NULL;
   int echoreplytype = 0, timeexceededtype = 0, unreachabletype = 0;
@@ -695,6 +840,43 @@ void net_process_return(void)
       sequence = ntohs(udpheader->dstport);
     }
     break;
+
+  case IPPROTO_TCP:
+    if (header->type == timeexceededtype || header->type == unreachabletype) {
+      switch ( af ) {
+      case AF_INET:
+
+        if ((size_t) num < sizeof(struct IPHeader) +
+                           sizeof(struct ICMPHeader) +
+                           sizeof (struct IPHeader) +
+                           sizeof (struct TCPHeader))
+          return;
+        tcpheader = (struct TCPHeader *)(packet + sizeof (struct IPHeader) +
+                                                  sizeof (struct ICMPHeader) +
+                                                  sizeof (struct IPHeader));
+
+        if(num > 160)
+          decodempls(num, packet, &mpls, 156);
+
+      break;
+#ifdef ENABLE_IPV6
+      case AF_INET6:
+        if ( num < sizeof (struct ICMPHeader) +
+                   sizeof (struct ip6_hdr) + sizeof (struct TCPHeader) )
+          return;
+        tcpheader = (struct TCPHeader *) ( packet +
+                                           sizeof (struct ICMPHeader) +
+                                           sizeof (struct ip6_hdr) );
+
+        if(num > 140)
+          decodempls(num, packet, &mpls, 136);
+
+        break;
+#endif
+      }
+      sequence = ntohs(tcpheader->srcport);
+    }
+    break;
   }
 
   if (sequence)
@@ -778,7 +960,6 @@ int net_stdev(int at)
 }
 
 
-/* jitter stuff */
 int net_jitter(int at) 
 { 
   return (host[at].jitter); 
@@ -801,7 +982,6 @@ int net_jinta(int at)
 { 
   return (host[at].jinta); 
 }
-/* end jitter */
 
 
 int net_max(void) 
@@ -810,8 +990,7 @@ int net_max(void)
   int max;
 
   max = 0;
-  /* replacedByMin
-     for(at = 0; at < MaxHost-2; at++) { */
+  /* for(at = 0; at < MaxHost-2; at++) { */
   for(at = 0; at < maxTTL-1; at++) {
     if ( addrcmp( (void *) &(host[at].addr),
                   (void *) remoteaddress, af ) == 0 ) {
@@ -826,14 +1005,12 @@ int net_max(void)
 }
 
 
-/* add by Min (wonder its named net_min;-)) because of ttl stuff */
 int net_min (void) 
 {
   return ( fstTTL - 1 );
 }
 
 
-/* Added by Brian Casey December 1997 bcasey@imagiware.com*/
 int net_returned(int at) 
 { 
   return host[at].returned;
@@ -890,7 +1067,7 @@ int net_send_batch(void)
            As our detination range (in the example 10000) is much 
            smaller (reasonable packet sizes), and our rand() range much 
            larger, this effect is insignificant. Oh! That other formula
-           didn't work. -- REW */
+           didn't work. */
       packetsize = MINPACKET + rand () % (-cpacketsize - MINPACKET);
     } else {
       packetsize = cpacketsize;
@@ -912,7 +1089,7 @@ int net_send_batch(void)
 	but I don't remember why. It makes mtr stop skipping sections of unknown
 	hosts. Removed in 0.65. 
 	If the line proves neccesary, it should at least NOT trigger that line 
-	when host[i].addr == 0 -- REW */
+	when host[i].addr == 0 */
     if ( ( addrcmp( (void *) &(host[i].addr),
                     (void *) remoteaddress, af ) == 0 )
 	/* || (host[i].addr == host[batch_at].addr)  */)
@@ -1137,6 +1314,10 @@ void net_reset(void)
   
   for (at = 0; at < MaxSequence; at++) {
     sequence[at].transit = 0;
+    if (sequence[at].socket > 0) {
+      close(sequence[at].socket);
+      sequence[at].socket = 0;
+    }
   }
 
   gettimeofday(&reset, NULL);
@@ -1230,7 +1411,7 @@ void net_save_return(int at, int seq, int ms)
 {
   int idx;
   idx = seq - host[at].saved_seq_offset;
-  if (idx < 0 || idx > SAVED_PINGS) {
+  if (idx < 0 || idx >= SAVED_PINGS) {
     return;
   }
   host[at].saved[idx] = ms;
@@ -1333,3 +1514,70 @@ void decodempls(int num, char *packet, struct mplslen *mpls, int offset) {
     }
   }
 }
+
+/* Add open sockets to select() */
+void net_add_fds(fd_set *writefd, int *maxfd)
+{
+  int at, fd;
+  for (at = 0; at < MaxSequence; at++) {
+    fd = sequence[at].socket;
+    if (fd > 0) {
+      FD_SET(fd, writefd);
+      if (fd >= *maxfd)
+        *maxfd = fd + 1;
+    }
+  }
+}
+
+/* check if we got connection or error on any fds */
+void net_process_fds(fd_set *writefd)
+{
+  int at, fd, r;
+  struct timeval now;
+  uint64_t unow, utime;
+
+  /* Can't do MPLS decoding */
+  struct mplslen mpls;
+  mpls.labels = 0;
+
+  gettimeofday(&now, NULL);
+  unow = now.tv_sec * 1000000L + now.tv_usec;
+
+  for (at = 0; at < MaxSequence; at++) {
+    fd = sequence[at].socket;
+    if (fd > 0 && FD_ISSET(fd, writefd)) {
+      r = write(fd, "G", 1);
+      /* if write was successful, or connection refused we have
+       * (probably) reached the remote address. Anything else happens to the
+       * connection, we write it off to avoid leaking sockets */
+      if (r == 1 || errno == ECONNREFUSED)
+        net_process_ping(at, mpls, remoteaddress, now);
+      else if (errno != EAGAIN) {
+        close(fd);
+        sequence[at].socket = 0;
+      }
+    }
+    if (fd > 0) {
+      utime = sequence[at].time.tv_sec * 1000000L + sequence[at].time.tv_usec;
+      if (unow - utime > timeout) {
+        close(fd);
+        sequence[at].socket = 0;
+      }
+    }
+  }
+}
+
+/* for GTK frontend */
+void net_harvest_fds(void)
+{
+  fd_set writefd;
+  int maxfd = 0;
+  struct timeval tv;
+
+  FD_ZERO(&writefd);
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+  net_add_fds(&writefd, &maxfd);
+  select(maxfd, NULL, &writefd, NULL, &tv);
+  net_process_fds(&writefd);
+}
diff --git a/net.h b/net.h
index 6e2c172..de3555c 100644
--- a/net.h
+++ b/net.h
@@ -35,6 +35,7 @@ void net_reset(void);
 void net_close(void);
 int net_waitfd(void);
 void net_process_return(void);
+void net_harvest_fds(void);
 
 int net_max(void);
 int net_min(void);
@@ -62,8 +63,6 @@ void net_end_transit(void);
 
 int calc_deltatime (float WaitTime);
 
-
-/* Added by Brian Casey, December 1997 bcasey@imagiware.com*/
 int net_returned(int at);
 int net_xmit(int at);
 int net_transit(int at);
@@ -80,6 +79,9 @@ 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 );
 
+void net_add_fds(fd_set *writefd, int *maxfd);
+void net_process_fds(fd_set *writefd);
+
 #define MAXPATH 8
 #define MaxHost 256
 #define MinSequence 33000
@@ -90,7 +92,7 @@ void addrcpy( char * a, char * b, int af );
 #define MINPACKET 28		/* 20 bytes IP header and 8 bytes ICMP or UDP */
 #define MAXLABELS 8 		/* http://kb.juniper.net/KB2190 (+ 3 just in case) */
 
-/* stuff used by display such as report, curses... --Min */
+/* stuff used by display such as report, curses... */
 #define MAXFLD 20		/* max stats fields to display */
 
 #if defined (__STDC__) && __STDC__
@@ -101,7 +103,7 @@ void addrcpy( char * a, char * b, int af );
 
 
 /* XXX This doesn't really belong in this header file, but as the
-   right c-files include it, it will have to do for now. -- REW */
+   right c-files include it, it will have to do for now. */
 
 /* dynamic field drawing */
 struct fields {
diff --git a/raw.c b/raw.c
index 8b0df47..0e1f4f4 100644
--- a/raw.c
+++ b/raw.c
@@ -18,7 +18,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <config.h>
+#include "config.h"
+
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -27,7 +28,6 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-
 #include "mtr.h"
 #include "raw.h"
 #include "net.h"
diff --git a/report.c b/report.c
index 6a8baec..39b2fb2 100644
--- a/report.c
+++ b/report.c
@@ -16,7 +16,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <config.h>
+#include "config.h"
+
 #include <sys/types.h>
 #include <stdio.h>
 #include <netdb.h>
@@ -27,9 +28,11 @@
 #include <time.h>
 
 #include "mtr.h"
+#include "version.h"
 #include "report.h"
 #include "net.h"
 #include "dns.h"
+#include "asn.h"
 
 #define MAXLOADBAL 5
 
@@ -73,9 +76,17 @@ static size_t snprint_addr(char *dst, size_t dst_len, ip_t *addr)
 }
 
 
+#ifdef IPINFO
+void print_mpls(struct mplslen *mpls) {
+  int k;
+  for (k=0; k < mpls->labels; k++)
+    printf("       [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]);
+}
+#endif
+
 void report_close(void) 
 {
-  int i, j, k, at, max, z, w;
+  int i, j, at, max, z, w;
   struct mplslen *mpls, *mplss;
   ip_t *addr;
   ip_t *addr2 = NULL;  
@@ -100,7 +111,21 @@ void report_close(void)
     }
   }
   
+#ifdef IPINFO
+  int len_tmp = len_hosts;
+  if (ipinfo_no >= 0) {
+    ipinfo_no %= iiwidth_len;
+    if (reportwide) {
+      len_hosts++;    // space
+      len_tmp   += get_iiwidth();
+      if (!ipinfo_no)
+        len_tmp += 2; // align header: AS
+    }
+  }
+  snprintf( fmt, sizeof(fmt), "HOST: %%-%ds", len_tmp);
+#else
   snprintf( fmt, sizeof(fmt), "HOST: %%-%ds", len_hosts);
+#endif
   snprintf(buf, sizeof(buf), fmt, LocalHostname);
   len = reportwide ? strlen(buf) : len_hosts;
   for( i=0; i<MAXFLD; i++ ) {
@@ -120,8 +145,17 @@ void report_close(void)
     mpls = net_mpls(at);
     snprint_addr(name, sizeof(name), addr);
 
+#ifdef IPINFO
+    if (is_printii()) {
+      snprintf(fmt, sizeof(fmt), " %%2d. %%s%%-%ds", len_hosts);
+      snprintf(buf, sizeof(buf), fmt, at+1, fmt_ipinfo(addr), name);
+    } else {
+#endif
     snprintf( fmt, sizeof(fmt), " %%2d.|-- %%-%ds", len_hosts);
     snprintf(buf, sizeof(buf), fmt, at+1, name);
+#ifdef IPINFO
+    }
+#endif
     len = reportwide ? strlen(buf) : len_hosts;  
     for( i=0; i<MAXFLD; i++ ) {
       j = fld_index[fld_active [i]];
@@ -139,10 +173,8 @@ void report_close(void)
     }
     printf("%s\n",buf);
 
-    /* Thales (thales@paponline.net) -- 
-     * This feature show 'loadbalances' on routes 
-     */
-    
+    /* This feature shows 'loadbalances' on routes */
+
     /* z is starting at 1 because addrs[0] is the same that addr */
     for (z = 1; z < MAXPATH ; z++) {
       addr2 = net_addrs(at, z);
@@ -151,7 +183,7 @@ void report_close(void)
       if ((addrcmp ((void *) &unspec_addr, (void *) addr2, af)) == 0)
         break;
       for (w = 0; w < z; w++)
-        /* Thales -- Ok... checking if there are ips repeated on same hop */
+        /* Ok... checking if there are ips repeated on same hop */
         if ((addrcmp ((void *) addr2, (void *) net_addrs (at,w), af)) == 0) {
            found = 1;
            break;
@@ -159,6 +191,17 @@ void report_close(void)
 
       if (!found) {
   
+#ifdef IPINFO
+        if (is_printii()) {
+          if (mpls->labels && z == 1 && enablempls)
+            print_mpls(mpls);
+          snprint_addr(name, sizeof(name), addr2);
+          printf("     %s%s\n", fmt_ipinfo(addr2), name);
+          if (enablempls)
+            print_mpls(mplss);
+        } else {
+#else
+        int k;
         if (mpls->labels && z == 1 && enablempls) {
           for (k=0; k < mpls->labels; k++) {
             printf("    |  |+-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]);
@@ -176,15 +219,30 @@ void report_close(void)
             printf("    |   +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]);
           }
         }
+#endif
+#ifdef IPINFO
+        }
+#endif
       }
     }
 
     /* No multipath */
+#ifdef IPINFO
+    if (is_printii()) {
+      if (mpls->labels && z == 1 && enablempls)
+        print_mpls(mpls);
+    } else {
+#else
     if(mpls->labels && z == 1 && enablempls) {
+      int k;
       for (k=0; k < mpls->labels; k++) {
         printf("    |   +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]);
       }
     }
+#endif
+#ifdef IPINFO
+    }
+#endif
   }
 }
 
@@ -263,37 +321,16 @@ void csv_open(void)
 {
 }
 
-
-void csv_close(void)
+void csv_close(time_t now)
 {
   int i, j, at, max;
   ip_t *addr;
   char name[81];
 
-  /* Caption */
-  printf("<SRC=%s DST=%s", LocalHostname, Hostname);
-  printf(" TOS=0x%X", tos);
-  if(cpacketsize >= 0) {
-    printf(" PSIZE=%d", cpacketsize);
-  } else {
-    printf(" PSIZE=rand(%d-%d)",MINPACKET, -cpacketsize);
-  }
-  if( bitpattern>=0 ) {
-    printf(" BITPATTERN=0x%02X", (unsigned char)(bitpattern));
-  } else {
-    printf(" BITPATTERN=rand(0x00-FF)");
-  }
-  printf(" TESTS=%d>\n", MaxPing);
-
-  /* Header */
-  printf("HUPCOUNT, HOST");
   for( i=0; i<MAXFLD; i++ ) {
       j = fld_index[fld_active[i]];
       if (j < 0) continue; 
-
-      printf( ", %s", data_fields[j].title );
   }
-  printf("\n");
 
   max = net_max();
   at  = net_min();
@@ -301,7 +338,18 @@ void csv_close(void)
     addr = net_addr(at);
     snprint_addr(name, sizeof(name), addr);
 
-    printf("%d, %s", at+1, name);
+    int last = net_last(at);
+#ifdef IPINFO
+    if(!ipinfo_no) {
+      char* fmtinfo = fmt_ipinfo(addr);
+      if (fmtinfo != NULL) fmtinfo = trim(fmtinfo);
+      printf("MTR.%s;%lld;%s;%s;%d;%s;%s;%d", MTR_VERSION, (long long)now, "OK", Hostname,
+             at+1, name, fmtinfo, last);
+    } else
+#endif
+      printf("MTR.%s;%lld;%s;%s;%d;%s;%d", MTR_VERSION, (long long)now, "OK", Hostname,
+             at+1, name, last);
+
     for( i=0; i<MAXFLD; i++ ) {
       j = fld_index[fld_active[j]];
       if (j < 0) continue; 
diff --git a/report.h b/report.h
index 755c596..81c2d81 100644
--- a/report.h
+++ b/report.h
@@ -25,4 +25,4 @@ void txt_close(void);
 void xml_open(void);
 void xml_close(void);
 void csv_open(void);
-void csv_close(void);
+void csv_close(time_t now);
diff --git a/select.c b/select.c
index 4134080..62478f4 100644
--- a/select.c
+++ b/select.c
@@ -16,7 +16,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <config.h>
+#include "config.h"
+
 #include <sys/types.h>
 #include <sys/time.h>
 #include <stdlib.h>
@@ -29,22 +30,27 @@
 #include <errno.h>
 
 #include "mtr.h"
-#include "display.h"
 #include "dns.h"
 #include "net.h"
+#include "asn.h"
+#include "display.h"
 
 extern int Interactive;
 extern int MaxPing;
 extern int ForceMaxPing;
 extern float WaitTime;
 double dnsinterval;
+extern int mtrtype;
 
 static struct timeval intervaltime;
 int display_offset = 0;
 
 
+#define GRACETIME (5 * 1000*1000)
+
 void select_loop(void) {
   fd_set readfd;
+  fd_set writefd;
   int anyset = 0;
   int maxfd = 0;
   int dnsfd, netfd;
@@ -54,8 +60,12 @@ void select_loop(void) {
   int NumPing = 0;
   int paused = 0;
   struct timeval lasttime, thistime, selecttime;
+  struct timeval startgrace;
   int dt;
   int rv; 
+  int graceperiod = 0;
+
+  memset(&startgrace, 0, sizeof(startgrace));
 
   gettimeofday(&lasttime, NULL);
 
@@ -65,6 +75,7 @@ void select_loop(void) {
     intervaltime.tv_usec = dt % 1000000;
 
     FD_ZERO(&readfd);
+    FD_ZERO(&writefd);
 
     maxfd = 0;
 
@@ -76,8 +87,12 @@ void select_loop(void) {
 #ifdef ENABLE_IPV6
     if (dns) {
       dnsfd6 = dns_waitfd6();
-      FD_SET(dnsfd6, &readfd);
-      if(dnsfd6 >= maxfd) maxfd = dnsfd6 + 1;
+      if (dnsfd6 >= 0) {
+        FD_SET(dnsfd6, &readfd);
+        if(dnsfd6 >= maxfd) maxfd = dnsfd6 + 1;
+      } else {
+        dnsfd6 = 0;
+      }
     } else
       dnsfd6 = 0;
 #endif
@@ -92,12 +107,20 @@ void select_loop(void) {
     FD_SET(netfd, &readfd);
     if(netfd >= maxfd) maxfd = netfd + 1;
 
+    if (mtrtype == IPPROTO_TCP)
+      net_add_fds(&writefd, &maxfd);
+
     do {
       if(anyset || paused) {
+	/* Set timeout to 0.1s.
+	 * While this is almost instantaneous for human operators,
+	 * it's slow enough for computers to go do something else;
+	 * this prevents mtr from hogging 100% CPU time on one core.
+	 */
 	selecttime.tv_sec = 0;
-	selecttime.tv_usec = 0;
+	selecttime.tv_usec = paused?100000:0; 
       
-	rv = select(maxfd, (void *)&readfd, NULL, NULL, &selecttime);
+	rv = select(maxfd, (void *)&readfd, &writefd, NULL, &selecttime);
 
       } else {
 	if(Interactive) display_redraw();
@@ -108,10 +131,24 @@ void select_loop(void) {
 	   (thistime.tv_sec == lasttime.tv_sec + intervaltime.tv_sec &&
 	    thistime.tv_usec >= lasttime.tv_usec + intervaltime.tv_usec)) {
 	  lasttime = thistime;
-	  if(NumPing >= MaxPing && (!Interactive || ForceMaxPing))
+
+	  if (!graceperiod) {
+	    if (NumPing >= MaxPing && (!Interactive || ForceMaxPing)) {
+	      graceperiod = 1;
+	      startgrace = thistime;
+	    }
+
+	    /* do not send out batch when we've already initiated grace period */
+	    if (!graceperiod && net_send_batch())
+	      NumPing++;
+	  }
+	}
+
+	if (graceperiod) {
+	  dt = (thistime.tv_usec - startgrace.tv_usec) +
+		    1000000 * (thistime.tv_sec - startgrace.tv_sec);
+	  if (dt > GRACETIME)
 	    return;
-	  if (net_send_batch())
-	    NumPing++;
 	}
 
 	selecttime.tv_usec = (thistime.tv_usec - lasttime.tv_usec);
@@ -160,12 +197,12 @@ void select_loop(void) {
 
     /*  Have we finished a nameservice lookup?  */
 #ifdef ENABLE_IPV6
-    if(dns && FD_ISSET(dnsfd6, &readfd)) {
+    if(dns && dnsfd6 && FD_ISSET(dnsfd6, &readfd)) {
       dns_ack6();
       anyset = 1;
     }
 #endif
-    if(dns && FD_ISSET(dnsfd, &readfd)) {
+    if(dns && dnsfd && FD_ISSET(dnsfd, &readfd)) {
       dns_ack();
       anyset = 1;
     }
@@ -201,6 +238,19 @@ void select_loop(void) {
 	  display_clear();
 	}
 	break;
+#ifdef IPINFO
+      case ActionII:
+	if (ipinfo_no >= 0) {
+	  ipinfo_no++;
+          if (ipinfo_no > ipinfo_max)
+            ipinfo_no = 0;
+	}
+	break;
+      case ActionAS:
+	if (ipinfo_no >= 0)
+          ipinfo_no = ipinfo_no?0:ipinfo_max;
+	break;
+#endif
 
       case ActionScrollDown:
         display_offset += 5;
@@ -214,6 +264,10 @@ void select_loop(void) {
       }
       anyset = 1;
     }
+
+    /* Check for activity on open sockets */
+    if (mtrtype == IPPROTO_TCP)
+      net_process_fds(&writefd);
   }
   return;
 }
diff --git a/split.c b/split.c
index 642353e..5ead235 100644
--- a/split.c
+++ b/split.c
@@ -20,7 +20,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <config.h>
+#include "config.h"
+
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
