android: Add ability to lookup IPv6 source addresses

This commit is contained in:
Tobias Brunner
2020-10-29 10:22:51 +01:00
parent 217d8ab81e
commit 294c022fae
2 changed files with 44 additions and 5 deletions
@@ -545,6 +545,7 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder,
PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"),
PLUGIN_CALLBACK(kernel_net_register, kernel_android_net_create), PLUGIN_CALLBACK(kernel_net_register, kernel_android_net_create),
PLUGIN_PROVIDE(CUSTOM, "kernel-net"), PLUGIN_PROVIDE(CUSTOM, "kernel-net"),
PLUGIN_DEPENDS(CUSTOM, "socket"),
PLUGIN_CALLBACK(charonservice_register, NULL), PLUGIN_CALLBACK(charonservice_register, NULL),
PLUGIN_PROVIDE(CUSTOM, "android-backend"), PLUGIN_PROVIDE(CUSTOM, "android-backend"),
PLUGIN_DEPENDS(CUSTOM, "libcharon"), PLUGIN_DEPENDS(CUSTOM, "libcharon"),
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012-2015 Tobias Brunner * Copyright (C) 2012-2016 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil * HSR Hochschule fuer Technik Rapperswil
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -58,10 +58,15 @@ struct private_android_net_t {
linked_list_t *vips; linked_list_t *vips;
/** /**
* Socket used to determine source address * Socket used to determine source address (IPv4)
*/ */
int socket_v4; 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
*/ */
@@ -116,10 +121,24 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
socklen_t addrlen; socklen_t addrlen;
timeval_t now; timeval_t now;
job_t *job; job_t *job;
int socket;
if (dest->get_family(dest) == AF_INET)
{
socket = this->socket_v4;
}
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); addrlen = *dest->get_sockaddr_len(dest);
addr.sockaddr.sa_family = AF_UNSPEC; addr.sockaddr.sa_family = AF_UNSPEC;
if (connect(this->socket_v4, &addr.sockaddr, addrlen) < 0) if (connect(socket, &addr.sockaddr, addrlen) < 0)
{ {
DBG1(DBG_KNL, "failed to disconnect socket: %s", strerror(errno)); DBG1(DBG_KNL, "failed to disconnect socket: %s", strerror(errno));
return NULL; return NULL;
@@ -129,7 +148,7 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
* at all */ * at all */
charonservice->bypass_socket(charonservice, -1, 0); charonservice->bypass_socket(charonservice, -1, 0);
} }
if (connect(this->socket_v4, dest->get_sockaddr(dest), addrlen) < 0) if (connect(socket, dest->get_sockaddr(dest), 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)
@@ -159,7 +178,7 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
} }
return NULL; return NULL;
} }
if (getsockname(this->socket_v4, &addr.sockaddr, &addrlen) < 0) if (getsockname(socket, &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 NULL;
@@ -276,6 +295,7 @@ METHOD(kernel_net_t, destroy, void,
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_v4);
close(this->socket_v6);
free(this); free(this);
} }
@@ -314,6 +334,24 @@ kernel_net_t *kernel_android_net_create()
} }
charonservice->bypass_socket(charonservice, this->socket_v4, AF_INET); 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);