I've done some work on getting openvpn to tunnel ipv6 without having to use TAP tunnels. I think to get ipv6 tunneling to work on other platforms it may require changes in the tunnel driver. But I figure I'll post this here as it might be of use to somebody.
Regards, Aaron Index: Makefile.in =================================================================== RCS file: /cvsroot/openvpn/openvpn/Makefile.in,v retrieving revision 1.6 diff -u -r1.6 Makefile.in --- Makefile.in 25 Jun 2002 06:56:16 -0000 1.6 +++ Makefile.in 27 Sep 2002 22:41:09 -0000 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -74,6 +74,7 @@ INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) transform = @program_transform_name@ @@ -170,6 +171,9 @@ .SUFFIXES: .SUFFIXES: .c .o .obj + +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile @@ -199,7 +203,7 @@ touch $(srcdir)/config.h.in distclean-hdr: - -rm -f config.h + -rm -f config.h stamp-h1 sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @@ -208,8 +212,7 @@ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ - p1=`echo "$$p1" | sed -e 's,^.*/,,'`; \ - f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f; \ else :; fi; \ @@ -218,8 +221,7 @@ uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ - f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ - f=`echo "$$f" | sed -e 's,^.*/,,'`; \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ rm -f $(DESTDIR)$(sbindir)/$$f; \ done @@ -286,6 +288,10 @@ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 8*) ;; \ + *) ext='8' ;; \ + esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ @@ -361,7 +367,7 @@ distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ @@ -459,7 +465,7 @@ clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -469,7 +475,7 @@ clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am - -rm -f config.status config.cache config.log + -rm -f $(am__CONFIG_DISTCLEAN_FILES) distclean-am: clean-am distclean-compile distclean-depend \ distclean-generic distclean-hdr distclean-tags @@ -492,7 +498,8 @@ installcheck-am: maintainer-clean: maintainer-clean-am - + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf autom4te.cache maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am Index: aclocal.m4 =================================================================== RCS file: /cvsroot/openvpn/openvpn/aclocal.m4,v retrieving revision 1.31 diff -u -r1.31 aclocal.m4 --- aclocal.m4 14 Sep 2002 21:54:10 -0000 1.31 +++ aclocal.m4 27 Sep 2002 22:41:11 -0000 @@ -1,4 +1,4 @@ -# aclocal.m4 generated automatically by aclocal 1.6.1 -*- Autoconf -*- +# aclocal.m4 generated automatically by aclocal 1.6.3 -*- Autoconf -*- # Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. @@ -96,7 +96,7 @@ dnl macros posted by AFC to the autoconf macro repository. We are also dnl grateful for the helpful feedback of numerous users. dnl -dnl @version $Id: aclocal.m4,v 1.31 2002/09/14 21:54:10 jimyonan Exp $ +dnl @version $Id: acinclude.m4,v 1.1 2002/05/30 00:04:45 jimyonan Exp $ dnl @author Steven G. Johnson <stev...@alum.mit.edu> and Alejandro Forero Cuervo <bac...@bachue.com> AC_DEFUN([ACX_PTHREAD], [ @@ -490,7 +490,7 @@ # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.6.1])]) + [AM_AUTOMAKE_VERSION([1.6.3])]) # Helper functions for option handling. -*- Autoconf -*- @@ -822,7 +822,7 @@ ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'] + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) @@ -947,7 +947,13 @@ [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` - if (sed 1q $mf | fgrep 'generated by automake') > /dev/null 2>&1; then + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue Index: config.h.in =================================================================== RCS file: /cvsroot/openvpn/openvpn/config.h.in,v retrieving revision 1.6 diff -u -r1.6 config.h.in --- config.h.in 28 Jul 2002 07:54:57 -0000 1.6 +++ config.h.in 27 Sep 2002 22:41:12 -0000 @@ -78,6 +78,9 @@ /* Define to 1 if you have the <netdb.h> header file. */ #undef HAVE_NETDB_H +/* Define to 1 if you have the <netinet/if_ether.h> header file. */ +#undef HAVE_NETINET_IF_ETHER_H + /* Define to 1 if you have the <netinet/in.h> header file. */ #undef HAVE_NETINET_IN_H Index: configure =================================================================== RCS file: /cvsroot/openvpn/openvpn/configure,v retrieving revision 1.37 diff -u -r1.37 configure --- configure 14 Sep 2002 21:54:10 -0000 1.37 +++ configure 27 Sep 2002 22:41:39 -0000 @@ -6759,6 +6759,120 @@ done +for ac_header in netinet/if_ether.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_header in netinet/tcp.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -12646,7 +12760,13 @@ depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` - if (sed 1q $mf | fgrep 'generated by automake') > /dev/null 2>&1; then + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ Index: configure.ac =================================================================== RCS file: /cvsroot/openvpn/openvpn/configure.ac,v retrieving revision 1.37 diff -u -r1.37 configure.ac --- configure.ac 14 Sep 2002 21:54:10 -0000 1.37 +++ configure.ac 27 Sep 2002 22:41:39 -0000 @@ -169,6 +169,7 @@ AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS(netinet/in_systm.h) AC_CHECK_HEADERS(netinet/ip.h) +AC_CHECK_HEADERS(netinet/if_ether.h) AC_CHECK_HEADERS(netinet/tcp.h) AC_CHECK_HEADERS(resolv.h) AC_CHECK_HEADERS(arpa/inet.h) Index: syshead.h =================================================================== RCS file: /cvsroot/openvpn/openvpn/syshead.h,v retrieving revision 1.10 diff -u -r1.10 syshead.h --- syshead.h 28 Jul 2002 07:54:57 -0000 1.10 +++ syshead.h 27 Sep 2002 22:41:40 -0000 @@ -141,8 +141,16 @@ #ifdef TARGET_LINUX +#ifdef HAVE_NETINET_IF_ETHER_H +#include <netinet/if_ether.h> +#endif + #ifdef HAVE_LINUX_IF_TUN_H #include <linux/if_tun.h> +#endif + +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> #endif #endif /* TARGET_LINUX */ Index: tun.c =================================================================== RCS file: /cvsroot/openvpn/openvpn/tun.c,v retrieving revision 1.17 diff -u -r1.17 tun.c --- tun.c 28 Jul 2002 07:54:57 -0000 1.17 +++ tun.c 27 Sep 2002 22:41:41 -0000 @@ -277,7 +277,6 @@ msg (M_ERR, "Cannot open tun/tap dev %s", dev_node); CLEAR (ifr); - ifr.ifr_flags = IFF_NO_PI; if (is_dev_type (dev, dev_type, "tun")) { @@ -339,13 +338,43 @@ int write_tun (struct tuntap* tt, uint8_t *buf, int len) { - return write (tt->fd, buf, len); + struct tun_pi pi; + struct iphdr *iph; + struct iovec vect[2]; + int ret; + + iph = (struct iphdr *)buf; + + pi.flags = 0; + + if(iph->version == 6) + pi.proto = htons(ETH_P_IPV6); + else + pi.proto = htons(ETH_P_IP); + + vect[0].iov_len = sizeof(pi); + vect[0].iov_base = π + vect[1].iov_len = len; + vect[1].iov_base = buf; + + ret = writev(tt->fd, vect, 2); + return(ret - sizeof(pi)); } int read_tun (struct tuntap* tt, uint8_t *buf, int len) { - return read (tt->fd, buf, len); + struct iovec vect[2]; + struct tun_pi pi; + int ret; + + vect[0].iov_len = sizeof(pi); + vect[0].iov_base = π + vect[1].iov_len = len; + vect[1].iov_base = buf; + + ret = readv(tt->fd, vect, 2); + return(ret - sizeof(pi)); } #elif defined(TARGET_SOLARIS)