diff --git a/.tarball-version b/.tarball-version
new file mode 100644
index 0000000..fc73074
--- /dev/null
+++ b/.tarball-version
@@ -0,0 +1 @@
+0.94
diff --git a/AUTHORS b/AUTHORS
index d4c2a1f..a2025ce 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,7 +7,7 @@
   Bug reports and feature requests should be sent as described in
   the README file.
 
-  Thanks to everyone who has provided feedback on mtr.  
+  Thanks to everyone who has provided feedback on mtr.
 
   Thanks especially to those of you who have sent code:
   (Reverse alphabetical order, and sometimes I just add people at
@@ -30,11 +30,11 @@
         Davin Milun
         Josh Martin <jmartin@columbiaservices.net>
         Alexander V. Lukyanov <lav@yars.free.net>
-        Charles Levert <charles@comm.polymtl.ca> 
+        Charles Levert <charles@comm.polymtl.ca>
         Bertrand Leconte <B.Leconte@mail.dotcom.fr>
         Anand Kumria
         Olav Kvittem <Olav.Kvittem@uninett.no>
-        Adam Kramer <l3zqc@qcunix1.acc.qc.edu> 
+        Adam Kramer <l3zqc@qcunix1.acc.qc.edu>
         Philip Kizer <pckizer@nostrum.com>
         Simon Kirby
         Sami Kerola <kerolasa@iki.fi>
@@ -49,7 +49,7 @@
         Travis Cross <tc@traviscross.com>
         Brian Casey <bcasey@imagiware.com>
         Andrew Brown <atatat@atatdot.net>
-        Bill Bogstad <bogstad@pobox.com> 
+        Bill Bogstad <bogstad@pobox.com>
         Marc Bejarano <marc.bejarano@openwave.com>
         Moritz Barsnick <barsnick@gmx.net>
         Thomas Klausner <wiz@NetBSD.org>
@@ -63,7 +63,7 @@
 
         and anyone who has slipped through the cracks of my mail file.
 
-Authors: If you want your Email mentioned here, send it to me. 
-         If you don't want your Email mentioned here, tell me.  
+Authors: If you want your Email mentioned here, send it to me.
+         If you don't want your Email mentioned here, tell me.
 
         -- REW
diff --git a/FORMATS b/FORMATS
index 3e64e17..cae643d 100644
--- a/FORMATS
+++ b/FORMATS
@@ -6,12 +6,12 @@ gui-library with a setuid program.
 
 The split format is:
 
-<pos> <host> <loss%> <rcvd pckts> <sent pckts> <best> <avg> <worst> 
+<pos> <host> <loss%> <rcvd pckts> <sent pckts> <best> <avg> <worst>
 
 
 The "raw" format is:
 
-hostline|xmitline|pingline|dnsline|timestampline
+hostline|xmitline|pingline|dnsline|timestampline|mplsline
 
 hostline:
 h <pos> <host IP>
@@ -22,12 +22,14 @@ x <pos> <seqnum>
 pingline:
 p <pos> <pingtime (ms)> <seqnum>
 
-dnsline: 
+dnsline:
 d <pos> <hostname>
 
 timestampline:
 t <pos> <pingtime> <timestamp>
 
+mplsline:
+m <pos> <label> <traffic_class> <bottom_stack> <ttl>
 
 Timestampline is not  yet implemented. Need to find out how to do
 ICMP timestamping first. :-)
@@ -35,7 +37,7 @@ ICMP timestamping first. :-)
 
 Someone suggested to put the following text here. As to context: Some
 people are wondering why mtr sometimes reports hosts beyond the
-destination host. 
+destination host.
 
 
 The FINAL host will occasionally be mentioned at position n, n+1, n+2
@@ -100,4 +102,3 @@ h 15 152.63.50.89
 h 16 152.179.99.218
 h 17 152.179.99.218
 h 18 152.179.99.218
-
diff --git a/Makefile.am b/Makefile.am
index 29435e1..3737a93 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -40,7 +40,7 @@ $(PATHFILES): Makefile
 dist_man_MANS = mtr.8 mtr-packet.8
 PATHFILES += man/mtr.8 man/mtr-packet.8
 
-install-exec-hook: 
+install-exec-hook:
 	`setcap cap_net_raw+ep $(DESTDIR)$(sbindir)/mtr-packet` \
 	|| chmod u+s $(DESTDIR)$(sbindir)/mtr-packet
 
@@ -55,6 +55,7 @@ mtr_SOURCES = ui/mtr.c ui/mtr.h \
               ui/select.c ui/select.h \
               ui/utils.c ui/utils.h \
               packet/cmdparse.c packet/cmdparse.h \
+              packet/sockaddr.c packet/sockaddr.h \
               ui/mtr-curses.h \
               img/mtr_icon.xpm \
               ui/mtr-gtk.h
@@ -84,9 +85,15 @@ if WITH_GTK
 mtr_SOURCES += ui/gtk.c
 endif
 
+if WITH_LIBASAN
+ASAN_CFLAGS = -fno-omit-frame-pointer
+ASAN_CFLAGS += -fsanitize=undefined
+ASAN_CFLAGS += -fsanitize=address
+endif
+
 mtr_INCLUDES = $(GLIB_CFLAGS) -I$(top_builddir) -I$(top_srcdir)
-mtr_CFLAGS = $(GTK_CFLAGS) $(NCURSES_CFLAGS)
-mtr_LDADD = $(GTK_LIBS) $(NCURSES_LIBS) $(RESOLV_LIBS)
+mtr_CFLAGS = $(GTK_CFLAGS) $(NCURSES_CFLAGS) $(ASAN_CFLAGS) $(JANSSON_CFLAGS)
+mtr_LDADD = $(GTK_LIBS) $(NCURSES_LIBS) $(RESOLV_LIBS) $(JANSSON_LIBS)
 
 
 mtr_packet_SOURCES = \
@@ -165,4 +172,3 @@ endif
 
 dist-hook:
 	$(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version
-
diff --git a/NEWS b/NEWS
index bb2bf87..3df0766 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,207 @@ The new release script will do a "git shortlog" to add
 the commit messages here. 
 
 #NEW_STUFF_HERE this is a tag my script looks for. 
+V0.94
+   Aaron Lipinski (37):
+         gtk_menu_append -> gtk_menu_shell_append
+         GTK_OBJECT -> G_OBJECT
+         gtk_button_new_from_stock -> gtk_button_new_with_label
+         gtk3
+         hbox/vbox -> gtk_box_new
+         gtk_menu_popup -> gtk_menu_popup_at_pointer
+         show resolved hostname in raw dnsline
+         rely on final return NULL
+         introduce libasan
+         avoid stack use after scope
+         move net_send_batch call to its caller
+         addr -> hostent for consistency
+         re-init source too
+         additional call from net_reopen
+         refactor - group local, remote inits
+         reset ctl address family at net_reopen
+         accept only value used in structure
+         accept only value used in structure
+         accept only value used in structure
+         tell dns process if we want 4 or 6
+         resolve ipv6 only if we have ipv6
+         remove wrapper only function
+         init structures correctly wired up
+         prepare host with h_addr_list
+         remove temporaries
+         extract convert_addrinfo_to_hostent function
+         move conversion call to caller
+         use addrinfo
+         remove conversion function
+         switch gui to addrinfo
+         export DEFAULT_AF
+         reset addr family before searching again
+         freeaddrinfo
+         export get_hostent_from_name
+         make Hostname as const
+         rename function
+         dont show json option if not available
+   
+   Alejandro Leal (2):
+         few updates to manual page and README.md
+         Updating some comments
+   
+   Chongyu Zhu (1):
+         probe: fix find_source_addr
+   
+   Egor Panov (1):
+         Updated Readme
+   
+   Konrad Bucheli (1):
+         fix segmentation fault if there is no IP address on an interface (fixes #320)
+   
+   Kulemin Alexander (1):
+         report: json: reworked with libjansson
+   
+   Mark Egan-Fuller (1):
+         Add display of destination.
+   
+   Markus Kötter (6):
+         simplification - remove sockaddrtop
+         simplification - remove addrcpy
+         simplification - remove rsa{4,6}
+         simplification - address addrcmp
+         simplification - improve readability
+         ip6 udp - fix probes with local or remote port
+   
+   R.E. Wolff (14):
+         fix warning on recent compilers.
+         Merge branch 'master' of github.com:traviscross/mtr
+         net find local address fix by meingtsla
+         proposed patch for bsd compile error
+         fix closing brace
+         Added include errno --obouizi
+         Merge branch 'master' of github.com:traviscross/mtr
+         More compilation warning fixes from obouizi
+         Added extra help text to configure --yvs
+         Changed MAXPATH to MAX_PATH for AIX compatibility. -- aixtools
+         The release script bumped the version number to 94
+         The release script bumped the version number to 94
+         Slight cleanup, but no fix for code that came up in a bugreport.
+         increased max length suggested by YVS2014
+   
+   Roger Wolff (28):
+         make the code for gtk2/3 a bit nicer.
+   
+   Rogier Wolff (5):
+         Merge branch 'gtk3_with_fallback' of https://github.com/krisl/mtr
+         Merge branch 'master' of github.com:traviscross/mtr
+         in hindsight my previous patch wasn't so nice. And nobody told me.
+         Code formatting for Zenithal pull
+         added clarification to readme suggested by Zenithal
+   
+   Sean Wei (1):
+         Fix parameter in ui/net.c
+   
+   Sergei Trofimovich (1):
+         ui/curses: always use "%s"-style format for printf()-style functions
+   
+   Siyuan Miao (1):
+         show mpls information in raw output
+   
+   Vincent Bernat (3):
+         ui: don't cast to void* when calling display_rawhost()
+         net: fix MPLS display for curses and report
+         report: fix display of MPLS labels when using --report
+   
+   Zenithal (1):
+         Add display of destination with resolved addr under curses mode
+   
+   a1346054 (5):
+         fix wrong bash completion flag
+         fix shellcheck warnings
+         unify codestyle
+         fix spelling
+         trim trailing whitespace
+   
+   atib (1):
+         Added code to print multiple addresses regitered on the same hop count
+   
+   atibdialpad (2):
+         Change TTL dynamically to adjust for path changes
+         TODO list changes
+   
+   gaamox@tutanota.com (1):
+         Report secondary servers when CSV + wide report is enabled
+   
+   meingtsla (2):
+         asn_{open,close}: Always initialize ipinfo hash table
+         Merge branch 'master' of https://github.com/traviscross/mtr into asn-open-always-hcreate
+   
+V0.94
+   Aaron Lipinski (10):
+         gtk_menu_append -> gtk_menu_shell_append
+         GTK_OBJECT -> G_OBJECT
+         gtk_button_new_from_stock -> gtk_button_new_with_label
+         gtk3
+         hbox/vbox -> gtk_box_new
+         gtk_menu_popup -> gtk_menu_popup_at_pointer
+         show resolved hostname in raw dnsline
+         rely on final return NULL
+         introduce libasan
+         avoid stack use after scope
+   
+   Alejandro Leal (2):
+         few updates to manual page and README.md
+         Updating some comments
+   
+   Chongyu Zhu (1):
+         probe: fix find_source_addr
+   
+   Konrad Bucheli (1):
+         fix segmentation fault if there is no IP address on an interface (fixes #320)
+   
+   Kulemin Alexander (1):
+         report: json: reworked with libjansson
+   
+   Mark Egan-Fuller (1):
+         Add display of destination.
+   
+   Markus Kötter (6):
+         simplification - remove sockaddrtop
+         simplification - remove addrcpy
+         simplification - remove rsa{4,6}
+         simplification - address addrcmp
+         simplification - improve readability
+         ip6 udp - fix probes with local or remote port
+   
+   R.E. Wolff (29):
+         fix warning on recent compilers.
+         Merge branch 'master' of github.com:traviscross/mtr
+         net find local address fix by meingtsla
+         proposed patch for bsd compile error
+         fix closing brace
+         Added include errno --obouizi
+         Merge branch 'master' of github.com:traviscross/mtr
+         More compilation warning fixes from obouizi
+         Added extra help text to configure --yvs
+         Changed MAXPATH to MAX_PATH for AIX compatibility. -- aixtools
+         make the code for gtk2/3 a bit nicer.
+         Merge branch 'gtk3_with_fallback' of https://github.com/krisl/mtr
+         Merge branch 'master' of github.com:traviscross/mtr
+         in hindsight my previous patch wasn't so nice. And nobody told me.
+   
+   Sean Wei (1):
+         Fix parameter in ui/net.c
+   
+   Siyuan Miao (1):
+         show mpls information in raw output
+   
+   atib (1):
+         Added code to print multiple addresses regitered on the same hop count
+   
+   atibdialpad (2):
+         Change TTL dynamically to adjust for path changes
+         TODO list changes
+   
+   meingtsla (2):
+         asn_{open,close}: Always initialize ipinfo hash table
+         Merge branch 'master' of https://github.com/traviscross/mtr into asn-open-always-hcreate
+   
 V0.93
     Adam (1):
           Update README
diff --git a/README.md b/README.md
index 77b6f79..9e4ebbb 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,10 @@ simple as:
 
 	./configure && make
 
+Please note that this refers to the tarballs from
+ https://www.bitwizard.nl/mtr/files/
+and not the tarballs that github can produce.
+
 (in the past, there was a Makefile in the distribution that did
 the `./configure` for you and then ran make again with the generated
 Makefile, but this has suffered some bitrot. It didn't work well
@@ -31,7 +35,7 @@ If you're building from the git repository, you'll need to run:
 
 	./bootstrap.sh && ./configure && make
 
-When it looks as if the compilation was succesful, you can
+When it looks as if the compilation was successful, you can
 test mtr with
 
 	sudo ./mtr <host>
@@ -71,10 +75,10 @@ BUILDING FOR WINDOWS
 
 Building for Windows requires Cygwin.  To obtain Cygwin, see
 https://cygwin.com/install.html.
-Next, re-run cygwin's `setup-x86.exe` (or `setup-x86_64.exe` if you're using 64bit cygwin) with the following arguments,  
+Next, re-run cygwin's `setup-x86.exe` (or `setup-x86_64.exe` if you're using 64bit cygwin) with the following arguments,
 which will install the packages required for building:
 
-        setup-x86.exe --package-manager --wait --packages automake,pkg-config,make,gcc-core,libncurses-devel
+        setup-x86.exe --package-manager --wait --packages automake,pkg-config,make,gcc-core,libncurses-devel,libjansson-devel
 
 Build as under Unix:
 
@@ -106,4 +110,3 @@ when the server was upgraded, the mailing list died.)
 
 
 REW
-
diff --git a/SECURITY b/SECURITY
index 82c697c..3dae7e5 100644
--- a/SECURITY
+++ b/SECURITY
@@ -35,7 +35,7 @@ minimal.
 3. Make mtr-packet a setuid-root binary.
 
 The mtr-packet binary can be made setuid-root, which is what "make install"
-does by default.
+does only if using setcap (above) fails.  Using setcap is tried first.
 
 When mtr-packet is installed as suid-root, some concern over security is
 justified.  mtr-packet does the following two things after it is launched:
diff --git a/TODO b/TODO
index 0673b24..95481c5 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
-
-Hi everyone, 
+Hi everyone,
 
 This is the "todo" file for mtr. I just realized that some people
 might think that this is all in MY queue to implement. That is not
@@ -16,13 +15,15 @@ implement something on this list. That way we get the design of
 these things the way I like them. This should result in a better
 maintainable mtr.
 
-Oh, Feel free to provide suggestions for this list. 
+Oh, Feel free to provide suggestions for this list.
 
 
 -- REW
 
 ----------------------------------------------------------------------
 
+- cleanup
+  - cleanup warnings that the newer GCC produces.
 
 - Stuff to implement:
 
@@ -32,52 +33,50 @@ Oh, Feel free to provide suggestions for this list.
     mtr.
 
   - Request timestamping at the remote site.
-       Andreas Fasbender has an algorithm that will allow us to 
+       Andreas Fasbender has an algorithm that will allow us to
        convert these measurements into one-way measurements, not just
        round-trip.
 
-  - allow "keyboard navigation" in the GTK version. 
+  - allow "keyboard navigation" in the GTK version.
 
   - Keep all packets and make the "best" and "worst" columns show the
     xx-th percentile....
 
-  - Can the reports generated also include any secondary servers?  In 
-    the interactive mode, any new servers that are found in the 
-    traceroute are added to the list, but it seems to only include 
-    one set of servers when using the -r option.  
-
-  - Being able to expand the "column width" of the hosts listed would 
+  - Being able to expand the "column width" of the hosts listed would
     be nice, too.
 
+  - Display per host stats when multiple servers respond at a particular
+    hop count.
+
 
 - Bugs to fix?
 
-  - Do something useful if host couldn't be resolved. 
-       -- Done. 
+  - Do something useful if host couldn't be resolved.
+       -- Done.
 
   - Revert to curses mode even if DISPLAY is set, but a problem
     prevents us from running in X11 mode.
        -->  The problem is that gtk_init simply calls exit for us if
-            it finds a problem. Tricky! Suggestions welcome. 
+            it finds a problem. Tricky! Suggestions welcome.
        --> Call "gtk_check_init" when available. (i.e. new enough
            (1.2?) GTK version).
 
 - Nice to have:
 
-  - stop sending packets when a new host is getting entered. 
+  - stop sending packets when a new host is getting entered.
 
   - Show state ("looking up host") while doing the DNS lookup for a new
     host.
 
   - to have a choice of icmp, tcp, and udp pings. -- Matt Martini
 
-  - Autoconf 2.13 has a neat function that can be used to find the 
-    res_init function: 
+  - Autoconf 2.13 has a neat function that can be used to find the
+    res_init function:
 
 	   AC_SEARCH_LIBS(res_init, bind resolv, ,
 	      AC_MSG_ERROR(No resolver library found))
 
-    At the moment (march 1999) autoconf 2.13 is still too new to require 
+    At the moment (march 1999) autoconf 2.13 is still too new to require
     everyone to upgrade. About a year from now we can put this in....
 
   - Implement rfc2317 mechanism to do reverse lookups for networks that
@@ -104,11 +103,11 @@ Oh, Feel free to provide suggestions for this list.
 
 Things that shouldn't be on the TODO list because they're done. ;-)
 
-  - Allow a toggle between hostname/IP number display. (for example a 
+  - Allow a toggle between hostname/IP number display. (for example a
     click on the hostname could revert to ip number display in gtk version.
     curses: "n" key toggles hostnames/ipnumbers?)
 
-  - Allow mtr to also send larger packets. 
+  - Allow mtr to also send larger packets.
        This will enable us to get a feel for the speed of the links
        we're traversing. (Van Jacobson was working on this His tool
        was slow, mtr will rock with this feature.... :-)
@@ -120,9 +119,8 @@ Things that shouldn't be on the TODO list because they're done. ;-)
     It should not probe more than 10 unknown hosts, but the counter need
     not be reset at the start of the "round". This way if you probe
     slowly (relative to the RTT time to the end host), it can probe
-    all hosts in the first "round". 
+    all hosts in the first "round".
        -- DONE.
 
   - Read environment variable "MTR_DEFAULTS" as a commandline before
     parsing the commandline.  -- DONE. (ok it's MTR_OPTIONS.)
-
diff --git a/bash-completion/mtr b/bash-completion/mtr
index 4d9d5dd..63b153b 100644
--- a/bash-completion/mtr
+++ b/bash-completion/mtr
@@ -8,43 +8,43 @@ _mtr_module()
     '-F'|'--filename')
       local IFS=$'\n'
       compopt -o filenames
-      COMPREPLY=( $(compgen -f -- $cur) )
+      COMPREPLY=( $(compgen -f -- "$cur") )
       return 0
       ;;
     '-a'|'--address')
-      COMPREPLY=( $(compgen -W "ADDRESS" -- $cur) )
+      COMPREPLY=( $(compgen -W "ADDRESS" -- "$cur") )
       return 0
       ;;
-    '-f'|'--first-ttl'|'-m'|'--max-ttl'|'-m'|'--max-unknown'|'-B'|'--bitpattern'|'-Q'|'--tos'|'-c'|'--report-cycles')
-      COMPREPLY=( $(compgen -W "NUMBER" -- $cur) )
+    '-f'|'--first-ttl'|'-m'|'--max-ttl'|'-U'|'--max-unknown'|'-B'|'--bitpattern'|'-Q'|'--tos'|'-c'|'--report-cycles')
+      COMPREPLY=( $(compgen -W "NUMBER" -- "$cur") )
       return 0
       ;;
     '-P'|'--port'|'-L'|'--localport')
-      COMPREPLY=( $(compgen -W "PORT" -- $cur) )
+      COMPREPLY=( $(compgen -W "PORT" -- "$cur") )
       return 0
       ;;
     '-s'|'--psize')
-      COMPREPLY=( $(compgen -W "SIZE" -- $cur) )
+      COMPREPLY=( $(compgen -W "SIZE" -- "$cur") )
       return 0
       ;;
     '-i'|'--interval'|'-G'|'--gracetime'|'-Z'|'--timeout')
-      COMPREPLY=( $(compgen -W "SECONDS" -- $cur) )
+      COMPREPLY=( $(compgen -W "SECONDS" -- "$cur") )
       return 0
       ;;
     '-M'|'--mark')
-      COMPREPLY=( $(compgen -W "MARK" -- $cur) )
+      COMPREPLY=( $(compgen -W "MARK" -- "$cur") )
       return 0
       ;;
     '--displaymode')
-      COMPREPLY=( $(compgen -W "{0..2}" -- $cur) )
+      COMPREPLY=( $(compgen -W "{0..2}" -- "$cur") )
       return 0
       ;;
     '-y'|'--ipinfo')
-      COMPREPLY=( $(compgen -W "{0..4}" -- $cur) )
+      COMPREPLY=( $(compgen -W "{0..4}" -- "$cur") )
       return 0
       ;;
     '-o'|'--order')
-      COMPREPLY=( $(compgen -W "LDRSNBAWVGJMXI" -- $cur) )
+      COMPREPLY=( $(compgen -W "LDRSNBAWVGJMXI" -- "$cur") )
       return 0
       ;;
   esac
@@ -58,11 +58,11 @@ _mtr_module()
         --curses --displaymode --gtk --no-dns --show-ips --order --ipinfo
         --aslookup --help --version
       '
-      COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
+      COMPREPLY=( $(compgen -W "${OPTS[*]}" -- "$cur") )
       return 0
       ;;
   esac
-  COMPREPLY=( $(compgen -W "ip_address hostname" -- $cur) )
+  COMPREPLY=( $(compgen -W "ip_address hostname" -- "$cur") )
   return 0
 }
 complete -F _mtr_module mtr
diff --git a/build-aux/mangen.sh b/build-aux/mangen.sh
index 6ce777e..cdc2a01 100755
--- a/build-aux/mangen.sh
+++ b/build-aux/mangen.sh
@@ -7,7 +7,7 @@
 #
 
 if [ $# -lt 3 ]; then
-    echo Usage: mangen.sh VERSION IN OUT
+    echo "Usage: mangen.sh VERSION IN OUT"
     exit 1
 fi
 
@@ -20,10 +20,10 @@ OUT=$3
 #  URL completely disappear from man pages.  We need to strip
 #  those codes out when building for MacOS
 #
-if [ $(uname -s) = "Darwin" ]; then
+if [ "$(uname -s)" = "Darwin" ]; then
    RMURUE='-e s/\.UR.//g -e s/\.UE//g'
 else
    RMURUE=""
 fi
 
-sed -e "s|@VERSION[@]|$VERSION|g" $RMURUE $IN >$OUT
+sed -e "s|@VERSION[@]|$VERSION|g" $RMURUE "$IN" >"$OUT"
diff --git a/configure.ac b/configure.ac
index ad81332..3175d56 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,12 +21,11 @@ AC_CANONICAL_HOST
 AC_PROG_CC
 
 # Check pkg-config availability.
-m4_ifndef([PKG_PROG_PKG_CONFIG],
-  [m4_fatal(
+m4_ifndef([PKG_CHECK_MODULES], [m4_defun([PKG_CHECK_MODULES], [AC_MSG_ERROR(
 [Could not locate the pkg-config autoconf macros.  These are usually located
 in /usr/share/aclocal/pkg.m4.  If your macros are in a different location,
 try setting the environment variable ACLOCAL_OPTS="-I/other/macro/dir"
-before running ./bootstrap.sh again.])
+before running ./bootstrap.sh again, or configure --without-gtk ----without-jansson ])])
 ])
 PKG_PROG_PKG_CONFIG
 
@@ -84,17 +83,35 @@ AM_CONDITIONAL([WITH_GETOPT], [test "x$with_getopt" = "xyes"])
 
 AC_CHECK_LIB([m], [floor], [], [AC_MSG_ERROR([No math library found])])
 
+# libasan
+AC_ARG_WITH([libasan],
+ [AS_HELP_STRING([--with-libasan], [Build with AddressSanitizer])],
+ [with_libasan=yes], [])
+AM_CONDITIONAL([WITH_LIBASAN], [test "x$with_libasan" = "xyes"])
+
 # Find GTK
 AC_ARG_WITH([gtk],
-  [AS_HELP_STRING([--without-gtk], [Build without the GTK+2.0 interface])],
+  [AS_HELP_STRING([--without-gtk], [Build without the GTK+ interface])],
   [], [with_gtk=yes])
 AS_IF([test "x$with_gtk" = "xyes"],
-  [PKG_CHECK_MODULES([GTK], [gtk+-2.0],
-    [AC_DEFINE([HAVE_GTK], [1], [Define if gtk+-2.0 library available])],
-    [with_gtk=no])
+  [PKG_CHECK_MODULES([GTK], [gtk+-3.0],
+    [AC_DEFINE([HAVE_GTK], [1], [Define if gtk+ library available])]
+      [AC_DEFINE([HAVE_GTK3], [1], [Define if gtk+-3.0 library available])],
+    [PKG_CHECK_MODULES([GTK], [gtk+-2.0],
+      [AC_DEFINE([HAVE_GTK], [1], [Define if gtk+ library available])],
+      [with_gtk=no])])
 ])
 AM_CONDITIONAL([WITH_GTK], [test "x$with_gtk" = xyes])
 
+AC_ARG_WITH([jansson],
+  [AS_HELP_STRING([--without-jansson], [Build without JSON output])],
+  [], [with_jansson=yes])
+AS_IF([test "x$with_jansson" = "xyes"],
+  [PKG_CHECK_MODULES([JANSSON], [jansson],
+    [AC_DEFINE([HAVE_JANSSON], [1], [Define if jansson library available])],
+    [with_jansson=no])
+])
+
 # Find ncurses
 AC_ARG_WITH([ncurses],
   [AS_HELP_STRING([--without-ncurses], [Build without the ncurses interface])],
@@ -245,10 +262,12 @@ AC_ARG_ENABLE([bash-completion],
 AM_CONDITIONAL([BUILD_BASH_COMPLETION], [test "x$enable_bash_completion" = xyes])
 echo "build options:"
 echo "--------------"
+echo "libasan :$with_libasan"
 echo "ipv6    :$USES_IPV6"
 echo "ipinfo  :$with_ipinfo"
 echo "ncurses :$with_ncurses"
 echo "gtk     :$with_gtk"
+echo "jansson :$with_jansson"
 echo "cap     :$have_cap"
 echo "libs    :$LIBS"
 echo "cflags  :$CFLAGS"
diff --git a/man/mtr-packet.8.in b/man/mtr-packet.8.in
index 9c02470..090c3ad 100644
--- a/man/mtr-packet.8.in
+++ b/man/mtr-packet.8.in
@@ -121,7 +121,7 @@ probes.
 .I IP-ADDRESS
 .HP 14
 .IP
-The local Internet Procol version 4 address to use when sending probes.
+The local Internet Protocol version 4 address to use when sending probes.
 .HP 7
 .IP
 .B local-ip-6
@@ -407,7 +407,7 @@ value, are used.
 \&...
 .RE 0
 .LP
-Each interemediate host would respond with a
+Each intermediate host would respond with a
 .B ttl-expired
 message, and the destination host would respond with a
 .BR reply :
diff --git a/man/mtr.8.in b/man/mtr.8.in
index db55012..80c4790 100644
--- a/man/mtr.8.in
+++ b/man/mtr.8.in
@@ -114,38 +114,38 @@ mtr \- a network diagnostic tool
 ]
 .I HOSTNAME
 .SH DESCRIPTION
-.B mtr 
-combines the functionality of the 
+.B mtr
+combines the functionality of the
 .B traceroute
-and 
+and
 .B ping
 programs in a single network diagnostic tool.
 .PP
-As 
-.B mtr 
-starts, it investigates the network connection between the host 
+As
 .B mtr
-runs on and 
+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
 packets with low TTL, noting the response time of the intervening
-routers.  This allows 
-.B mtr 
+routers.  This allows
+.B mtr
 to print the response percentage and response times of the internet
-route to 
-.BR HOSTNAME . 
+route to
+.BR HOSTNAME .
 A sudden increase in packet loss or response time is often an indication
-of a bad (or simply overloaded) link. 
+of a bad (or simply overloaded) link.
 .PP
 The results are usually reported as round-trip-response times in milliseconds
-and the percentage of packetloss. 
+and the percentage of packet loss.
 .SH OPTIONS
 .TP
 .B \-h\fR, \fB\-\-help
 Print the summary of command line argument options.
 .TP
 .B \-v\fR, \fB\-\-version
-Print the installed version of mtr.  
+Print the installed version of mtr.
 .TP
 .B \-4
 Use IPv4 only.
@@ -157,33 +157,33 @@ Use IPv6 only.  (IPV4 may be used for DNS lookups.)
 Reads the list of hostnames from the specified file.
 .TP
 .B \-r\fR, \fB\-\-report
-This option puts 
+This option puts
 .B mtr
-into 
+into
 .B report
 mode.  When in this mode,
 .B mtr
-will run for the number of cycles specified by the 
+will run for the number of cycles specified by the
 .B \-c
-option, and then print statistics and exit.  
+option, and then print statistics and exit.
 .TP
 \c
-This mode is useful for generating statistics about network quality.  
-Note that each running instance of 
+This mode is useful for generating statistics about network quality.
+Note that each running instance of
 .B mtr
-generates a significant amount of network traffic.  Using 
+generates a significant amount of network traffic.  Using
 .B mtr
 to measure the quality of your network may result in decreased
-network performance.  
+network performance.
 .TP
 .B \-w\fR, \fB\-\-report\-wide
-This option puts 
+This option puts
 .B mtr
-into 
+into
 .B wide report
 mode.  When in this mode,
 .B mtr
-will not cut hostnames in the report. 
+will not cut hostnames in the report.
 .TP
 .B \-x\fR, \fB\-\-xml
 Use this option to tell
@@ -192,12 +192,12 @@ to use the xml output format.  This format is better suited for
 automated processing of the measurement results.
 .TP
 .B \-t\fR, \fB\-\-curses
-Use this option to force 
-.B mtr 
+Use this option to force
+.B mtr
 to use the curses based terminal
 interface (if available).
-In case the list of hops exceeds the 
-height of your terminal, you can use the 
+In case the list of hops exceeds the
+height of your terminal, you can use the
 .B +
 and
 .B -
@@ -215,19 +215,19 @@ information.
 .TP
 .B \-g\fR, \fB\-\-gtk
 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 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
 .UR http://\:www.\:gtk.\:org/
 .UE
 for more information about GTK+.
 .TP
 .B \-l\fR, \fB\-\-raw
 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. 
+archival of the measurement results.  It could be parsed to
+be presented into any of the other display methods.
 .IP
 Example of the raw output format:
 .nf
@@ -267,17 +267,20 @@ Use this option to tell
 .B mtr
 to use the JSON output format.  This format is better suited for
 automated processing of the measurement results.
+Jansson library must have been available on the system when
+.B mtr
+was built for this to work.
 .TP
 .B \-p\fR, \fB\-\-split
 Use this option to set
-.B mtr 
+.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 
+Use this option to force
+.B mtr
 to display numeric IP numbers and not try to resolve the
-host names. 
+host names.
 .TP
 .B \-b\fR, \fB\-\-show\-ips
 Use this option to tell
@@ -285,7 +288,7 @@ Use this option to tell
 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
-wide report (-w) mode to see the IPs in report mode. 
+wide report (-w) mode to see the IPs in report mode.
 .TP
 .B \-o \fIFIELDS\fR, \fB\-\-order \fIFIELDS
 Use this option to specify which fields to display and in which order.
@@ -351,7 +354,7 @@ root user may choose values between zero and one.
 .TP
 .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 
+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
@@ -375,8 +378,8 @@ Specifies value for type of service field in IP header.  Should be within range
 - 255.
 .TP
 .B \-e\fR, \fB\-\-mpls
-Use this option to tell 
-.B mtr 
+Use this option to tell
+.B mtr
 to display information from ICMP extensions for MPLS (RFC 4950)
 that are encoded in the response packets.
 .TP
@@ -498,15 +501,15 @@ can be controlled while it is running with the following keys:
   z       toggle ASN info on/off
   q       exit
 .SH BUGS
-Some modern routers give a lower priority to ICMP ECHO packets than 
+Some modern routers give a lower priority to ICMP ECHO packets than
 to other network traffic.  Consequently, the reliability of these
-routers reported by 
+routers reported by
 .B mtr
-will be significantly lower than the actual reliability of 
-these routers.  
+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 
+For the latest version, see the mtr web page at
 .UR http://\:www.\:bitwizard.\:nl/\:mtr/
 .UE
 .PP
diff --git a/packet/cmdparse.c b/packet/cmdparse.c
index 76e6c91..85757b6 100644
--- a/packet/cmdparse.c
+++ b/packet/cmdparse.c
@@ -66,8 +66,8 @@ int tokenize_command(
     structure for later semantic interpretation.  Returns EINVAL if the
     command string is unparseable or zero for success.
 
-    comamnd_string will be modified in-place with NUL characters terminating
-    tokens, and the command_t will use pointers to the conents of
+    command_string will be modified in-place with NUL characters terminating
+    tokens, and the command_t will use pointers to the contents of
     command_string without copying, so any interpretation of the
     command_t structure requires that the command_string memory has not yet
     been freed or otherwise reused.
diff --git a/packet/cmdparse.h b/packet/cmdparse.h
index 77c8281..e5cfeab 100644
--- a/packet/cmdparse.h
+++ b/packet/cmdparse.h
@@ -29,7 +29,7 @@ struct command_t {
     /*  A unique value for matching command requests with replies  */
     int token;
 
-    /*  Text indiciating the command type, or reply type  */
+    /*  Text indicating the command type, or reply type  */
     char *command_name;
 
     /*  The number of key, value argument pairs used  */
diff --git a/packet/command.c b/packet/command.c
index 2026352..b624ea6 100644
--- a/packet/command.c
+++ b/packet/command.c
@@ -424,7 +424,7 @@ void dispatch_buffer_commands(
     if (buffer->incoming_read_position >= COMMAND_BUFFER_SIZE - 1) {
         /*
            If we've filled the buffer without a complete command, the
-           only thing we can do is discard what we've read and hope that 
+           only thing we can do is discard what we've read and hope that
            new data is better formatted.
          */
         printf("0 command-buffer-overflow\n");
diff --git a/packet/construct_unix.c b/packet/construct_unix.c
index 09250bc..644536d 100644
--- a/packet/construct_unix.c
+++ b/packet/construct_unix.c
@@ -591,7 +591,7 @@ int construct_ip4_packet(
     /*
        The routing mark requires CAP_NET_ADMIN, as opposed to the
        CAP_NET_RAW which we are sometimes explicitly given.
-       If we don't have CAP_NET_ADMIN, this will fail, so we'll 
+       If we don't have CAP_NET_ADMIN, this will fail, so we'll
        only set the mark if the user has explicitly requested it.
 
        Unfortunately, this means that once the mark is set, it won't
@@ -724,7 +724,7 @@ int construct_ip6_packet(
     /*
        Check the current socket address, and if it is the same
        as the source address we intend, we will skip the bind.
-       This is to accomodate Solaris, which, as of Solaris 11.3,
+       This is to accommodate Solaris, which, as of Solaris 11.3,
        will return an EINVAL error on bind if the socket is already
        bound, even if the same address is used.
      */
@@ -754,7 +754,7 @@ int construct_ip6_packet(
         }
     }
 
-    /*  The traffic class in IPv6 is analagous to ToS in IPv4  */
+    /*  The traffic class in IPv6 is analogous to ToS in IPv4  */
     if (setsockopt(send_socket, IPPROTO_IPV6,
                    IPV6_TCLASS, &param->type_of_service, sizeof(int))) {
         return -1;
diff --git a/packet/deconstruct_unix.c b/packet/deconstruct_unix.c
index 1af7419..61c6e91 100644
--- a/packet/deconstruct_unix.c
+++ b/packet/deconstruct_unix.c
@@ -99,22 +99,22 @@ void handle_inner_udp_packet(
     {
         saddr = &((struct IPHeader *)ip)->saddr;
         daddr = &((struct IPHeader *)ip)->daddr;
-    }else
+    } else
     if (af == AF_INET6)
     {
         daddr = &((struct IP6Header *)ip)->daddr;
         saddr = &((struct IP6Header *)ip)->saddr;
-    }else
+    } else
     {
         return;
     }
 
-    if( memcmp(sockaddr_addr_offset(&probe->remote_addr),
+    if ( memcmp(sockaddr_addr_offset(&probe->remote_addr),
                daddr,
                sockaddr_addr_size(&probe->remote_addr)) != 0 )
             return;
 
-    if( memcmp(sockaddr_addr_offset(&probe->local_addr),
+    if ( memcmp(sockaddr_addr_offset(&probe->local_addr),
            saddr,
            sockaddr_addr_size(&probe->local_addr)) != 0)
         return;
diff --git a/packet/packet.c b/packet/packet.c
index a8c2b6e..3821d91 100644
--- a/packet/packet.c
+++ b/packet/packet.c
@@ -35,7 +35,7 @@
 
 #include "wait.h"
 
-/*  Drop SUID privileges.  To be used after accquiring raw sockets.  */
+/*  Drop SUID privileges.  To be used after acquiring raw sockets.  */
 static
 int drop_elevated_permissions(
     void)
@@ -82,7 +82,7 @@ int main(
     struct net_state_t net_state;
 
     /*
-       To minimize security risk, the only thing done prior to 
+       To minimize security risk, the only thing done prior to
        dropping SUID should be opening the network state for
        raw sockets.
      */
diff --git a/packet/probe.c b/packet/probe.c
index 0177e97..6581015 100644
--- a/packet/probe.c
+++ b/packet/probe.c
@@ -38,6 +38,8 @@
 #include "timeval.h"
 #include "sockaddr.h"
 
+char *probe_err;
+
 /*  Convert the destination address from text to sockaddr  */
 int decode_address_string(
     int ip_version,
@@ -98,18 +100,23 @@ int resolve_probe_addresses(
 {
     if (decode_address_string
         (param->ip_version, param->remote_address, dest_sockaddr)) {
+        probe_err = "decode address string remote";
         return -1;
     }
 
     if (param->local_address) {
         if (decode_address_string
             (param->ip_version, param->local_address, src_sockaddr)) {
+            probe_err = "decode address string local";
             return -1;
         }
     } else {
+        probe_err = "find source address";
         if (find_source_addr(src_sockaddr, dest_sockaddr)) {
+            //probe_err = "find source address";
             return -1;
         }
+        probe_err = "";
     }
     /* DGRAM ICMP id is taken from src_port not from ICMP header */
     if (param->protocol == IPPROTO_ICMP) {
@@ -311,8 +318,12 @@ int find_source_addr(
     int sock;
     int len;
     struct sockaddr_storage dest_with_port;
+#ifdef __linux__
+    // The Linux code needs these.
     struct sockaddr_in *srcaddr4;
     struct sockaddr_in6 *srcaddr6;
+#endif
+
 
     dest_with_port = *destaddr;
 
@@ -323,16 +334,18 @@ int find_source_addr(
        anything to the port.
      */
     *sockaddr_port_offset(&dest_with_port) = htons(1);
-    len = sockaddr_addr_size(&dest_with_port);
+    len = sockaddr_size(&dest_with_port);
 
     sock = socket(destaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP);
     if (sock == -1) {
+        probe_err = "open socket";
         return -1;
     }
 
     if (connect(sock, (struct sockaddr *) &dest_with_port, len) == 0) {
         if (getsockname(sock, (struct sockaddr *) srcaddr, &len)) {
             close(sock);
+            probe_err = "getsockname";
             return -1;
         }
     } else {
@@ -341,6 +354,7 @@ int find_source_addr(
          * a case when mtr is run against unreachable host (that can become
          * reachable) */
         if (errno != EHOSTUNREACH) {
+            probe_err = "not hostunreach";
             close(sock);
             return -1;
         }
@@ -354,6 +368,7 @@ int find_source_addr(
         }
 #else
         close(sock);
+        probe_err = "connect failed";
         return -1;
 #endif
     }
@@ -364,7 +379,7 @@ int find_source_addr(
        Zero the port, as we may later use this address to finding, and
        we don't want to use the port from the socket we just created.
      */
-    *sockaddr_port_offset(&srcaddr) = 0;
+    *sockaddr_port_offset(srcaddr) = 0;
 
     return 0;
 }
diff --git a/packet/probe.h b/packet/probe.h
index 53b8037..e7b8bee 100644
--- a/packet/probe.h
+++ b/packet/probe.h
@@ -68,7 +68,7 @@ struct probe_param_t {
     /*  The packet "mark" used for mark-based routing on Linux  */
     int routing_mark;
 
-    /*  Time to live for the transmited probe  */
+    /*  Time to live for the transmitted probe  */
     int ttl;
 
     /*  The packet size (in bytes) including protocol headers  */
@@ -207,4 +207,6 @@ int find_source_addr(
     struct sockaddr_storage *srcaddr,
     const struct sockaddr_storage *destaddr);
 
+extern char *probe_err;
+
 #endif
diff --git a/packet/probe_cygwin.c b/packet/probe_cygwin.c
index 79e9fdb..f41e514 100644
--- a/packet/probe_cygwin.c
+++ b/packet/probe_cygwin.c
@@ -81,7 +81,7 @@
 
     We use the Cygwin pipe() to create the pipes, but in the ICMP
     service thread we use the Win32 HANDLE that corresponds to the
-    recieving end of the input pipe to wait for ICMP requests.
+    receiving end of the input pipe to wait for ICMP requests.
 */
 
 
@@ -94,7 +94,7 @@ void init_net_state_privileged(
 }
 
 /*
-    Convienience similar to error(), but for reporting Windows
+    Convenience similar to error(), but for reporting Windows
     error codes instead of errno codes.
 */
 void error_win(int exit_code, int win_error, const char *str) {
@@ -352,7 +352,7 @@ void icmp_send_probe(
         timeout = 1000 * request->timeout;
     } else {
         /*
-           IcmpSendEcho2 will return invalid argument on a timeout of 
+           IcmpSendEcho2 will return invalid argument on a timeout of
            zero.  Our Unix implementation allows it.  Bump up the timeout
            to 1 millisecond.
          */
@@ -483,7 +483,7 @@ DWORD WINAPI icmp_service_thread(LPVOID param) {
     HANDLE event;
     BOOL success;
     bool read_pending;
-    int read_count;
+    DWORD read_count;
     int err;
 
     /*
@@ -717,7 +717,7 @@ void receive_replies(
 }
 
 /*
-    On Windows, an implementation of check_probe_timeout is unnecesary because
+    On Windows, an implementation of check_probe_timeout is unnecessary because
     timeouts are managed by ICMP.DLL, including a call to the I/O completion
     routine when the time fully expires.
 */
diff --git a/packet/probe_unix.c b/packet/probe_unix.c
index 363930f..f7f393f 100644
--- a/packet/probe_unix.c
+++ b/packet/probe_unix.c
@@ -52,9 +52,12 @@ int send_packet(
     int packet_size,
     const struct sockaddr_storage *sockaddr)
 {
+    struct sockaddr_storage dst;
     int send_socket = 0;
     int sockaddr_length;
 
+    memcpy(&dst, sockaddr, sizeof(struct sockaddr_storage));
+
     if (sockaddr->ss_family == AF_INET6) {
         sockaddr_length = sizeof(struct sockaddr_in6);
 
@@ -67,12 +70,17 @@ int send_packet(
         } else if (param->protocol == IPPROTO_UDP) {
             if (net_state->platform.ip6_socket_raw) {
                 send_socket = net_state->platform.udp6_send_socket;
+                /* we got a ipv6 udp raw socket
+                 * the remote port is in the payload
+                 * we do not set in the sockaddr
+                 */
+                *sockaddr_port_offset(&dst) = 0;
             } else {
                 send_socket = net_state->platform.ip6_txrx_udp_socket;
                 if (param->dest_port) {
-                    *sockaddr_port_offset(sockaddr) = htons(param->dest_port);
+                    *sockaddr_port_offset(&dst) = htons(param->dest_port);
                 } else {
-                    *sockaddr_port_offset(sockaddr) = sequence;
+                    *sockaddr_port_offset(&dst) = sequence;
                 }
             }
         }
@@ -91,9 +99,9 @@ int send_packet(
             } else if (param->protocol == IPPROTO_UDP) {
                 send_socket = net_state->platform.ip4_txrx_udp_socket;
                 if (param->dest_port) {
-                    *sockaddr_port_offset(sockaddr) = htons(param->dest_port);
+                    *sockaddr_port_offset(&dst) = htons(param->dest_port);
                 } else {
-                    *sockaddr_port_offset(sockaddr) = sequence;
+                    *sockaddr_port_offset(&dst) = sequence;
                 }
             }
         }
@@ -105,7 +113,7 @@ int send_packet(
     }
 
     return sendto(send_socket, packet, packet_size, 0,
-                  (struct sockaddr *) sockaddr, sockaddr_length);
+                  (struct sockaddr *) &dst, sockaddr_length);
 }
 
 /*
@@ -145,7 +153,8 @@ void check_length_order(
 
     if (resolve_probe_addresses(net_state, &param, &p0.remote_addr,
                 &p0.local_addr)) {
-        fprintf(stderr, "Error decoding localhost address\n");
+        fprintf(stderr, "Error decoding localhost address (%s/%s)\n",
+                probe_err, strerror (errno));
         exit(EXIT_FAILURE);
     }
 
@@ -566,18 +575,18 @@ void send_probe(
         error(EXIT_FAILURE, errno, "gettimeofday failure");
     }
 
-    // there might be an off-by-one in the number of tries here. 
+    // there might be an off-by-one in the number of tries here.
     // this is intentional.  It is no use exhausting the very last
-    // open port. Max 10 retries would've been acceptable too I think. 
+    // open port. Max 10 retries would've been acceptable too I think.
     for (trytimes=MIN_PORT; trytimes < MAX_PORT; trytimes++) {
-			
+
         packet_size = construct_packet(net_state, &probe->platform.socket,
                          probe, packet, PACKET_BUFFER_SIZE,
                          param);
 
         if (packet_size > 0) break; // no retry if we succeed.
 
-        if ((param->protocol != IPPROTO_TCP) && 
+        if ((param->protocol != IPPROTO_TCP) &&
             (param->protocol != IPPROTO_SCTP)) break; // no retry if not TCP/SCTP
 
         if ((errno != EADDRINUSE) && (errno != EADDRNOTAVAIL)) {
@@ -585,7 +594,7 @@ void send_probe(
         }
 
      	probe->sequence = net_state->platform.next_sequence++;
-        	
+
        	if (net_state->platform.next_sequence > MAX_PORT) {
             net_state->platform.next_sequence = MIN_PORT;
         }
@@ -683,7 +692,7 @@ void receive_probe(
 
 /*
     Read all available packets through our receiving raw socket, and
-    handle any responses to probes we have preivously sent.
+    handle any responses to probes we have previously sent.
 */
 static
 void receive_replies_from_recv_socket(
@@ -795,7 +804,6 @@ void receive_replies_from_recv_socket(
                 memcpy(&remote_addr, SO_EE_OFFENDER(ee), sizeof(remote_addr));
             }
         }
-#endif
 
 #ifdef SO_PROTOCOL
         if (icmp_connrefused_received) {
@@ -814,12 +822,15 @@ void receive_replies_from_recv_socket(
             handle_error_queue_packet(net_state, &remote_addr, ICMP_TIME_EXCEEDED, proto,
                     packet, packet_length, &timestamp);
         } else {
+#endif
 #endif
             /* ICMP packets received from raw socket */
             handle_received_packet(net_state, &remote_addr, packet,
                                    packet_length, &timestamp);
+#ifdef HAVE_LINUX_ERRQUEUE_H
 #ifdef SO_PROTOCOL
         }
+#endif
 #endif
     }
 }
diff --git a/packet/probe_unix.h b/packet/probe_unix.h
index cc01e1e..f217a66 100644
--- a/packet/probe_unix.h
+++ b/packet/probe_unix.h
@@ -20,7 +20,7 @@
 #define PROBE_UNIX_H
 
 #ifndef IPPROTO_SCTP
-// Needed for Netbsd. 
+// Needed for Netbsd.
 #define IPPROTO_SCTP           132             /* SCTP */
 #endif
 
@@ -40,7 +40,7 @@ struct probe_platform_t {
     struct timeval departure_time;
 };
 
-/*  We'll use rack sockets to send and recieve probes on Unix systems  */
+/*  We'll use rack sockets to send and receive probes on Unix systems  */
 struct net_state_platform_t {
     /*  true if we were successful at opening IPv4 sockets  */
     bool ip4_present;
diff --git a/packet/protocols.h b/packet/protocols.h
index 89d0a96..51fce9a 100644
--- a/packet/protocols.h
+++ b/packet/protocols.h
@@ -50,7 +50,7 @@
 #define HTTP_PORT 80
 
 /*  We can't rely on header files to provide this information, because
-    the fields have different names between, for instance, Linux and 
+    the fields have different names between, for instance, Linux and
     Solaris  */
 struct ICMPHeader {
     uint8_t type;
diff --git a/packet/sockaddr.c b/packet/sockaddr.c
index 2a4b34a..892d7ee 100644
--- a/packet/sockaddr.c
+++ b/packet/sockaddr.c
@@ -5,14 +5,14 @@
 
 void *sockaddr_addr_offset(const void *x)
 {
-	if( x == NULL )
+	if ( x == NULL )
 		return NULL;
 
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET )
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET )
 	{
 		return ((void *)(x) + offsetof(struct sockaddr_in, sin_addr));
-	}else
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
+	} else
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
 	{
 		return ((void *)(x) + offsetof(struct sockaddr_in6, sin6_addr));
 	}
@@ -22,13 +22,13 @@ void *sockaddr_addr_offset(const void *x)
 
 unsigned int sockaddr_addr_size(const void *x)
 {
-	if( x == NULL )
+	if ( x == NULL )
 		return 0;
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET )
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET )
 	{
 		return sizeof(struct in_addr);
-	}else
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
+	} else
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
 	{
 		return sizeof(struct in6_addr);
 	}
@@ -38,13 +38,13 @@ unsigned int sockaddr_addr_size(const void *x)
 
 unsigned int sockaddr_size(const void *x)
 {
-	if( x == NULL )
+	if ( x == NULL )
 		return 0;
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET )
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET )
 	{
 		return sizeof(struct sockaddr_in);
-	}else
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
+	} else
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
 	{
 		return sizeof(struct sockaddr_in6);
 	}
@@ -53,14 +53,14 @@ unsigned int sockaddr_size(const void *x)
 
 in_port_t *sockaddr_port_offset(const void *x)
 {
-	if( x == NULL )
+	if ( x == NULL )
 		return NULL;
 
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET )
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET )
 	{
 		return ((void *)(x) + offsetof(struct sockaddr_in, sin_port));
-	}else
-	if( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
+	} else
+	if ( ((struct sockaddr *)(x))->sa_family == AF_INET6 )
 	{
 		return ((void *)(x) + offsetof(struct sockaddr_in6, sin6_port));
 	}
diff --git a/packet/wait_cygwin.c b/packet/wait_cygwin.c
index 6f93fb1..0546231 100644
--- a/packet/wait_cygwin.c
+++ b/packet/wait_cygwin.c
@@ -19,6 +19,7 @@
 #include "wait.h"
 
 #include <error.h>
+#include <errno.h>
 #include <sys/select.h>
 
 #include "command.h"
diff --git a/packet/wait_unix.c b/packet/wait_unix.c
index 06d2ea7..ad14238 100644
--- a/packet/wait_unix.c
+++ b/packet/wait_unix.c
@@ -104,7 +104,7 @@ int gather_read_fds(
     Sleep until we receive a new probe response, a new command on the
     command stream, or a probe timeout.  On Unix systems, this means
     we use select to wait on file descriptors for the command stream
-    and the raw recieve socket.
+    and the raw receive socket.
 */
 void wait_for_activity(
     struct command_buffer_t *command_buffer,
diff --git a/portability/getopt.c b/portability/getopt.c
index fcd0b7d..0c6a1b9 100644
--- a/portability/getopt.c
+++ b/portability/getopt.c
@@ -550,7 +550,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
 		    fprintf (stderr,
 		     _("%s: option `%c%s' doesn't allow an argument\n"),
 		     argv[0], argv[optind - 1][0], pfound->name);
-		  } 
+		  }
 		  nextchar += strlen (nextchar);
 		  return '?';
 		}
diff --git a/portability/queue.h b/portability/queue.h
index d19a425..e1222db 100644
--- a/portability/queue.h
+++ b/portability/queue.h
@@ -305,7 +305,7 @@ struct {								\
 #define	STAILQ_FIRST(head)	((head)->stqh_first)
 
 #define	STAILQ_FOREACH(var, head, field)				\
-	for((var) = STAILQ_FIRST((head));				\
+	for ((var) = STAILQ_FIRST((head));				\
 	   (var);							\
 	   (var) = STAILQ_NEXT((var), field))
 
diff --git a/test/packet_listen.c b/test/packet_listen.c
index a822707..9a1d931 100644
--- a/test/packet_listen.c
+++ b/test/packet_listen.c
@@ -34,7 +34,7 @@
 #define SEQUENCE_NUM 33000
 
 /*
-    Check to see if the packet we've recieved is intended for this test
+    Check to see if the packet we've received is intended for this test
     process.  We expected the ICMP sequence number to be equal to our
     process ID.
 */
diff --git a/test/param.py b/test/param.py
index d220019..edb8f5c 100755
--- a/test/param.py
+++ b/test/param.py
@@ -62,7 +62,7 @@ class TestParameters(mtrpacket.MtrPacketTest):
 
 @unittest.skipIf(sys.platform == 'cygwin', 'No Cygwin test')
 class TestIPv6Parameters(mtrpacket.MtrPacketTest):
-    'Test packet paramter customization for IPv6'
+    'Test packet parameter customization for IPv6'
 
     @unittest.skipUnless(mtrpacket.HAVE_IPV6, 'No IPv6')
     def test_param(self):
diff --git a/test/probe.py b/test/probe.py
index e69214c..df5f496 100755
--- a/test/probe.py
+++ b/test/probe.py
@@ -17,7 +17,7 @@
 #   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #
 
-'''Test sending probes and receiving respones.'''
+'''Test sending probes and receiving responses.'''
 
 import socket
 import sys
@@ -136,7 +136,7 @@ class TestProbeICMPv4(mtrpacket.MtrPacketTest):
         'Test timeouts when sending to a non-existant address'
 
         #
-        #  Probe a non-existant address, and expect no reply
+        #  Probe a non-existent address, and expect no reply
         #
         #  I'm not sure what the best way to find an address that doesn't
         #  exist, but is still route-able.  If we use a reserved IP
@@ -208,7 +208,7 @@ class TestProbeICMPv4(mtrpacket.MtrPacketTest):
     def test_ttl_expired(self):
         'Test sending a probe which will have its time-to-live expire'
 
-        #  Probe Goolge's DNS server, but give the probe only one hop
+        #  Probe Google's DNS server, but give the probe only one hop
         #  to live.
         self.write_command('16 send-probe ip-4 8.8.8.8 ttl 1')
         reply = self.parse_reply()
@@ -220,7 +220,7 @@ class TestProbeICMPv4(mtrpacket.MtrPacketTest):
         '''Test sending multiple probes in parallel
 
         We will expect the probes to complete out-of-order by sending
-        a probe to a distant host immeidately followed by a probe to
+        a probe to a distant host immediately followed by a probe to
         the local host.'''
 
         success_count = 0
@@ -268,9 +268,10 @@ class TestProbeICMPv6(mtrpacket.MtrPacketTest):
     '''Test sending probes using IP version 6'''
 
     def __init__(self, *args):
-        google_addr = resolve_ipv6_address(mtrpacket.IPV6_TEST_HOST)
+        if mtrpacket.HAVE_IPV6:
+            google_addr = resolve_ipv6_address(mtrpacket.IPV6_TEST_HOST)
 
-        self.google_addr = google_addr  # type: str
+            self.google_addr = google_addr  # type: str
 
         super(TestProbeICMPv6, self).__init__(*args)
 
@@ -300,7 +301,7 @@ class TestProbeICMPv6(mtrpacket.MtrPacketTest):
     def test_ttl_expired(self):
         'Test sending a probe which will have its time-to-live expire'
 
-        #  Probe Goolge's DNS server, but give the probe only one hop
+        #  Probe Google's DNS server, but give the probe only one hop
         #  to live.
         cmd = '53 send-probe ip-6 ' + self.google_addr + ' ttl 1'
         self.write_command(cmd)
diff --git a/ui/asn.c b/ui/asn.c
index 0ed0398..3f424e0 100644
--- a/ui/asn.c
+++ b/ui/asn.c
@@ -207,11 +207,11 @@ static void reverse_host6(
 {
     int i;
     char *b = buff;
-    for (i = (sizeof(*addr) / 2 - 1); i >= 0; i--, b += 4)      /* 64b portion */
+    // We need to process the top 64 bits, or 8 bytes.
+    for (i = 8-1; i >= 0; i--, b += 4, buff_length -= 4)
         snprintf(b, buff_length,
                  "%x.%x.", addr->s6_addr[i] & 0xf, addr->s6_addr[i] >> 4);
-
-    buff[strlen(buff) - 1] = '\0';
+    *--b = 0;
 }
 #endif
 
@@ -313,17 +313,15 @@ int is_printii(
 void asn_open(
     struct mtr_ctl *ctl)
 {
-    if (ctl->ipinfo_no >= 0) {
-        DEB_syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
-        if (!(iihash = hcreate(IIHASH_HI)))
-            error(0, errno, "ipinfo hash");
-    }
+    DEB_syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
+    if (!(iihash = hcreate(IIHASH_HI)))
+        error(0, errno, "ipinfo hash");
 }
 
 void asn_close(
     struct mtr_ctl *ctl)
 {
-    if ((ctl->ipinfo_no >= 0) && iihash) {
+    if (iihash) {
         DEB_syslog(LOG_INFO, "hdestroy()");
         hdestroy();
         iihash = 0;
diff --git a/ui/cmdpipe.c b/ui/cmdpipe.c
index 3581086..d22b236 100644
--- a/ui/cmdpipe.c
+++ b/ui/cmdpipe.c
@@ -73,9 +73,9 @@ int send_synchronous_command(
     struct mtr_ctl *ctl,
     struct packet_command_pipe_t *cmdpipe,
     const char *cmd,
-    struct command_t *result)
+    struct command_t *result,
+    char *reply)
 {
-    char reply[PACKET_REPLY_BUFFER_SIZE];
     int command_length;
     int write_length;
     int read_length;
@@ -120,11 +120,12 @@ int check_feature(
 {
     char check_command[COMMAND_BUFFER_SIZE];
     struct command_t reply;
+    char reply_buf[PACKET_REPLY_BUFFER_SIZE];
 
     snprintf(check_command, COMMAND_BUFFER_SIZE,
              "1 check-support feature %s\n", feature);
 
-    if (send_synchronous_command(ctl, cmdpipe, check_command, &reply) ==
+    if (send_synchronous_command(ctl, cmdpipe, check_command, &reply, reply_buf) ==
         -1) {
         return -1;
     }
@@ -206,7 +207,7 @@ int check_packet_features(
 
 extern char *myname;
 /*
-    Execute mtr-packet, allowing the MTR_PACKET evironment to override
+    Execute mtr-packet, allowing the MTR_PACKET environment to override
     the PATH when locating the executable.
 */
 static
@@ -230,8 +231,8 @@ void execute_packet_child(
      */
     execlp(mtr_packet_path, "mtr-packet", (char *) NULL);
 
-    /* 
-       Then try to find it where WE were executed from.  
+    /*
+       Then try to find it where WE were executed from.
      */
     strncpy (buf, myname, 240);
     strcat (buf, "-packet");
@@ -354,7 +355,7 @@ void construct_base_command(
     const char *local_ip_type;
     const char *protocol = NULL;
 
-    /*  Conver the remote IP address to a string  */
+    /*  Convert the remote IP address to a string  */
     if (inet_ntop(ctl->af, address, ip_string, INET6_ADDRSTRLEN) == NULL) {
 
         display_close(ctl);
@@ -741,7 +742,7 @@ void consume_reply_buffer(
 
     /*
        We may have multiple completed replies.  Loop until we don't
-       have any more newlines termininating replies.
+       have any more newlines terminating replies.
      */
     while (true) {
         /*  If no newline is found, our reply isn't yet complete  */
@@ -754,7 +755,7 @@ void consume_reply_buffer(
         /*
            Terminate the reply string at the newline, which
            is necessary in the case where we are able to read
-           mulitple replies arriving simultaneously.
+           multiple replies arriving simultaneously.
          */
         *end_of_reply = 0;
 
@@ -802,7 +803,7 @@ void handle_command_replies(
     reply_buffer = cmdpipe->reply_buffer;
 
     /*
-       Read the available reply text, up to the the remaining
+       Read the available reply text, up to the remaining
        buffer space.  (Minus one for the terminating NUL.)
      */
     read_buffer = &reply_buffer[cmdpipe->reply_buffer_used];
diff --git a/ui/curses.c b/ui/curses.c
index b0bc02e..d01e178 100644
--- a/ui/curses.c
+++ b/ui/curses.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,
@@ -390,7 +390,7 @@ static void format_field(
         format_number(n, 5, dst);
     } else if (strchr(format, 'f')) {
         /* this is for fields where we measure integer microseconds but
-           display floating point miliseconds. Convert to float here. */
+           display floating point milliseconds. Convert to float here. */
         snprintf(dst, dst_length, format, n / 1000.0);
         /* this was marked as a temporary hack over 10 years ago. -- REW */
     } else {
@@ -424,8 +424,7 @@ static void mtr_curses_hosts(
         addr = net_addr(at);
         mpls = net_mpls(at);
 
-        addrcmp_result = addrcmp(
-            (void *) addr, (void *) &ctl->unspec_addr, ctl->af);
+        addrcmp_result = addrcmp(addr, &ctl->unspec_addr, ctl->af);
 
         if (err == 0 && addrcmp_result != 0) {
             name = dns_lookup(ctl, addr);
@@ -433,15 +432,15 @@ static void mtr_curses_hosts(
                 attron(A_BOLD);
 #ifdef HAVE_IPINFO
             if (is_printii(ctl))
-                printw(fmt_ipinfo(ctl, addr));
+                printw("%s", fmt_ipinfo(ctl, addr));
 #endif
             if (name != NULL) {
                 if (ctl->show_ips)
-                    printw("%s (%s)", name, strlongip(ctl, addr));
+                    printw("%s (%s)", name, strlongip(ctl->af, addr));
                 else
                     printw("%s", name);
             } else {
-                printw("%s", strlongip(ctl, addr));
+                printw("%s", strlongip(ctl->af, addr));
             }
             attroff(A_BOLD);
 
@@ -452,7 +451,7 @@ static void mtr_curses_hosts(
             hd_len = 0;
             for (i = 0; i < MAXFLD; i++) {
                 /* Ignore options that don't exist */
-                /* On the other hand, we now check the input side. Shouldn't happen, 
+                /* On the other hand, we now check the input side. Shouldn't happen,
                    can't be careful enough. */
                 j = ctl->fld_index[ctl->fld_active[i]];
                 if (j == -1)
@@ -472,14 +471,12 @@ static void mtr_curses_hosts(
             }
 
             /* Multi path */
-            for (i = 0; i < MAXPATH; i++) {
+            for (i = 0; i < MAX_PATH; i++) {
                 addrs = net_addrs(at, i);
                 mplss = net_mplss(at, i);
-                if (addrcmp((void *) addrs, (void *) addr, ctl->af) == 0)
+                if (addrcmp(addrs, addr, ctl->af) == 0)
                     continue;
-                if (addrcmp
-                    ((void *) addrs, (void *) &ctl->unspec_addr,
-                     ctl->af) == 0)
+                if (addrcmp(addrs, &ctl->unspec_addr,ctl->af) == 0)
                     break;
 
                 name = dns_lookup(ctl, addrs);
@@ -488,15 +485,15 @@ static void mtr_curses_hosts(
                 printw("\n    ");
 #ifdef HAVE_IPINFO
                 if (is_printii(ctl))
-                    printw(fmt_ipinfo(ctl, addrs));
+                    printw("%s", fmt_ipinfo(ctl, addrs));
 #endif
                 if (name != NULL) {
                     if (ctl->show_ips)
-                        printw("%s (%s)", name, strlongip(ctl, addrs));
+                        printw("%s (%s)", name, strlongip(ctl->af, addrs));
                     else
                         printw("%s", name);
                 } else {
-                    printw("%s", strlongip(ctl, addrs));
+                    printw("%s", strlongip(ctl->af, addrs));
                 }
                 for (k = 0; k < mplss->labels && ctl->enablempls; k++) {
                     printw("\n    [MPLS: Lbl %lu TC %u S %u TTL %u]",
@@ -645,7 +642,7 @@ static void mtr_curses_graph(
         }
 
         if (err == 0
-            && addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
+            && addrcmp(addr, &ctl->unspec_addr, ctl->af)) {
 
             if (!net_up(at)) {
                 attron(A_BOLD);
@@ -653,10 +650,10 @@ static void mtr_curses_graph(
 
 #ifdef HAVE_IPINFO
             if (is_printii(ctl))
-                printw(fmt_ipinfo(ctl, addr));
+                printw("%s", fmt_ipinfo(ctl, addr));
 #endif
             name = dns_lookup(ctl, addr);
-            printw("%s", name ? name : strlongip(ctl, addr));
+            printw("%s", name ? name : strlongip(ctl->af, addr));
         } else {
             attron(A_BOLD);
             printw("(%s)", host_error_to_string(err));
@@ -701,9 +698,11 @@ void mtr_curses_redraw(
     pwcenter(buf);
     attroff(A_BOLD);
 
-    mvprintw(1, 0, "%s (%s)", ctl->LocalHostname, net_localaddr());
+    mvprintw(1, 0, "%s (%s) -> %s (%s)",
+	ctl->LocalHostname, net_localaddr(),
+	ctl->Hostname, net_remoteaddr());
     t = time(NULL);
-    mvprintw(1, maxx - 25, iso_time(&t));
+    mvprintw(1, maxx - 25, "%s", iso_time(&t));
     printw("\n");
 
     printw("Keys:  ");
@@ -763,7 +762,7 @@ void mtr_curses_redraw(
         startstat = padding - 2;
 
         snprintf(msg, sizeof(msg), " Last %3d pings", max_cols);
-        mvprintw(rowstat - 1, startstat, msg);
+        mvprintw(rowstat - 1, startstat, "%s", msg);
 
         attroff(A_BOLD);
         move(rowstat, 0);
diff --git a/ui/display.c b/ui/display.c
index 9a8ac60..e457b59 100644
--- a/ui/display.c
+++ b/ui/display.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,
@@ -81,9 +81,11 @@ void display_open(
     case DisplayTXT:
         txt_open();
         break;
+#ifdef HAVE_JANSSON
     case DisplayJSON:
         json_open();
         break;
+#endif
     case DisplayXML:
         xml_open();
         break;
@@ -127,9 +129,11 @@ void display_close(
     case DisplayTXT:
         txt_close(ctl);
         break;
+#ifdef HAVE_JANSSON
     case DisplayJSON:
         json_close(ctl);
         break;
+#endif
     case DisplayXML:
         xml_close(ctl);
         break;
@@ -225,10 +229,11 @@ void display_rawping(
 void display_rawhost(
     struct mtr_ctl *ctl,
     int host,
-    ip_t * ip_addr)
+    ip_t * ip_addr,
+    struct mplslen *mpls)
 {
     if (ctl->DisplayMode == DisplayRaw)
-        raw_rawhost(ctl, host, ip_addr);
+        raw_rawhost(ctl, host, ip_addr, mpls);
 }
 
 
diff --git a/ui/display.h b/ui/display.h
index c577d3f..0c16e90 100644
--- a/ui/display.h
+++ b/ui/display.h
@@ -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,
@@ -18,7 +18,7 @@
 
 #include <netinet/in.h>
 
-/* Don't put a trailing comma in enumeration lists. Some compilers 
+/* Don't put a trailing comma in enumeration lists. Some compilers
    (notably the one on Irix 5.2) do not like that. */
 enum { ActionNone, ActionQuit, ActionReset, ActionDisplay,
     ActionClear, ActionPause, ActionResume, ActionMPLS, ActionDNS,
@@ -41,7 +41,9 @@ enum {
     DisplayXML,
     DisplayCSV,
     DisplayTXT,
-    DisplayJSON
+#ifdef HAVE_JANSSON
+    DisplayJSON,
+#endif
 };
 
 enum {
@@ -74,7 +76,8 @@ extern void display_rawping(
 extern void display_rawhost(
     struct mtr_ctl *ctl,
     int hostnum,
-    ip_t * ip_addr);
+    ip_t *ip_addr,
+    struct mplslen *mpls);
 extern int display_keyaction(
     struct mtr_ctl *ctl);
 extern void display_loop(
diff --git a/ui/dns.c b/ui/dns.c
index 8b323ff..824b401 100644
--- a/ui/dns.c
+++ b/ui/dns.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,
@@ -41,6 +41,7 @@
 #include "dns.h"
 #include "net.h"
 #include "utils.h"
+#include "packet/sockaddr.h"
 
 struct dns_results {
     ip_t ip;
@@ -51,13 +52,13 @@ struct dns_results {
 static struct dns_results *results;
 
 char *strlongip(
-    struct mtr_ctl *ctl,
+    sa_family_t family,
     ip_t * ip)
 {
 #ifdef ENABLE_IPV6
     static char addrstr[INET6_ADDRSTRLEN];
 
-    return (char *) inet_ntop(ctl->af, ip, addrstr, sizeof addrstr);
+    return (char *) inet_ntop(family, ip, addrstr, sizeof addrstr);
 #else
     return inet_ntoa(*ip);
 #endif
@@ -86,18 +87,6 @@ static int longipstr(
 }
 
 
-struct hostent *dns_forward(
-    const char *name)
-{
-    struct hostent *host;
-
-    if ((host = gethostbyname(name)))
-        return host;
-    else
-        return NULL;
-}
-
-
 static struct dns_results *findip(
     struct mtr_ctl *ctl,
     ip_t * ip)
@@ -105,7 +94,7 @@ static struct dns_results *findip(
     struct dns_results *t;
 
     for (t = results; t; t = t->next) {
-        if (addrcmp((void *) ip, (void *) &t->ip, ctl->af) == 0)
+        if (addrcmp(ip, &t->ip, ctl->af) == 0)
             return t;
     }
 
@@ -113,30 +102,17 @@ static struct dns_results *findip(
 }
 
 static void set_sockaddr_ip(
-    struct mtr_ctl *ctl,
+    sa_family_t family,
     struct sockaddr_storage *sa,
     ip_t * ip)
 {
-    struct sockaddr_in *sa_in;
-    struct sockaddr_in6 *sa_in6;
-
     memset(sa, 0, sizeof(struct sockaddr_storage));
-    switch (ctl->af) {
-    case AF_INET:
-        sa_in = (struct sockaddr_in *) sa;
-        sa_in->sin_family = ctl->af;
-        addrcpy((void *) &sa_in->sin_addr, (void *) ip, ctl->af);
-        break;
-    case AF_INET6:
-        sa_in6 = (struct sockaddr_in6 *) sa;
-        sa_in6->sin6_family = ctl->af;
-        addrcpy((void *) &sa_in6->sin6_addr, (void *) ip, ctl->af);
-        break;
-    }
+    sa->ss_family = family;
+    memcpy(sockaddr_addr_offset(sa), ip, sockaddr_addr_size(sa));
 }
 
 void dns_open(
-    struct mtr_ctl *ctl)
+    void)
 {
     int pid;
 
@@ -162,7 +138,7 @@ void dns_open(
             error(EXIT_FAILURE, errno, "signal");
         }
 
-        /* Close all unneccessary FDs.
+        /* Close all unnecessary FDs.
            for debugging and error reporting, keep std-in/out/err. */
         for (i = 3; i < fromdns[1]; i++) {
             if (i == todns[0])
@@ -185,16 +161,17 @@ void dns_open(
 
                 buf[strlen(buf) - 1] = 0;       /* chomp newline. */
 
-                longipstr(buf, &host, ctl->af);
-                set_sockaddr_ip(ctl, &sa, &host);
-                salen = (ctl->af == AF_INET) ? sizeof(struct sockaddr_in) :
+                sa_family_t family = (buf[0] == '4') ? AF_INET : AF_INET6;
+                longipstr(buf +1, &host, family);
+                set_sockaddr_ip(family, &sa, &host);
+                salen = (family == AF_INET) ? sizeof(struct sockaddr_in) :
                     sizeof(struct sockaddr_in6);
 
                 rv = getnameinfo((struct sockaddr *) &sa, salen,
                                  hostname, sizeof(hostname), NULL, 0, 0);
                 if (rv == 0) {
                     snprintf(result, sizeof(result),
-                             "%s %s\n", strlongip(ctl, &host), hostname);
+                             "%s %s\n", strlongip(family, &host), hostname);
 
                     rv = write(fromdns[1], result, strlen(result));
                     if (rv < 0)
@@ -268,7 +245,7 @@ char *dns_lookup2(
     ip_t * ip)
 {
     struct dns_results *r;
-    char buf[INET6_ADDRSTRLEN + 1];
+    char buf[INET6_ADDRSTRLEN + 2]; // af_byte + addr + null
     int rv;
 
     r = findip(ctl, ip);
@@ -276,20 +253,19 @@ char *dns_lookup2(
         /* we've got a result. */
         if (r->name)
             return r->name;
-        else
-            return strlongip(ctl, ip);
     } else {
         r = xmalloc(sizeof(struct dns_results));
         memcpy(&r->ip, ip, sizeof(r->ip));
         r->name = NULL;
         r->next = results;
         results = r;
-        snprintf(buf, sizeof(buf), "%s\n", strlongip(ctl, ip));
+        char ip4or6 = (ctl->af == AF_INET) ? '4' : '6';
+        snprintf(buf, sizeof(buf), "%c%s\n", ip4or6, strlongip(ctl->af, ip));
         rv = write(todns[1], buf, strlen(buf));
         if (rv < 0)
             error(0, errno, "couldn't write to resolver process");
     }
-    return strlongip(ctl, ip);
+    return NULL;
 }
 
 
@@ -302,7 +278,7 @@ char *dns_lookup(
     if (!ctl->dns || !ctl->use_dns)
         return NULL;
     t = dns_lookup2(ctl, ip);
-    return t;
+    return t ? t : strlongip(ctl->af, ip);
 }
 
 /* XXX check if necessary/exported. */
diff --git a/ui/dns.h b/ui/dns.h
index c04d184..52ce1b7 100644
--- a/ui/dns.h
+++ b/ui/dns.h
@@ -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,
@@ -23,7 +23,7 @@
 /*  Prototypes for dns.c  */
 
 extern void dns_open(
-    struct mtr_ctl *ctl);
+    void);
 extern int dns_waitfd(
     void);
 extern void dns_ack(
@@ -41,10 +41,8 @@ extern char *dns_lookup(
 extern char *dns_lookup2(
     struct mtr_ctl *ctl,
     ip_t * address);
-extern struct hostent *dns_forward(
-    const char *name);
 extern char *strlongip(
-    struct mtr_ctl *ctl,
+    sa_family_t family,
     ip_t * ip);
 
 extern void addr2ip6arpa(
diff --git a/ui/gtk.c b/ui/gtk.c
index a978d35..742c5c9 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -4,7 +4,7 @@
     Changes/additions Copyright (C) 1998 R.E.Wolff@BitWizard.nl
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License 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,
@@ -94,7 +94,7 @@ int gtk_detect(
 {
     if (getenv("DISPLAY") != NULL) {
         /* If we do this here, gtk_init exits on an error. This happens
-           BEFORE the user has had a chance to tell us not to use the 
+           BEFORE the user has had a chance to tell us not to use the
            display... */
         return TRUE;
     } else {
@@ -244,11 +244,14 @@ static gint Host_activate(
     gpointer data)
 {
     struct mtr_ctl *ctl = (struct mtr_ctl *) data;
-    struct hostent *addr;
-
-    addr = dns_forward(gtk_entry_get_text(GTK_ENTRY(entry)));
-    if (addr) {
-        net_reopen(ctl, addr);
+    struct addrinfo *res = NULL;
+
+    ctl->af = DEFAULT_AF;  // should this obey the cmd line option?
+    ctl->Hostname = gtk_entry_get_text(GTK_ENTRY(entry));
+    if (get_addrinfo_from_name(ctl, &res, ctl->Hostname) == 0) {
+        net_reopen(ctl, res);
+        freeaddrinfo(res);
+        net_send_batch(ctl);
         /* If we are "Paused" at this point it is usually because someone
            entered a non-existing host. Therefore do the go-ahead... */
         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Pause_Button), 0);
@@ -272,25 +275,25 @@ static void Toolbar_fill(
     GtkWidget *Label;
     GtkAdjustment *Adjustment;
 
-    Button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
+    Button = gtk_button_new_with_label("Quit");
     gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
-    g_signal_connect(GTK_OBJECT(Button), "clicked",
-                     GTK_SIGNAL_FUNC(Window_destroy), NULL);
+    g_signal_connect(G_OBJECT(Button), "clicked",
+                     G_CALLBACK(Window_destroy), NULL);
 
-    Button = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
+    Button = gtk_button_new_with_label("About");
     gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
-    g_signal_connect(GTK_OBJECT(Button), "clicked",
-                     GTK_SIGNAL_FUNC(About_clicked), NULL);
+    g_signal_connect(G_OBJECT(Button), "clicked",
+                     G_CALLBACK(About_clicked), NULL);
 
     Button = gtk_button_new_with_mnemonic("_Restart");
     gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
-    g_signal_connect(GTK_OBJECT(Button), "clicked",
-                     GTK_SIGNAL_FUNC(Restart_clicked), ctl);
+    g_signal_connect(G_OBJECT(Button), "clicked",
+                     G_CALLBACK(Restart_clicked), ctl);
 
     Pause_Button = gtk_toggle_button_new_with_mnemonic("_Pause");
     gtk_box_pack_end(GTK_BOX(Toolbar), Pause_Button, FALSE, FALSE, 0);
-    g_signal_connect(GTK_OBJECT(Pause_Button), "clicked",
-                     GTK_SIGNAL_FUNC(Pause_clicked), ctl);
+    g_signal_connect(G_OBJECT(Pause_Button), "clicked",
+                     G_CALLBACK(Pause_clicked), ctl);
 
     /* allow root only to set zero delay */
     Adjustment = (GtkAdjustment *) gtk_adjustment_new(ctl->WaitTime,
@@ -301,16 +304,16 @@ static void Toolbar_fill(
     gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(Button), TRUE);
     gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
     ctl->gtk_data = Button;
-    g_signal_connect(GTK_OBJECT(Adjustment), "value_changed",
-                     GTK_SIGNAL_FUNC(WaitTime_changed), ctl);
+    g_signal_connect(G_OBJECT(Adjustment), "value_changed",
+                     G_CALLBACK(WaitTime_changed), ctl);
 
     Label = gtk_label_new_with_mnemonic("_Hostname:");
     gtk_box_pack_start(GTK_BOX(Toolbar), Label, FALSE, FALSE, 0);
 
     Entry = gtk_entry_new();
     gtk_entry_set_text(GTK_ENTRY(Entry), ctl->Hostname);
-    g_signal_connect(GTK_OBJECT(Entry), "activate",
-                     GTK_SIGNAL_FUNC(Host_activate), ctl);
+    g_signal_connect(G_OBJECT(Entry), "activate",
+                     G_CALLBACK(Host_activate), ctl);
     gtk_box_pack_start(GTK_BOX(Toolbar), Entry, TRUE, TRUE, 0);
 
     gtk_label_set_mnemonic_widget(GTK_LABEL(Label), Entry);
@@ -394,7 +397,7 @@ static void TreeViewCreate(
     ReportTreeView =
         gtk_tree_view_new_with_model(GTK_TREE_MODEL(ReportStore));
 
-    g_signal_connect(GTK_OBJECT(ReportTreeView), "button_press_event",
+    g_signal_connect(G_OBJECT(ReportTreeView), "button_press_event",
                      G_CALLBACK(ReportTreeView_clicked), ctl);
 
 #ifdef HAVE_IPINFO
@@ -507,15 +510,15 @@ static void update_tree_row(
     char str[256] = "???", *name = str;
 
     addr = net_addr(row);
-    if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
+    if (addrcmp(addr, &ctl->unspec_addr, ctl->af)) {
         if ((name = dns_lookup(ctl, addr))) {
             if (ctl->show_ips) {
                 snprintf(str, sizeof(str), "%s (%s)", name,
-                         strlongip(ctl, addr));
+                         strlongip(ctl->af, addr));
                 name = str;
             }
         } else
-            name = strlongip(ctl, addr);
+            name = strlongip(ctl->af, addr);
     }
 
     gtk_list_store_set(ReportStore, iter,
@@ -564,6 +567,15 @@ void gtk_redraw(
     }
 }
 
+// GTK 3 has changed the interface a bit. Here a few defines so that we can
+// work with GTK2 or GTK3 as required.
+#ifdef HAVE_GTK3
+#define gtk_vbox_new_(orientation,sz) gtk_box_new(orientation, sz)
+#define gtk_hbox_new_(orientation,sz) gtk_box_new(orientation, sz)
+#else
+#define gtk_vbox_new_(orientation,sz) gtk_vbox_new(FALSE, sz)
+#define gtk_hbox_new_(orientation,sz) gtk_hbox_new(FALSE, sz)
+#endif
 
 static void Window_fill(
     struct mtr_ctl *ctl,
@@ -576,9 +588,10 @@ static void Window_fill(
     gtk_window_set_title(GTK_WINDOW(Window), "My traceroute");
     gtk_window_set_default_size(GTK_WINDOW(Window), 650, 400);
     gtk_container_set_border_width(GTK_CONTAINER(Window), 10);
-    VBox = gtk_vbox_new(FALSE, 10);
 
-    Toolbar = gtk_hbox_new(FALSE, 10);
+    VBox    = gtk_vbox_new_(GTK_ORIENTATION_VERTICAL,   10);
+    Toolbar = gtk_hbox_new_(GTK_ORIENTATION_HORIZONTAL, 10);
+
     Toolbar_fill(ctl, Toolbar);
     gtk_box_pack_start(GTK_BOX(VBox), Toolbar, FALSE, FALSE, 0);
 
@@ -619,10 +632,10 @@ void gtk_open(
 
     Window_fill(ctl, main_window);
 
-    g_signal_connect(GTK_OBJECT(main_window), "delete_event",
-                     GTK_SIGNAL_FUNC(Window_destroy), NULL);
-    g_signal_connect(GTK_OBJECT(main_window), "destroy",
-                     GTK_SIGNAL_FUNC(Window_destroy), NULL);
+    g_signal_connect(G_OBJECT(main_window), "delete_event",
+                     G_CALLBACK(Window_destroy), NULL);
+    g_signal_connect(G_OBJECT(main_window), "destroy",
+                     G_CALLBACK(Window_destroy), NULL);
 
     gtk_widget_show_all(main_window);
 }
@@ -801,20 +814,24 @@ static gboolean ReportTreeView_clicked(
     newdestination_item =
         gtk_menu_item_new_with_label("Set as new destination");
 
-    gtk_menu_append(GTK_MENU(popup_menu), copy_item);
-    gtk_menu_append(GTK_MENU(popup_menu), newdestination_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), copy_item);
+    gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), newdestination_item);
 
-    g_signal_connect(GTK_OBJECT(copy_item), "activate",
-                     GTK_SIGNAL_FUNC(Copy_activate), path);
+    g_signal_connect(G_OBJECT(copy_item), "activate",
+                     G_CALLBACK(Copy_activate), path);
 
     ctl->gtk_data = path;
-    g_signal_connect(GTK_OBJECT(newdestination_item), "activate",
-                     GTK_SIGNAL_FUNC(NewDestination_activate), ctl);
+    g_signal_connect(G_OBJECT(newdestination_item), "activate",
+                     G_CALLBACK(NewDestination_activate), ctl);
 
     gtk_widget_show(copy_item);
     gtk_widget_show(newdestination_item);
 
+#ifdef HAVE_GTK3
+    gtk_menu_popup_at_pointer(GTK_MENU(popup_menu), NULL);
+#else
     gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL,
                    0, event->time);
+#endif
     return TRUE;
 }
diff --git a/ui/mtr-curses.h b/ui/mtr-curses.h
index 7bb1975..4f3359f 100644
--- a/ui/mtr-curses.h
+++ b/ui/mtr-curses.h
@@ -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,
diff --git a/ui/mtr-gtk.h b/ui/mtr-gtk.h
index 524de1c..a3691f5 100644
--- a/ui/mtr-gtk.h
+++ b/ui/mtr-gtk.h
@@ -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,
diff --git a/ui/mtr.c b/ui/mtr.c
index a3fef48..2c6fc68 100644
--- a/ui/mtr.c
+++ b/ui/mtr.c
@@ -38,7 +38,6 @@
 #include <sys/limits.h>
 #endif
 
-#include <netdb.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <ctype.h>
@@ -63,13 +62,6 @@
 #include "portability/getopt.h"
 #endif
 
-#ifdef ENABLE_IPV6
-#define DEFAULT_AF AF_UNSPEC
-#else
-#define DEFAULT_AF AF_INET
-#endif
-
-
 char *myname;
 
 const struct fields data_fields[MAXFLD] = {
@@ -150,7 +142,9 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
     fputs(" -w, --report-wide          output wide report\n", out);
     fputs(" -c, --report-cycles COUNT  set the number of pings sent\n",
           out);
+#ifdef HAVE_JANSSON
     fputs(" -j, --json                 output json\n", out);
+#endif
     fputs(" -x, --xml                  output xml\n", out);
     fputs(" -C, --csv                  output comma separated values\n",
           out);
@@ -299,7 +293,7 @@ static void init_fld_options(
 {
     int i;
 
-    memset(ctl->fld_index, -1, FLD_INDEX_SZ);
+    memset(ctl->fld_index, -1, FLD_INDEX_SZ*sizeof(ctl->fld_index[0]));
 
     for (i = 0; data_fields[i].key != 0; i++) {
         ctl->available_options[i] = data_fields[i].key;
@@ -349,7 +343,9 @@ static void parse_arg(
 #endif
         {"raw", 0, NULL, 'l'},
         {"csv", 0, NULL, 'C'},
+#ifdef HAVE_JANSSON
         {"json", 0, NULL, 'j'},
+#endif
         {"displaymode", 1, NULL, OPT_DISPLAYMODE},
         {"split", 0, NULL, 'p'},        /* BL */
         /* maybe above should change to -d 'x' */
@@ -445,9 +441,11 @@ static void parse_arg(
         case 'C':
             ctl->DisplayMode = DisplayCSV;
             break;
+#ifdef HAVE_JANSSON
         case 'j':
             ctl->DisplayMode = DisplayJSON;
             break;
+#endif
         case 'x':
             ctl->DisplayMode = DisplayXML;
             break;
@@ -644,7 +642,9 @@ static void parse_arg(
 
     if (ctl->DisplayMode == DisplayReport ||
         ctl->DisplayMode == DisplayTXT ||
+#ifdef HAVE_JANSSON
         ctl->DisplayMode == DisplayJSON ||
+#endif
         ctl->DisplayMode == DisplayXML ||
         ctl->DisplayMode == DisplayRaw || ctl->DisplayMode == DisplayCSV)
         ctl->Interactive = 0;
@@ -690,31 +690,25 @@ static void init_rand(
     srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
 }
 
-
 /*
     For historical reasons, we need a hostent structure to represent
     our remote target for probing.  The obsolete way of doing this
     would be to use gethostbyname().  We'll use getaddrinfo() instead
     to generate the hostent.
 */
-static int get_hostent_from_name(
+int get_addrinfo_from_name(
     struct mtr_ctl *ctl,
-    struct hostent *host,
-    const char *name,
-    char **alptr)
+    struct addrinfo **res,
+    const char *name)
 {
     int gai_error;
-    struct addrinfo hints, *res;
-    struct sockaddr_in *sa4;
-#ifdef ENABLE_IPV6
-    struct sockaddr_in6 *sa6;
-#endif
+    struct addrinfo hints;
 
     /* gethostbyname2() is deprecated so we'll use getaddrinfo() instead. */
     memset(&hints, 0, sizeof hints);
     hints.ai_family = ctl->af;
     hints.ai_socktype = SOCK_DGRAM;
-    gai_error = getaddrinfo(name, NULL, &hints, &res);
+    gai_error = getaddrinfo(name, NULL, &hints, res);
     if (gai_error) {
         if (gai_error == EAI_SYSTEM)
             error(0, 0, "Failed to resolve host: %s", name);
@@ -725,33 +719,7 @@ static int get_hostent_from_name(
         return -1;
     }
 
-    /* Convert the first addrinfo into a hostent. */
-    memset(host, 0, sizeof(struct hostent));
-    host->h_name = res->ai_canonname;
-    host->h_aliases = NULL;
-    host->h_addrtype = res->ai_family;
-    ctl->af = res->ai_family;
-    host->h_length = res->ai_addrlen;
-    host->h_addr_list = alptr;
-    switch (ctl->af) {
-    case AF_INET:
-        sa4 = (struct sockaddr_in *) res->ai_addr;
-        alptr[0] = (void *) &(sa4->sin_addr);
-        break;
-#ifdef ENABLE_IPV6
-    case AF_INET6:
-        sa6 = (struct sockaddr_in6 *) res->ai_addr;
-        alptr[0] = (void *) &(sa6->sin6_addr);
-        break;
-#endif
-    default:
-        error(0, 0, "unknown address type");
-
-        errno = EINVAL;
-        return -1;
-    }
-    alptr[1] = NULL;
-
+    ctl->af = (*res)->ai_family;
     return 0;
 }
 
@@ -760,9 +728,6 @@ int main(
     int argc,
     char **argv)
 {
-    struct hostent *host = NULL;
-    struct hostent trhost;
-    char *alptr[2];
     names_t *names_head = NULL;
     names_t *names_walk;
 
@@ -831,8 +796,8 @@ int main(
                      sizeof(ctl.LocalHostname));
         }
 
-        host = &trhost;
-        if (get_hostent_from_name(&ctl, host, ctl.Hostname, alptr) != 0) {
+        struct addrinfo *res = NULL;
+        if (get_addrinfo_from_name(&ctl, &res, ctl.Hostname) != 0) {
             if (ctl.Interactive)
                 exit(EXIT_FAILURE);
             else {
@@ -841,7 +806,7 @@ int main(
             }
         }
 
-        if (net_open(&ctl, host) != 0) {
+        if (net_open(&ctl, res) != 0) {
             error(0, 0, "Unable to start net module");
             if (ctl.Interactive)
                 exit(EXIT_FAILURE);
@@ -851,8 +816,10 @@ int main(
             }
         }
 
+        freeaddrinfo(res);
+
         lock(stdout);
-        dns_open(&ctl);
+        dns_open();
         display_open(&ctl);
 
         display_loop(&ctl);
diff --git a/ui/mtr.h b/ui/mtr.h
index ac38016..8be1da9 100644
--- a/ui/mtr.h
+++ b/ui/mtr.h
@@ -4,7 +4,7 @@
     Copyright (C) 2005 R.E.Wolff@BitWizard.nl
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License 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,
@@ -23,6 +23,7 @@
 #include "config.h"
 
 #include <stdint.h>
+#include <netdb.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 
@@ -32,8 +33,10 @@
 
 /* Typedefs */
 #ifdef ENABLE_IPV6
+#define DEFAULT_AF AF_UNSPEC
 typedef struct in6_addr ip_t;
 #else
+#define DEFAULT_AF AF_INET
 typedef struct in_addr ip_t;
 #endif
 
@@ -61,7 +64,7 @@ typedef int time_t;
 
 /* net related definitions */
 #define SAVED_PINGS 200
-#define MAXPATH 8
+#define MAX_PATH 8
 #define MaxHost 256
 #define MinPort 1024
 #define MaxPort 65535
@@ -82,7 +85,7 @@ struct mtr_ctl {
     int MaxPing;
     float WaitTime;
     float GraceTime;
-    char *Hostname;
+    const char *Hostname;
     char *InterfaceName;
     char *InterfaceAddress;
     char LocalHostname[128];
@@ -146,4 +149,9 @@ struct mplslen {
 #define running_as_root() (getuid() == 0)
 #endif
 
+int get_addrinfo_from_name(
+    struct mtr_ctl *ctl,
+    struct addrinfo **res,
+    const char *name);
+
 #endif                          /* MTR_MTR_H */
diff --git a/ui/net.c b/ui/net.c
index 1c78466..efeb782 100644
--- a/ui/net.c
+++ b/ui/net.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,
@@ -39,20 +39,16 @@
 #include "display.h"
 #include "dns.h"
 #include "utils.h"
+#include "packet/sockaddr.h"
 
 #define MinSequence 33000
 #define MaxSequence 65536
 
 static int packetsize;          /* packet size used by ping */
 
-static void sockaddrtop(
-    struct sockaddr *saddr,
-    char *strptr,
-    size_t len);
-
 struct nethost {
-    ip_t addr;
-    ip_t addrs[MAXPATH];        /* for multi paths byMin */
+    ip_t addr;                  /* Latest host to respond */
+    ip_t addrs[MAX_PATH];        /* For Multi paths/Path Changes: List of all hosts that have responded */
     int err;
     int xmit;
     int returned;
@@ -72,7 +68,7 @@ struct nethost {
     int saved[SAVED_PINGS];
     int saved_seq_offset;
     struct mplslen mpls;
-    struct mplslen mplss[MAXPATH];
+    struct mplslen mplss[MAX_PATH];
 };
 
 
@@ -88,42 +84,39 @@ static struct nethost host[MaxHost];
 static struct sequence sequence[MaxSequence];
 static struct packet_command_pipe_t packet_command_pipe;
 
-#ifdef ENABLE_IPV6
 static struct sockaddr_storage sourcesockaddr_struct;
 static struct sockaddr_storage remotesockaddr_struct;
-static struct sockaddr_in6 *ssa6 =
-    (struct sockaddr_in6 *) &sourcesockaddr_struct;
-static struct sockaddr_in6 *rsa6 =
-    (struct sockaddr_in6 *) &remotesockaddr_struct;
-#else
-static struct sockaddr_in sourcesockaddr_struct;
-static struct sockaddr_in remotesockaddr_struct;
-#endif
 
 static struct sockaddr *sourcesockaddr =
     (struct sockaddr *) &sourcesockaddr_struct;
 static struct sockaddr *remotesockaddr =
     (struct sockaddr *) &remotesockaddr_struct;
-static struct sockaddr_in *ssa4 =
-    (struct sockaddr_in *) &sourcesockaddr_struct;
-static struct sockaddr_in *rsa4 =
-    (struct sockaddr_in *) &remotesockaddr_struct;
 
 static ip_t *sourceaddress;
 static ip_t *remoteaddress;
 
 #ifdef ENABLE_IPV6
 static char localaddr[INET6_ADDRSTRLEN];
+static char remoteaddr[INET6_ADDRSTRLEN];
 #else
 #ifndef INET_ADDRSTRLEN
 #define INET_ADDRSTRLEN 16
 #endif
 static char localaddr[INET_ADDRSTRLEN];
+static char remoteaddr[INET_ADDRSTRLEN];
 #endif
 
 static int batch_at = 0;
 static int numhosts = 10;
 
+
+#define host_addr_cmp(index, other, af) \
+    addrcmp((void *) &(host[(index)].addr), (void *) (other), (af))
+
+#define host_addrs_cmp(index, path, other, af) \
+    addrcmp((void *) &(host[(index)].addrs[path]), (void *) (other), (af))
+
+
 /* return the number of microseconds to wait before sending the next
    ping */
 int calc_deltatime(
@@ -184,7 +177,7 @@ static void net_send_query(
     int time_to_live = index + 1;
 
     send_probe_command(ctl, &packet_command_pipe, remoteaddress,
-                       sourceaddress, packetsize, seq, time_to_live);
+                       sourceaddress, packet_size, seq, time_to_live);
 }
 
 
@@ -215,6 +208,7 @@ static int mark_sequence_complete(
 
     Record the round trip time and address of the responding host.
 */
+
 static void net_process_ping(
     struct mtr_ctl *ctl,
     int seq,
@@ -227,99 +221,99 @@ static void net_process_ping(
     int oldavg;                 /* usedByMin */
     int oldjavg;                /* usedByMin */
     int i;                      /* usedByMin */
+    int found = 0;
 #ifdef ENABLE_IPV6
     char addrcopy[sizeof(struct in6_addr)];
 #else
     char addrcopy[sizeof(struct in_addr)];
 #endif
+    struct nethost *nh = NULL;
 
-    addrcpy((void *) &addrcopy, (char *) addr, ctl->af);
+    memcpy(&addrcopy, addr, sockaddr_addr_size(sourcesockaddr));
 
     index = mark_sequence_complete(seq);
     if (index < 0) {
         return;
     }
+    nh = &host[index];
+    nh->err = err;
 
-    host[index].err = err;
 
-    if (addrcmp((void *) &(host[index].addr),
-                (void *) &ctl->unspec_addr, ctl->af) == 0) {
-        /* should be out of if as addr can change */
-        addrcpy((void *) &(host[index].addr), addrcopy, ctl->af);
-        host[index].mpls = *mpls;
-        display_rawhost(ctl, index, (void *) &(host[index].addr));
 
-        /* multi paths */
-        addrcpy((void *) &(host[index].addrs[0]), addrcopy, ctl->af);
-        host[index].mplss[0] = *mpls;
-    } else {
-        for (i = 0; i < MAXPATH;) {
-            if (addrcmp
-                ((void *) &(host[index].addrs[i]), (void *) &addrcopy,
-                 ctl->af) == 0
-                || addrcmp((void *) &(host[index].addrs[i]),
-                           (void *) &ctl->unspec_addr, ctl->af) == 0) {
+    if (addrcmp(&nh->addr, &addrcopy, ctl->af) != 0) {
+        for (i = 0; i < MAX_PATH; i++) {
+            if (addrcmp(&nh->addrs[i], &addrcopy, ctl->af) == 0) {
+                found = 1; /* This host is already in the list */
                 break;
             }
-            i++;
+            if (addrcmp(&nh->addrs[i], &ctl->unspec_addr, ctl->af) == 0) {
+                break; /* Found first vacant position */
+            }
         }
 
-        if (addrcmp((void *) &(host[index].addrs[i]), addrcopy, ctl->af) !=
-            0 && i < MAXPATH) {
-            addrcpy((void *) &(host[index].addrs[i]), addrcopy, ctl->af);
-            host[index].mplss[i] = *mpls;
-            display_rawhost(ctl, index, (void *) &(host[index].addrs[i]));
+        if (found == 0 && i < MAX_PATH) {
+            memcpy(&nh->addrs[i], &addrcopy, sockaddr_addr_size(sourcesockaddr));
+
+            nh->mplss[i] = *mpls;
+            display_rawhost(ctl, index, &nh->addrs[i], mpls);
         }
+
+        /* Always save the latest host in nh->addr. This
+         * allows maxTTL to change whenever path changes.
+         */
+        memcpy(&nh->addr, addrcopy, sockaddr_addr_size(sourcesockaddr));
+        nh->mpls = *mpls;
+        display_rawhost(ctl, index, &nh->addr, mpls);
     }
 
-    host[index].jitter = totusec - host[index].last;
-    if (host[index].jitter < 0) {
-        host[index].jitter = -host[index].jitter;
+    nh->jitter = totusec - nh->last;
+    if (nh->jitter < 0) {
+        nh->jitter = -nh->jitter;
     }
 
-    host[index].last = totusec;
+    nh->last = totusec;
 
-    if (host[index].returned < 1) {
-        host[index].best = host[index].worst = host[index].gmean = totusec;
-        host[index].avg = host[index].ssd = 0;
+    if (nh->returned < 1) {
+        nh->best = nh->worst = nh->gmean = totusec;
+        nh->avg = nh->ssd = 0;
 
-        host[index].jitter = host[index].jworst = host[index].jinta = 0;
+        nh->jitter = nh->jworst = nh->jinta = 0;
     }
 
-    if (totusec < host[index].best) {
-        host[index].best = totusec;
+    if (totusec < nh->best) {
+        nh->best = totusec;
     }
-    if (totusec > host[index].worst) {
-        host[index].worst = totusec;
+    if (totusec > nh->worst) {
+        nh->worst = totusec;
     }
 
-    if (host[index].jitter > host[index].jworst) {
-        host[index].jworst = host[index].jitter;
+    if (nh->jitter > nh->jworst) {
+        nh->jworst = nh->jitter;
     }
 
-    host[index].returned++;
-    oldavg = host[index].avg;
-    host[index].avg += (totusec - oldavg + .0) / host[index].returned;
-    host[index].ssd +=
-        (totusec - oldavg + .0) * (totusec - host[index].avg);
+    nh->returned++;
+    oldavg = nh->avg;
+    nh->avg += (totusec - oldavg + .0) / nh->returned;
+    nh->ssd +=
+        (totusec - oldavg + .0) * (totusec - nh->avg);
 
-    oldjavg = host[index].javg;
-    host[index].javg +=
-        (host[index].jitter - oldjavg) / host[index].returned;
+    oldjavg = nh->javg;
+    nh->javg +=
+        (nh->jitter - oldjavg) / nh->returned;
     /* below algorithm is from rfc1889, A.8 */
-    host[index].jinta +=
-        host[index].jitter - ((host[index].jinta + 8) >> 4);
+    nh->jinta +=
+        nh->jitter - ((nh->jinta + 8) >> 4);
 
-    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);
+    if (nh->returned > 1) {
+        nh->gmean =
+            pow((double) nh->gmean,
+                (nh->returned - 1.0) / nh->returned)
+            * pow((double) totusec, 1.0 / nh->returned);
     }
 
-    host[index].sent = 0;
-    host[index].up = 1;
-    host[index].transit = 0;
+    nh->sent = 0;
+    nh->up = 1;
+    nh->transit = 0;
 
     net_save_return(index, sequence[seq].saved_seq, totusec);
     display_rawping(ctl, index, totusec, seq);
@@ -339,7 +333,7 @@ void net_process_return(
 ip_t *net_addr(
     int at)
 {
-    return (ip_t *) & (host[at].addr);
+    return & (host[at].addr);
 }
 
 
@@ -347,7 +341,7 @@ ip_t *net_addrs(
     int at,
     int i)
 {
-    return (ip_t *) & (host[at].addrs[i]);
+    return & (host[at].addrs[i]);
 }
 
 /*
@@ -359,17 +353,17 @@ int net_err(
     return host[at].err;
 }
 
-void *net_mpls(
+struct mplslen *net_mpls(
     int at)
 {
-    return (struct mplslen *) &(host[at].mplss);
+    return & (host[at].mpls);
 }
 
-void *net_mplss(
+struct mplslen *net_mplss(
     int at,
     int i)
 {
-    return (struct mplslen *) &(host[at].mplss[i]);
+    return & (host[at].mplss[i]);
 }
 
 int net_loss(
@@ -475,8 +469,7 @@ int net_max(
 
     max = 0;
     for (at = 0; at < ctl->maxTTL; at++) {
-        if (addrcmp((void *) &(host[at].addr),
-                    (void *) remoteaddress, ctl->af) == 0) {
+        if (host_addr_cmp(at , remoteaddress, ctl->af) == 0) {
             return at + 1;
         } else if (host[at].err != 0) {
             /*
@@ -485,8 +478,7 @@ int net_max(
                 final hop.
             */
             return at + 1;
-        } else if (addrcmp((void *) &(host[at].addr),
-                           (void *) &ctl->unspec_addr, ctl->af) != 0) {
+        } else if (host_addr_cmp(at, &ctl->unspec_addr, ctl->af) != 0) {
             max = at + 2;
         }
     }
@@ -532,6 +524,13 @@ char *net_localaddr(
 }
 
 
+char *net_remoteaddr(
+    void)
+{
+    return remoteaddr;
+}
+
+
 void net_end_transit(
     void)
 {
@@ -546,19 +545,20 @@ int net_send_batch(
     struct mtr_ctl *ctl)
 {
     int n_unknown = 0, i;
+    int restart = 0;
 
-    /* randomized packet size and/or bit pattern if packetsize<0 and/or 
-       bitpattern<0.  abs(packetsize) and/or abs(bitpattern) will be used 
+    /* randomized packet size and/or bit pattern if packetsize<0 and/or
+       bitpattern<0.  abs(packetsize) and/or abs(bitpattern) will be used
      */
     if (batch_at < ctl->fstTTL) {
         if (ctl->cpacketsize < 0) {
-            /* Someone used a formula here that tried to correct for the 
-               "end-error" in "rand()". By "end-error" I mean that if you 
-               have a range for "rand()" that runs to 32768, and the 
-               destination range is 10000, you end up with 4 out of 32768 
-               0-2768's and only 3 out of 32768 for results 2769 .. 9999. 
-               As our detination range (in the example 10000) is much 
-               smaller (reasonable packet sizes), and our rand() range much 
+            /* Someone used a formula here that tried to correct for the
+               "end-error" in "rand()". By "end-error" I mean that if you
+               have a range for "rand()" that runs to 32768, and the
+               destination range is 10000, you end up with 4 out of 32768
+               0-2768's and only 3 out of 32768 for results 2769 .. 9999.
+               As our destination 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. */
             packetsize =
@@ -575,29 +575,32 @@ int net_send_batch(
     net_send_query(ctl, batch_at, abs(packetsize));
 
     for (i = ctl->fstTTL - 1; i < batch_at; i++) {
-        if (addrcmp
-            ((void *) &(host[i].addr), (void *) &ctl->unspec_addr,
-             ctl->af) == 0)
+        if (host_addr_cmp(i, &ctl->unspec_addr, ctl->af) == 0)
             n_unknown++;
 
-        /* The second condition in the next "if" statement was added in mtr-0.56, 
+        /* The second condition in the next "if" statement was added in mtr-0.56,
            but I don't remember why. It makes mtr stop skipping sections of unknown
-           hosts. Removed in 0.65. 
+           hosts. Removed in 0.65.
            If the line proves necessary, it should at least NOT trigger that line
            when host[i].addr == 0 */
-        if ((addrcmp((void *) &(host[i].addr),
-                     (void *) remoteaddress, ctl->af) == 0))
-            n_unknown = MaxHost;        /* Make sure we drop into "we should restart" */
+        if (host_addr_cmp(i, remoteaddress, ctl->af) == 0) {
+            restart = 1;
+            numhosts = i + 1; /* Saves batch_at - index number of probes in the next round!*/
+            break;
+        }
     }
 
     if (                        /* success in reaching target */
-           (addrcmp((void *) &(host[batch_at].addr),
-                    (void *) remoteaddress, ctl->af) == 0) ||
+           (host_addr_cmp(batch_at, remoteaddress, ctl->af) == 0) ||
            /* fail in consecutive maxUnknown (firewall?) */
            (n_unknown > ctl->maxUnknown) ||
            /* or reach limit  */
            (batch_at >= ctl->maxTTL - 1)) {
+        restart = 1;
         numhosts = batch_at + 1;
+    }
+
+    if (restart) {
         batch_at = ctl->fstTTL - 1;
         return 1;
     }
@@ -644,7 +647,7 @@ static void net_find_interface_address_from_name(
 
     interface = ifaddrs;
     while (interface != NULL) {
-        if (!strcmp(interface->ifa_name, interface_name)) {
+        if (interface->ifa_addr != NULL && !strcmp(interface->ifa_name, interface_name)) {
             found_interface_name = 1;
 
             if (interface->ifa_addr->sa_family == address_family) {
@@ -690,8 +693,6 @@ static void net_find_local_address(
     int udp_socket;
     int addr_length;
     struct sockaddr_storage remote_sockaddr;
-    struct sockaddr_in *remote4;
-    struct sockaddr_in6 *remote6;
 
     udp_socket =
         socket(remotesockaddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
@@ -703,24 +704,12 @@ static void net_find_local_address(
        We need to set the port to a non-zero value for the connect
        to succeed.
      */
-    if (remotesockaddr->sa_family == AF_INET6) {
-#ifdef ENABLE_IPV6
-        addr_length = sizeof(struct sockaddr_in6);
-
-        memcpy(&remote_sockaddr, rsa6, addr_length);
-        remote6 = (struct sockaddr_in6 *) &remote_sockaddr;
-        remote6->sin6_port = htons(1);
-#endif
-    } else {
-        addr_length = sizeof(struct sockaddr_in);
-
-        memcpy(&remote_sockaddr, rsa4, addr_length);
-        remote4 = (struct sockaddr_in *) &remote_sockaddr;
-        remote4->sin_port = htons(1);
-    }
+    addr_length = sockaddr_size(&remotesockaddr_struct);
+    memcpy(&remote_sockaddr, &remotesockaddr_struct, addr_length);
+    *sockaddr_port_offset(&remote_sockaddr) = htons(1);
 
     if (connect
-        (udp_socket, (struct sockaddr *) &remote_sockaddr, addr_length)) {
+        (udp_socket, (struct sockaddr *) &remote_sockaddr, sockaddr_size(&remote_sockaddr))) {
 #ifdef __linux__
         /* Linux doesn't require source address, so we can support
          * a case when mtr is run against unreachable host (that can become
@@ -739,7 +728,7 @@ static void net_find_local_address(
         error(EXIT_FAILURE, errno, "local address determination failed");
     }
 
-    sockaddrtop(sourcesockaddr, localaddr, sizeof(localaddr));
+    inet_ntop(sourcesockaddr->sa_family, sockaddr_addr_offset(sourcesockaddr), localaddr, sizeof(localaddr));
 
     close(udp_socket);
 }
@@ -747,7 +736,7 @@ static void net_find_local_address(
 
 int net_open(
     struct mtr_ctl *ctl,
-    struct hostent *hostent)
+    struct addrinfo *res)
 {
     int err;
 
@@ -757,37 +746,7 @@ int net_open(
         return err;
     }
 
-    net_reset(ctl);
-
-    remotesockaddr->sa_family = hostent->h_addrtype;
-
-    switch (hostent->h_addrtype) {
-    case AF_INET:
-        addrcpy((void *) &(rsa4->sin_addr), hostent->h_addr, AF_INET);
-        sourceaddress = (ip_t *) & (ssa4->sin_addr);
-        remoteaddress = (ip_t *) & (rsa4->sin_addr);
-        break;
-#ifdef ENABLE_IPV6
-    case AF_INET6:
-        addrcpy((void *) &(rsa6->sin6_addr), hostent->h_addr, AF_INET6);
-        sourceaddress = (ip_t *) & (ssa6->sin6_addr);
-        remoteaddress = (ip_t *) & (rsa6->sin6_addr);
-        break;
-#endif
-    default:
-        error(EXIT_FAILURE, 0, "net_open bad address type");
-    }
-
-    if (ctl->InterfaceAddress) {
-        net_validate_interface_address(ctl->af, ctl->InterfaceAddress);
-    } else if (ctl->InterfaceName) {
-        net_find_interface_address_from_name(
-            &sourcesockaddr_struct, ctl->af, ctl->InterfaceName);
-
-        sockaddrtop(sourcesockaddr, localaddr, sizeof(localaddr));
-    } else {
-        net_find_local_address();
-    }
+    net_reopen(ctl, res);
 
     return 0;
 }
@@ -795,7 +754,7 @@ int net_open(
 
 void net_reopen(
     struct mtr_ctl *ctl,
-    struct hostent *addr)
+    struct addrinfo *res)
 {
     int at;
 
@@ -803,24 +762,25 @@ void net_reopen(
         memset(&host[at], 0, sizeof(host[at]));
     }
 
-    remotesockaddr->sa_family = addr->h_addrtype;
-    addrcpy((void *) remoteaddress, addr->h_addr, addr->h_addrtype);
+    net_reset(ctl);
 
-    switch (addr->h_addrtype) {
-    case AF_INET:
-        addrcpy((void *) &(rsa4->sin_addr), addr->h_addr, AF_INET);
-        break;
-#ifdef ENABLE_IPV6
-    case AF_INET6:
-        addrcpy((void *) &(rsa6->sin6_addr), addr->h_addr, AF_INET6);
-        break;
-#endif
-    default:
-        error(EXIT_FAILURE, 0, "net_reopen bad address type");
+    ctl->af = remotesockaddr->sa_family = sourcesockaddr->sa_family = res->ai_family;
+    remoteaddress = sockaddr_addr_offset(remotesockaddr);
+    memcpy(remoteaddress, sockaddr_addr_offset(res->ai_addr), sockaddr_addr_size(remotesockaddr));
+    inet_ntop(remotesockaddr->sa_family, remoteaddress, remoteaddr, sizeof(remoteaddr));
+
+    sourceaddress = sockaddr_addr_offset(sourcesockaddr);
+
+    if (ctl->InterfaceAddress) {
+        net_validate_interface_address(ctl->af, ctl->InterfaceAddress);
+    } else if (ctl->InterfaceName) {
+        net_find_interface_address_from_name(
+            &sourcesockaddr_struct, ctl->af, ctl->InterfaceName);
+        inet_ntop(sourcesockaddr->sa_family, sourceaddress, localaddr, sizeof(localaddr));
+    } else {
+        net_find_local_address();
     }
 
-    net_reset(ctl);
-    net_send_batch(ctl);
 }
 
 
@@ -907,41 +867,10 @@ void net_save_return(
     host[at].saved[idx] = ms;
 }
 
-/* Similar to inet_ntop but uses a sockaddr as it's argument. */
-static void sockaddrtop(
-    struct sockaddr *saddr,
-    char *strptr,
-    size_t len)
-{
-    struct sockaddr_in *sa4;
-#ifdef ENABLE_IPV6
-    struct sockaddr_in6 *sa6;
-#endif
-
-    switch (saddr->sa_family) {
-    case AF_INET:
-        sa4 = (struct sockaddr_in *) saddr;
-        xstrncpy(strptr, inet_ntoa(sa4->sin_addr), len - 1);
-        strptr[len - 1] = '\0';
-        return;
-#ifdef ENABLE_IPV6
-    case AF_INET6:
-        sa6 = (struct sockaddr_in6 *) saddr;
-        inet_ntop(sa6->sin6_family, &(sa6->sin6_addr), strptr, len);
-        return;
-#endif
-    default:
-        error(0, 0, "sockaddrtop unknown address type");
-        strptr[0] = '\0';
-        return;
-    }
-}
-
-
 /* Address comparison. */
 int addrcmp(
-    char *a,
-    char *b,
+    void *a,
+    void *b,
     int family)
 {
     int rc = -1;
@@ -960,25 +889,6 @@ int addrcmp(
     return rc;
 }
 
-/* Address copy. */
-void addrcpy(
-    char *a,
-    char *b,
-    int family)
-{
-
-    switch (family) {
-    case AF_INET:
-        memcpy(a, b, sizeof(struct in_addr));
-        break;
-#ifdef ENABLE_IPV6
-    case AF_INET6:
-        memcpy(a, b, sizeof(struct in6_addr));
-        break;
-#endif
-    }
-}
-
 /* for GTK frontend */
 void net_harvest_fds(
     struct mtr_ctl *ctl)
diff --git a/ui/net.h b/ui/net.h
index 0fb4700..354c998 100644
--- a/ui/net.h
+++ b/ui/net.h
@@ -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,
@@ -33,10 +33,10 @@
 
 extern int net_open(
     struct mtr_ctl *ctl,
-    struct hostent *host);
+    struct addrinfo *res);
 extern void net_reopen(
     struct mtr_ctl *ctl,
-    struct hostent *address);
+    struct addrinfo *res);
 extern void net_reset(
     struct mtr_ctl *ctl);
 extern void net_close(
@@ -58,9 +58,9 @@ extern ip_t *net_addr(
     int at);
 extern int net_err(
     int at);
-extern void *net_mpls(
+extern struct mplslen *net_mpls(
     int at);
-extern void *net_mplss(
+extern struct mplslen *net_mplss(
     int,
     int);
 extern int net_loss(
@@ -90,6 +90,8 @@ extern ip_t *net_addrs(
     int i);
 extern char *net_localaddr(
     void);
+extern char *net_remoteaddr(
+    void);
 
 extern int net_send_batch(
     struct mtr_ctl *ctl);
@@ -117,12 +119,8 @@ extern void net_save_return(
     int ms);
 
 extern int addrcmp(
-    char *a,
-    char *b,
-    int af);
-extern void addrcpy(
-    char *a,
-    char *b,
+    void *a,
+    void *b,
     int af);
 
 extern void net_add_fds(
diff --git a/ui/raw.c b/ui/raw.c
index 429a831..74ed35f 100644
--- a/ui/raw.c
+++ b/ui/raw.c
@@ -5,7 +5,7 @@
     raw.c -- raw output (for logging for later analysis)
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License 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,
@@ -64,12 +64,19 @@ void raw_rawping(
     fflush(stdout);
 }
 
-
 void raw_rawhost(
     struct mtr_ctl *ctl,
     int host,
-    ip_t * ip_addr)
+    ip_t *ip_addr,
+    struct mplslen *mpls)
 {
-    printf("h %d %s\n", host, strlongip(ctl, ip_addr));
+    printf("h %d %s\n", host, strlongip(ctl->af, ip_addr));
+    if (ctl->enablempls) {
+        int k;
+        for (k = 0; k < mpls->labels; k++)
+            printf("m %d %lu %u %u %u\n",
+                   host, mpls->label[k], mpls->tc[k], mpls->s[k], mpls->ttl[k]);
+    }
+
     fflush(stdout);
 }
diff --git a/ui/raw.h b/ui/raw.h
index bd1920c..f3fde96 100644
--- a/ui/raw.h
+++ b/ui/raw.h
@@ -5,7 +5,7 @@
     raw.h -- raw output (for logging for later analysis)
 
     This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License 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,
@@ -30,4 +30,5 @@ extern void raw_rawping(
 extern void raw_rawhost(
     struct mtr_ctl *ctl,
     int host,
-    ip_t * addr);
+    ip_t *addr,
+    struct mplslen *mpls);
diff --git a/ui/report.c b/ui/report.c
index 97a3fa4..a63ed55 100644
--- a/ui/report.c
+++ b/ui/report.c
@@ -26,6 +26,14 @@
 #include <string.h>
 #include <strings.h>
 #include <time.h>
+#ifdef HAVE_JANSSON
+#include <jansson.h>
+#endif
+#ifdef HAVE_ERROR_H
+#include <error.h>
+#else
+#include "portability/error.h"
+#endif
 
 #include "mtr.h"
 #include "report.h"
@@ -35,7 +43,7 @@
 #include "utils.h"
 
 #define MAXLOADBAL 5
-#define MAX_FORMAT_STR 81
+#define MAX_FORMAT_STR 320
 
 
 void report_open(
@@ -57,10 +65,10 @@ static size_t snprint_addr(
         struct hostent *host =
             ctl->dns ? addr2host((void *) addr, ctl->af) : NULL;
         if (!host)
-            return snprintf(dst, dst_len, "%s", strlongip(ctl, addr));
+            return snprintf(dst, dst_len, "%s", strlongip(ctl->af, addr));
         else if (ctl->dns && ctl->show_ips)
             return snprintf(dst, dst_len, "%s (%s)", host->h_name,
-                            strlongip(ctl, addr));
+                            strlongip(ctl->af, addr));
         else
             return snprintf(dst, dst_len, "%s", host->h_name);
     } else
@@ -162,7 +170,7 @@ void report_close(
             if (j < 0)
                 continue;
 
-            /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
+            /* 1000.0 is a temporary hack for stats usec to ms, impacted net_loss. */
             if (strchr(data_fields[j].format, 'f')) {
                 snprintf(buf + len, sizeof(buf), data_fields[j].format,
                          data_fields[j].net_xxx(at) / 1000.0);
@@ -176,15 +184,25 @@ void report_close(
 
         /* 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++) {
+        /* Print list of all hosts that have responded from ttl = at + 1 away */
+        for (z = 0; z < MAX_PATH; z++) {
             int found = 0;
             addr2 = net_addrs(at, z);
             mplss = net_mplss(at, z);
             if ((addrcmp
                  ((void *) &ctl->unspec_addr, (void *) addr2,
-                  ctl->af)) == 0)
+                  ctl->af)) == 0) {
                 break;
+            } else if ((addrcmp
+                        ((void *) addr, (void *) addr2,
+                          ctl->af)) == 0) {
+                continue; /* Latest Host is already printed */
+            } else {
+                snprint_addr(ctl, name, sizeof(name), addr2);
+                snprintf(fmt, sizeof(fmt), "        %%-%zus", len_hosts);
+                snprintf(buf, sizeof(buf), fmt,  name);
+                printf("%s\n", buf);
+            }
             for (w = 0; w < z; w++)
                 /* Ok... checking if there are ips repeated on same hop */
                 if ((addrcmp
@@ -197,14 +215,14 @@ void report_close(
             if (!found) {
 
 #ifdef HAVE_IPINFO
+                if (mpls->labels && z == 1 && ctl->enablempls)
+                    print_mpls(mpls);
                 if (is_printii(ctl)) {
-                    if (mpls->labels && z == 1 && ctl->enablempls)
-                        print_mpls(mpls);
                     snprint_addr(ctl, name, sizeof(name), addr2);
                     printf("     %s%s\n", fmt_ipinfo(ctl, addr2), name);
-                    if (ctl->enablempls)
-                        print_mpls(mplss);
                 }
+                if (ctl->enablempls)
+                    print_mpls(mplss);
 #else
                 int k;
                 if (mpls->labels && z == 1 && ctl->enablempls) {
@@ -217,7 +235,7 @@ void report_close(
                 }
 
                 if (z == 1) {
-                    printf("    |  `|-- %s\n", strlongip(ctl, addr2));
+                    printf("    |  `|-- %s\n", strlongip(ctl->af, addr2));
                     for (k = 0; k < mplss->labels && ctl->enablempls; k++) {
                         printf
                             ("    |   +-- [MPLS: Lbl %lu TC %u S %u TTL %u]\n",
@@ -225,7 +243,7 @@ void report_close(
                              mplss->ttl[k]);
                     }
                 } else {
-                    printf("    |   |-- %s\n", strlongip(ctl, addr2));
+                    printf("    |   |-- %s\n", strlongip(ctl->af, addr2));
                     for (k = 0; k < mplss->labels && ctl->enablempls; k++) {
                         printf
                             ("    |   +-- [MPLS: Lbl %lu TC %u S %u TTL %u]\n",
@@ -269,111 +287,111 @@ void txt_close(
     report_close(ctl);
 }
 
-
+#ifdef HAVE_JANSSON
 void json_open(
     void)
 {
 }
 
-
-void json_close(
-    struct mtr_ctl *ctl)
+void json_close(struct mtr_ctl *ctl)
 {
-    int i, j, at, first, max;
+    int i, j, at, max;
+    int ret;
+    char buf[128];
+    json_t *jreport, *jmtr, *jhubs, *jh;
     ip_t *addr;
     char name[MAX_FORMAT_STR];
 
-    printf("{\n");
-    printf("  \"report\": {\n");
-    printf("    \"mtr\": {\n");
-    printf("      \"src\": \"%s\",\n", ctl->LocalHostname);
-    printf("      \"dst\": \"%s\",\n", ctl->Hostname);
-    printf("      \"tos\": \"0x%X\",\n", ctl->tos);
+    jmtr = json_pack("{ss ss si si}",
+                     "src", ctl->LocalHostname,
+                     "dst", ctl->Hostname,
+                     "tos", ctl->tos,
+                     "tests", ctl->MaxPing);
+    if (!jmtr)
+        goto on_error;
+
     if (ctl->cpacketsize >= 0) {
-        printf("      \"psize\": \"%d\",\n", ctl->cpacketsize);
+        snprintf(buf, sizeof(buf), "%d", ctl->cpacketsize);
     } else {
-        printf("      \"psize\": \"rand(%d-%d)\",\n", MINPACKET,
-               -ctl->cpacketsize);
+        snprintf(buf, sizeof(buf), "rand(%d-%d)", MINPACKET, -ctl->cpacketsize);
     }
+    ret = json_object_set_new(jmtr, "psize", json_string(buf));
+    if (ret == -1)
+        goto on_error;
+
     if (ctl->bitpattern >= 0) {
-        printf("      \"bitpattern\": \"0x%02X\",\n",
-               (unsigned char) (ctl->bitpattern));
+        snprintf(buf, sizeof(buf), "0x%02X", (unsigned char)(ctl->bitpattern));
     } else {
-        printf("      \"bitpattern\": \"rand(0x00-FF)\",\n");
+        snprintf(buf, sizeof(buf), "rand(0x00-FF)");
     }
-    printf("      \"tests\": \"%d\"\n", ctl->MaxPing);
-    printf("    },\n");
 
-    printf("    \"hubs\": [");
+    ret = json_object_set_new(jmtr, "bitpattern", json_string(buf));
+    if (ret == -1)
+        goto on_error;
+
+    jhubs = json_array();
+    if (!jhubs)
+        goto on_error;
 
     max = net_max(ctl);
-    at = first = net_min(ctl);
+    at = net_min(ctl);
     for (; at < max; at++) {
         addr = net_addr(at);
         snprint_addr(ctl, name, sizeof(name), addr);
 
-        if (at == first) {
-            printf("{\n");
-        } else {
-            printf("    {\n");
-        }
-        printf("      \"count\": \"%d\",\n", at + 1);
-        printf("      \"host\": \"%s\",\n", name);
+        jh = json_pack("{si ss}", "count", at + 1, "host", name);
+        if (!jh)
+            goto on_error;
+
 #ifdef HAVE_IPINFO
-        if(!ctl->ipinfo_no) {
-          char* fmtinfo = fmt_ipinfo(ctl, addr);
-          if (fmtinfo != NULL) fmtinfo = trim(fmtinfo, '\0');
-          printf("      \"ASN\": \"%s\",\n", fmtinfo);
+        if (!ctl->ipinfo_no) {
+            char* fmtinfo = fmt_ipinfo(ctl, addr);
+            if (fmtinfo != NULL)
+                fmtinfo = trim(fmtinfo, '\0');
+
+            ret = json_object_set_new(jh, "ASN", json_string(fmtinfo));
+            if (ret == -1)
+                goto on_error;
         }
 #endif
-        for (i = 0; i < MAXFLD; i++) {
-            const char *format;
 
+        for (i = 0; i < MAXFLD; i++) {
             j = ctl->fld_index[ctl->fld_active[i]];
 
-            /* Commas */
-            if (i + 1 == MAXFLD) {
-                printf("\n");
-            } else if (j > 0 && i != 0) {
-                printf(",\n");
-            }
-
             if (j <= 0)
-                continue;       /* Field nr 0, " " shouldn't be printed in this method. */
-
-            /* Format value */
-            format = data_fields[j].format;
-            if (strchr(format, 'f')) {
-                format = "%.2f";
-            } else {
-                format = "%d";
-            }
+                continue; /* Field nr 0, " " shouldn't be printed in this method. */
 
-            /* Format json line */
-            snprintf(name, sizeof(name), "%s%s", "      \"%s\": ", format);
-
-            /* Output json line */
             if (strchr(data_fields[j].format, 'f')) {
-                /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
-                printf(name,
-                       data_fields[j].title,
-                       data_fields[j].net_xxx(at) / 1000.0);
+                ret = json_object_set_new(
+                    jh, data_fields[j].title,
+                    json_real(data_fields[j].net_xxx(at) / 1000.0));
             } else {
-                printf(name,
-                       data_fields[j].title, data_fields[j].net_xxx(at));
+                ret = json_object_set_new(
+                    jh, data_fields[j].title,
+                    json_integer(data_fields[j].net_xxx(at)));
             }
+            if (ret == -1)
+                goto on_error;
         }
-        if (at + 1 == max) {
-            printf("    }");
-        } else {
-            printf("    },\n");
-        }
+
+        ret = json_array_append_new(jhubs, jh);
+        if (ret == -1)
+            goto on_error;
     }
-    printf("]\n");
-    printf("  }\n");
-    printf("}\n");
-}
 
+    jreport = json_pack("{s{so so}}", "report", "mtr", jmtr, "hubs", jhubs);
+
+    ret = json_dumpf(jreport, stdout, JSON_INDENT(4) | JSON_REAL_PRECISION(5));
+    if (ret == -1)
+        goto on_error;
+
+    printf("\n"); // bash prompt should be on new line
+    json_decref(jreport);
+    return;
+on_error:
+    error(EXIT_FAILURE, 0, "json_close failed");
+}
+#endif
 
 
 void xml_open(
@@ -429,7 +447,7 @@ void xml_close(
                 title = "Loss";
             }
 
-            /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
+            /* 1000.0 is a temporary hack for stats usec to ms, impacted net_loss. */
             if (strchr(data_fields[j].format, 'f')) {
                 printf(name,
                        title, data_fields[j].net_xxx(at) / 1000.0, title);
@@ -452,8 +470,9 @@ void csv_close(
     struct mtr_ctl *ctl,
     time_t now)
 {
-    int i, j, at, max;
+    int i, j, at, max, z, w;
     ip_t *addr;
+    ip_t *addr2 = NULL;
     char name[MAX_FORMAT_STR];
 
     for (i = 0; i < MAXFLD; i++) {
@@ -500,7 +519,7 @@ void csv_close(
             if (j < 0)
                 continue;
 
-            /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
+            /* 1000.0 is a temporary hack for stats usec to ms, impacted net_loss. */
             if (strchr(data_fields[j].format, 'f')) {
                 printf(",%.2f",
                        (double) (data_fields[j].net_xxx(at) / 1000.0));
@@ -509,5 +528,61 @@ void csv_close(
             }
         }
         printf("\n");
+        if (ctl->reportwide == 0)
+            continue;
+        
+        for (z = 0; z < MAX_PATH; z++) {
+            int found = 0;
+            addr2 = net_addrs(at, z);
+            snprint_addr(ctl, name, sizeof(name), addr2);
+            if ((addrcmp
+                    ((void *) &ctl->unspec_addr, (void *) addr2,
+                     ctl->af)) == 0) {
+                break;
+            } else if ((addrcmp
+                    ((void *) addr, (void *) addr2,
+                     ctl->af)) == 0) {
+                continue; /* Latest Host is already printed */
+            } else {
+                for (w = 0; w < z; w++)
+                    /* Ok... checking if there are ips repeated on same hop */
+                    if ((addrcmp
+                            ((void *) addr2, (void *) net_addrs(at, w),
+                             ctl->af)) == 0) {
+                        found = 1;
+                        break;
+                    }
+
+                if (!found) {
+#ifdef HAVE_IPINFO
+                    if (!ctl->ipinfo_no) {
+                        char *fmtinfo = fmt_ipinfo(ctl, addr2);
+                        fmtinfo = trim(fmtinfo, '\0');
+                        printf("MTR.%s,%lld,%s,%s,%d,%s,%s", PACKAGE_VERSION,
+                            (long long) now, "OK", ctl->Hostname, at + 1, name,
+                            fmtinfo);
+                    } else
+#endif
+                        printf("MTR.%s,%lld,%s,%s,%d,%s", PACKAGE_VERSION,
+                           (long long) now, "OK", ctl->Hostname, at + 1, name);
+
+                    /* Use values associated with the first ip discovered for this hop */
+                    for (i = 0; i < MAXFLD; i++) {
+                        j = ctl->fld_index[ctl->fld_active[i]];
+                        if (j < 0)
+                            continue;
+
+                        /* 1000.0 is a temporary hack for stats usec to ms, impacted net_loss. */
+                        if (strchr(data_fields[j].format, 'f')) {
+                            printf(",%.2f",
+                                   (double) (data_fields[j].net_xxx(at) / 1000.0));
+                        } else {
+                            printf(",%d", data_fields[j].net_xxx(at));
+                        }
+                    }
+                    printf("\n");
+                }
+            }    
+        }
     }
 }
diff --git a/ui/report.h b/ui/report.h
index 96eb46f..dffc431 100644
--- a/ui/report.h
+++ b/ui/report.h
@@ -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,
diff --git a/ui/select.c b/ui/select.c
index 26748ac..1a9f5c2 100644
--- a/ui/select.c
+++ b/ui/select.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,
diff --git a/ui/select.h b/ui/select.h
index a6b2764..6567b66 100644
--- a/ui/select.h
+++ b/ui/select.h
@@ -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,
diff --git a/ui/split.c b/ui/split.c
index c0f46be..c88b4fe 100644
--- a/ui/split.c
+++ b/ui/split.c
@@ -7,7 +7,7 @@
     Copyright (C) 1998  Bertrand Leconte <B.Leconte@mail.dotcom.fr>
 
     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,
@@ -77,7 +77,7 @@ void split_redraw(
     fprintf(stderr, "split_redraw()\n");
 #endif
 
-    /* 
+    /*
      * If there is less lines than last time, we delete them
      * TEST THIS PLEASE
      */
@@ -92,13 +92,13 @@ void split_redraw(
      */
     for (at = 0; at < max; at++) {
         addr = net_addr(at);
-        if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
+        if (addrcmp(addr, &ctl->unspec_addr, ctl->af)) {
             char str[256], *name;
             if (!(name = dns_lookup(ctl, addr)))
-                name = strlongip(ctl, addr);
+                name = strlongip(ctl->af, addr);
             if (ctl->show_ips) {
                 snprintf(str, sizeof(str), "%s %s", name,
-                         strlongip(ctl, addr));
+                         strlongip(ctl->af, addr));
                 name = str;
             }
             /* May be we should test name's length */
@@ -166,7 +166,7 @@ int split_keyaction(
     tv.tv_usec = 0;
 
     if (select(1, &readfds, NULL, NULL, &tv) > 0) {
-        if (read(0, &c, 1) <= 0) 
+        if (read(0, &c, 1) <= 0)
           return ActionQuit;
     } else
         return 0;
diff --git a/ui/split.h b/ui/split.h
index d6938c7..c2b6094 100644
--- a/ui/split.h
+++ b/ui/split.h
@@ -5,7 +5,7 @@
     Copyright (C) 1998  Bertrand Leconte <B.Leconte@mail.dotcom.fr>
 
     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,
diff --git a/ui/utils.c b/ui/utils.c
index bbdf69d..edd5905 100644
--- a/ui/utils.c
+++ b/ui/utils.c
@@ -176,7 +176,7 @@ void close_stdout(
         _exit(EXIT_FAILURE);
 }
 
-/* ctime() replacement that will reteturn ISO-8601 timestamp string such as:
+/* ctime() replacement that will return ISO-8601 timestamp string such as:
  * 2016-08-29T19:25:02+01:00 */
 const char *iso_time(
     const time_t * t)
