Browse code

Implement listing on IPv4/IPv6 dual socket on all platform

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>

Arne Schwabe authored on 2013/11/25 21:31:18
Showing 7 changed files
... ...
@@ -684,7 +684,7 @@ TCP/UDP port number or name for bind.
684 684
 TCP/UDP port number or name for remote.
685 685
 .\"*********************************************************
686 686
 .TP
687
-.B \-\-bind
687
+.B \-\-bind [ipv6only]
688 688
 Bind to local address and port. This is the default unless any of 
689 689
 .B \-\-proto tcp-client
690 690
 ,
... ...
@@ -692,6 +692,12 @@ Bind to local address and port. This is the default unless any of
692 692
 or
693 693
 .B \-\-socks-proxy
694 694
 are used.
695
+
696
+If the
697
+.B ipv6only
698
+keyword is present OpenVPN will bind only to IPv6 (as oposed
699
+to IPv6 and IPv4) when a IPv6 socket is opened.
700
+
695 701
 .\"*********************************************************
696 702
 .TP
697 703
 .B \-\-nobind
... ...
@@ -2690,6 +2690,7 @@ do_init_socket_1 (struct context *c, const int mode)
2690 2690
 			   c->options.ce.remote_port,
2691 2691
 			   c->options.ce.proto,
2692 2692
 			   c->options.ce.af,
2693
+			   c->options.ce.bind_ipv6_only,
2693 2694
 			   mode,
2694 2695
 			   c->c2.accept_from,
2695 2696
 #ifdef ENABLE_HTTP_PROXY
... ...
@@ -1570,7 +1570,7 @@ man_listen (struct management *man)
1570 1570
 	{
1571 1571
 	  man->connection.sd_top = create_socket_tcp (AF_INET);
1572 1572
 	  socket_bind (man->connection.sd_top, man->settings.local,
1573
-                       AF_INET, "MANAGEMENT");
1573
+                       AF_INET, "MANAGEMENT", true);
1574 1574
 	}
1575 1575
 
1576 1576
       /*
... ...
@@ -779,6 +779,7 @@ init_options (struct options *o, const bool init_gc)
779 779
   o->topology = TOP_NET30;
780 780
   o->ce.proto = PROTO_UDP;
781 781
   o->ce.af = AF_UNSPEC;
782
+  o->ce.bind_ipv6_only = false;
782 783
   o->ce.connect_retry_seconds = 5;
783 784
   o->ce.connect_timeout = 10;
784 785
   o->connect_retry_max = 0;
... ...
@@ -4870,6 +4871,9 @@ add_option (struct options *options,
4870 4870
     {
4871 4871
       VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
4872 4872
       options->ce.bind_defined = true;
4873
+      if (p[1] && streq (p[1], "ipv6only"))
4874
+          options->ce.bind_ipv6_only=true;
4875
+
4873 4876
     }
4874 4877
   else if (streq (p[0], "nobind"))
4875 4878
     {
... ...
@@ -95,6 +95,7 @@ struct connection_entry
95 95
   const char *remote;
96 96
   bool remote_float;
97 97
   bool bind_defined;
98
+  bool bind_ipv6_only;
98 99
   bool bind_local;
99 100
   int connect_retry_seconds;
100 101
   int connect_timeout;
... ...
@@ -662,11 +662,10 @@ create_socket (struct link_socket *sock)
662 662
 {
663 663
   /* create socket, use information carried over from getaddrinfo */
664 664
   const int ai_proto = sock->info.lsa->actual.ai_protocol;
665
-  const int ai_family = sock->info.lsa->actual.ai_family;
665
+  int ai_family = sock->info.lsa->actual.ai_family;
666 666
 
667 667
   ASSERT (sock->info.af == AF_UNSPEC  || sock->info.af == ai_family);
668 668
 
669
-    
670 669
   if (ai_proto == IPPROTO_UDP)
671 670
     {
672 671
       sock->sd = create_socket_udp (ai_family, sock->sockflags);
... ...
@@ -880,7 +879,8 @@ void
880 880
 socket_bind (socket_descriptor_t sd,
881 881
              struct addrinfo *local,
882 882
              int ai_family,
883
-	     const char *prefix)
883
+	     const char *prefix,
884
+             bool ipv6only)
884 885
 {
885 886
   struct gc_arena gc = gc_new ();
886 887
 
... ...
@@ -891,9 +891,11 @@ socket_bind (socket_descriptor_t sd,
891 891
    * What is the correct way to deal with it?
892 892
    */
893 893
 
894
-  ASSERT(local);
895 894
   struct addrinfo* cur;
896 895
 
896
+  ASSERT(local);
897
+
898
+
897 899
   /* find the first addrinfo with correct ai_family */
898 900
   for (cur = local; cur; cur=cur->ai_next)
899 901
     {
... ...
@@ -904,6 +906,15 @@ socket_bind (socket_descriptor_t sd,
904 904
       msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record",
905 905
            prefix, addr_family_name(ai_family));
906 906
 
907
+  if (ai_family == AF_INET6)
908
+    {
909
+      int v6only = ipv6only ? 0: 1;	/* setsockopt must have an "int" */
910
+
911
+      if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)))
912
+	{
913
+	  msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only);
914
+	}
915
+    }
907 916
   if (bind (sd, cur->ai_addr, cur->ai_addrlen))
908 917
     {
909 918
       const int errnum = openvpn_errno ();
... ...
@@ -1153,11 +1164,12 @@ static void bind_local (struct link_socket *sock)
1153 1153
 #ifdef ENABLE_SOCKS
1154 1154
         if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
1155 1155
             socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
1156
-                         sock->info.lsa->actual.ai_family, "SOCKS");
1156
+                         sock->info.lsa->actual.ai_family, "SOCKS", false);
1157 1157
         else
1158 1158
 #endif
1159 1159
             socket_bind (sock->sd, sock->info.lsa->bind_local,
1160
-                         sock->info.lsa->actual.ai_family,  "TCP/UDP");
1160
+                         sock->info.lsa->actual.ai_family,
1161
+                         "TCP/UDP", sock->info.bind_ipv6_only);
1161 1162
       }
1162 1163
 }
1163 1164
 
... ...
@@ -1294,11 +1306,12 @@ create_new_socket (struct link_socket* sock)
1294 1294
       resolve_bind_local (sock, sock->info.af);
1295 1295
   }
1296 1296
   resolve_remote (sock, 1, NULL, NULL);
1297
+
1297 1298
   /*
1298 1299
    * In P2P or server mode we must create the socket even when resolving
1299 1300
    * the remote site fails/is not specified. */
1300 1301
 
1301
-  if (sock->info.af && sock->info.lsa->actual.ai_family==0 && sock->bind_local)
1302
+  if (sock->info.lsa->actual.ai_family==0 && sock->bind_local)
1302 1303
     {
1303 1304
       /* Copy sock parameters from bind addr */
1304 1305
       set_actual_address (&sock->info.lsa->actual, sock->info.lsa->bind_local);
... ...
@@ -1309,7 +1322,7 @@ create_new_socket (struct link_socket* sock)
1309 1309
   /*
1310 1310
    * Create the socket early if socket should be bound
1311 1311
    */
1312
-  if (sock->bind_local && sock->info.lsa->actual.ai_family)
1312
+  if (sock->bind_local)
1313 1313
     {
1314 1314
       create_socket (sock);
1315 1315
 
... ...
@@ -1328,6 +1341,7 @@ link_socket_init_phase1 (struct link_socket *sock,
1328 1328
 			 const char *remote_port,
1329 1329
 			 int proto,
1330 1330
 			 sa_family_t af,
1331
+			 bool bind_ipv6_only,
1331 1332
 			 int mode,
1332 1333
 			 const struct link_socket *accept_from,
1333 1334
 #ifdef ENABLE_HTTP_PROXY
... ...
@@ -1388,6 +1402,7 @@ link_socket_init_phase1 (struct link_socket *sock,
1388 1388
   sock->info.af = af;
1389 1389
   sock->info.remote_float = remote_float;
1390 1390
   sock->info.lsa = lsa;
1391
+  sock->info.bind_ipv6_only = bind_ipv6_only;
1391 1392
   sock->info.ipchange_command = ipchange_command;
1392 1393
   sock->info.plugins = plugins;
1393 1394
 
... ...
@@ -118,6 +118,7 @@ struct link_socket_info
118 118
   bool remote_float;  
119 119
   int proto;                    /* Protocol (PROTO_x defined below) */
120 120
   sa_family_t af;                       /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/
121
+  bool bind_ipv6_only;
121 122
   int mtu_changed;              /* Set to true when mtu value is changed */
122 123
 };
123 124
 
... ...
@@ -289,7 +290,8 @@ struct link_socket *link_socket_new (void);
289 289
 void socket_bind (socket_descriptor_t sd,
290 290
 		  struct addrinfo *local,
291 291
                   int af_family,
292
-		  const char *prefix);
292
+		  const char *prefix,
293
+                  bool ipv6only);
293 294
 
294 295
 int openvpn_connect (socket_descriptor_t sd,
295 296
 		     const struct sockaddr *remote,
... ...
@@ -308,6 +310,7 @@ link_socket_init_phase1 (struct link_socket *sock,
308 308
 			 const char *remote_port,
309 309
 			 int proto,
310 310
 			 sa_family_t af,
311
+			 bool bind_ipv6_only,
311 312
 			 int mode,
312 313
 			 const struct link_socket *accept_from,
313 314
 #ifdef ENABLE_HTTP_PROXY