[Pkg-privacy-commits] [onioncat] 218/340: - configure.ac refined - OC now compiles and runs on Solaris 10 using the Universal TUN/TAP driver version 1.1 (http://vtun.sourceforge.net/tun/index.html) - ocathosts.[ch] added. It reads IPv6 addresses from /etc/hosts - /etc/hosts reverse lookup for I2P .b32 names added

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 13:04:41 UTC 2015


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch debian
in repository onioncat.

commit 90d8c404543bce5e0a3d0e62dd18ccb5d937b5ff
Author: eagle <eagle at 58e1ccc2-750e-0410-8d0d-f93ca75ab447>
Date:   Mon Apr 26 11:29:15 2010 +0000

    - configure.ac refined
    - OC now compiles and runs on Solaris 10 using the Universal TUN/TAP driver
      version 1.1 (http://vtun.sourceforge.net/tun/index.html)
    - ocathosts.[ch] added. It reads IPv6 addresses from /etc/hosts
    - /etc/hosts reverse lookup for I2P .b32 names added
    
    
    
    git-svn-id: http://www.cypherpunk.at/svn/onioncat/trunk@547 58e1ccc2-750e-0410-8d0d-f93ca75ab447
---
 ChangeLog                        |   5 +
 TODO                             |   2 +
 config.h.in                      |  27 ++
 configure                        | 609 +++++++++++++++++++++++++++++++++++++--
 configure.ac                     |  80 ++++-
 src/Makefile.am                  |   4 +-
 src/Makefile.in                  |   7 +-
 src/ocat.c                       |  15 +-
 src/ocat.h                       |  53 +++-
 src/ocat_netdesc.h               |   8 +
 src/ocatcompat.c                 |   2 +
 src/ocateth.c                    |  30 +-
 src/ocatfdbuf.c                  |   5 +-
 src/ocathosts.c                  | 271 +++++++++++++++++
 src/{ocatfdbuf.h => ocathosts.h} |  50 ++--
 src/ocatroute.c                  |  47 ++-
 src/ocatsetup.c                  |  50 +++-
 src/ocatsocks.c                  |  31 +-
 src/ocattun.c                    |  73 ++---
 src/ocatv6conv.c                 |   2 +-
 20 files changed, 1224 insertions(+), 147 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d430407..9395bba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,9 @@
 * version 0.2.2
+ - configure.ac refined
+ - OC now compiles and runs on Solaris 10 using the Universal TUN/TAP driver
+   version 1.1 (http://vtun.sourceforge.net/tun/index.html)
+ - ocathosts.[ch] added. It reads IPv6 addresses from /etc/hosts
+ - /etc/hosts reverse lookup for I2P .b32 names added
  - debian directory included into source package.
  - freebsd directory included into source package.
  - acx_pthread.m4 replaced by newer ax_pthread.m4 for autoconf.
diff --git a/TODO b/TODO
index 05b8b24..6e33b61 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,5 @@
+* Solaris: tunnel device should be unplumbed on program exit
+* Solaris TAP device untestet
 * OpenBSD TAP device might not work (see OpenBSD man page tun(4))
 * finish SOCKS5 code for I2P
 * work on header compression (start at RFC2507 or 3095)
diff --git a/config.h.in b/config.h.in
index cf7ba80..02f79e8 100644
--- a/config.h.in
+++ b/config.h.in
@@ -12,18 +12,27 @@
 /* Define to 1 if you have the <endian.h> header file. */
 #undef HAVE_ENDIAN_H
 
+/* Do we have ether_header.ether_dhost.ether_addr_octet */
+#undef HAVE_ETHER_ADDR_OCTET
+
 /* Define to 1 if you have the `ether_ntoa' function. */
 #undef HAVE_ETHER_NTOA
 
 /* Define to 1 if you have the `ether_ntoa_r' function. */
 #undef HAVE_ETHER_NTOA_R
 
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
 /* Define to 1 if you have the <linux/if_tun.h> header file. */
 #undef HAVE_LINUX_IF_TUN_H
 
 /* Define to 1 if you have the <linux/sockios.h> header file. */
 #undef HAVE_LINUX_SOCKIOS_H
 
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
 /* Define to 1 if you have the <netinet/ether.h> header file. */
 #undef HAVE_NETINET_ETHER_H
 
@@ -63,6 +72,12 @@
 /* Do we have sockaddr_in.sin_len? */
 #undef HAVE_SIN_LEN
 
+/* Do we have stat.st_mtim? */
+#undef HAVE_STAT_ST_MTIM
+
+/* Do we have stat.st_mtimespec? */
+#undef HAVE_STAT_ST_MTIMESPEC
+
 /* Define to 1 if you have the `strlcat' function. */
 #undef HAVE_STRLCAT
 
@@ -81,15 +96,24 @@
 /* Define to 1 if you have the <sys/endian.h> header file. */
 #undef HAVE_SYS_ENDIAN_H
 
+/* Define to 1 if you have the <sys/ethernet.h> header file. */
+#undef HAVE_SYS_ETHERNET_H
+
 /* Define to 1 if you have the <sys/socket.h> header file. */
 #undef HAVE_SYS_SOCKET_H
 
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
 /* Define to 1 if you have the <sys/wait.h> header file. */
 #undef HAVE_SYS_WAIT_H
 
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
 /* enable RTT measurement */
 #undef MEASURE_RTT
 
@@ -127,5 +151,8 @@
 /* Version number of package */
 #undef VERSION
 
+/* exclude tunnel device code */
+#undef WITHOUT_TUN
+
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
diff --git a/configure b/configure
index c243da4..f2c32aa 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.62 for onioncat 0.2.2.r546.
+# Generated by GNU Autoconf 2.62 for onioncat 0.2.2.r547.
 #
 # Report bugs to <rahra at cypherpunk.at>.
 #
@@ -596,8 +596,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='onioncat'
 PACKAGE_TARNAME='onioncat'
-PACKAGE_VERSION='0.2.2.r546'
-PACKAGE_STRING='onioncat 0.2.2.r546'
+PACKAGE_VERSION='0.2.2.r547'
+PACKAGE_STRING='onioncat 0.2.2.r547'
 PACKAGE_BUGREPORT='rahra at cypherpunk.at'
 
 ac_subst_vars='SHELL
@@ -699,6 +699,7 @@ enable_handle_http
 enable_packet_queue
 enable_check_ipsrc
 enable_rtt
+enable_tundev
 enable_dependency_tracking
 '
       ac_precious_vars='build_alias
@@ -1261,7 +1262,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures onioncat 0.2.2.r546 to adapt to many kinds of systems.
+\`configure' configures onioncat 0.2.2.r547 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1331,7 +1332,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of onioncat 0.2.2.r546:";;
+     short | recursive ) echo "Configuration of onioncat 0.2.2.r547:";;
    esac
   cat <<\_ACEOF
 
@@ -1345,6 +1346,7 @@ Optional Features:
   --enable-packet-queue   enable queueuing of packets while connecting setup
   --disable-check-ipsrc   disable source ip checking before forwarding
   --enable-rtt            enable inband RTT measurement
+  --disable-tundev        compile without tunnel device code
   --disable-dependency-tracking  speeds up one-time build
   --enable-dependency-tracking   do not reject slow dependency extractors
 
@@ -1423,7 +1425,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-onioncat configure 0.2.2.r546
+onioncat configure 0.2.2.r547
 generated by GNU Autoconf 2.62
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1437,7 +1439,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by onioncat $as_me 0.2.2.r546, which was
+It was created by onioncat $as_me 0.2.2.r547, which was
 generated by GNU Autoconf 2.62.  Invocation command line was
 
   $ $0 $@
@@ -2086,7 +2088,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='onioncat'
- VERSION='0.2.2.r546'
+ VERSION='0.2.2.r547'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2237,22 +2239,22 @@ ac_config_headers="$ac_config_headers config.h"
 
 
 cat >>confdefs.h <<\_ACEOF
-#define SVN_REVISION "546"
+#define SVN_REVISION "547"
 _ACEOF
 
 
-CFLAGS="-Wall -O2"
-
 
 # Check whether --enable-debug was given.
 if test "${enable_debug+set}" = set; then
   enableval=$enable_debug;
 cat >>confdefs.h <<\_ACEOF
-#define DEBUG /**/
+#define DEBUG 1
 _ACEOF
 
+
 fi
 
+
 # Check whether --enable-packet-log was given.
 if test "${enable_packet_log+set}" = set; then
   enableval=$enable_packet_log;
@@ -2262,6 +2264,7 @@ _ACEOF
 
 fi
 
+
 # Check whether --enable-handle-http was given.
 if test "${enable_handle_http+set}" = set; then
   enableval=$enable_handle_http;
@@ -2271,6 +2274,7 @@ _ACEOF
 
 fi
 
+
 # Check whether --enable-packet-queue was given.
 if test "${enable_packet_queue+set}" = set; then
   enableval=$enable_packet_queue;
@@ -2280,25 +2284,46 @@ _ACEOF
 
 fi
 
+
 # Check whether --enable-check-ipsrc was given.
 if test "${enable_check_ipsrc+set}" = set; then
   enableval=$enable_check_ipsrc;
 cat >>confdefs.h <<\_ACEOF
-#define CHECK_IPSRC /**/
+#define CHECK_IPSRC 1
 _ACEOF
 
 fi
 
+
 # Check whether --enable-rtt was given.
 if test "${enable_rtt+set}" = set; then
   enableval=$enable_rtt;
 cat >>confdefs.h <<\_ACEOF
-#define MEASURE_RTT /**/
+#define MEASURE_RTT 1
 _ACEOF
 
 fi
 
 
+# Check whether --enable-tundev was given.
+if test "${enable_tundev+set}" = set; then
+  enableval=$enable_tundev;
+cat >>confdefs.h <<\_ACEOF
+#define WITHOUT_TUN 1
+_ACEOF
+
+fi
+
+
+
+if test "${enable_debug+set}" = set ; then
+   CFLAGS="-Wall -g -D_POSIX_PTHREAD_SEMANTICS"
+
+else
+   CFLAGS="-Wall -O2 -D_POSIX_PTHREAD_SEMANTICS"
+
+fi
+
 # Checks for programs.
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -4099,6 +4124,181 @@ CC="$PTHREAD_CC"
 #AC_CHECK_LIB([rt], [clock_gettime])
 #AC_CHECK_LIB([readline], [main])
 
+{ $as_echo "$as_me:$LINENO: checking for library containing bind" >&5
+$as_echo_n "checking for library containing bind... " >&6; }
+if test "${ac_cv_search_bind+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char bind ();
+int
+main ()
+{
+return bind ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_search_bind=$ac_res
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_bind+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_bind+set}" = set; then
+  :
+else
+  ac_cv_search_bind=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_bind" >&5
+$as_echo "$ac_cv_search_bind" >&6; }
+ac_res=$ac_cv_search_bind
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:$LINENO: checking for library containing inet_ntop" >&5
+$as_echo_n "checking for library containing inet_ntop... " >&6; }
+if test "${ac_cv_search_inet_ntop+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_ntop ();
+int
+main ()
+{
+return inet_ntop ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_search_inet_ntop=$ac_res
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_inet_ntop+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_inet_ntop+set}" = set; then
+  :
+else
+  ac_cv_search_inet_ntop=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_inet_ntop" >&5
+$as_echo "$ac_cv_search_inet_ntop" >&6; }
+ac_res=$ac_cv_search_inet_ntop
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
 # Checks for header files.
 #AC_HEADER_STDC
 
@@ -4119,7 +4319,12 @@ CC="$PTHREAD_CC"
 
 
 
-for ac_header in sys/types.h sys/wait.h sys/socket.h netinet/in.h netinet/in_systm.h netinet/ip.h netinet/ip6.h netinet/in6.h net/if.h net/if_tun.h linux/if_tun.h linux/sockios.h endian.h sys/endian.h netinet/icmp6.h net/ethernet.h netinet/if_ether.h netinet/ether.h
+
+
+
+
+
+for ac_header in sys/types.h sys/wait.h sys/socket.h sys/stat.h netdb.h netinet/in.h netinet/in_systm.h netinet/ip.h netinet/ip6.h netinet/in6.h net/if.h net/if_tun.h linux/if_tun.h linux/sockios.h endian.h sys/endian.h netinet/icmp6.h net/ethernet.h netinet/if_ether.h netinet/ether.h sys/ethernet.h fcntl.h time.h
 do
 as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
@@ -4716,8 +4921,12 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
+#ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -4763,8 +4972,12 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
+#ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -4822,6 +5035,368 @@ _ACEOF
 fi
 
 
+{ $as_echo "$as_me:$LINENO: checking for struct stat.st_mtim" >&5
+$as_echo_n "checking for struct stat.st_mtim... " >&6; }
+if test "${ac_cv_member_struct_stat_st_mtim+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_mtim)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_mtim=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_mtim)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_mtim=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_member_struct_stat_st_mtim=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_mtim" >&5
+$as_echo "$ac_cv_member_struct_stat_st_mtim" >&6; }
+if test $ac_cv_member_struct_stat_st_mtim = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STAT_ST_MTIM 1
+_ACEOF
+
+else
+
+{ $as_echo "$as_me:$LINENO: checking for struct stat.st_mtimespec" >&5
+$as_echo_n "checking for struct stat.st_mtimespec... " >&6; }
+if test "${ac_cv_member_struct_stat_st_mtimespec+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_mtimespec)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_mtimespec=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+
+int
+main ()
+{
+static struct stat ac_aggr;
+if (sizeof ac_aggr.st_mtimespec)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_stat_st_mtimespec=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_member_struct_stat_st_mtimespec=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_member_struct_stat_st_mtimespec" >&5
+$as_echo "$ac_cv_member_struct_stat_st_mtimespec" >&6; }
+if test $ac_cv_member_struct_stat_st_mtimespec = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STAT_ST_MTIMESPEC 1
+_ACEOF
+
+fi
+
+
+fi
+
+
+{ $as_echo "$as_me:$LINENO: checking for struct ether_header.ether_dhost.ether_addr_octet" >&5
+$as_echo_n "checking for struct ether_header.ether_dhost.ether_addr_octet... " >&6; }
+if test "${ac_cv_member_struct_ether_header_ether_dhost_ether_addr_octet+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ETHERNET_H
+#include <sys/ethernet.h>
+#endif
+
+
+int
+main ()
+{
+static struct ether_header ac_aggr;
+if (ac_aggr.ether_dhost.ether_addr_octet)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_ether_header_ether_dhost_ether_addr_octet=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ETHERNET_H
+#include <sys/ethernet.h>
+#endif
+
+
+int
+main ()
+{
+static struct ether_header ac_aggr;
+if (sizeof ac_aggr.ether_dhost.ether_addr_octet)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_member_struct_ether_header_ether_dhost_ether_addr_octet=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_member_struct_ether_header_ether_dhost_ether_addr_octet=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_member_struct_ether_header_ether_dhost_ether_addr_octet" >&5
+$as_echo "$ac_cv_member_struct_ether_header_ether_dhost_ether_addr_octet" >&6; }
+if test $ac_cv_member_struct_ether_header_ether_dhost_ether_addr_octet = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ETHER_ADDR_OCTET 1
+_ACEOF
+
+fi
+
+
 # Checks for library functions.
 #AC_PROG_GCC_TRADITIONAL
 #AC_FUNC_MALLOC
@@ -5369,7 +5944,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by onioncat $as_me 0.2.2.r546, which was
+This file was extended by onioncat $as_me 0.2.2.r547, which was
 generated by GNU Autoconf 2.62.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -5422,7 +5997,7 @@ Report bugs to <bug-autoconf at gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_version="\\
-onioncat config.status 0.2.2.r546
+onioncat config.status 0.2.2.r547
 configured by $0, generated by GNU Autoconf 2.62,
   with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
diff --git a/configure.ac b/configure.ac
index e6e2d49..0e9065f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,14 +7,35 @@ AC_CONFIG_HEADERS([config.h])
 
 AC_DEFINE(SVN_REVISION, "svnversion", [SVN Revision])
 
-AC_SUBST([CFLAGS], [["-Wall -O2"]])
 
-AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug],[enable debugging]), AC_DEFINE([DEBUG], [], [enable debugging]))
-AC_ARG_ENABLE([packet-log], AS_HELP_STRING([--enable-packet-log],[enable packet logging]), AC_DEFINE([PACKET_LOG], [], [enable packet logging]))
-AC_ARG_ENABLE([handle-http], AS_HELP_STRING([--enable-handle-http],[enable handling of accidental HTTP requests]), AC_DEFINE([HANDLE_HTTP], [], [enable handling of accidental HTTP requests]))
-AC_ARG_ENABLE([packet-queue], AS_HELP_STRING([--enable-packet-queue],[enable queueuing of packets while connecting setup]), AC_DEFINE([PACKET_QUEUE], [], [enable packet queue]))
-AC_ARG_ENABLE([check-ipsrc], AS_HELP_STRING([--disable-check-ipsrc],[disable source ip checking before forwarding]), AC_DEFINE([CHECK_IPSRC], [], [disable source ip checking]))
-AC_ARG_ENABLE([rtt], AS_HELP_STRING([--enable-rtt],[enable inband RTT measurement]), AC_DEFINE([MEASURE_RTT], [], [enable RTT measurement]))
+AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug],[enable debugging]), 
+   AC_DEFINE([DEBUG], [1], [enable debugging])
+   )
+
+AC_ARG_ENABLE([packet-log], AS_HELP_STRING([--enable-packet-log],[enable packet logging]), 
+   AC_DEFINE([PACKET_LOG], [], [enable packet logging]))
+
+AC_ARG_ENABLE([handle-http], AS_HELP_STRING([--enable-handle-http],[enable handling of accidental HTTP requests]),
+   AC_DEFINE([HANDLE_HTTP], [], [enable handling of accidental HTTP requests]))
+
+AC_ARG_ENABLE([packet-queue], AS_HELP_STRING([--enable-packet-queue],[enable queueuing of packets while connecting setup]),
+   AC_DEFINE([PACKET_QUEUE], [], [enable packet queue]))
+
+AC_ARG_ENABLE([check-ipsrc], AS_HELP_STRING([--disable-check-ipsrc],[disable source ip checking before forwarding]),
+   AC_DEFINE([CHECK_IPSRC], [1], [disable source ip checking]))
+
+AC_ARG_ENABLE([rtt], AS_HELP_STRING([--enable-rtt],[enable inband RTT measurement]), 
+   AC_DEFINE([MEASURE_RTT], [1], [enable RTT measurement]))
+
+AC_ARG_ENABLE([tundev], AS_HELP_STRING([--disable-tundev],[compile without tunnel device code]),
+   AC_DEFINE([WITHOUT_TUN], [1], [exclude tunnel device code]))
+
+
+if test "${enable_debug+set}" = set ; then
+   AC_SUBST([CFLAGS], [["-Wall -g -D_POSIX_PTHREAD_SEMANTICS"]])
+else
+   AC_SUBST([CFLAGS], [["-Wall -O2 -D_POSIX_PTHREAD_SEMANTICS"]])
+fi
 
 # Checks for programs.
 AC_PROG_CC
@@ -34,9 +55,12 @@ CC="$PTHREAD_CC"
 #AC_CHECK_LIB([rt], [clock_gettime])
 #AC_CHECK_LIB([readline], [main])
 
+AC_SEARCH_LIBS([bind], [socket])
+AC_SEARCH_LIBS([inet_ntop], [nsl])
+
 # Checks for header files.
 #AC_HEADER_STDC
-AC_CHECK_HEADERS([sys/types.h sys/wait.h sys/socket.h netinet/in.h netinet/in_systm.h netinet/ip.h netinet/ip6.h netinet/in6.h net/if.h net/if_tun.h linux/if_tun.h linux/sockios.h endian.h sys/endian.h netinet/icmp6.h net/ethernet.h netinet/if_ether.h netinet/ether.h], [], [],
+AC_CHECK_HEADERS([sys/types.h sys/wait.h sys/socket.h sys/stat.h netdb.h netinet/in.h netinet/in_systm.h netinet/ip.h netinet/ip6.h netinet/in6.h net/if.h net/if_tun.h linux/if_tun.h linux/sockios.h endian.h sys/endian.h netinet/icmp6.h net/ethernet.h netinet/if_ether.h netinet/ether.h sys/ethernet.h fcntl.h time.h], [], [],
 [[
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -116,13 +140,53 @@ AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
       [ AC_DEFINE(HAVE_SIN_LEN, 1, [Do we have sockaddr_in.sin_len?]) ],
       [],
       [
+#ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
 ])
 
+AC_CHECK_MEMBER([struct stat.st_mtim],
+                [AC_DEFINE(HAVE_STAT_ST_MTIM, 1, [Do we have stat.st_mtim?])],
+                [
+AC_CHECK_MEMBER([struct stat.st_mtimespec],
+                [AC_DEFINE(HAVE_STAT_ST_MTIMESPEC, 1, [Do we have stat.st_mtimespec?])],
+                [],
+                [
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+                 ])
+                 ],
+                [
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+                 ])
+
+AC_CHECK_MEMBER([struct ether_header.ether_dhost.ether_addr_octet],
+                [AC_DEFINE(HAVE_ETHER_ADDR_OCTET, 1, [Do we have ether_header.ether_dhost.ether_addr_octet])],
+                [],
+                [
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_ETHERNET_H
+#include <sys/ethernet.h>
+#endif
+])
+
 # Checks for library functions.
 #AC_PROG_GCC_TRADITIONAL
 #AC_FUNC_MALLOC
diff --git a/src/Makefile.am b/src/Makefile.am
index 7d21e59..2415d07 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
 bin_PROGRAMS = ocat
-ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c ocateth.c ocatsocks.c ocatlibe.c ocatctrl.c ocatipv6route.c ocaticmp.c ocat_wintuntap.c ocat_netdesc.c
-noinst_HEADERS = ocat.h ocat_netdesc.h strlcpy.c strlcat.c
+ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c ocateth.c ocatsocks.c ocatlibe.c ocatctrl.c ocatipv6route.c ocaticmp.c ocat_wintuntap.c ocat_netdesc.c ocathosts.c
+noinst_HEADERS = ocat.h ocat_netdesc.h strlcpy.c strlcat.c ocathosts.h
 AM_CFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\"
 
 install-exec-hook:
diff --git a/src/Makefile.in b/src/Makefile.in
index 427404f..8055335 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -58,7 +58,7 @@ am_ocat_OBJECTS = ocat.$(OBJEXT) ocatlog.$(OBJEXT) ocatroute.$(OBJEXT) \
 	ocatipv4route.$(OBJEXT) ocateth.$(OBJEXT) ocatsocks.$(OBJEXT) \
 	ocatlibe.$(OBJEXT) ocatctrl.$(OBJEXT) ocatipv6route.$(OBJEXT) \
 	ocaticmp.$(OBJEXT) ocat_wintuntap.$(OBJEXT) \
-	ocat_netdesc.$(OBJEXT)
+	ocat_netdesc.$(OBJEXT) ocathosts.$(OBJEXT)
 ocat_OBJECTS = $(am_ocat_OBJECTS)
 ocat_LDADD = $(LDADD)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@@ -163,8 +163,8 @@ sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 sysconfdir = @sysconfdir@
 target_alias = @target_alias@
-ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c ocateth.c ocatsocks.c ocatlibe.c ocatctrl.c ocatipv6route.c ocaticmp.c ocat_wintuntap.c ocat_netdesc.c
-noinst_HEADERS = ocat.h ocat_netdesc.h strlcpy.c strlcat.c
+ocat_SOURCES = ocat.c ocatlog.c ocatroute.c ocatthread.c ocattun.c ocatv6conv.c ocatcompat.c ocatpeer.c ocatsetup.c ocatipv4route.c ocateth.c ocatsocks.c ocatlibe.c ocatctrl.c ocatipv6route.c ocaticmp.c ocat_wintuntap.c ocat_netdesc.c ocathosts.c
+noinst_HEADERS = ocat.h ocat_netdesc.h strlcpy.c strlcat.c ocathosts.h
 AM_CFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\"
 all: all-am
 
@@ -238,6 +238,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatcompat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatctrl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocateth.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocathosts.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocaticmp.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatipv4route.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ocatipv6route.Po at am__quote@
diff --git a/src/ocat.c b/src/ocat.c
index 11fda8e..7578716 100644
--- a/src/ocat.c
+++ b/src/ocat.c
@@ -29,6 +29,7 @@ void usage(const char *s)
          "   -b                    daemonize (default = %d)\n"
          "   -B                    do not daemonize (default = %d)\n"
          "   -h                    display usage message\n"
+         "   -H                    ignore /etc/hosts while in GarliCat mode\n"
          "   -C                    disable local controller interface\n"
          "   -d <n>                set debug level to n, default = %d\n"
          "   -f <config_file>      read config from config_file (default = %s)\n"
@@ -101,7 +102,7 @@ int mk_pid_file(void)
       return -1;
    }
 
-   fprintf(f, "%d\n", getpid());
+   fprintf(f, "%d\n", (int) getpid());
    fclose(f);
    log_debug("pid_file %s created, pid = %d", CNF(pid_file), getpid());
 
@@ -299,7 +300,7 @@ void parse_opt_early(int argc, char *argv_orig[])
    opterr = 0;
    while ((c = getopt(argc, argv, "f:I")) != -1)
    {
-      log_debug("getopt(): c = %c, optind = %d, opterr = %d, optarg = \"%s\"", c, optind, opterr, optarg);
+      log_debug("getopt(): c = %c, optind = %d, opterr = %d, optarg = \"%s\"", c, optind, opterr, SSTR(optarg));
       switch (c)
       {
          case 'f':
@@ -325,9 +326,9 @@ int parse_opt(int argc, char *argv[])
    log_debug("parse_opt_early()");
    opterr = 1;
    optind = 1;
-   while ((c = getopt(argc, argv, "f:IabBCd:hrRiopl:t:T:s:u:4L:P:")) != -1)
+   while ((c = getopt(argc, argv, "f:IabBCd:hHrRiopl:t:T:s:u:4L:P:")) != -1)
    {
-      log_debug("getopt(): c = %c, optind = %d, opterr = %d, optarg = \"%s\"", c, optind, opterr, optarg);
+      log_debug("getopt(): c = %c, optind = %d, opterr = %d, optarg = \"%s\"", c, optind, opterr, SSTR(optarg));
       switch (c)
       {
          // those options are parsed in parse_opt_early()
@@ -363,6 +364,10 @@ int parse_opt(int argc, char *argv[])
             usage(argv[0]);
             exit(1);
 
+         case 'H':
+            CNF(hosts_lookup) = 0;
+            break;
+
          case 'l':
             add_listener(optarg);
             break;
@@ -513,7 +518,7 @@ int main(int argc, char *argv[])
    }
 
    // copy onion-URL from command line
-   log_debug("argv[%d] = \"%s\"", optind, argv[optind]);
+   log_debug("argv[%d] = \"%s\"", optind, SSTR(argv[optind]));
    if (!CNF(rand_addr))
       strncpy(CNF(onion_url), argv[optind], NDESC(name_size));
    // ...or generate a random one
diff --git a/src/ocat.h b/src/ocat.h
index 089868e..29bfe25 100644
--- a/src/ocat.h
+++ b/src/ocat.h
@@ -18,7 +18,9 @@
 #ifndef OCAT_H
 #define OCAT_H
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -55,6 +57,9 @@
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
+#ifdef HAVE_SYS_ETHERNET_H
+#include <sys/ethernet.h>
+#endif
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -103,6 +108,23 @@
 #define ETHERTYPE_IPV6 0x86dd
 #endif
 
+#ifndef ETHER_ADDR_LEN
+#ifdef ETHERADDRL
+#define ETHER_ADDR_LEN ETHERADDRL
+#endif
+#endif
+
+// At least on Solaris the Ethernet addresses are defined as struct containing
+// an array of bytes.  This is different from most other OSes which define the
+// addresses directly as array.
+#ifdef HAVE_ETHER_ADDR_OCTET
+#define ether_dst ether_dhost.ether_addr_octet
+#define ether_src ether_shost.ether_addr_octet
+#else
+#define ether_dst ether_dhost
+#define ether_src ether_shost
+#endif
+
 #define IP6HLEN sizeof(struct ip6_hdr)
 //! Length of an .onion-URL (without ".onion" and '\0')
 #define ONION_URL_LEN 16
@@ -226,6 +248,18 @@
 #define SYSCONFDIR "/etc"
 #endif
 
+// this macro returns a constains string if a buffer points to NULL.
+#define SSTR(x) (x != NULL ? x : "(nil)")
+
+// Solaris and the Windows OpenVPN tunnel driver do not send a 4 byte tunnel
+// header thus we adjust reads and writes.
+#if defined(__sun__) || defined(__CYGWIN__)
+#define BUF_OFF 4
+#else
+#define BUF_OFF 0
+#endif
+
+
 struct OcatSetup
 {
    //! frame header of local OS in network byte order
@@ -305,6 +339,7 @@ struct OcatSetup
    //! pipe filedescriptors for pid deletion process
    int pid_fd[2];
    int sig_usr1, clear_stats;
+   int hosts_lookup;
 };
 
 #ifdef PACKET_QUEUE
@@ -467,14 +502,16 @@ typedef struct OcatCtrlHdr
 
 
 #ifndef WITHOUT_TUN
-#ifdef __FreeBSD__
-#define TUN_DEV "/dev/tun0"
-#elif __OpenBSD__
-#define TUN_DEV "/dev/tun0"
-#else
+#ifdef __sun__
+#define TUN_DEV "/dev/tun"
+#elif __linux__
 #define TUN_DEV "/dev/net/tun"
+#else
+#define TUN_DEV "/dev/tun0"
 #endif
 extern char *tun_dev_;
+#else
+#define TUN_DEV "STDIO"
 #endif
 
 extern pthread_mutex_t thread_mutex_;
@@ -613,7 +650,13 @@ int win_open_tun(char *, int);
 int win_close_tun(void);
 int win_read_tun(char *, int);
 int win_write_tun(const char *, int);
+#define tun_read(x,y,z) win_read_tun(y,z)
+#define tun_write(x,y,z) win_write_tun(y,z)
+#else
+#define tun_read(x,y,z) read(x,y,z)
+#define tun_write(x,y,z) write(x,y,z)
 #endif
 
+
 #endif
 
diff --git a/src/ocat_netdesc.h b/src/ocat_netdesc.h
index 27050ee..59cea41 100644
--- a/src/ocat_netdesc.h
+++ b/src/ocat_netdesc.h
@@ -52,10 +52,18 @@ extern const struct NetDesc netdesc_[2];
 #define TOR_PREFIX {{{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0,0,0,0,0,0,0,0,0,0}}}
 #define TOR_PREFIX_LEN 48
 #if BYTE_ORDER == LITTLE_ENDIAN
+#ifdef __sun__
+#define TOR_PREFIX4 {{{0x0000000a}}}
+#else
 #define TOR_PREFIX4 {0x0000000a}
+#endif
 #define TOR_PREFIX4_MASK 0x000000ff
 #else
+#ifdef __sun__
+#define TOR_PREFIX4 {{{0x0a000000}}}
+#else
 #define TOR_PREFIX4 {0x0a000000}
+#endif
 #define TOR_PREFIX4_MASK 0xff000000
 #endif
 //! internal domain
diff --git a/src/ocatcompat.c b/src/ocatcompat.c
index ebdbfde..2979a15 100644
--- a/src/ocatcompat.c
+++ b/src/ocatcompat.c
@@ -15,7 +15,9 @@
  * along with OnionCat. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef HAVE_CONFIG_H
 #include "config.h"
+#endif
 
 #ifndef HAVE_STRLCAT
 #include "strlcat.c"
diff --git a/src/ocateth.c b/src/ocateth.c
index f6c76f3..2c72137 100644
--- a/src/ocateth.c
+++ b/src/ocateth.c
@@ -252,10 +252,10 @@ int ndp_solicit(const struct in6_addr *src, const struct in6_addr *dst)
    set_tunheader(buf, htonl(CNF(fhd_key[IPV6_KEY])));
 
    // ethernet header
-   ndp6->eth.ether_dhost[0] = 0x33;
-   ndp6->eth.ether_dhost[1] = 0x33;
-   memcpy(&ndp6->eth.ether_dhost[2], ((char*) &mcastd) + 12, 4);
-   memcpy(ndp6->eth.ether_shost, CNF(ocat_hwaddr), ETHER_ADDR_LEN);
+   ndp6->eth.ether_dst[0] = 0x33;
+   ndp6->eth.ether_dst[1] = 0x33;
+   memcpy(&ndp6->eth.ether_dst[2], ((char*) &mcastd) + 12, 4);
+   memcpy(ndp6->eth.ether_src, CNF(ocat_hwaddr), ETHER_ADDR_LEN);
    ndp6->eth.ether_type = htons(ETHERTYPE_IPV6);
 
    // ipv6 header
@@ -275,7 +275,7 @@ int ndp_solicit(const struct in6_addr *src, const struct in6_addr *dst)
    // icmpv6 ndp option
    ohd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
    ohd->nd_opt_len = 1;
-   memcpy(ohd + 1, ndp6->eth.ether_shost, ETHER_ADDR_LEN);
+   memcpy(ohd + 1, ndp6->eth.ether_src, ETHER_ADDR_LEN);
 
    // calculate checksum
    ckb = malloc_ckbuf(&ndp6->ip6.ip6_src, &ndp6->ip6.ip6_dst, ntohs(ndp6->ip6.ip6_plen), IPPROTO_ICMPV6, &ndp6->icmp6);
@@ -310,12 +310,12 @@ int ndp_soladv(char *buf, int rlen)
    char hw[20];
 #endif
 
-   if (ndp6->eth.ether_dhost[0] & 1)
+   if (ndp6->eth.ether_dst[0] & 1)
    {
       // check for right multicast destination on ethernet
-      if (ndp6->eth.ether_dhost[2] != 0xff)
+      if (ndp6->eth.ether_dst[2] != 0xff)
       {
-         log_debug("ethernet multicast destination %s cannot be solicited node address", ether_ntoa_r((struct ether_addr*) ndp6->eth.ether_dhost, hw));
+         log_debug("ethernet multicast destination %s cannot be solicited node address", ether_ntoa_r((struct ether_addr*) ndp6->eth.ether_dst, hw));
          return -1;
       }
 
@@ -354,16 +354,16 @@ int ndp_soladv(char *buf, int rlen)
 
    log_debug("generating response");
    // add source MAC to table
-   if (mac_set(&ndp6->ip6.ip6_src, ndp6->eth.ether_shost) == -1)
-      if (mac_add_entry(ndp6->eth.ether_shost, &ndp6->ip6.ip6_src) == -1)
+   if (mac_set(&ndp6->ip6.ip6_src, ndp6->eth.ether_src) == -1)
+      if (mac_add_entry(ndp6->eth.ether_src, &ndp6->ip6.ip6_src) == -1)
       {
          log_msg(LOG_ERR, "MAC table full");
          return -1;
       }
 
    // set MAC addresses for response
-   memcpy(ndp6->eth.ether_dhost, ndp6->eth.ether_shost, ETHER_ADDR_LEN);
-   memcpy(ndp6->eth.ether_shost, CNF(ocat_hwaddr), ETHER_ADDR_LEN);
+   memcpy(ndp6->eth.ether_dst, ndp6->eth.ether_src, ETHER_ADDR_LEN);
+   memcpy(ndp6->eth.ether_src, CNF(ocat_hwaddr), ETHER_ADDR_LEN);
 
    // init ip6 header
    memcpy(&ndp6->ip6.ip6_dst, &ndp6->ip6.ip6_src, sizeof(struct in6_addr));
@@ -405,8 +405,8 @@ int ndp_recadv(char *buf, int len)
    ndp6_t *ndp6 = (ndp6_t*) (buf + 4);
 
    // add source MAC to table
-   if (mac_set(&ndp6->ip6.ip6_src, ndp6->eth.ether_shost) == -1)
-      if (mac_add_entry(ndp6->eth.ether_shost, &ndp6->ip6.ip6_src) == -1)
+   if (mac_set(&ndp6->ip6.ip6_src, ndp6->eth.ether_src) == -1)
+      if (mac_add_entry(ndp6->eth.ether_src, &ndp6->ip6.ip6_src) == -1)
       {
          log_msg(LOG_ERR, "MAC table full");
          return -1;
@@ -449,7 +449,7 @@ int eth_check(char *buf, int len)
    }
 
    // check ethernet destination
-   if ((ndp6->eth.ether_dhost[0] != 0x33) && (ndp6->eth.ether_dhost[1] != 0x33) && memcmp(ndp6->eth.ether_dhost, CNF(ocat_hwaddr), ETHER_ADDR_LEN))
+   if ((ndp6->eth.ether_dst[0] != 0x33) && (ndp6->eth.ether_dst[1] != 0x33) && memcmp(ndp6->eth.ether_dst, CNF(ocat_hwaddr), ETHER_ADDR_LEN))
    {
       log_debug("unknown destination MAC");
       return E_ETH_ILLDEST;
diff --git a/src/ocatfdbuf.c b/src/ocatfdbuf.c
index a5244dd..7ca3e78 100644
--- a/src/ocatfdbuf.c
+++ b/src/ocatfdbuf.c
@@ -29,8 +29,9 @@
  *  it must be freed again with fdf_free().
  *  @param fd File descriptor if open file.
  *  @param delim Delimiting character.
- *  @return Pointer to fdFile_t structure.
- */
+ *  @return Pointer to fdFile_t structure or NULL in case of error.
+ *          In the latter case errno is set appropriately.
+ **/
 fdFile_t* fdf_init(int fd, char delim)
 {
    fdFile_t *fdf;
diff --git a/src/ocathosts.c b/src/ocathosts.c
new file mode 100644
index 0000000..fc94447
--- /dev/null
+++ b/src/ocathosts.c
@@ -0,0 +1,271 @@
+/* Copyright 2008-2010 Bernhard R. Fischer.
+ *
+ * This file is part of OnionCat.
+ *
+ * OnionCat is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * OnionCat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with OnionCat. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+// For testing compile this file with
+// gcc -DINC_MAIN -Wall -DHAVE_CONFIG_H -I.. -o ocathosts -lpthread ocathosts.c strlcpy.c
+#ifndef INC_MAIN
+#include "ocat.h"
+#else
+#define log_msg(x,y...) fprintf(stderr, ## y),fprintf(stderr, "\n")
+#define log_debug(x...) log_msg(LOG_DEBUG, ## x)
+#endif
+#include "ocathosts.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+
+static struct hosts_info hosts_ = {{0, 0}, -1, NULL, 0, ""};
+static char *path_hosts_ = NULL;
+static pthread_mutex_t hosts_mutex_ = PTHREAD_MUTEX_INITIALIZER;
+
+
+/*! Test if modification time changed.
+ *  @param fd File descriptor of file to test;
+ *  @param ts Pointer to buffer of old timespec.
+ *  @return 0 if nothing changed, -1 on error (i.e. file
+ *          might have changed) and 1 if mtime changed. In the latter case
+ *          ts will be updated.
+ **/
+int hosts_file_modified_r(struct timespec *ts)
+{
+   struct stat st;
+
+   log_debug("checking if file \"%s\" was modified", path_hosts_);
+   if (stat(path_hosts_, &st) == -1)
+   {
+      log_debug("stat on \"%s\" failed: \"%s\"", path_hosts_, strerror(errno));
+      return -1;
+   }
+
+#ifdef HAVE_STAT_ST_MTIM
+   if ((st.st_mtim.tv_sec == ts->tv_sec) && (st.st_mtim.tv_nsec == ts->tv_nsec))
+#elif HAVE_STAT_ST_MTIMESPEC
+   if ((st.st_mtimespec.tv_sec == ts->tv_sec) && (st.st_mtimespec.tv_nsec == ts->tv_nsec))
+#else
+   if (st.st_mtime == ts->tv_sec)
+#endif
+      return 0;
+
+   log_debug("%s modified", path_hosts_);
+#ifdef HAVE_STAT_ST_MTIM
+   *ts = st.st_mtim;
+#elif HAVE_STAT_ST_MTIMESPEC
+   *ts = st.st_mtimespec;
+#else
+   ts.tv_sec = st.st_mtime;
+#endif
+   return 1;
+}
+
+
+int hosts_read(struct hosts_ent **hent)
+{
+   int e, n = 0, c;
+   char buf[HOSTS_LINE_LENGTH + 1], *s;
+   struct addrinfo hints, *res;
+   struct hosts_ent *h;
+   FILE *f;
+
+   if ((f = fopen(path_hosts_, "r")) == NULL)
+   {
+      log_debug("fopen(\"%s\"...) failed: \"%s\"", path_hosts_, strerror(errno));
+      return -1;
+   }
+
+   pthread_mutex_lock(&hosts_mutex_);
+   if (*hent)
+   {
+      free(*hent);
+      *hent = NULL;
+   }
+
+   memset(&hints, 0, sizeof(hints));
+   hints.ai_family = AF_INET6;
+   hints.ai_flags = AI_NUMERICHOST;
+   while (fgets(buf, HOSTS_LINE_LENGTH, f) != NULL)
+   {
+      if ((s = strtok(buf, " \t\r\n")) == NULL)
+         continue;
+
+      // skip comments
+      if (s[0] == '#')
+         continue;
+
+      if ((e = getaddrinfo(s, NULL, &hints, &res)) != 0)
+      {
+         log_debug("getaddrinfo(\"%s\"...) failed: \"%s\"", s, gai_strerror(e));
+         continue;
+      }
+
+      // to be on the safe side check address family
+      if (res->ai_family != AF_INET6)
+      {
+         // this should never happen
+         log_debug("ai_family = %d (!= AF_INET6)", res->ai_family);
+         freeaddrinfo(res);
+         continue;
+      }
+
+      // parse all hostnames behind IPv6 address
+      for (c = 0; (s = strtok(NULL, " \t\r\n")); c++)
+      {
+         // copy hostname if it ends with "${hdom_}"
+         if ((strlen(s) > strlen(hosts_.hdom)) && !strcasecmp(s + (strlen(s) - strlen(hosts_.hdom)), hosts_.hdom))
+         {
+            if ((*hent = realloc(*hent, ++n * sizeof(struct hosts_ent))) == NULL)
+            {
+               log_msg(LOG_ERR, "realloc failed: \"%s\"", strerror(errno));
+               n--;
+               break;
+            }
+
+            h = (*hent) + n - 1;
+            h->addr = ((struct sockaddr_in6*) res->ai_addr)->sin6_addr;
+            strlcpy(h->name, s, NI_MAXHOST);
+            break;
+         }
+      }
+      freeaddrinfo(res);
+   }
+
+   pthread_mutex_unlock(&hosts_mutex_);
+   (void) fclose(f);
+
+   log_debug("found %d valid IPv6 records in %s", n, path_hosts_);
+
+   return n;
+}
+
+
+/*! Open hosts file and read IPv6 records.
+ *  @return -1 on error and 0 on success.
+ */
+int hosts_check(void)
+{
+#ifdef __CYGWIN__
+   static char path_hosts[1024] = {'\0'};
+   char *s;
+#endif
+
+   if (path_hosts_ == NULL)
+   {
+#ifdef __CYGWIN__
+      if ((s = getenv("WINDIR")) != NULL)
+      {
+         snprintf(path_hosts, sizeof(path_hosts), "%s\\system32\\drivers\\etc\\hosts", s);
+         path_hosts_ = path_hosts;
+      }
+#else
+      path_hosts_ = _PATH_HOSTS;
+#endif
+   }
+
+   if (hosts_file_modified_r(&hosts_.hosts_ts))
+      hosts_.hosts_ent_cnt = hosts_read(&hosts_.hosts_ent);
+
+   return 0;
+}
+
+
+/*! Return name for IPv6 address.
+ *  @return 0 on success, -1 on error.
+ **/
+int hosts_get_name(const struct in6_addr *addr, char *buf, int s)
+{
+   int i;
+   struct hosts_ent *h;
+
+   log_debug("looking up name");
+   pthread_mutex_lock(&hosts_mutex_);
+   for (i = hosts_.hosts_ent_cnt - 1, h = hosts_.hosts_ent; i >= 0; i--, h++)
+      if (IN6_ARE_ADDR_EQUAL(addr, &h->addr))
+      {
+         strlcpy(buf, h->name, s);
+         log_debug("name \"%s\" found", buf);
+         break;
+      }
+   pthread_mutex_unlock(&hosts_mutex_);
+
+   if (i < 0)
+      return -1;
+
+   return 0;
+}
+
+
+void hosts_init(const char *dom)
+{
+   hosts_.hdom = dom;
+}
+
+
+#ifdef INC_MAIN
+int main()
+{
+   int i;
+   struct hosts_ent *h;
+   struct in6_addr addr = IN6ADDR_LOOPBACK_INIT;
+   char buf[NI_MAXHOST];
+
+   hosts_init(".b32.i2p");
+   hosts_check();
+
+   h = hosts_.hosts_ent;
+   for (i = 0; i < hosts_.hosts_ent_cnt; i++, h++)
+   {
+      printf("%s\n", h->name);
+   }
+
+   if (!hosts_get_name(&addr, buf, NI_MAXHOST))
+      printf("loopname = \"%s\"\n", buf);
+
+   return 0;
+}
+#endif
+
diff --git a/src/ocatfdbuf.h b/src/ocathosts.h
similarity index 50%
copy from src/ocatfdbuf.h
copy to src/ocathosts.h
index 8b1bdda..20e6323 100644
--- a/src/ocatfdbuf.h
+++ b/src/ocathosts.h
@@ -1,4 +1,4 @@
-/* Copyright 2008-2009 Bernhard R. Fischer.
+/* Copyright 2008-2010 Bernhard R. Fischer.
  *
  * This file is part of OnionCat.
  *
@@ -15,29 +15,43 @@
  * along with OnionCat. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef OCATFDBUF_H
-#define OCATFDBUF_H
+#ifndef OCATHOSTS_H
+#define OCATHOSTS_H
 
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
 
-#define FDBUF_SIZE 2048
 
+#define HOSTS_LINE_LENGTH 1024
 
-typedef struct fdFile
+struct hosts_ent
 {
-   int fd;                 //!< file descriptor
-   char buf[FDBUF_SIZE];   //!< buffer
-   char *wp;               //!< write position
-   char *rp;               //!< read position
-   int len;                //!< readable bytes starting at read position
-   char delim;             //!< delimiting character
-   int eof;                //!< flag is set if EOF
-} fdFile_t;
-
-
-fdFile_t* fdf_init(int, char);
-void fdf_free(fdFile_t *);
-int fdf_read(fdFile_t *, char *, int);
+   struct in6_addr addr;
+   char name[NI_MAXHOST];
+};
 
+struct hosts_info
+{
+   struct timespec hosts_ts;
+   int hosts_fd;
+   struct hosts_ent *hosts_ent;
+   int hosts_ent_cnt;
+   const char *hdom;
+};
+
+int hosts_check(void);
+int hosts_get_name(const struct in6_addr*, char*, int);
+void hosts_init(const char*);
 
 #endif
 
diff --git a/src/ocatroute.c b/src/ocatroute.c
index c347a82..7d00d4f 100644
--- a/src/ocatroute.c
+++ b/src/ocatroute.c
@@ -507,9 +507,9 @@ void *socket_receiver(void *p)
                // write directly on TUN device
                if (!CNF(use_tap))
                {
-                  log_debug("writing to tun %d framesize %d + 4", CNF(tunfd[1]), len);
-                  if (write(CNF(tunfd[1]), peer->tunhdr, len + 4) != (len + 4))
-                     log_msg(LOG_ERR, "could not write %d bytes to tunnel %d", len + 4, CNF(tunfd[1]));
+                  log_debug("writing to tun %d framesize %d + %d", CNF(tunfd[1]), len, 4 - BUF_OFF);
+                  if (tun_write(CNF(tunfd[1]), ((char*) peer->tunhdr) + BUF_OFF, len + 4 - BUF_OFF) != (len + 4 - BUF_OFF))
+                     log_msg(LOG_ERR, "could not write %d bytes to tunnel %d", len + 4 - BUF_OFF, CNF(tunfd[1]));
                }
                // create ethernet header and handle MAC on TAP device
                else if (*peer->tunhdr == CNF(fhd_key[IPV6_KEY]))
@@ -517,8 +517,8 @@ void *socket_receiver(void *p)
                   log_debug("creating ethernet header");
 
                   // FIXME: should differentiate between IPv6 and IP!!
-                  memset(eh->ether_dhost, 0, ETHER_ADDR_LEN);
-                  if (mac_set(&((struct ip6_hdr*)peer->fragbuf)->ip6_dst, eh->ether_dhost) == -1)
+                  memset(eh->ether_dst, 0, ETHER_ADDR_LEN);
+                  if (mac_set(&((struct ip6_hdr*)peer->fragbuf)->ip6_dst, eh->ether_dst) == -1)
                   {
                      log_debug("dest MAC unknown, resolving");
                      ndp_solicit(&((struct ip6_hdr*)peer->fragbuf)->ip6_src, &((struct ip6_hdr*)peer->fragbuf)->ip6_dst);
@@ -527,20 +527,15 @@ void *socket_receiver(void *p)
                   {
                      set_tunheader(buf, *peer->tunhdr);
                      memcpy(buf + 4 + sizeof(struct ether_header), peer->fragbuf, len);
-                     memcpy(eh->ether_shost, CNF(ocat_hwaddr), ETHER_ADDR_LEN);
+                     memcpy(eh->ether_src, CNF(ocat_hwaddr), ETHER_ADDR_LEN);
 
                      if (*peer->tunhdr == CNF(fhd_key[IPV6_KEY]))
                         eh->ether_type = htons(ETHERTYPE_IPV6);
                      else if (*peer->tunhdr == CNF(fhd_key[IPV4_KEY]))
                         eh->ether_type = htons(ETHERTYPE_IP);
 
-#ifdef __CYGWIN__
-                     if (win_write_tun(buf + 4, len + sizeof(struct ether_header)) != (len + sizeof(struct ether_header)))
-                        log_msg(LOG_ERR, "could not write %d bytes to WinTAP", len + sizeof(struct ether_header));
-#else
-                     if (write(CNF(tunfd[1]), buf, len + 4 + sizeof(struct ether_header)) != (len + 4 + sizeof(struct ether_header)))
-                        log_msg(LOG_ERR, "could not write %d bytes to tunnel %d", len + 4 + sizeof(struct ether_header), CNF(tunfd[1]));
-#endif
+                     if (tun_write(CNF(tunfd[1]), buf + BUF_OFF, len + 4 + sizeof(struct ether_header) - BUF_OFF) != (len + 4 + sizeof(struct ether_header) - BUF_OFF))
+                        log_msg(LOG_ERR, "could not write %d bytes to tunnel %d", len + 4 + sizeof(struct ether_header) - BUF_OFF, CNF(tunfd[1]));
                   }
                }
                else
@@ -811,21 +806,12 @@ void packet_forwarder(void)
       if (term_req())
          break;
 
-#ifdef __CYGWIN__
-      log_debug("reading from WinTAP");
-      if ((rlen = win_read_tun(buf + 4, FRAME_SIZE - 4)) == -1)
-      {
-         log_debug("win_read_tun failed. restarting");
-         continue;
-      }
-      rlen += 4;
-#else
 #ifdef __OpenBSD__
       // workaround for OpenBSD userland threads
       fcntl(CNF(tunfd[0]), F_SETFL, fcntl(CNF(tunfd[0]), F_GETFL) & ~O_NONBLOCK);
 #endif
       log_debug("reading from tunfd[0] = %d", CNF(tunfd[0]));
-      if ((rlen = read(CNF(tunfd[0]), buf, FRAME_SIZE)) == -1)
+      if ((rlen = tun_read(CNF(tunfd[0]), buf + BUF_OFF, FRAME_SIZE - BUF_OFF)) == -1)
       {
          rlen = errno;
          log_debug("read from tun %d returned on error: \"%s\"", CNF(tunfd[0]), strerror(rlen));
@@ -849,9 +835,9 @@ void packet_forwarder(void)
          log_debug("restarting");
          continue;
       }
-#endif
+      rlen += BUF_OFF;
 
-      log_debug("received on tunfd %d, framesize %d + 4", CNF(tunfd[0]), rlen - 4);
+      log_debug("received on tunfd %d, framesize %d + %d", CNF(tunfd[0]), rlen - 4, 4 - BUF_OFF);
 
 #ifdef PACKET_LOG
       if ((pktlog != -1) && (write(pktlog, buf, rlen) == -1))
@@ -877,6 +863,17 @@ void packet_forwarder(void)
          memmove(eh, eh + 1, rlen - 4);
       }
 
+#if defined(__sun__) || defined(__CYGWIN__)
+      // Solaris tunnel driver does not send tunnel
+      // header thus we guess and set it manually
+      if ((buf[BUF_OFF] & 0xf0) == 0x60)
+         set_tunheader(buf, CNF(fhd_key[IPV6_KEY]));
+      else if ((buf[BUF_OFF] & 0xf0) == 0x40)
+         set_tunheader(buf, CNF(fhd_key[IPV4_KEY]));
+      else
+         set_tunheader(buf, -1);
+#endif
+
       if (get_tunheader(buf) == CNF(fhd_key[IPV6_KEY]))
       {
          if (((rlen - 4) < IP6HLEN))
diff --git a/src/ocatsetup.c b/src/ocatsetup.c
index a632e8a..0719c47 100644
--- a/src/ocatsetup.c
+++ b/src/ocatsetup.c
@@ -25,15 +25,17 @@
 
 #include "ocat.h"
 #include "ocat_netdesc.h"
+#include "ocathosts.h"
 
 
 static struct sockaddr_in6 socks_dst6_;
 static struct sockaddr_in ctrl_listen_;
 static struct sockaddr_in6 ctrl_listen6_;
 static struct sockaddr *ctrl_listen_ptr_[] = 
-   {(struct sockaddr*) &ctrl_listen_, 
+{
+   (struct sockaddr*) &ctrl_listen_, 
 #ifndef __CYGWIN__
-      (struct sockaddr*) &ctrl_listen6_, 
+   (struct sockaddr*) &ctrl_listen6_, 
 #endif
       NULL};
 static int ctrl_fd_[2] = {-1, -1};
@@ -104,7 +106,7 @@ struct OcatSetup setup_ =
    // oc_listen_fd
    ctrl_fd_,
    // oc_listen_cnt
-#ifdef __CYGWIN__
+#if defined(__CYGWIN__)
    1
 #else
    2
@@ -119,7 +121,9 @@ struct OcatSetup setup_ =
    // pid_fd
    {-1, -1},
    // sig_usr1, clear_stats
-   0, 0
+   0, 0,
+   // hosts_lookup
+   1
 };
 
 
@@ -129,6 +133,7 @@ struct OcatSetup setup_ =
 void init_setup(void)
 {
    struct timeval tv;
+   const uint32_t loop_ = htonl(INADDR_LOOPBACK);
 
    // seeding PRNG rand()
    if (gettimeofday(&tv, NULL) == -1)
@@ -139,16 +144,32 @@ void init_setup(void)
    setup_.uptime = time(NULL);
    memset(&socks_dst6_, 0, sizeof(socks_dst6_));
    setup_.socks_dst->sin_family = AF_INET;
-   setup_.socks_dst->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+   //setup_.socks_dst->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+   memcpy(&setup_.socks_dst->sin_addr, &loop_, sizeof(setup_.socks_dst->sin_addr));
 #ifdef HAVE_SIN_LEN
    setup_.socks_dst->sin_len = SOCKADDR_SIZE(setup_.socks_dst);
 #endif
+
+   memset(&ctrl_listen_, 0, sizeof(ctrl_listen_));
+   memset(&ctrl_listen6_, 0, sizeof(ctrl_listen6_));
+
+   hosts_init(".b32.i2p");
+
+#ifdef __linux__
+   CNF(fhd_key[IPV6_KEY]) = htonl(ETHERTYPE_IPV6);
+   CNF(fhd_key[IPV4_KEY]) = htonl(ETHERTYPE_IP);
+#else
+   CNF(fhd_key[IPV6_KEY]) = htonl(AF_INET6);
+   CNF(fhd_key[IPV4_KEY]) = htonl(AF_INET);
+#endif
 }
 
 
 void post_init_setup(void)
 {
    size_t l;
+   const uint32_t loop_ = htonl(INADDR_LOOPBACK);
+
    setup_.ocat_addr4 = NDESC(prefix4);
    setup_.ocat_addr4_mask = NDESC(addr4_mask);
    setup_.ocat_dest_port = NDESC(vdest_port);
@@ -165,7 +186,8 @@ void post_init_setup(void)
 
    ctrl_listen_.sin_family = AF_INET;
    ctrl_listen_.sin_port = htons(setup_.ocat_ctrl_port);
-   ctrl_listen_.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+   //ctrl_listen_.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+   memcpy(&ctrl_listen_.sin_addr, &loop_, sizeof(ctrl_listen_.sin_addr));
 #ifdef HAVE_SIN_LEN
    ctrl_listen_.sin_len = sizeof(ctrl_listen_);
 #endif
@@ -247,6 +269,8 @@ void print_setup_struct(FILE *f)
          "ctrl_active            = %d\n"
          "pid_fd[2]              = {%d, %d}\n"
          "clear_stats            = %d\n"
+         "ctrl_listen_cnt        = %d\n"
+         "hosts_lookup           = %d\n"
          ,
          IPV4_KEY, ntohl(setup_.fhd_key[IPV4_KEY]), IPV6_KEY, ntohl(setup_.fhd_key[IPV6_KEY]),
          setup_.fhd_key_len,
@@ -273,7 +297,7 @@ void print_setup_struct(FILE *f)
          setup_.use_tap,
          hw,
          setup_.pid_file,
-         setup_.logfn,
+         SSTR(setup_.logfn),
          logf,
          setup_.daemon,
          t / (3600 * 24), t / 3600 % 24, t / 60 % 60,
@@ -283,7 +307,9 @@ void print_setup_struct(FILE *f)
          setup_.net_type, setup_.net_type == NTYPE_TOR ? "NTYPE_TOR" : setup_.net_type == NTYPE_I2P ? "NTYPE_I2P" : "unknown",
          setup_.max_ctrl, setup_.ctrl_active,
          setup_.pid_fd[0], setup_.pid_fd[1],
-         setup_.clear_stats
+         setup_.clear_stats,
+         setup_.ctrl_listen_cnt,
+         setup_.hosts_lookup
          );
 
 #ifdef CONNECT_ROOT_PEERS
@@ -314,6 +340,14 @@ void print_setup_struct(FILE *f)
          log_msg(LOG_WARNING, "could not convert struct sockaddr: \"%s\"", strerror(errno));
       fprintf(f, "oc_listen_fd[%d]        = %d\n", i, CNF(oc_listen_fd)[i]);
    }
+
+   for (i = 0; i < CNF(ctrl_listen_cnt); i++)
+   {
+      if (inet_ntops(ctrl_listen_ptr_[i], &sas))
+         fprintf(f, "ctrl_listen_ptr_[%d]    = %s:%d (0x%04x)\n", i, sas.sstr_addr, ntohs(sas.sstr_port), sas.sstr_family);
+      else
+         log_msg(LOG_WARNING, "could not convert struct sockaddr: \"%s\"", strerror(errno));
+   }
 }
 
 
diff --git a/src/ocatsocks.c b/src/ocatsocks.c
index 3a8f56c..1ff0fc9 100644
--- a/src/ocatsocks.c
+++ b/src/ocatsocks.c
@@ -26,6 +26,7 @@
 
 #include "ocat.h"
 #include "ocat_netdesc.h"
+#include "ocathosts.h"
 
 
 // SOCKS connector queue vars
@@ -36,13 +37,33 @@ static SocksQueue_t *socks_queue_ = NULL;
 
 int socks_send_request(const SocksQueue_t *sq)
 {
-   int len, ret;
-   char buf[SOCKS_BUFLEN], onion[NDESC(name_size)];
+   int len, ret = -1;
+   char buf[SOCKS_BUFLEN], onion[NI_MAXHOST];
    SocksHdr_t *shdr = (SocksHdr_t*) buf;
 
-   ipv6tonion(&sq->addr, onion);
-   strlcat(onion, NDESC(domain), sizeof(onion));
-   log_msg(LOG_INFO, "trying to connect to \"%s\" [%s]", onion, inet_ntop(AF_INET6, &sq->addr, buf, SOCKS_BUFLEN));
+   // Do a hostname lookup if network type is I2P.
+   // This is done in order to be able to retrieve a 256 bit base32 
+   // host from e.g. /etc/hosts.
+   if ((CNF(net_type) == NTYPE_I2P) && CNF(hosts_lookup))
+   {
+      hosts_check();
+      ret = hosts_get_name(&sq->addr, onion, sizeof(onion));
+   }
+
+   // If no hostname was found above or network type is Tor
+   // do usual OnionCat name transformation.
+   if (ret == -1)
+   {
+      ipv6tonion(&sq->addr, onion);
+      strlcat(onion, NDESC(domain), sizeof(onion));
+   }
+
+   if (inet_ntop(AF_INET6, &sq->addr, buf, sizeof(buf)) == NULL)
+   {
+      log_msg(LOG_WARNING, "inet_ntop failed: \"%s\"", strerror(errno));
+      buf[0] = '\0';
+   }
+   log_msg(LOG_INFO, "trying to connect to \"%s\" [%s] on %d", onion, buf, sq->fd);
 
    log_debug("doing SOCKS4a handshake");
    shdr->ver = 4;
diff --git a/src/ocattun.c b/src/ocattun.c
index 6869fcd..509c68b 100644
--- a/src/ocattun.c
+++ b/src/ocattun.c
@@ -22,28 +22,44 @@
  *  @version 2008/02/03-01
  */
 
-#ifndef WITHOUT_TUN
 
 
 #include "ocat.h"
 #include "ocat_netdesc.h"
 
+#ifndef WITHOUT_TUN
 
 char *tun_dev_ = TUN_DEV;
 
 #define IFCBUF 1024
 
+
+void system_w(const char *s)
+{
+   int e;
+
+   log_debug("running command \"%s\"", s);
+   if ((e = system(s)) == -1)
+      log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", s, strerror(errno));
+   log_debug("exit status = %d", WEXITSTATUS(e));
+}
+
+
 int tun_alloc(char *dev, int dev_s, struct in6_addr addr)
 {
 #ifdef __linux__
    struct ifreq ifr;
 #endif
+#ifdef __sun__
+   int ppa = -1;
+#endif
    int fd;
    char astr[INET6_ADDRSTRLEN];
    char astr4[INET_ADDRSTRLEN];
    char buf[IFCBUF];
-   struct in_addr netmask = {CNF(ocat_addr4_mask)};
+   struct in_addr netmask;// = {CNF(ocat_addr4_mask)};
 
+   memcpy(&netmask, &CNF(ocat_addr4_mask), sizeof(netmask));
    inet_ntop(AF_INET6, &addr, astr, INET6_ADDRSTRLEN);
    inet_ntop(AF_INET, &CNF(ocat_addr4), astr4, INET_ADDRSTRLEN);
 
@@ -57,14 +73,10 @@ int tun_alloc(char *dev, int dev_s, struct in6_addr addr)
       // 183    // % netsh interface ipv6 add route  fd87:d87e:eb43::/48 "LAN-Verbindung 2"
 
    snprintf(buf, sizeof(buf), "netsh interface ipv6 add address \"%s\" %s", dev, astr);
-   log_debug("setting IP on tun: \"%s\"", buf);
-   if (system(buf) == -1)
-      log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+   system_w(buf);
 
    snprintf(buf, sizeof(buf), "netsh interface ipv6 add route %s/%d \"%s\"", astr, NDESC(prefix_len), dev);
-   log_debug("setting IP routing: \"%s\"", buf);
-   if (system(buf) == -1)
-      log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+   system_w(buf);
 
    return 0;
 #endif
@@ -93,9 +105,7 @@ int tun_alloc(char *dev, int dev_s, struct in6_addr addr)
    if (!CNF(use_tap))
    {
       snprintf(buf, sizeof(buf), "ifconfig %s add %s/%d up", dev, astr, NDESC(prefix_len));
-      log_msg(LOG_INFO, "configuring tun IP: \"%s\"", buf);
-      if (system(buf) == -1)
-         log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+      system_w(buf);
    }
 
    // according to drivers/net/tun.c only IFF_MULTICAST and IFF_PROMISC are supported.
@@ -104,16 +114,8 @@ int tun_alloc(char *dev, int dev_s, struct in6_addr addr)
       log_msg(LOG_ERR, "could not set interface flags: \"%s\"", strerror(errno));
       */
 
-   // set tun frame header to ethertype IPv6
-   CNF(fhd_key[IPV6_KEY]) = htonl(ETHERTYPE_IPV6);
-   CNF(fhd_key[IPV4_KEY]) = htonl(ETHERTYPE_IP);
-
 #else
 
-   // set tun frame header to address family AF_INET6 (FreeBSD = 0x1c, OpenBSD = 0x18)
-   CNF(fhd_key[IPV6_KEY]) = htonl(AF_INET6);
-   CNF(fhd_key[IPV4_KEY]) = htonl(AF_INET);
-
    // get interface name
    if (!CNF(use_tap))
    {
@@ -165,27 +167,36 @@ int tun_alloc(char *dev, int dev_s, struct in6_addr addr)
 
 #endif /* __linux__ */
 
+#ifdef __sun__
+   if( (ppa = ioctl(fd, TUNNEWPPA, ppa)) == -1)
+      log_msg(LOG_ERR, "Can't assign new interface");
+   else
+      snprintf(dev, dev_s, "%s%d", dev, ppa);
+
+#endif
 
    if (!CNF(use_tap))
    {
 #ifdef __OpenBSD__
       snprintf(buf, sizeof(buf), "ifconfig %s inet6 %s prefixlen %d up", dev, astr, NDESC(prefix_len));
+#elif __sun__
+      snprintf(buf, sizeof(buf), "ifconfig %s inet6 plumb %s/%d %s up", dev, astr, NDESC(prefix_len), astr);
 #else
       snprintf(buf, sizeof(buf), "ifconfig %s inet6 %s/%d up", dev, astr, NDESC(prefix_len));
 #endif
-      log_debug("setting IP on tun: \"%s\"", buf);
-      if (system(buf) == -1)
-         log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+      system_w(buf);
 
+      // some OSes require routes to be set manually
 #ifdef __APPLE__
-
       // MacOSX requires the route to be set up manually
       // FIXME: the prefix shouldn't be hardcoded here
       snprintf(buf, sizeof(buf), "route add -inet6 -net fd87:d87e:eb43:: -prefixlen %d -gateway %s", NDESC(prefix_len), astr);
-      log_msg(LOG_INFO, "setup routing: \"%s\"", buf);
-      if (system(buf) == -1)
-         log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
- 
+      system_w(buf);
+#elif __sun__
+      // Solaris requires the route to be set up manually
+      // FIXME: the prefix shouldn't be hardcoded here
+      snprintf(buf, sizeof(buf), "route add -inet6 fd87:d87e:eb43::/%d %s -iface", NDESC(prefix_len), astr);
+      system_w(buf);
 #endif
 
    }
@@ -196,18 +207,14 @@ int tun_alloc(char *dev, int dev_s, struct in6_addr addr)
    if (CNF(ipv4_enable) && !CNF(use_tap))
    {
       snprintf(buf, sizeof(buf), "ifconfig %s %s netmask %s", dev, astr4, inet_ntoa(netmask));
-      log_msg(LOG_INFO, "configuring tun IP: \"%s\"", buf);
-      if (system(buf) == -1)
-         log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+      system_w(buf);
    }
 
    // bring up tap device
    if (CNF(use_tap))
    {
       snprintf(buf, sizeof(buf), "ifconfig %s up", dev);
-      log_msg(LOG_INFO, "bringing up TAP device \"%s\"", buf);
-      if (system(buf) == -1)
-         log_msg(LOG_ERR, "could not exec \"%s\": \"%s\"", buf, strerror(errno));
+      system_w(buf);
    }
 
    return fd;
diff --git a/src/ocatv6conv.c b/src/ocatv6conv.c
index b31dc24..df09f0e 100644
--- a/src/ocatv6conv.c
+++ b/src/ocatv6conv.c
@@ -80,7 +80,7 @@ int oniontipv6(const char *onion, struct in6_addr *ip6)
    for (i = 0; i < 16; i++)
    {
       shl5((char*) ip6);
-      j = toupper(onion[i]);
+      j = toupper((int) onion[i]);
       if ((j < '2') || (j > 'Z'))
          return -1;
       if ((j = deBASE32_[j - '2']) == -1)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/onioncat.git



More information about the Pkg-privacy-commits mailing list