]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Implement listing on IPv4/IPv6 dual socket on all platform
authorArne Schwabe <arne@rfc2549.org>
Mon, 25 Nov 2013 12:31:18 +0000 (13:31 +0100)
committerGert Doering <gert@greenie.muc.de>
Fri, 29 Nov 2013 20:21:29 +0000 (21:21 +0100)
With this patch OpenVPN will listen on Ipv4 as well as IPv6 when an IPv6
socket is used. Using bind ipv6only will disable this behavior
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1385382680-5912-7-git-send-email-arne@rfc2549.org>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8052

Signed-off-by: Gert Doering <gert@greenie.muc.de>
doc/openvpn.8
src/openvpn/init.c
src/openvpn/manage.c
src/openvpn/options.c
src/openvpn/options.h
src/openvpn/socket.c
src/openvpn/socket.h

index d5376f903e252e7f8aae0cd4790e13c0aa3f97eb..f06d5365e4d43d96123e875160b31aff9e52950f 100644 (file)
@@ -684,7 +684,7 @@ TCP/UDP port number or name for bind.
 TCP/UDP port number or name for remote.
 .\"*********************************************************
 .TP
-.B \-\-bind
+.B \-\-bind [ipv6only]
 Bind to local address and port. This is the default unless any of 
 .B \-\-proto tcp-client
 ,
@@ -692,6 +692,12 @@ Bind to local address and port. This is the default unless any of
 or
 .B \-\-socks-proxy
 are used.
+
+If the
+.B ipv6only
+keyword is present OpenVPN will bind only to IPv6 (as oposed
+to IPv6 and IPv4) when a IPv6 socket is opened.
+
 .\"*********************************************************
 .TP
 .B \-\-nobind
index 41d6fad0714ee284194ae3b111cf6c85c0c0b7da..ae08562b84e3a734c2dcbb1290149bcdba11f537 100644 (file)
@@ -2690,6 +2690,7 @@ do_init_socket_1 (struct context *c, const int mode)
                           c->options.ce.remote_port,
                           c->options.ce.proto,
                           c->options.ce.af,
+                          c->options.ce.bind_ipv6_only,
                           mode,
                           c->c2.accept_from,
 #ifdef ENABLE_HTTP_PROXY
index dc6293af2e54f4bd91b8c6048320ff324cb38891..22dbe1305ec69b8d28a85fd23fb67a22585383c5 100644 (file)
@@ -1570,7 +1570,7 @@ man_listen (struct management *man)
        {
          man->connection.sd_top = create_socket_tcp (AF_INET);
          socket_bind (man->connection.sd_top, man->settings.local,
-                       AF_INET, "MANAGEMENT");
+                       AF_INET, "MANAGEMENT", true);
        }
 
       /*
index 3edab5828639dfc0e19b4236841bdd25bfc2a514..e8704fee40cafd848faf64456e166f95b5476191 100644 (file)
@@ -779,6 +779,7 @@ init_options (struct options *o, const bool init_gc)
   o->topology = TOP_NET30;
   o->ce.proto = PROTO_UDP;
   o->ce.af = AF_UNSPEC;
+  o->ce.bind_ipv6_only = false;
   o->ce.connect_retry_seconds = 5;
   o->ce.connect_timeout = 10;
   o->connect_retry_max = 0;
@@ -4870,6 +4871,9 @@ add_option (struct options *options,
     {
       VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
       options->ce.bind_defined = true;
+      if (p[1] && streq (p[1], "ipv6only"))
+          options->ce.bind_ipv6_only=true;
+
     }
   else if (streq (p[0], "nobind"))
     {
index 86760bbffc1e799fb72fb10fb4f164faa3a3c8c9..95e67dfcde796e0dd77671d5038cc4ba112af359 100644 (file)
@@ -95,6 +95,7 @@ struct connection_entry
   const char *remote;
   bool remote_float;
   bool bind_defined;
+  bool bind_ipv6_only;
   bool bind_local;
   int connect_retry_seconds;
   int connect_timeout;
index 5ba1ee392ff28879212fe9b7eaf32eb4883c517f..141af72dd4b613081e051e4df508c38e3b1bff65 100644 (file)
@@ -662,11 +662,10 @@ create_socket (struct link_socket *sock)
 {
   /* create socket, use information carried over from getaddrinfo */
   const int ai_proto = sock->info.lsa->actual.ai_protocol;
-  const int ai_family = sock->info.lsa->actual.ai_family;
+  int ai_family = sock->info.lsa->actual.ai_family;
 
   ASSERT (sock->info.af == AF_UNSPEC  || sock->info.af == ai_family);
 
-    
   if (ai_proto == IPPROTO_UDP)
     {
       sock->sd = create_socket_udp (ai_family, sock->sockflags);
@@ -880,7 +879,8 @@ void
 socket_bind (socket_descriptor_t sd,
              struct addrinfo *local,
              int ai_family,
-            const char *prefix)
+            const char *prefix,
+             bool ipv6only)
 {
   struct gc_arena gc = gc_new ();
 
@@ -891,9 +891,11 @@ socket_bind (socket_descriptor_t sd,
    * What is the correct way to deal with it?
    */
 
-  ASSERT(local);
   struct addrinfo* cur;
 
+  ASSERT(local);
+
+
   /* find the first addrinfo with correct ai_family */
   for (cur = local; cur; cur=cur->ai_next)
     {
@@ -904,6 +906,15 @@ socket_bind (socket_descriptor_t sd,
       msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record",
            prefix, addr_family_name(ai_family));
 
+  if (ai_family == AF_INET6)
+    {
+      int v6only = ipv6only ? 0: 1;    /* setsockopt must have an "int" */
+
+      if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)))
+       {
+         msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only);
+       }
+    }
   if (bind (sd, cur->ai_addr, cur->ai_addrlen))
     {
       const int errnum = openvpn_errno ();
@@ -1153,11 +1164,12 @@ static void bind_local (struct link_socket *sock)
 #ifdef ENABLE_SOCKS
         if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
             socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
-                         sock->info.lsa->actual.ai_family, "SOCKS");
+                         sock->info.lsa->actual.ai_family, "SOCKS", false);
         else
 #endif
             socket_bind (sock->sd, sock->info.lsa->bind_local,
-                         sock->info.lsa->actual.ai_family,  "TCP/UDP");
+                         sock->info.lsa->actual.ai_family,
+                         "TCP/UDP", sock->info.bind_ipv6_only);
       }
 }
 
@@ -1294,11 +1306,12 @@ create_new_socket (struct link_socket* sock)
       resolve_bind_local (sock, sock->info.af);
   }
   resolve_remote (sock, 1, NULL, NULL);
+
   /*
    * In P2P or server mode we must create the socket even when resolving
    * the remote site fails/is not specified. */
 
-  if (sock->info.af && sock->info.lsa->actual.ai_family==0 && sock->bind_local)
+  if (sock->info.lsa->actual.ai_family==0 && sock->bind_local)
     {
       /* Copy sock parameters from bind addr */
       set_actual_address (&sock->info.lsa->actual, sock->info.lsa->bind_local);
@@ -1309,7 +1322,7 @@ create_new_socket (struct link_socket* sock)
   /*
    * Create the socket early if socket should be bound
    */
-  if (sock->bind_local && sock->info.lsa->actual.ai_family)
+  if (sock->bind_local)
     {
       create_socket (sock);
 
@@ -1328,6 +1341,7 @@ link_socket_init_phase1 (struct link_socket *sock,
                         const char *remote_port,
                         int proto,
                         sa_family_t af,
+                        bool bind_ipv6_only,
                         int mode,
                         const struct link_socket *accept_from,
 #ifdef ENABLE_HTTP_PROXY
@@ -1388,6 +1402,7 @@ link_socket_init_phase1 (struct link_socket *sock,
   sock->info.af = af;
   sock->info.remote_float = remote_float;
   sock->info.lsa = lsa;
+  sock->info.bind_ipv6_only = bind_ipv6_only;
   sock->info.ipchange_command = ipchange_command;
   sock->info.plugins = plugins;
 
index 5c934747f41f9d0035e318e0fae8e0004aac7de7..e0e0fff08752cbb324f4ae116819bbb28b305ca8 100644 (file)
@@ -118,6 +118,7 @@ struct link_socket_info
   bool remote_float;  
   int proto;                    /* Protocol (PROTO_x defined below) */
   sa_family_t af;                       /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/
+  bool bind_ipv6_only;
   int mtu_changed;              /* Set to true when mtu value is changed */
 };
 
@@ -289,7 +290,8 @@ struct link_socket *link_socket_new (void);
 void socket_bind (socket_descriptor_t sd,
                  struct addrinfo *local,
                   int af_family,
-                 const char *prefix);
+                 const char *prefix,
+                  bool ipv6only);
 
 int openvpn_connect (socket_descriptor_t sd,
                     const struct sockaddr *remote,
@@ -308,6 +310,7 @@ link_socket_init_phase1 (struct link_socket *sock,
                         const char *remote_port,
                         int proto,
                         sa_family_t af,
+                        bool bind_ipv6_only,
                         int mode,
                         const struct link_socket *accept_from,
 #ifdef ENABLE_HTTP_PROXY