mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-08 00:02:03 -04:00
android: Use new sockets to determine source IP
Particularly on Samsung devices, the connect() call to dissolve the previous connection on an existing socket via AF_UNSPEC does fail in some situations with ECONNREFUSED: [KNL] failed to disconnect socket: Connection refused While creating a new socket is potentially a bit more overhead, this should avoid the issue. Closes strongswan/strongswan#1691
This commit is contained in:
parent
5005c2e4ab
commit
6d87a86510
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2016 Tobias Brunner
|
* Copyright (C) 2012-2023 Tobias Brunner
|
||||||
*
|
*
|
||||||
* Copyright (C) secunet Security Networks AG
|
* Copyright (C) secunet Security Networks AG
|
||||||
*
|
*
|
||||||
@ -58,16 +58,6 @@ struct private_android_net_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *vips;
|
linked_list_t *vips;
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket used to determine source address (IPv4)
|
|
||||||
*/
|
|
||||||
int socket_v4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket used to determine source address (IPv6)
|
|
||||||
*/
|
|
||||||
int socket_v6;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the device is currently connected
|
* Whether the device is currently connected
|
||||||
*/
|
*/
|
||||||
@ -112,44 +102,34 @@ static void connectivity_cb(private_android_net_t *this,
|
|||||||
}
|
}
|
||||||
|
|
||||||
METHOD(kernel_net_t, get_source_addr, host_t*,
|
METHOD(kernel_net_t, get_source_addr, host_t*,
|
||||||
private_android_net_t *this, host_t *dest, host_t *src)
|
private_android_net_t *this, host_t *dst, host_t *src)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
struct sockaddr sockaddr;
|
struct sockaddr sockaddr;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
struct sockaddr_in6 sin6;
|
struct sockaddr_in6 sin6;
|
||||||
} addr;
|
} addr = {};
|
||||||
socklen_t addrlen;
|
socklen_t addrlen = *dst->get_sockaddr_len(dst);
|
||||||
timeval_t now;
|
timeval_t now;
|
||||||
job_t *job;
|
job_t *job;
|
||||||
int socket;
|
host_t *host = NULL;
|
||||||
|
int skt;
|
||||||
|
|
||||||
if (dest->get_family(dest) == AF_INET)
|
skt = socket(dst->get_family(dst), SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (skt < 0)
|
||||||
{
|
{
|
||||||
socket = this->socket_v4;
|
DBG1(DBG_KNL, "failed to create socket to lookup src addresses: %s",
|
||||||
}
|
strerror(errno));
|
||||||
else
|
|
||||||
{
|
|
||||||
socket = this->socket_v6;
|
|
||||||
}
|
|
||||||
if (socket < 0)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "unable to determine src address for address family");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
addrlen = *dest->get_sockaddr_len(dest);
|
|
||||||
addr.sockaddr.sa_family = AF_UNSPEC;
|
|
||||||
if (connect(socket, &addr.sockaddr, addrlen) < 0)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "failed to disconnect socket: %s", strerror(errno));
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
charonservice->bypass_socket(charonservice, skt, dst->get_family(dst));
|
||||||
|
|
||||||
if (android_sdk_version <= ANDROID_JELLY_BEAN_MR2)
|
if (android_sdk_version <= ANDROID_JELLY_BEAN_MR2)
|
||||||
{ /* this seems to help avoiding the VIP, unless there is no connectivity
|
{ /* this seems to help avoiding the VIP, unless there is no connectivity
|
||||||
* at all */
|
* at all */
|
||||||
charonservice->bypass_socket(charonservice, -1, 0);
|
charonservice->bypass_socket(charonservice, -1, 0);
|
||||||
}
|
}
|
||||||
if (connect(socket, dest->get_sockaddr(dest), addrlen) < 0)
|
if (connect(skt, dst->get_sockaddr(dst), addrlen) < 0)
|
||||||
{
|
{
|
||||||
/* don't report an error if we are not connected (ENETUNREACH) */
|
/* don't report an error if we are not connected (ENETUNREACH) */
|
||||||
if (errno != ENETUNREACH)
|
if (errno != ENETUNREACH)
|
||||||
@ -177,14 +157,17 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
|
|||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (getsockname(socket, &addr.sockaddr, &addrlen) < 0)
|
else if (getsockname(skt, &addr.sockaddr, &addrlen) < 0)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "failed to determine src address: %s", strerror(errno));
|
DBG1(DBG_KNL, "failed to determine src address: %s", strerror(errno));
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
return host_create_from_sockaddr((sockaddr_t*)&addr);
|
else
|
||||||
|
{
|
||||||
|
host = host_create_from_sockaddr((sockaddr_t*)&addr);
|
||||||
|
}
|
||||||
|
close(skt);
|
||||||
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK(vip_equals, bool,
|
CALLBACK(vip_equals, bool,
|
||||||
@ -295,8 +278,6 @@ METHOD(kernel_net_t, destroy, void,
|
|||||||
(void*)connectivity_cb);
|
(void*)connectivity_cb);
|
||||||
this->mutex->destroy(this->mutex);
|
this->mutex->destroy(this->mutex);
|
||||||
this->vips->destroy(this->vips);
|
this->vips->destroy(this->vips);
|
||||||
close(this->socket_v4);
|
|
||||||
close(this->socket_v6);
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,32 +308,6 @@ kernel_net_t *kernel_android_net_create()
|
|||||||
this->public.get_source_addr = _get_source_addr_old;
|
this->public.get_source_addr = _get_source_addr_old;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->socket_v4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
if (this->socket_v4 < 0)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "failed to create socket to lookup src addresses: %s",
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
charonservice->bypass_socket(charonservice, this->socket_v4, AF_INET);
|
|
||||||
|
|
||||||
switch (charon->socket->supported_families(charon->socket))
|
|
||||||
{
|
|
||||||
case SOCKET_FAMILY_IPV6:
|
|
||||||
case SOCKET_FAMILY_BOTH:
|
|
||||||
this->socket_v6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
if (this->socket_v6 < 0)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "failed to create socket to lookup IPv6 src "
|
|
||||||
"addresses: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
charonservice->bypass_socket(charonservice, this->socket_v6,
|
|
||||||
AF_INET6);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this->socket_v6 = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
this->network_manager->add_connectivity_cb(
|
this->network_manager->add_connectivity_cb(
|
||||||
this->network_manager, (void*)connectivity_cb, this);
|
this->network_manager, (void*)connectivity_cb, this);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user