Peter Rabbitson wrote:
> Peter Rabbitson wrote:
>> Samuli Seppänen wrote:
>>> Hi,
>>>
>>> Is someone successfully using the --multihome option on latest OpenVPN
>>> release? Or is this bug report still valid:
>>>
>>> <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=562099>
>>>
>> I am sorry I dropped the ball on testing that one. Will test the coming 
>> night EST, and update.
>>
> 
> Looking more at the *debian* changelog, I see that there was a 3rd party
> ipv6 patch, which *could* have caused these problems. However it is not
> very easy for me to compile a "clean" openvpn on the multihomed server.
> Please let me know if this can be diagnosed in any other way, if not -
> I will find a way to test with vanilla openvpn.
> 

And unfortunately I was right (proven with the help of [1]) :(

openvpn_2.1~rc20-1_i386.deb works
openvpn_2.1~rc20-2_i386.deb does not

The only code-change between the two is:

  * patches/jjo-ipv6-support.patch: Added ipv6 support. (Closes: #307846)
    Patch from JuanJo Ciarlante.

So this got to be the culprit. Attaching a -U10 diff between the sources of
both debian packages (not too long):

[1] http://snapshot.debian.org/package/openvpn/

diff -U10 -r openvpn-2.1_rc21-1/mroute.c openvpn-2.1_rc21-2/mroute.c
--- openvpn-2.1_rc21-1/mroute.c 2010-05-01 21:33:38.520080366 +0200
+++ openvpn-2.1_rc21-2/mroute.c 2010-05-01 21:33:51.746080500 +0200
@@ -358,21 +358,21 @@
              }
          }
          break;
        case MR_ADDR_IPV6:
 #ifdef USE_PF_INET6
           {
            struct buffer buf;
            struct sockaddr_in6 sin6;
            int port;
            char buf6[INET6_ADDRSTRLEN] = "";
-           memset(&sin6, 0, sizeof sin6);
+           CLEAR(sin6);
            sin6.sin6_family = AF_INET6;
            buf_set_read (&buf, maddr.addr, maddr.len);
             if (buf_read(&buf, &sin6.sin6_addr, sizeof (sin6.sin6_addr)))
             {
               if (getnameinfo((struct sockaddr *)&sin6, sizeof (struct 
sockaddr_in6),
                                       buf6, sizeof (buf6), NULL, 0, 
NI_NUMERICHOST) != 0)
                 {
                   buf_printf (&out, "MR_ADDR_IPV6 getnameinfo() err");
                   break;
                }
diff -U10 -r openvpn-2.1_rc21-1/options.c openvpn-2.1_rc21-2/options.c
--- openvpn-2.1_rc21-1/options.c        2010-05-01 21:33:38.529079829 +0200
+++ openvpn-2.1_rc21-2/options.c        2010-05-01 21:33:51.792080328 +0200
@@ -1,19 +1,22 @@
 /*
  *  OpenVPN -- An application to securely tunnel IP networks
  *             over a single UDP port, with support for SSL/TLS-based
  *             session authentication and key exchange,
  *             packet encryption, packet authentication, and
  *             packet compression.
  *
  *  Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sa...@openvpn.net>
  *
+ *  Additions for eurephia plugin done by:
+ *         David Sommerseth <d...@users.sourceforge.net> Copyright (C) 2009
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2
  *  as published by the Free Software Foundation.
  *
  *  This program 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
@@ -72,20 +75,21 @@
 #endif
 #ifdef ENABLE_PKCS11
   " [PKCS11]"
 #endif
 #ifdef ENABLE_IP_PKTINFO
   " [MH]"
 #endif
 #ifdef USE_PF_INET6
   " [PF_INET6]"
 #endif
+  " [eurephia]"
   " built on " __DATE__
 ;

 #ifndef ENABLE_SMALL

 static const char usage_message[] =
   "%s\n"
   "\n"
   "General Options:\n"
   "--config file   : Read configuration options from file.\n"
@@ -1545,28 +1549,36 @@

   /*
    * Sanity check on TCP mode options
    */

   if (ce->connect_retry_defined && ce->proto != PROTO_TCPv4_CLIENT
 #ifdef USE_PF_INET6
       && ce->proto != PROTO_TCPv6_CLIENT
 #endif
       )
-    msg (M_USAGE, "--connect-retry doesn't make sense unless also used with 
--proto tcp-client");
+    msg (M_USAGE, "--connect-retry doesn't make sense unless also used with 
--proto tcp-client"
+#ifdef USE_PF_INET6
+        " or tcp6-client"
+#endif
+        );

   if (ce->connect_timeout_defined && ce->proto != PROTO_TCPv4_CLIENT
 #ifdef USE_PF_INET6
       && ce->proto != PROTO_TCPv6_CLIENT
 #endif
       )
-    msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with 
--proto tcp-client");
+    msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with 
--proto tcp-client"
+#ifdef USE_PF_INET6
+        " or tcp6-client"
+#endif
+        );

   /*
    * Sanity check on MTU parameters
    */
   if (options->tun_mtu_defined && options->link_mtu_defined)
     msg (M_USAGE, "only one of --tun-mtu or --link-mtu may be defined (note 
that --ifconfig implies --link-mtu %d)", LINK_MTU_DEFAULT);

 #ifdef ENABLE_OCC
   if (!proto_is_udp(ce->proto) && options->mtu_test)
     msg (M_USAGE, "--mtu-test only makes sense with --proto udp");
@@ -1695,29 +1707,37 @@
     {
       if (!(dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP))
        msg (M_USAGE, "--mode server only works with --dev tun or --dev tap");
       if (options->pull)
        msg (M_USAGE, "--pull cannot be used with --mode server");
       if (!(proto_is_udp(ce->proto) || ce->proto == PROTO_TCPv4_SERVER
 #ifdef USE_PF_INET6
            || ce->proto == PROTO_TCPv6_SERVER
 #endif
            ))
-       msg (M_USAGE, "--mode server currently only supports --proto udp or 
--proto tcp-server");
+       msg (M_USAGE, "--mode server currently only supports --proto udp or 
--proto tcp-server"
+#ifdef USE_PF_INET6
+           " or proto tcp6-server"
+#endif
+            );
 #if PORT_SHARE
       if ((options->port_share_host || options->port_share_port) &&
             (ce->proto != PROTO_TCPv4_SERVER
 #ifdef USE_PF_INET6
             && ce->proto != PROTO_TCPv6_SERVER
 #endif
             ))
-       msg (M_USAGE, "--port-share only works in TCP server mode (--proto 
tcp-server)");
+       msg (M_USAGE, "--port-share only works in TCP server mode (--proto 
tcp-server"
+#ifdef USE_PF_INET6
+            " or tcp6-server"
+#endif
+         ")");
 #endif
       if (!options->tls_server)
        msg (M_USAGE, "--mode server requires --tls-server");
       if (ce->remote)
        msg (M_USAGE, "--remote cannot be used with --mode server");
       if (!ce->bind_local)
        msg (M_USAGE, "--nobind cannot be used with --mode server");
 #ifdef ENABLE_HTTP_PROXY
       if (ce->http_proxy_options)
        msg (M_USAGE, "--http-proxy cannot be used with --mode server");
@@ -1736,21 +1756,25 @@
        msg (M_USAGE, "--shaper cannot be used with --mode server");
       if (options->inetd)
        msg (M_USAGE, "--inetd cannot be used with --mode server");
       if (options->ipchange)
        msg (M_USAGE, "--ipchange cannot be used with --mode server (use 
--client-connect instead)");
       if (!(proto_is_dgram(ce->proto) || ce->proto == PROTO_TCPv4_SERVER
 #ifdef USE_PF_INET6
            || ce->proto == PROTO_TCPv6_SERVER
 #endif
            ))
-       msg (M_USAGE, "--mode server currently only supports --proto udp or 
--proto tcp-server");
+       msg (M_USAGE, "--mode server currently only supports --proto udp or 
--proto tcp-server"
+#ifdef USE_PF_INET6
+           " or --proto tcp6-server"
+#endif
+            );
       if (!proto_is_udp(ce->proto) && (options->cf_max || options->cf_per))
        msg (M_USAGE, "--connect-freq only works with --mode server --proto 
udp.  Try --max-clients instead.");
       if (!(dev == DEV_TYPE_TAP || (dev == DEV_TYPE_TUN && options->topology 
== TOP_SUBNET)) && options->ifconfig_pool_netmask)
        msg (M_USAGE, "The third parameter to --ifconfig-pool (netmask) is only 
valid in --dev tap mode");
 #ifdef ENABLE_OCC
       if (options->explicit_exit_notification)
        msg (M_USAGE, "--explicit-exit-notify cannot be used with --mode 
server");
 #endif
       if (options->routes && (options->routes->flags & RG_ENABLE))
        msg (M_USAGE, "--redirect-gateway cannot be used with --mode server 
(however --push \"redirect-gateway\" is fine)");
diff -U10 -r openvpn-2.1_rc21-1/route.c openvpn-2.1_rc21-2/route.c
--- openvpn-2.1_rc21-1/route.c  2009-10-01 20:02:18.000000000 +0200
+++ openvpn-2.1_rc21-2/route.c  2010-05-01 21:33:51.760080170 +0200
@@ -565,27 +565,37 @@
              }
            else if (tla == TLA_LOCAL)
              {
                dmsg (D_ROUTE, "ROUTE remote_host is LOCAL");
                local = true;
              }
          }
          if (!local)
            {
              /* route remote host to original default gateway */
-             add_route3 (rl->spec.remote_host,
-                         ~0,
-                         rl->spec.net_gateway,
-                         tt,
-                         flags,
-                         es);
-             rl->did_local = true;
+#ifdef USE_PF_INET6
+             /* if remote_host is not ipv4 (ie: ipv6), just skip
+              * adding this special /32 route */
+             if (rl->spec.remote_host != IPV4_INVALID_ADDR) {
+#endif
+               add_route3 (rl->spec.remote_host,
+                           ~0,
+                           rl->spec.net_gateway,
+                           tt,
+                           flags,
+                           es);
+               rl->did_local = true;
+#ifdef USE_PF_INET6
+             } else {
+               dmsg (D_ROUTE, "ROUTE remote_host protocol differs from 
tunneled");
+             }
+#endif
            }

          /* route DHCP/DNS server traffic through original default gateway */
          add_bypass_routes (&rl->spec.bypass, rl->spec.net_gateway, tt, flags, 
es);

          if (rl->flags & RG_REROUTE_GW)
            {
              if (rl->flags & RG_DEF1)
                {
                  /* add new default route (1st component) */
diff -U10 -r openvpn-2.1_rc21-1/socket.c openvpn-2.1_rc21-2/socket.c
--- openvpn-2.1_rc21-1/socket.c 2010-05-01 21:33:38.541079913 +0200
+++ openvpn-2.1_rc21-2/socket.c 2010-05-01 21:33:51.763079902 +0200
@@ -2109,24 +2109,24 @@

 /*
  * This logic supports "redirect-gateway" semantic, which
  * makes sense only for PF_INET routes over PF_INET endpoints
  *
  * Maybe in the future consider PF_INET6 endpoints also ...
  * by now just ignore it
  *
  */
 #ifdef USE_PF_INET6
-  if(lsa->actual.dest.addr.sa.sa_family != AF_INET)
-    return 0;
+  if (lsa->actual.dest.addr.sa.sa_family != AF_INET)
+    return IPV4_INVALID_ADDR;
 #else
-  ASSERT(lsa->actual.dest.addr.sa.sa_family == AF_INET);
+  ASSERT (lsa->actual.dest.addr.sa.sa_family == AF_INET);
 #endif

   if (link_socket_actual_defined (&lsa->actual))
     return ntohl (lsa->actual.dest.addr.in4.sin_addr.s_addr);
   else if (addr_defined (&lsa->remote))
     return ntohl (lsa->remote.addr.in4.sin_addr.s_addr);
   else
     return 0;
 }

@@ -2438,21 +2438,21 @@
                  CLEAR (sa);
                  sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst;
                  buf_printf (&out, " (via %s)", print_sockaddr_ex (&sa, 
separator, 0, gc));
                }
 #ifdef USE_PF_INET6
              break;
            case AF_INET6:
                {
                  struct sockaddr_in6 sin6;
                  char buf[INET6_ADDRSTRLEN] = "[undef]";
-                 memset(&sin6, 0, sizeof sin6);
+                 CLEAR(sin6);
                  sin6.sin6_family = AF_INET6;
                  sin6.sin6_addr = act->pi.in6.ipi6_addr;
                    {
                      if (getnameinfo((struct sockaddr *)&sin6, sizeof (struct 
sockaddr_in6),
                                      buf, sizeof (buf), NULL, 0, 
NI_NUMERICHOST) == 0)
                        buf_printf (&out, " (via %s)", buf);
                      else
                        buf_printf (&out, " (via [getnameinfo() err])");
                    }
                }
@@ -2664,22 +2664,22 @@
 #endif
   if (proto)
     {
       return proto_sa_family(proto);   /* already stamped */
     }
 #ifdef USE_PF_INET6
   else
     {
       struct addrinfo hints , *ai;
       int err;
-      memset(&hints, 0, sizeof hints);
-      hints.ai_flags=AI_NUMERICHOST;
+      CLEAR(hints);
+      hints.ai_flags = AI_NUMERICHOST;
       err = getaddrinfo(name, NULL, &hints, &ai);
       if ( 0 == err )
        {
          ret=ai->ai_family;
          freeaddrinfo(ai);
          return ret;
        }
     }
 #endif
   return AF_INET;      /* default */
@@ -2966,82 +2966,65 @@

 int
 socket_recv_queue (struct link_socket *sock, int maxsize)
 {
   if (sock->reads.iostate == IOSTATE_INITIAL)
     {
       WSABUF wsabuf[1];
       int status;

       /* reset buf to its initial state */
-      if (sock->info.proto == PROTO_UDPv4
-#ifdef USE_PF_INET6
-          || sock->info.proto == PROTO_UDPv6
-#endif
-        )
+      if (proto_is_udp(sock->info.proto))
        {
          sock->reads.buf = sock->reads.buf_init;
        }
-      else if (sock->info.proto == PROTO_TCPv4_CLIENT || sock->info.proto == 
PROTO_TCPv4_SERVER
-#ifdef USE_PF_INET6
-              || sock->info.proto == PROTO_TCPv6_CLIENT || sock->info.proto == 
PROTO_TCPv6_SERVER
-#endif
-              )
+      else if (proto_is_tcp(sock->info.proto))
        {
          stream_buf_get_next (&sock->stream_buf, &sock->reads.buf);
        }
       else
        {
          ASSERT (0);
        }

       /* Win32 docs say it's okay to allocate the wsabuf on the stack */
       wsabuf[0].buf = BPTR (&sock->reads.buf);
       wsabuf[0].len = maxsize ? maxsize : BLEN (&sock->reads.buf);

       /* check for buffer overflow */
       ASSERT (wsabuf[0].len <= BLEN (&sock->reads.buf));

       /* the overlapped read will signal this event on I/O completion */
       ASSERT (ResetEvent (sock->reads.overlapped.hEvent));
       sock->reads.flags = 0;

-      if (sock->info.proto == PROTO_UDPv4
-#ifdef USE_PF_INET6
-          || sock->info.proto == PROTO_UDPv6
-#endif
-         )
+      if (proto_is_udp(sock->info.proto))
        {
          sock->reads.addr_defined = true;
 #ifdef USE_PF_INET6
          if (sock->info.proto == PROTO_UDPv6)
            sock->reads.addrlen = sizeof (sock->reads.addr6);
          else
 #endif
            sock->reads.addrlen = sizeof (sock->reads.addr);
          status = WSARecvFrom(
                               sock->sd,
                               wsabuf,
                               1,
                               &sock->reads.size,
                               &sock->reads.flags,
                               (struct sockaddr *) &sock->reads.addr,
                               &sock->reads.addrlen,
                               &sock->reads.overlapped,
                               NULL);
        }
-      else if (sock->info.proto == PROTO_TCPv4_CLIENT || sock->info.proto == 
PROTO_TCPv4_SERVER
-#ifdef USE_PF_INET6
-              || sock->info.proto == PROTO_TCPv6_CLIENT || sock->info.proto == 
PROTO_TCPv6_SERVER
-#endif
-              )
-
+      else if (proto_is_tcp(sock->info.proto))
        {
          sock->reads.addr_defined = false;
          status = WSARecv(
                           sock->sd,
                           wsabuf,
                           1,
                           &sock->reads.size,
                           &sock->reads.flags,
                           &sock->reads.overlapped,
                           NULL);
@@ -3113,25 +3096,21 @@
       ASSERT (buf_copy (&sock->writes.buf, buf));

       /* Win32 docs say it's okay to allocate the wsabuf on the stack */
       wsabuf[0].buf = BPTR (&sock->writes.buf);
       wsabuf[0].len = BLEN (&sock->writes.buf);

       /* the overlapped write will signal this event on I/O completion */
       ASSERT (ResetEvent (sock->writes.overlapped.hEvent));
       sock->writes.flags = 0;

-      if (sock->info.proto == PROTO_UDPv4
-#ifdef USE_PF_INET6
-         || sock->info.proto == PROTO_UDPv6
-#endif
-        )
+      if (proto_is_udp(sock->info.proto))
        {
          /* set destination address for UDP writes */
          sock->writes.addr_defined = true;
 #ifdef USE_PF_INET6
          if (sock->info.proto == PROTO_UDPv6)
            {
              sock->writes.addr6 = to->dest.addr.in6;
              sock->writes.addrlen = sizeof (sock->writes.addr6);
            }
          else
@@ -3145,25 +3124,21 @@
                               sock->sd,
                               wsabuf,
                               1,
                               &sock->writes.size,
                               sock->writes.flags,
                               (struct sockaddr *) &sock->writes.addr,
                               sock->writes.addrlen,
                               &sock->writes.overlapped,
                               NULL);
        }
-      else if (sock->info.proto == PROTO_TCPv4_CLIENT || sock->info.proto == 
PROTO_TCPv4_SERVER
-#ifdef USE_PF_INET6
-              || sock->info.proto == PROTO_TCPv6_CLIENT || sock->info.proto == 
PROTO_TCPv6_SERVER
-#endif
-             )
+      else if (proto_is_tcp(sock->info.proto))
        {
          /* destination address for TCP writes was established on connection 
initiation */
          sock->writes.addr_defined = false;

          status = WSASend(
                           sock->sd,
                           wsabuf,
                           1,
                           &sock->writes.size,
                           sock->writes.flags,
diff -U10 -r openvpn-2.1_rc21-1/socket.h openvpn-2.1_rc21-2/socket.h
--- openvpn-2.1_rc21-1/socket.h 2010-05-01 21:33:38.542079929 +0200
+++ openvpn-2.1_rc21-2/socket.h 2010-05-01 21:33:51.772080120 +0200
@@ -376,20 +376,26 @@
                       in_addr_t addr,
                       const bool flags);

 void setenv_link_socket_actual (struct env_set *es,
                                const char *name_prefix,
                                const struct link_socket_actual *act,
                                const bool flags);

 void bad_address_length (int actual, int expected);

+#ifdef USE_PF_INET6
+/* IPV4_INVALID_ADDR: returned by link_socket_current_remote()
+ * to ease redirect-gateway logic for ipv4 tunnels on ipv6 endpoints
+ */
+#define IPV4_INVALID_ADDR 0xffffffff
+#endif
 in_addr_t link_socket_current_remote (const struct link_socket_info *info);

 void link_socket_connection_initiated (const struct buffer *buf,
                                       struct link_socket_info *info,
                                       const struct link_socket_actual *addr,
                                       const char *common_name,
                                       struct env_set *es);

 void link_socket_bad_incoming_addr (struct buffer *buf,
                                    const struct link_socket_info *info,
diff -U10 -r openvpn-2.1_rc21-1/ssl.c openvpn-2.1_rc21-2/ssl.c
--- openvpn-2.1_rc21-1/ssl.c    2009-10-25 16:28:02.000000000 +0100
+++ openvpn-2.1_rc21-2/ssl.c    2010-05-01 21:33:51.795080798 +0200
@@ -1,19 +1,23 @@
 /*
  *  OpenVPN -- An application to securely tunnel IP networks
  *             over a single TCP/UDP port, with support for SSL/TLS-based
  *             session authentication and key exchange,
  *             packet encryption, packet authentication, and
  *             packet compression.
  *
  *  Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sa...@openvpn.net>
  *
+ *  Additions for eurephia plugin done by:
+ *         David Sommerseth <d...@users.sourceforge.net> Copyright (C) 
2008-2009
+ *
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2
  *  as published by the Free Software Foundation.
  *
  *  This program 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
@@ -770,20 +774,28 @@

   /* save common name in session object */
   if (ctx->error_depth == 0)
     set_common_name (session, common_name);

   /* export subject name string as environmental variable */
   session->verify_maxlevel = max_int (session->verify_maxlevel, 
ctx->error_depth);
   openvpn_snprintf (envname, sizeof(envname), "tls_id_%d", ctx->error_depth);
   setenv_str (opt->es, envname, subject);

+  /* export X509 cert SHA1 fingerprint */
+  {
+    struct gc_arena gc = gc_new ();
+    openvpn_snprintf (envname, sizeof(envname), "tls_digest_%d", 
ctx->error_depth);
+    setenv_str (opt->es, envname,
+               format_hex_ex(ctx->current_cert->sha1_hash, SHA_DIGEST_LENGTH, 
0, 1, ":", &gc));
+    gc_free(&gc);
+  }
 #if 0
   /* export common name string as environmental variable */
   openvpn_snprintf (envname, sizeof(envname), "tls_common_name_%d", 
ctx->error_depth);
   setenv_str (opt->es, envname, common_name);
 #endif

   /* export serial number as environmental variable */
   {
     const int serial = (int) ASN1_INTEGER_get (X509_get_serialNumber 
(ctx->current_cert));
     openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", 
ctx->error_depth);
diff -U10 -r openvpn-2.1_rc21-1/tun.c openvpn-2.1_rc21-2/tun.c
--- openvpn-2.1_rc21-1/tun.c    2009-10-01 20:02:18.000000000 +0200
+++ openvpn-2.1_rc21-2/tun.c    2010-05-01 21:33:51.788080607 +0200
@@ -1598,21 +1598,23 @@
   /* Enable multicast on the interface */
   if (tt->fd >= 0)
     {
       struct tuninfo info;

       if (ioctl (tt->fd, TUNGIFINFO, &info) < 0) {
        msg (M_WARN | M_ERRNO, "Can't get interface info: %s",
          strerror(errno));
       }

+#ifdef IFF_MULTICAST /* openbsd 4.x doesn't have this */
       info.flags |= IFF_MULTICAST;
+#endif

       if (ioctl (tt->fd, TUNSIFINFO, &info) < 0) {
        msg (M_WARN | M_ERRNO, "Can't set interface info: %s",
          strerror(errno));
       }
     }
 }

 void
 close_tun (struct tuntap* tt)




--
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to