android: Fix kernel-net implementation on Android 4.3 and earlier
Before fwmarks were used protected sockets were bound to the outbound interface via SO_BINDTODEVICE. This does not always seem to work well together with our connect()/getsockname() trick if the server is covered by the traffic selectors. Calling protect() again after disconnecting the socket seems to help, but if there is no connectivity at all we still get the virtual IP back (maybe protect() does not bind the socket to any interface then).
This commit is contained in:
@@ -54,6 +54,8 @@ typedef enum {
|
||||
ANDROID_ICE_CREAM_SANDWICH = 14,
|
||||
ANDROID_ICE_CREAM_SANDWICH_MR1 = 15,
|
||||
ANDROID_JELLY_BEAN = 16,
|
||||
ANDROID_JELLY_BEAN_MR1 = 17,
|
||||
ANDROID_JELLY_BEAN_MR2 = 18,
|
||||
} android_sdk_version_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "android_net.h"
|
||||
|
||||
#include "../android_jni.h"
|
||||
#include "../charonservice.h"
|
||||
#include <hydra.h>
|
||||
#include <processing/jobs/callback_job.h>
|
||||
@@ -114,6 +115,11 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
|
||||
DBG1(DBG_KNL, "failed to disconnect socket: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (android_sdk_version <= ANDROID_JELLY_BEAN_MR2)
|
||||
{ /* this seems to help avoiding the VIP, unless there is no connectivity
|
||||
* at all */
|
||||
charonservice->bypass_socket(charonservice, -1, 0);
|
||||
}
|
||||
if (connect(this->socket_v4, dest->get_sockaddr(dest), addrlen) < 0)
|
||||
{
|
||||
/* don't report an error if we are not connected (ENETUNREACH) */
|
||||
@@ -131,6 +137,29 @@ METHOD(kernel_net_t, get_source_addr, host_t*,
|
||||
return host_create_from_sockaddr((sockaddr_t*)&addr);
|
||||
}
|
||||
|
||||
METHOD(kernel_net_t, get_source_addr_old, host_t*,
|
||||
private_android_net_t *this, host_t *dest, host_t *src)
|
||||
{
|
||||
host_t *host;
|
||||
|
||||
/* on older Android versions we might get the virtual IP back because
|
||||
* the protect() implementation there and connect() don't properly work
|
||||
* together, on newer releases (using fwmarks) that's not a problem */
|
||||
host = get_source_addr(this, dest, src);
|
||||
if (host)
|
||||
{
|
||||
this->mutex->lock(this->mutex);
|
||||
if (this->vips->find_first(this->vips, (void*)host->ip_equals,
|
||||
NULL, host) == SUCCESS)
|
||||
{
|
||||
host->destroy(host);
|
||||
host = NULL;
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
METHOD(kernel_net_t, get_nexthop, host_t*,
|
||||
private_android_net_t *this, host_t *dest, int prefix, host_t *src)
|
||||
{
|
||||
@@ -233,6 +262,11 @@ kernel_net_t *kernel_android_net_create()
|
||||
);
|
||||
timerclear(&this->next_roam);
|
||||
|
||||
if (android_sdk_version <= ANDROID_JELLY_BEAN_MR2)
|
||||
{
|
||||
this->public.get_source_addr = _get_source_addr_old;
|
||||
}
|
||||
|
||||
this->socket_v4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (this->socket_v4 < 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user