Browse code

change the type of 'remote' to addrinfo*, and rename to 'remote_list'.

Warning: this is work in progress, preparing for the full dual-stack
client patch. With this commit in place, connecting via "--proto udp" or
"--proto tcp-client" to a host that has IPv4+IPv6 in place, on an OS that
will prefer IPv6 to IPv4 will always fail. The remote_list will have IPv6
in it's first entry, while the socket will try to do AF_INET, and that
will not work. This will be fixed by the upcoming change to handle
multiple remote IP addresses (as returned by getaddrinfo()) as multiple
<connection> blocks, with appropriate retry and AF selection logic.

Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1385382680-5912-4-git-send-email-arne@rfc2549.org>
URL: http://article.gmane.org/gmane.network.openvpn.devel/8053

Signed-off-by: Gert Doering <gert@greenie.muc.de>

Arne Schwabe authored on 2013/11/25 21:31:15
Showing 5 changed files
... ...
@@ -1356,7 +1356,7 @@ do_init_tun (struct context *c)
1356 1356
 			   c->options.ifconfig_ipv6_netbits,
1357 1357
 			   c->options.ifconfig_ipv6_remote,
1358 1358
 			   addr_host (&c->c1.link_socket_addr.local),
1359
-			   addr_host (&c->c1.link_socket_addr.remote),
1359
+			   c->c1.link_socket_addr.remote_list,
1360 1360
 			   !c->options.ifconfig_nowarn,
1361 1361
 			   c->c2.es);
1362 1362
 
... ...
@@ -2867,7 +2867,8 @@ do_close_link_socket (struct context *c)
2867 2867
 
2868 2868
   if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_remote_ip))
2869 2869
     {
2870
-      CLEAR (c->c1.link_socket_addr.remote);
2870
+      if (c->c1.link_socket_addr.remote_list)
2871
+        freeaddrinfo(c->c1.link_socket_addr.remote_list);
2871 2872
       CLEAR (c->c1.link_socket_addr.actual);
2872 2873
     }
2873 2874
 
... ...
@@ -1207,22 +1207,8 @@ resolve_remote (struct link_socket *sock,
1207 1207
   if (!sock->did_resolve_remote)
1208 1208
     {
1209 1209
       /* resolve remote address if undefined */
1210
-      if (!addr_defined (&sock->info.lsa->remote))
1210
+      if (!sock->info.lsa->remote_list)
1211 1211
 	{
1212
-          af = addr_guess_family(sock->info.af, sock->remote_host);
1213
-          switch(af)
1214
-            {
1215
-              case AF_INET:
1216
-                sock->info.lsa->remote.addr.in4.sin_family = AF_INET;
1217
-                sock->info.lsa->remote.addr.in4.sin_addr.s_addr = 0;
1218
-                break;
1219
-              case AF_INET6:
1220
-                CLEAR(sock->info.lsa->remote.addr.in6);
1221
-                sock->info.lsa->remote.addr.in6.sin6_family = AF_INET6;
1222
-                sock->info.lsa->remote.addr.in6.sin6_addr = in6addr_any;
1223
-                break;
1224
-            }
1225
-
1226 1212
 	  if (sock->remote_host)
1227 1213
 	    {
1228 1214
 	      unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);
... ...
@@ -1269,8 +1255,7 @@ resolve_remote (struct link_socket *sock,
1269 1269
 		  status = openvpn_getaddrinfo(flags, sock->remote_host, sock->remote_port,
1270 1270
                                                retry, signal_received, af, &ai);
1271 1271
 		  if(status == 0) {
1272
-			  sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr));
1273
-			  freeaddrinfo(ai);
1272
+                          sock->info.lsa->remote_list = ai;
1274 1273
 
1275 1274
 			  dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d",
1276 1275
 					flags,
... ...
@@ -1304,7 +1289,17 @@ resolve_remote (struct link_socket *sock,
1304 1304
       else
1305 1305
 	{
1306 1306
 	  CLEAR (sock->info.lsa->actual);
1307
-	  sock->info.lsa->actual.dest = sock->info.lsa->remote;
1307
+	  /* TODO(schwabe) will only use first address als dest address */
1308
+	  if(sock->info.lsa->remote_list) {
1309
+	      if (sock->info.lsa->remote_list->ai_family == AF_INET)
1310
+		  sock->info.lsa->actual.dest.addr.in4 =
1311
+		  *((struct sockaddr_in*) sock->info.lsa->remote_list->ai_addr);
1312
+	      else if (sock->info.lsa->remote_list->ai_family == AF_INET6)
1313
+		  sock->info.lsa->actual.dest.addr.in6 =
1314
+		  *((struct sockaddr_in6*) sock->info.lsa->remote_list->ai_addr);
1315
+	      else
1316
+		  ASSERT(0);
1317
+	    }
1308 1318
 	}
1309 1319
 
1310 1320
       /* remember that we finished */
... ...
@@ -1718,7 +1713,8 @@ phase2_socks_client (struct link_socket *sock, bool *remote_changed,
1718 1718
     sock->did_resolve_remote = false;
1719 1719
 
1720 1720
     addr_zero_host(&sock->info.lsa->actual.dest);
1721
-    addr_zero_host(&sock->info.lsa->remote);
1721
+    if (sock->info.lsa->remote_list)
1722
+	freeaddrinfo(sock->info.lsa->remote_list);
1722 1723
 
1723 1724
     resolve_remote (sock, 1, NULL, signal_received);
1724 1725
 }
... ...
@@ -1792,7 +1788,9 @@ link_socket_init_phase2 (struct link_socket *sock,
1792 1792
       if (remote_changed)
1793 1793
 	{
1794 1794
 	  msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP connection establishment");
1795
-	  addr_copy_host(&sock->info.lsa->remote, &sock->info.lsa->actual.dest);
1795
+	  /* TODO(schwabe) handle multiple addresses */
1796
+	  ASSERT(0);
1797
+	  addr_copy_host(&sock->info.lsa->remote_list->ai_addr, &sock->info.lsa->actual.dest);
1796 1798
 	}
1797 1799
     }
1798 1800
 
... ...
@@ -1936,6 +1934,10 @@ link_socket_bad_incoming_addr (struct buffer *buf,
1936 1936
 			       const struct link_socket_actual *from_addr)
1937 1937
 {
1938 1938
   struct gc_arena gc = gc_new ();
1939
+  struct openvpn_sockaddr firstremoteaddr;
1940
+
1941
+  /* TODO(schwabe) Fix this and print all remote addresses */
1942
+  firstremoteaddr.addr.in6 = *(struct sockaddr_in6*)info->lsa->remote_list->ai_addr;
1939 1943
 
1940 1944
   switch(from_addr->dest.addr.sa.sa_family)
1941 1945
     {
... ...
@@ -1945,7 +1947,7 @@ link_socket_bad_incoming_addr (struct buffer *buf,
1945 1945
 	   "TCP/UDP: Incoming packet rejected from %s[%d], expected peer address: %s (allow this incoming source address/port by removing --remote or adding --float)",
1946 1946
 	   print_link_socket_actual (from_addr, &gc),
1947 1947
 	   (int)from_addr->dest.addr.sa.sa_family,
1948
-	   print_sockaddr (&info->lsa->remote, &gc));
1948
+	   print_sockaddr (&firstremoteaddr, &gc));
1949 1949
       break;
1950 1950
     }
1951 1951
   buf->len = 0;
... ...
@@ -1971,13 +1973,14 @@ link_socket_current_remote (const struct link_socket_info *info)
1971 1971
  * by now just ignore it
1972 1972
  *
1973 1973
  */
1974
+/* TODO(schwabe) what to do for a remote with multiple IPs? */
1974 1975
   if (lsa->actual.dest.addr.sa.sa_family != AF_INET)
1975 1976
     return IPV4_INVALID_ADDR;
1976 1977
 
1977 1978
   if (link_socket_actual_defined (&lsa->actual))
1978 1979
     return ntohl (lsa->actual.dest.addr.in4.sin_addr.s_addr);
1979
-  else if (addr_defined (&lsa->remote))
1980
-    return ntohl (lsa->remote.addr.in4.sin_addr.s_addr);
1980
+  else if (lsa->remote_list)
1981
+    return ntohl (((struct sockaddr_in*)lsa->remote_list->ai_addr)->sin_addr.s_addr);
1981 1982
   else
1982 1983
     return 0;
1983 1984
 }
... ...
@@ -2816,7 +2819,7 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
2816 2816
   iov.iov_len = BLEN (buf);
2817 2817
   mesg.msg_iov = &iov;
2818 2818
   mesg.msg_iovlen = 1;
2819
-  switch (sock->info.lsa->remote.addr.sa.sa_family)
2819
+  switch (sock->info.lsa->remote_list->ai_family)
2820 2820
     {
2821 2821
     case AF_INET:
2822 2822
       {
... ...
@@ -98,7 +98,7 @@ struct link_socket_actual
98 98
 struct link_socket_addr
99 99
 {
100 100
   struct openvpn_sockaddr local;
101
-  struct openvpn_sockaddr remote;   /* initial remote */
101
+  struct addrinfo* remote_list;   /* initial remote */
102 102
   struct link_socket_actual actual; /* reply to this address */
103 103
 };
104 104
 
... ...
@@ -620,6 +620,29 @@ addr_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2
620 620
   return false;
621 621
 }
622 622
 
623
+static inline bool
624
+addrlist_match (const struct openvpn_sockaddr *a1, const struct addrinfo *addrlist)
625
+{
626
+  const struct addrinfo *curele;
627
+  for (curele = addrlist; curele; curele=curele->ai_next)
628
+    {
629
+      switch(a1->addr.sa.sa_family)
630
+        {
631
+	  case AF_INET:
632
+	    if (a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr)
633
+	      return true;
634
+	    break;
635
+	  case AF_INET6:
636
+	    if (IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr))
637
+	      return true;
638
+	    break;
639
+	  default:
640
+	    ASSERT(0);
641
+        }
642
+    }
643
+  return false;
644
+}
645
+
623 646
 static inline in_addr_t
624 647
 addr_host (const struct openvpn_sockaddr *addr)
625 648
 {
... ...
@@ -633,6 +656,36 @@ addr_host (const struct openvpn_sockaddr *addr)
633 633
   return ntohl (addr->addr.in4.sin_addr.s_addr);
634 634
 }
635 635
 
636
+
637
+static inline bool
638
+addrlist_port_match (const struct openvpn_sockaddr *a1, const struct addrinfo *a2)
639
+{
640
+  const struct addrinfo *curele;
641
+  for(curele=a2;curele;curele = curele->ai_next)
642
+    {
643
+      switch(a1->addr.sa.sa_family)
644
+        {
645
+          case AF_INET:
646
+            if (curele->ai_family == AF_INET
647
+                && a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr
648
+                && a1->addr.in4.sin_port == ((struct sockaddr_in*)curele->ai_addr)->sin_port)
649
+                return true;
650
+                break;
651
+          case AF_INET6:
652
+                if (curele->ai_family == AF_INET6
653
+                && IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr)
654
+                && a1->addr.in6.sin6_port == ((struct sockaddr_in6*) curele->ai_addr)->sin6_port)
655
+                    return true;
656
+                break;
657
+          default:
658
+                ASSERT(0);
659
+        }
660
+    }
661
+  return false;
662
+}
663
+
664
+
665
+
636 666
 static inline bool
637 667
 addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2)
638 668
 {
... ...
@@ -641,7 +694,7 @@ addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockadd
641 641
       return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr
642 642
 	&& a1->addr.in4.sin_port == a2->addr.in4.sin_port;
643 643
     case AF_INET6:
644
-      return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr) 
644
+      return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr)
645 645
 	&& a1->addr.in6.sin6_port == a2->addr.in6.sin6_port;
646 646
   }
647 647
   ASSERT(0);
... ...
@@ -658,6 +711,17 @@ addr_match_proto (const struct openvpn_sockaddr *a1,
658 658
     : addr_port_match (a1, a2);
659 659
 }
660 660
 
661
+
662
+static inline bool
663
+addrlist_match_proto (const struct openvpn_sockaddr *a1,
664
+		      struct addrinfo *addr_list,
665
+		      const int proto)
666
+{
667
+  return link_socket_proto_connection_oriented (proto)
668
+    ? addrlist_match (a1, addr_list)
669
+    : addrlist_port_match (a1, addr_list);
670
+}
671
+
661 672
 static inline void
662 673
 addr_zero_host(struct openvpn_sockaddr *addr)
663 674
 {
... ...
@@ -774,9 +838,9 @@ link_socket_verify_incoming_addr (struct buffer *buf,
774 774
 	case AF_INET:
775 775
 	  if (!link_socket_actual_defined (from_addr))
776 776
 	    return false;
777
-	  if (info->remote_float || !addr_defined (&info->lsa->remote))
777
+	  if (info->remote_float || !info->lsa->remote_list)
778 778
 	    return true;
779
-	  if (addr_match_proto (&from_addr->dest, &info->lsa->remote, info->proto))
779
+	  if (addrlist_match_proto (&from_addr->dest, info->lsa->remote_list, info->proto))
780 780
 	    return true;
781 781
       }
782 782
     }
... ...
@@ -818,8 +882,8 @@ link_socket_set_outgoing_addr (const struct buffer *buf,
818 818
 	   || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto))
819 819
 	  /* address undef or address == remote or --float */
820 820
 	  && (info->remote_float
821
-	      || !addr_defined (&lsa->remote)
822
-	      || addr_match_proto (&act->dest, &lsa->remote, info->proto))
821
+	      || !lsa->remote_list
822
+	      || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto))
823 823
 	  )
824 824
 	{
825 825
 	  link_socket_connection_initiated (buf, info, act, common_name, es);
... ...
@@ -412,7 +412,7 @@ init_tun (const char *dev,       /* --dev option */
412 412
 	  int         ifconfig_ipv6_netbits_parm,
413 413
 	  const char *ifconfig_ipv6_remote_parm,    /* --ifconfig parm 2 IPv6 */
414 414
 	  in_addr_t local_public,
415
-	  in_addr_t remote_public,
415
+	  struct addrinfo *remote_public,
416 416
 	  const bool strict_warn,
417 417
 	  struct env_set *es)
418 418
 {
... ...
@@ -466,6 +466,7 @@ init_tun (const char *dev,       /* --dev option */
466 466
        */
467 467
       if (strict_warn)
468 468
 	{
469
+	  struct addrinfo *curele;
469 470
 	  ifconfig_sanity_check (tt->type == DEV_TYPE_TUN, tt->remote_netmask, tt->topology);
470 471
 
471 472
 	  /*
... ...
@@ -479,11 +480,14 @@ init_tun (const char *dev,       /* --dev option */
479 479
 			    tt->local,
480 480
 			    tt->remote_netmask);
481 481
 
482
-	  check_addr_clash ("remote",
483
-			    tt->type,
484
-			    remote_public,
485
-			    tt->local,
486
-			    tt->remote_netmask);
482
+	  for (curele=remote_public;curele;curele=curele->ai_next) {
483
+	    if (curele->ai_family == AF_INET)
484
+	      check_addr_clash ("remote",
485
+				tt->type,
486
+				((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr,
487
+				tt->local,
488
+				tt->remote_netmask);
489
+         }
487 490
 
488 491
 	  if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))
489 492
 	    check_subnet_conflict (tt->local, tt->remote_netmask, "TUN/TAP adapter");
... ...
@@ -233,7 +233,7 @@ struct tuntap *init_tun (const char *dev,       /* --dev option */
233 233
 			 int ifconfig_ipv6_netbits_parm,           /* --ifconfig parm 1 / bits */
234 234
 			 const char *ifconfig_ipv6_remote_parm,    /* --ifconfig parm 2 / IPv6 */
235 235
 			 in_addr_t local_public,
236
-			 in_addr_t remote_public,
236
+			 struct addrinfo *remote_public,
237 237
 			 const bool strict_warn,
238 238
 			 struct env_set *es);
239 239