summaryrefslogtreecommitdiffstats
path: root/src/openvpn/socket.h
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2013-11-25 13:31:15 +0100
committerGert Doering <gert@greenie.muc.de>2013-11-27 20:18:36 +0100
commit6c5db192c30ff0c6b89e2e0aefec00329de39302 (patch)
tree9b364925444a5403c3652d7b4d2e33c9c42a0781 /src/openvpn/socket.h
parentbb9026a60a8ebdf20fdf9a99e16c0d8afc658747 (diff)
downloadopenvpn-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.h76
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);