diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c index bb8bdba82..6426e4502 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/charonservice.c @@ -545,6 +545,7 @@ static void charonservice_init(JNIEnv *env, jobject service, jobject builder, PLUGIN_PROVIDE(CUSTOM, "kernel-ipsec"), PLUGIN_CALLBACK(kernel_net_register, kernel_android_net_create), PLUGIN_PROVIDE(CUSTOM, "kernel-net"), + PLUGIN_DEPENDS(CUSTOM, "socket"), PLUGIN_CALLBACK(charonservice_register, NULL), PLUGIN_PROVIDE(CUSTOM, "android-backend"), PLUGIN_DEPENDS(CUSTOM, "libcharon"), diff --git a/src/frontends/android/app/src/main/jni/libandroidbridge/kernel/android_net.c b/src/frontends/android/app/src/main/jni/libandroidbridge/kernel/android_net.c index cc6072244..6423df167 100644 --- a/src/frontends/android/app/src/main/jni/libandroidbridge/kernel/android_net.c +++ b/src/frontends/android/app/src/main/jni/libandroidbridge/kernel/android_net.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Tobias Brunner + * Copyright (C) 2012-2016 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * 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; /** - * Socket used to determine source address + * 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 */ @@ -116,10 +121,24 @@ METHOD(kernel_net_t, get_source_addr, host_t*, socklen_t addrlen; timeval_t now; 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); 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)); return NULL; @@ -129,7 +148,7 @@ METHOD(kernel_net_t, get_source_addr, host_t*, * at all */ 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) */ if (errno != ENETUNREACH) @@ -159,7 +178,7 @@ METHOD(kernel_net_t, get_source_addr, host_t*, } 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)); return NULL; @@ -276,6 +295,7 @@ METHOD(kernel_net_t, destroy, void, this->mutex->destroy(this->mutex); this->vips->destroy(this->vips); close(this->socket_v4); + close(this->socket_v6); free(this); } @@ -314,6 +334,24 @@ kernel_net_t *kernel_android_net_create() } 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->network_manager->add_connectivity_cb( this->network_manager, (void*)connectivity_cb, this);