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>
... | ... |
@@ -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 |
|