diff options
author | Arne Schwabe <arne@rfc2549.org> | 2013-11-25 13:31:15 +0100 |
---|---|---|
committer | Gert Doering <gert@greenie.muc.de> | 2013-11-27 20:18:36 +0100 |
commit | 6c5db192c30ff0c6b89e2e0aefec00329de39302 (patch) | |
tree | 9b364925444a5403c3652d7b4d2e33c9c42a0781 /src/openvpn/socket.h | |
parent | bb9026a60a8ebdf20fdf9a99e16c0d8afc658747 (diff) | |
download | openvpn-6c5db192c30ff0c6b89e2e0aefec00329de39302.tar.gz openvpn-6c5db192c30ff0c6b89e2e0aefec00329de39302.tar.xz openvpn-6c5db192c30ff0c6b89e2e0aefec00329de39302.zip |
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>
Diffstat (limited to 'src/openvpn/socket.h')
-rw-r--r-- | src/openvpn/socket.h | 76 |
1 files changed, 70 insertions, 6 deletions
diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index a41a3d9..65def10 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -98,7 +98,7 @@ struct link_socket_actual struct link_socket_addr { struct openvpn_sockaddr local; - struct openvpn_sockaddr remote; /* initial remote */ + struct addrinfo* remote_list; /* initial remote */ struct link_socket_actual actual; /* reply to this address */ }; @@ -620,6 +620,29 @@ addr_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2 return false; } +static inline bool +addrlist_match (const struct openvpn_sockaddr *a1, const struct addrinfo *addrlist) +{ + const struct addrinfo *curele; + for (curele = addrlist; curele; curele=curele->ai_next) + { + switch(a1->addr.sa.sa_family) + { + case AF_INET: + if (a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr) + return true; + break; + case AF_INET6: + if (IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr)) + return true; + break; + default: + ASSERT(0); + } + } + return false; +} + static inline in_addr_t addr_host (const struct openvpn_sockaddr *addr) { @@ -633,6 +656,36 @@ addr_host (const struct openvpn_sockaddr *addr) return ntohl (addr->addr.in4.sin_addr.s_addr); } + +static inline bool +addrlist_port_match (const struct openvpn_sockaddr *a1, const struct addrinfo *a2) +{ + const struct addrinfo *curele; + for(curele=a2;curele;curele = curele->ai_next) + { + switch(a1->addr.sa.sa_family) + { + case AF_INET: + if (curele->ai_family == AF_INET + && a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr + && a1->addr.in4.sin_port == ((struct sockaddr_in*)curele->ai_addr)->sin_port) + return true; + break; + case AF_INET6: + if (curele->ai_family == AF_INET6 + && IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr) + && a1->addr.in6.sin6_port == ((struct sockaddr_in6*) curele->ai_addr)->sin6_port) + return true; + break; + default: + ASSERT(0); + } + } + return false; +} + + + static inline bool addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2) { @@ -641,7 +694,7 @@ addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockadd return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr && a1->addr.in4.sin_port == a2->addr.in4.sin_port; case AF_INET6: - return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr) + return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr) && a1->addr.in6.sin6_port == a2->addr.in6.sin6_port; } ASSERT(0); @@ -658,6 +711,17 @@ addr_match_proto (const struct openvpn_sockaddr *a1, : addr_port_match (a1, a2); } + +static inline bool +addrlist_match_proto (const struct openvpn_sockaddr *a1, + struct addrinfo *addr_list, + const int proto) +{ + return link_socket_proto_connection_oriented (proto) + ? addrlist_match (a1, addr_list) + : addrlist_port_match (a1, addr_list); +} + static inline void addr_zero_host(struct openvpn_sockaddr *addr) { @@ -774,9 +838,9 @@ link_socket_verify_incoming_addr (struct buffer *buf, case AF_INET: if (!link_socket_actual_defined (from_addr)) return false; - if (info->remote_float || !addr_defined (&info->lsa->remote)) + if (info->remote_float || !info->lsa->remote_list) return true; - if (addr_match_proto (&from_addr->dest, &info->lsa->remote, info->proto)) + if (addrlist_match_proto (&from_addr->dest, info->lsa->remote_list, info->proto)) return true; } } @@ -818,8 +882,8 @@ link_socket_set_outgoing_addr (const struct buffer *buf, || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto)) /* address undef or address == remote or --float */ && (info->remote_float - || !addr_defined (&lsa->remote) - || addr_match_proto (&act->dest, &lsa->remote, info->proto)) + || !lsa->remote_list + || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto)) ) { link_socket_connection_initiated (buf, info, act, common_name, es); |