Aaron,

Thanks for the patch, however I was not able to get it to work with IPv4 while 
talking between a 2.4.9 and 2.4.17 kernel, where both peers are running the 
patch.  The code compiles and runs, but pings don't go through.  Perhaps there 
is a minimum kernel version necessary for this to work?  Does the kernel need 
to be built with IPv6 support in order for this code to work with IPv4?

There is also the issue of breaking protocol compatibility by adding the 
ETH_P_IPV6/ETH_P_IP to the IP-over-tun packet encoding.  I would propose that:

(1) We run-time conditionalize your patch on a --tun-ipv6 option.

(2) We compile-time (e.g. #ifdef bracket on HAVE_NETINET_IF_ETHER_H, 
ETH_P_IPV6, etc.) and/or run-time conditionalize so that usage of --tun-ipv6 
produces a run-time error if ipv6 over tun is not supported.

(3) We add --tun-ipv6 enabled/disabled state to the options_string function in 
options.h as a sanity check between peers.

(4) We think about how to make --tun-ipv6 portable across the platforms which 
OpenVPN supports.  This may be better addressed at the tun driver level, to 
reduce the machine-specific ugliness in tun.c?

(5) We look into making an ipv6 option for the tunnel UDP channel and endpoints 
as well.

Thanks again for your contribution, and if we can deal with these issues, 
especially as they affect protocol compatibility, I will have no problem 
merging your patch.

James

Aaron Sethman <andro...@ratbox.org> said:

> 
> 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 = &pi;
> +  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 = &pi;
> +  vect[1].iov_len = len;
> +  vect[1].iov_base = buf;
> +
> +  ret = readv(tt->fd, vect, 2);
> +  return(ret - sizeof(pi));
>  }
> 
>  #elif defined(TARGET_SOLARIS)
> 
> 
> 
> -------------------------------------------------------
> This sf.net email is sponsored by:ThinkGeek
> Welcome to geek heaven.
> http://thinkgeek.com/sf
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel
> 



-- 




Reply via email to