Removed backend for old Android frontend patch
authorTobias Brunner <tobias@strongswan.org>
Sat, 2 Mar 2013 14:57:00 +0000 (15:57 +0100)
committerTobias Brunner <tobias@strongswan.org>
Sat, 2 Mar 2013 17:27:23 +0000 (18:27 +0100)
Moved the remaining DNS handler to a new plugin.

18 files changed:
Android.mk
configure.in
src/libcharon/Android.mk
src/libcharon/Makefile.am
src/libcharon/plugins/android/Makefile.am [deleted file]
src/libcharon/plugins/android/android_creds.c [deleted file]
src/libcharon/plugins/android/android_creds.h [deleted file]
src/libcharon/plugins/android/android_handler.c [deleted file]
src/libcharon/plugins/android/android_handler.h [deleted file]
src/libcharon/plugins/android/android_plugin.c [deleted file]
src/libcharon/plugins/android/android_plugin.h [deleted file]
src/libcharon/plugins/android/android_service.c [deleted file]
src/libcharon/plugins/android/android_service.h [deleted file]
src/libcharon/plugins/android_dns/Makefile.am [new file with mode: 0644]
src/libcharon/plugins/android_dns/android_dns_handler.c [new file with mode: 0644]
src/libcharon/plugins/android_dns/android_dns_handler.h [new file with mode: 0644]
src/libcharon/plugins/android_dns/android_dns_plugin.c [new file with mode: 0644]
src/libcharon/plugins/android_dns/android_dns_plugin.h [new file with mode: 0644]

index 0b8da5b..b17a3f6 100644 (file)
@@ -17,7 +17,7 @@ include $(CLEAR_VARS)
 # this is the list of plugins that are built into libstrongswan and charon
 # also these plugins are loaded by default (if not changed in strongswan.conf)
 strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \
-       pkcs1 pkcs8 pem xcbc hmac kernel-netlink socket-default android \
+       pkcs1 pkcs8 pem xcbc hmac kernel-netlink socket-default android-dns \
        stroke eap-identity eap-mschapv2 eap-md5 eap-gtc
 
 ifneq ($(strongswan_BUILD_SCEPCLIENT),)
index a2b36b2..0535be1 100644 (file)
@@ -218,7 +218,7 @@ ARG_ENABL_SET([gcm],            [enables the GCM AEAD wrapper crypto plugin.])
 ARG_ENABL_SET([addrblock],      [enables RFC 3779 address block constraint support.])
 ARG_ENABL_SET([unity],          [enables Cisco Unity extension plugin.])
 ARG_ENABL_SET([uci],            [enable OpenWRT UCI configuration plugin.])
-ARG_ENABL_SET([android],        [enable Android specific plugin.])
+ARG_ENABL_SET([android-dns],    [enable Android specific DNS handler.])
 ARG_ENABL_SET([android-log],    [enable Android specific logger plugin.])
 ARG_ENABL_SET([maemo],          [enable Maemo specific plugin.])
 ARG_ENABL_SET([nm],             [enable NetworkManager backend.])
@@ -800,7 +800,7 @@ if test x$uci = xtrue; then
        AC_CHECK_HEADER([uci.h],,[AC_MSG_ERROR([UCI header uci.h not found!])])
 fi
 
-if test x$android = xtrue; then
+if test x$android_dns = xtrue; then
        AC_CHECK_LIB([cutils],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([Android library libcutils not found])],[])
        AC_CHECK_HEADER([cutils/properties.h],,[AC_MSG_ERROR([Android header cutils/properties.h not found!])])
        # we have to force the use of libdl here because the autodetection
@@ -1007,7 +1007,7 @@ ADD_PLUGIN([tnccs-dynamic],        [c charon])
 ADD_PLUGIN([medsrv],               [c charon])
 ADD_PLUGIN([medcli],               [c charon])
 ADD_PLUGIN([dhcp],                 [c charon])
-ADD_PLUGIN([android],              [c charon])
+ADD_PLUGIN([android-dns],          [c charon])
 ADD_PLUGIN([android-log],          [c charon])
 ADD_PLUGIN([ha],                   [c charon])
 ADD_PLUGIN([whitelist],            [c charon])
@@ -1095,7 +1095,7 @@ AM_CONDITIONAL(USE_STROKE, test x$stroke = xtrue)
 AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue)
 AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue)
 AM_CONDITIONAL(USE_UCI, test x$uci = xtrue)
-AM_CONDITIONAL(USE_ANDROID, test x$android = xtrue)
+AM_CONDITIONAL(USE_ANDROID_DNS, test x$android_dns = xtrue)
 AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue)
 AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue)
 AM_CONDITIONAL(USE_SMP, test x$smp = xtrue)
@@ -1357,7 +1357,7 @@ AC_CONFIG_FILES([
        src/libcharon/plugins/duplicheck/Makefile
        src/libcharon/plugins/coupling/Makefile
        src/libcharon/plugins/radattr/Makefile
-       src/libcharon/plugins/android/Makefile
+       src/libcharon/plugins/android_dns/Makefile
        src/libcharon/plugins/android_log/Makefile
        src/libcharon/plugins/maemo/Makefile
        src/libcharon/plugins/stroke/Makefile
index b64174f..a931908 100644 (file)
@@ -125,9 +125,8 @@ processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h
 
 # adding the plugin source files
 
-LOCAL_SRC_FILES += $(call add_plugin, android)
-ifneq ($(call plugin_enabled, android),)
-LOCAL_C_INCLUDES += frameworks/base/cmds/keystore
+LOCAL_SRC_FILES += $(call add_plugin, android-dns)
+ifneq ($(call plugin_enabled, android-dns),)
 LOCAL_SHARED_LIBRARIES += libcutils
 endif
 
index 6b8aa0f..536bab4 100644 (file)
@@ -457,10 +457,10 @@ if MONOLITHIC
 endif
 endif
 
-if USE_ANDROID
-  SUBDIRS += plugins/android
+if USE_ANDROID_DNS
+  SUBDIRS += plugins/android_dns
 if MONOLITHIC
-  libcharon_la_LIBADD += plugins/android/libstrongswan-android.la
+  libcharon_la_LIBADD += plugins/android_dns/libstrongswan-android-dns.la
 endif
 endif
 
diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am
deleted file mode 100644 (file)
index b10cd95..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
-       -I$(top_srcdir)/src/libcharon
-
-AM_CFLAGS = -rdynamic
-
-if MONOLITHIC
-noinst_LTLIBRARIES = libstrongswan-android.la
-else
-plugin_LTLIBRARIES = libstrongswan-android.la
-endif
-
-libstrongswan_android_la_SOURCES = \
-       android_plugin.c android_plugin.h \
-       android_service.c android_service.h \
-       android_handler.c android_handler.h \
-       android_creds.c android_creds.h
-
-libstrongswan_android_la_LDFLAGS = -module -avoid-version
-libstrongswan_android_la_LIBADD  = -lcutils
diff --git a/src/libcharon/plugins/android/android_creds.c b/src/libcharon/plugins/android/android_creds.c
deleted file mode 100644 (file)
index 601c91e..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <keystore_get.h>
-
-#include "android_creds.h"
-
-#include <daemon.h>
-#include <threading/rwlock.h>
-
-typedef struct private_android_creds_t private_android_creds_t;
-
-/**
- * Private data of an android_creds_t object
- */
-struct private_android_creds_t {
-
-       /**
-        * Public interface
-        */
-       android_creds_t public;
-
-       /**
-        * List of trusted certificates, certificate_t*
-        */
-       linked_list_t *certs;
-
-       /**
-        * User name (ID)
-        */
-       identification_t *user;
-
-       /**
-        * User password
-        */
-       char *pass;
-
-       /**
-        * read/write lock
-        */
-       rwlock_t *lock;
-
-};
-
-/**
- * Certificate enumerator data
- */
-typedef struct {
-       private_android_creds_t *this;
-       key_type_t key;
-       identification_t *id;
-} cert_data_t;
-
-/**
- * Filter function for certificates enumerator
- */
-static bool cert_filter(cert_data_t *data, certificate_t **in,
-                                               certificate_t **out)
-{
-       certificate_t *cert = *in;
-       public_key_t *public;
-
-       public = cert->get_public_key(cert);
-       if (!public)
-       {
-               return FALSE;
-       }
-       if (data->key != KEY_ANY && public->get_type(public) != data->key)
-       {
-               public->destroy(public);
-               return FALSE;
-       }
-       if (data->id && data->id->get_type(data->id) == ID_KEY_ID &&
-               public->has_fingerprint(public, data->id->get_encoding(data->id)))
-       {
-               public->destroy(public);
-               *out = cert;
-               return TRUE;
-       }
-       public->destroy(public);
-       if (data->id && !cert->has_subject(cert, data->id))
-       {
-               return FALSE;
-       }
-       *out = cert;
-       return TRUE;
-}
-
-/**
- * Destroy certificate enumerator data
- */
-static void cert_data_destroy(cert_data_t *this)
-{
-       this->this->lock->unlock(this->this->lock);
-       free(this);
-}
-
-METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
-          private_android_creds_t *this, certificate_type_t cert, key_type_t key,
-          identification_t *id, bool trusted)
-{
-       if (cert == CERT_X509 || cert == CERT_ANY)
-       {
-               cert_data_t *data;
-               this->lock->read_lock(this->lock);
-               INIT(data, .this = this, .id = id, .key = key);
-               return enumerator_create_filter(
-                                               this->certs->create_enumerator(this->certs),
-                                               (void*)cert_filter, data, (void*)cert_data_destroy);
-       }
-       return NULL;
-}
-
-/**
- * Shared key enumerator implementation
- */
-typedef struct {
-       enumerator_t public;
-       private_android_creds_t *this;
-       shared_key_t *key;
-       bool done;
-} shared_enumerator_t;
-
-METHOD(enumerator_t, shared_enumerate, bool,
-          shared_enumerator_t *this, shared_key_t **key, id_match_t *me,
-          id_match_t *other)
-{
-       if (this->done)
-       {
-               return FALSE;
-       }
-       *key = this->key;
-       *me = ID_MATCH_PERFECT;
-       *other = ID_MATCH_ANY;
-       this->done = TRUE;
-       return TRUE;
-}
-
-METHOD(enumerator_t, shared_destroy, void,
-          shared_enumerator_t *this)
-{
-       this->key->destroy(this->key);
-       this->this->lock->unlock(this->this->lock);
-       free(this);
-}
-
-METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
-          private_android_creds_t *this, shared_key_type_t type,
-          identification_t *me, identification_t *other)
-{
-       shared_enumerator_t *enumerator;
-
-       this->lock->read_lock(this->lock);
-
-       if (!this->user || !this->pass)
-       {
-               this->lock->unlock(this->lock);
-               return NULL;
-       }
-       if (type != SHARED_EAP && type != SHARED_IKE)
-       {
-               this->lock->unlock(this->lock);
-               return NULL;
-       }
-       if (me && !me->equals(me, this->user))
-       {
-               this->lock->unlock(this->lock);
-               return NULL;
-       }
-
-       INIT(enumerator,
-               .public = {
-                       .enumerate = (void*)_shared_enumerate,
-                       .destroy = _shared_destroy,
-               },
-               .this = this,
-               .done = FALSE,
-               .key = shared_key_create(type, chunk_clone(chunk_create(this->pass,
-                                                                                                  strlen(this->pass)))),
-       );
-       return &enumerator->public;
-}
-
-METHOD(android_creds_t, add_certificate, bool,
-          private_android_creds_t *this, char *name)
-{
-       certificate_t *cert = NULL;
-       bool status = FALSE;
-       chunk_t chunk;
-#ifdef KEYSTORE_MESSAGE_SIZE
-       /* most current interface, the eclair interface (without key length) is
-        * currently not supported */
-       char value[KEYSTORE_MESSAGE_SIZE];
-       chunk.ptr = value;
-       chunk.len = keystore_get(name, strlen(name), chunk.ptr);
-       if (chunk.len > 0)
-#else
-       /* 1.6 interface, allocates memory */
-       chunk.ptr = keystore_get(name, &chunk.len);
-       if (chunk.ptr)
-#endif /* KEYSTORE_MESSAGE_SIZE */
-       {
-               cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
-                                                                 BUILD_BLOB_PEM, chunk, BUILD_END);
-               if (cert)
-               {
-                       this->lock->write_lock(this->lock);
-                       this->certs->insert_last(this->certs, cert);
-                       this->lock->unlock(this->lock);
-                       status = TRUE;
-               }
-#ifndef KEYSTORE_MESSAGE_SIZE
-               free(chunk.ptr);
-#endif /* KEYSTORE_MESSAGE_SIZE */
-       }
-       return status;
-}
-
-METHOD(android_creds_t, set_username_password, void,
-          private_android_creds_t *this, identification_t *id, char *password)
-{
-       this->lock->write_lock(this->lock);
-       DESTROY_IF(this->user);
-       this->user = id->clone(id);
-       free(this->pass);
-       this->pass = strdupnull(password);
-       this->lock->unlock(this->lock);
-}
-
-METHOD(android_creds_t, clear, void,
-          private_android_creds_t *this)
-{
-       certificate_t *cert;
-       this->lock->write_lock(this->lock);
-       while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS)
-       {
-               cert->destroy(cert);
-       }
-       DESTROY_IF(this->user);
-       free(this->pass);
-       this->user = NULL;
-       this->pass = NULL;
-       this->lock->unlock(this->lock);
-}
-
-METHOD(android_creds_t, destroy, void,
-          private_android_creds_t *this)
-{
-       clear(this);
-       this->certs->destroy(this->certs);
-       this->lock->destroy(this->lock);
-       free(this);
-}
-
-/**
- * Described in header.
- */
-android_creds_t *android_creds_create()
-{
-       private_android_creds_t *this;
-
-       INIT(this,
-               .public = {
-                       .set = {
-                               .create_cert_enumerator = _create_cert_enumerator,
-                               .create_shared_enumerator = _create_shared_enumerator,
-                               .create_private_enumerator = (void*)return_null,
-                               .create_cdp_enumerator = (void*)return_null,
-                               .cache_cert = (void*)nop,
-                       },
-                       .add_certificate = _add_certificate,
-                       .set_username_password = _set_username_password,
-                       .clear = _clear,
-                       .destroy = _destroy,
-               },
-               .certs = linked_list_create(),
-               .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
-       );
-
-       return &this->public;
-}
-
diff --git a/src/libcharon/plugins/android/android_creds.h b/src/libcharon/plugins/android/android_creds.h
deleted file mode 100644 (file)
index 0f7b8e0..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup android_creds android_creds
- * @{ @ingroup android
- */
-
-#ifndef ANDROID_CREDS_H_
-#define ANDROID_CREDS_H_
-
-#include <credentials/credential_set.h>
-
-typedef struct android_creds_t android_creds_t;
-
-/**
- * Android credentials helper.
- */
-struct android_creds_t {
-
-       /**
-        * Implements credential_set_t
-        */
-       credential_set_t set;
-
-       /**
-        * Add a trusted CA certificate from the Android keystore to serve by
-        * this set.
-        *
-        * @param name          name/ID of the certificate in the keystore
-        * @return                      FALSE if the certificate does not exist or is invalid
-        */
-       bool (*add_certificate)(android_creds_t *this, char *name);
-
-       /**
-        * Set the username and password for authentication.
-        *
-        * @param id            ID of the user
-        * @param password      password to use for authentication
-        */
-       void (*set_username_password)(android_creds_t *this, identification_t *id,
-                                                                 char *password);
-
-       /**
-        * Clear the stored credentials.
-        */
-       void (*clear)(android_creds_t *this);
-
-       /**
-        * Destroy a android_creds instance.
-        */
-       void (*destroy)(android_creds_t *this);
-
-};
-
-/**
- * Create an android_creds instance.
- */
-android_creds_t *android_creds_create();
-
-#endif /** ANDROID_CREDS_H_ @}*/
diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android/android_handler.c
deleted file mode 100644 (file)
index 29dbbbf..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Tobias Brunner
- * Copyright (C) 2010 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include "android_handler.h"
-
-#include <networking/host.h>
-#include <collections/linked_list.h>
-
-#include <cutils/properties.h>
-
-typedef struct private_android_handler_t private_android_handler_t;
-
-/**
- * Private data of an android_handler_t object.
- */
-struct private_android_handler_t {
-
-       /**
-        * Public android_handler_t interface.
-        */
-       android_handler_t public;
-
-       /**
-        * List of registered DNS servers
-        */
-       linked_list_t *dns;
-
-       /**
-        * Whether the VPN frontend is used
-        */
-       bool frontend;
-};
-
-/**
- * Prefixes to be used when installing DNS servers
- */
-#define DNS_PREFIX_DEFAULT  "net"
-#define DNS_PREFIX_FRONTEND "vpn"
-
-/**
- * Struct to store a pair of old and installed DNS servers
- */
-typedef struct {
-       /** installed dns server */
-       host_t *dns;
-       /** old dns server */
-       host_t *old;
-} dns_pair_t;
-
-/**
- * Destroy a pair of old and installed DNS servers
- */
-void destroy_dns_pair(dns_pair_t *this)
-{
-       DESTROY_IF(this->dns);
-       DESTROY_IF(this->old);
-       free(this);
-}
-
-/**
- * Filter pairs of DNS servers
- */
-bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out)
-{
-       *out = (*in)->dns;
-       return TRUE;
-}
-
-/**
- * Read DNS server property with a given index
- */
-host_t *get_dns_server(private_android_handler_t *this, int index)
-{
-       host_t *dns = NULL;
-       char key[10], value[PROPERTY_VALUE_MAX],
-                *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT;
-
-       if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key))
-       {
-               return NULL;
-       }
-
-       if (property_get(key, value, NULL) > 0)
-       {
-               dns = host_create_from_string(value, 0);
-       }
-       return dns;
-}
-
-/**
- * Set DNS server property with a given index
- */
-bool set_dns_server(private_android_handler_t *this, int index, host_t *dns)
-{
-       char key[10], value[PROPERTY_VALUE_MAX],
-                *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT;
-
-       if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key))
-       {
-               return FALSE;
-       }
-
-       if (dns)
-       {
-               if (snprintf(value, sizeof(value), "%H", dns) >= sizeof(value))
-               {
-                       return FALSE;
-               }
-       }
-       else
-       {
-               value[0] = '\0';
-       }
-
-       if (property_set(key, value) != 0)
-       {
-               return FALSE;
-       }
-       return TRUE;
-}
-
-METHOD(attribute_handler_t, handle, bool,
-       private_android_handler_t *this, identification_t *id,
-       configuration_attribute_type_t type, chunk_t data)
-{
-       switch (type)
-       {
-               case INTERNAL_IP4_DNS:
-               {
-                       host_t *dns;
-                       dns_pair_t *pair;
-                       int index;
-
-                       dns = host_create_from_chunk(AF_INET, data, 0);
-                       if (dns)
-                       {
-                               pair = malloc_thing(dns_pair_t);
-                               pair->dns = dns;
-                               index = this->dns->get_count(this->dns) + 1;
-                               pair->old = get_dns_server(this, index);
-                               set_dns_server(this, index, dns);
-                               this->dns->insert_last(this->dns, pair);
-                               return TRUE;
-                       }
-                       return FALSE;
-               }
-               default:
-                       return FALSE;
-       }
-}
-
-METHOD(attribute_handler_t, release, void,
-       private_android_handler_t *this, identification_t *server,
-       configuration_attribute_type_t type, chunk_t data)
-{
-       if (type == INTERNAL_IP4_DNS)
-       {
-               enumerator_t *enumerator;
-               dns_pair_t *pair;
-               int index;
-
-               enumerator = this->dns->create_enumerator(this->dns);
-               for (index = 1; enumerator->enumerate(enumerator, &pair); index++)
-               {
-                       if (chunk_equals(pair->dns->get_address(pair->dns), data))
-                       {
-                               this->dns->remove_at(this->dns, enumerator);
-                               set_dns_server(this, index, pair->old);
-                               destroy_dns_pair(pair);
-                       }
-               }
-               enumerator->destroy(enumerator);
-       }
-}
-
-METHOD(enumerator_t, enumerate_dns, bool,
-       enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data)
-{
-       *type = INTERNAL_IP4_DNS;
-       *data = chunk_empty;
-       /* stop enumeration */
-       this->enumerate = (void*)return_false;
-       return TRUE;
-}
-
-METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
-       android_handler_t *this, identification_t *id, linked_list_t *vips)
-{
-       enumerator_t *enumerator;
-
-       INIT(enumerator,
-               .enumerate = (void*)_enumerate_dns,
-               .destroy = (void*)free,
-       );
-       return enumerator;
-}
-
-METHOD(android_handler_t, destroy, void,
-       private_android_handler_t *this)
-{
-       this->dns->destroy_function(this->dns, (void*)destroy_dns_pair);
-       free(this);
-}
-
-/**
- * See header
- */
-android_handler_t *android_handler_create(bool frontend)
-{
-       private_android_handler_t *this;
-
-       INIT(this,
-               .public = {
-                       .handler = {
-                               .handle = _handle,
-                               .release = _release,
-                               .create_attribute_enumerator = _create_attribute_enumerator,
-                       },
-                       .destroy = _destroy,
-               },
-               .dns = linked_list_create(),
-               .frontend = frontend,
-       );
-
-       return &this->public;
-}
-
diff --git a/src/libcharon/plugins/android/android_handler.h b/src/libcharon/plugins/android/android_handler.h
deleted file mode 100644 (file)
index 0170958..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Tobias Brunner
- * Copyright (C) 2010 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup android_handler android_handler
- * @{ @ingroup android
- */
-
-#ifndef ANDROID_HANDLER_H_
-#define ANDROID_HANDLER_H_
-
-#include <attributes/attribute_handler.h>
-
-typedef struct android_handler_t android_handler_t;
-
-/**
- * Android specific DNS attribute handler.
- */
-struct android_handler_t {
-
-       /**
-        * Implements attribute_handler_t.
-        */
-       attribute_handler_t handler;
-
-       /**
-        * Destroy a android_handler_t.
-        */
-       void (*destroy)(android_handler_t *this);
-};
-
-/**
- * Create a android_handler instance.
- *
- * @param frontend             TRUE if the VPN frontend is used
- */
-android_handler_t *android_handler_create(bool frontend);
-
-#endif /** ANDROID_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android/android_plugin.c
deleted file mode 100644 (file)
index c0f58e9..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Copyright (C) 2010 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include "android_plugin.h"
-#include "android_handler.h"
-#include "android_creds.h"
-#include "android_service.h"
-
-#include <hydra.h>
-#include <daemon.h>
-
-typedef struct private_android_plugin_t private_android_plugin_t;
-
-/**
- * Private data of an android_plugin_t object.
- */
-struct private_android_plugin_t {
-
-       /**
-        * Public android_plugin_t interface.
-        */
-       android_plugin_t public;
-
-       /**
-        * Android specific DNS handler
-        */
-       android_handler_t *handler;
-
-       /**
-        * Android specific credential set
-        */
-       android_creds_t *creds;
-
-       /**
-        * Service that interacts with the Android Settings frontend
-        */
-       android_service_t *service;
-};
-
-METHOD(plugin_t, get_name, char*,
-       private_android_plugin_t *this)
-{
-       return "android";
-}
-
-METHOD(plugin_t, destroy, void,
-       private_android_plugin_t *this)
-{
-       hydra->attributes->remove_handler(hydra->attributes,
-                                                                         &this->handler->handler);
-       lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
-       this->creds->destroy(this->creds);
-       this->handler->destroy(this->handler);
-       DESTROY_IF(this->service);
-       free(this);
-}
-
-/**
- * See header
- */
-plugin_t *android_plugin_create()
-{
-       private_android_plugin_t *this;
-
-       INIT(this,
-               .public = {
-                       .plugin = {
-                               .get_name = _get_name,
-                               .reload = (void*)return_false,
-                               .destroy = _destroy,
-                       },
-               },
-               .creds = android_creds_create(),
-       );
-
-       this->service = android_service_create(this->creds);
-       this->handler = android_handler_create(this->service != NULL);
-
-       lib->credmgr->add_set(lib->credmgr, &this->creds->set);
-       hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
-
-       return &this->public.plugin;
-}
-
diff --git a/src/libcharon/plugins/android/android_plugin.h b/src/libcharon/plugins/android/android_plugin.h
deleted file mode 100644 (file)
index 987f2aa..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup android android
- * @ingroup cplugins
- *
- * @defgroup android_plugin android_plugin
- * @{ @ingroup android
- */
-
-#ifndef ANDROID_PLUGIN_H_
-#define ANDROID_PLUGIN_H_
-
-#include <plugins/plugin.h>
-
-typedef struct android_plugin_t android_plugin_t;
-
-/**
- * Plugin providing functionality specific to the Android platform.
- */
-struct android_plugin_t {
-
-       /**
-        * Implements plugin interface.
-        */
-       plugin_t plugin;
-};
-
-#endif /** ANDROID_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
deleted file mode 100644 (file)
index 9b9bcc3..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <unistd.h>
-#include <cutils/sockets.h>
-#include <cutils/properties.h>
-#include <signal.h>
-
-#include "android_service.h"
-
-#include <daemon.h>
-#include <threading/thread.h>
-#include <processing/jobs/callback_job.h>
-
-typedef struct private_android_service_t private_android_service_t;
-
-/**
- * private data of Android service
- */
-struct private_android_service_t {
-
-       /**
-        * public interface
-        */
-       android_service_t public;
-
-       /**
-        * current IKE_SA
-        */
-       ike_sa_t *ike_sa;
-
-       /**
-        * android credentials
-        */
-       android_creds_t *creds;
-
-       /**
-        * android control socket
-        */
-       int control;
-
-};
-
-/**
- * Some of the error codes defined in VpnManager.java
- */
-typedef enum {
-       /** Error code to indicate an error from authentication. */
-       VPN_ERROR_AUTH = 51,
-       /** Error code to indicate the connection attempt failed. */
-       VPN_ERROR_CONNECTION_FAILED = 101,
-       /** Error code to indicate an error of remote server hanging up. */
-       VPN_ERROR_REMOTE_HUNG_UP = 7,
-       /** Error code to indicate an error of losing connectivity. */
-       VPN_ERROR_CONNECTION_LOST = 103,
-} android_vpn_errors_t;
-
-/**
- * send a status code back to the Android app
- */
-static void send_status(private_android_service_t *this, u_char code)
-{
-       DBG1(DBG_CFG, "status of Android plugin changed: %d", code);
-       send(this->control, &code, 1, 0);
-}
-
-METHOD(listener_t, ike_updown, bool,
-          private_android_service_t *this, ike_sa_t *ike_sa, bool up)
-{
-       /* this callback is only registered during initiation, so if the IKE_SA
-        * goes down we assume an authentication error */
-       if (this->ike_sa == ike_sa && !up)
-       {
-               send_status(this, VPN_ERROR_AUTH);
-               return FALSE;
-       }
-       return TRUE;
-}
-
-METHOD(listener_t, child_state_change, bool,
-          private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
-          child_sa_state_t state)
-{
-       /* this callback is only registered during initiation, so we still have
-        * the control socket open */
-       if (this->ike_sa == ike_sa && state == CHILD_DESTROYING)
-       {
-               send_status(this, VPN_ERROR_CONNECTION_FAILED);
-               return FALSE;
-       }
-       return TRUE;
-}
-
-/**
- * Callback used to shutdown the daemon
- */
-static job_requeue_t shutdown_callback(void *data)
-{
-       kill(0, SIGTERM);
-       return JOB_REQUEUE_NONE;
-}
-
-METHOD(listener_t, child_updown, bool,
-          private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
-          bool up)
-{
-       if (this->ike_sa == ike_sa)
-       {
-               if (up)
-               {
-                       /* disable the hooks registered to catch initiation failures */
-                       this->public.listener.ike_updown = NULL;
-                       this->public.listener.child_state_change = NULL;
-                       property_set("vpn.status", "ok");
-               }
-               else
-               {
-                       callback_job_t *job;
-                       /* the control socket is closed as soon as vpn.status is set to "ok"
-                        * and the daemon proxy then only checks for terminated daemons to
-                        * detect lost connections, so... */
-                       DBG1(DBG_CFG, "connection lost, raising delayed SIGTERM");
-                       /* to avoid any conflicts we send the SIGTERM not directly from this
-                        * callback, but from a different thread. we also delay it to avoid
-                        * a race condition during a regular shutdown */
-                       job = callback_job_create(shutdown_callback, NULL, NULL, NULL);
-                       lib->scheduler->schedule_job(lib->scheduler, (job_t*)job, 1);
-                       return FALSE;
-               }
-       }
-       return TRUE;
-}
-
-METHOD(listener_t, ike_rekey, bool,
-          private_android_service_t *this, ike_sa_t *old, ike_sa_t *new)
-{
-       if (this->ike_sa == old)
-       {
-               this->ike_sa = new;
-       }
-       return TRUE;
-}
-
-/**
- * Read a string argument from the Android control socket
- */
-static char *read_argument(int fd, u_char length)
-{
-       int offset = 0;
-       char *data = malloc(length + 1);
-       while (offset < length)
-       {
-               int n = recv(fd, &data[offset], length - offset, 0);
-               if (n < 0)
-               {
-                       DBG1(DBG_CFG, "failed to read argument from Android"
-                                " control socket: %s", strerror(errno));
-                       free(data);
-                       return NULL;
-               }
-               offset += n;
-       }
-       data[length] = '\0';
-       DBG3(DBG_CFG, "received argument from Android control socket: %s", data);
-       return data;
-}
-
-/**
- * handle the request received from the Android control socket
- */
-static job_requeue_t initiate(private_android_service_t *this)
-{
-       bool oldstate;
-       int fd, i = 0;
-       char *hostname = NULL, *cacert = NULL, *username = NULL, *password = NULL;
-       identification_t *gateway = NULL, *user = NULL;
-       ike_cfg_t *ike_cfg;
-       peer_cfg_t *peer_cfg;
-       child_cfg_t *child_cfg;
-       traffic_selector_t *ts;
-       ike_sa_t *ike_sa;
-       auth_cfg_t *auth;
-       lifetime_cfg_t lifetime = {
-               .time = {
-                       .life = 10800, /* 3h */
-                       .rekey = 10200, /* 2h50min */
-                       .jitter = 300 /* 5min */
-               }
-       };
-
-       fd = accept(this->control, NULL, 0);
-       if (fd < 0)
-       {
-               DBG1(DBG_CFG, "accept on Android control socket failed: %s",
-                        strerror(errno));
-               return JOB_REQUEUE_NONE;
-       }
-       /* the original control socket is not used anymore */
-       close(this->control);
-       this->control = fd;
-
-       while (TRUE)
-       {
-               u_char length;
-               if (recv(fd, &length, 1, 0) != 1)
-               {
-                       DBG1(DBG_CFG, "failed to read from Android control socket: %s",
-                                strerror(errno));
-                       return JOB_REQUEUE_NONE;
-               }
-
-               if (length == 0xFF)
-               {       /* last argument */
-                       break;
-               }
-               else
-               {
-                       switch (i++)
-                       {
-                               case 0: /* gateway */
-                                       hostname = read_argument(fd, length);
-                                       break;
-                               case 1: /* CA certificate name */
-                                       cacert = read_argument(fd, length);
-                                       break;
-                               case 2: /* username */
-                                       username = read_argument(fd, length);
-                                       break;
-                               case 3: /* password */
-                                       password = read_argument(fd, length);
-                                       break;
-                       }
-               }
-       }
-
-       if (cacert)
-       {
-               if (!this->creds->add_certificate(this->creds, cacert))
-               {
-                       DBG1(DBG_CFG, "failed to load CA certificate");
-               }
-               /* if this is a server cert we could use the cert subject as id
-                * but we have to test first if that possible to configure */
-       }
-
-       gateway = identification_create_from_string(hostname);
-       DBG1(DBG_CFG, "using CA certificate, gateway identitiy '%Y'", gateway);
-
-       if (username)
-       {
-               user = identification_create_from_string(username);
-               this->creds->set_username_password(this->creds, user, password);
-       }
-
-       ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE,
-                                                        charon->socket->get_port(charon->socket, FALSE),
-                                                        hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO,
-                                                        0);
-       ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
-
-       peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED,
-                                                          UNIQUE_REPLACE, 1, /* keyingtries */
-                                                          36000, 0, /* rekey 10h, reauth none */
-                                                          600, 600, /* jitter, over 10min */
-                                                          TRUE, FALSE, /* mobike, aggressive */
-                                                          0, 0, /* DPD delay, timeout */
-                                                          FALSE, NULL, NULL); /* mediation */
-       peer_cfg->add_virtual_ip(peer_cfg,  host_create_from_string("0.0.0.0", 0));
-
-       auth = auth_cfg_create();
-       auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
-       auth->add(auth, AUTH_RULE_IDENTITY, user);
-       peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
-       auth = auth_cfg_create();
-       auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
-       auth->add(auth, AUTH_RULE_IDENTITY, gateway);
-       peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
-
-       child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
-                                                                ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE,
-                                                                0, 0, NULL, NULL, 0);
-       child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
-       ts = traffic_selector_create_dynamic(0, 0, 65535);
-       child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
-       ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0",
-                                                                                        0, "255.255.255.255", 65535);
-       child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
-       peer_cfg->add_child_cfg(peer_cfg, child_cfg);
-
-       /* get us an IKE_SA */
-       ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
-                                                                                                               peer_cfg);
-       if (!ike_sa)
-       {
-               peer_cfg->destroy(peer_cfg);
-               send_status(this, VPN_ERROR_CONNECTION_FAILED);
-               return JOB_REQUEUE_NONE;
-       }
-
-       if (!ike_sa->get_peer_cfg(ike_sa))
-       {
-               ike_sa->set_peer_cfg(ike_sa, peer_cfg);
-       }
-       peer_cfg->destroy(peer_cfg);
-
-       /* store the IKE_SA so we can track its progress */
-       this->ike_sa = ike_sa;
-
-       /* confirm that we received the request */
-       send_status(this, i);
-
-       /* get an additional reference because initiate consumes one */
-       child_cfg->get_ref(child_cfg);
-       if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
-       {
-               DBG1(DBG_CFG, "failed to initiate tunnel");
-               charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
-                                                                                                       ike_sa);
-               send_status(this, VPN_ERROR_CONNECTION_FAILED);
-               return JOB_REQUEUE_NONE;
-       }
-       charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-       return JOB_REQUEUE_NONE;
-}
-
-METHOD(android_service_t, destroy, void,
-          private_android_service_t *this)
-{
-       charon->bus->remove_listener(charon->bus, &this->public.listener);
-       close(this->control);
-       free(this);
-}
-
-/**
- * See header
- */
-android_service_t *android_service_create(android_creds_t *creds)
-{
-       private_android_service_t *this;
-
-       INIT(this,
-               .public = {
-                       .listener = {
-                               .ike_updown = _ike_updown,
-                               .child_state_change = _child_state_change,
-                               .child_updown = _child_updown,
-                               .ike_rekey = _ike_rekey,
-                       },
-                       .destroy = _destroy,
-               },
-               .creds = creds,
-       );
-
-       this->control = android_get_control_socket("charon");
-       if (this->control == -1)
-       {
-               DBG1(DBG_CFG, "failed to get Android control socket");
-               free(this);
-               return NULL;
-       }
-
-       if (listen(this->control, 1) < 0)
-       {
-               DBG1(DBG_CFG, "failed to listen on Android control socket: %s",
-                        strerror(errno));
-               close(this->control);
-               free(this);
-               return NULL;
-       }
-
-       charon->bus->add_listener(charon->bus, &this->public.listener);
-       lib->processor->queue_job(lib->processor,
-               (job_t*)callback_job_create((callback_job_cb_t)initiate, this,
-                                                                       NULL, NULL));
-
-       return &this->public;
-}
diff --git a/src/libcharon/plugins/android/android_service.h b/src/libcharon/plugins/android/android_service.h
deleted file mode 100644 (file)
index d096d6c..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup android_service android_service
- * @{ @ingroup android
- */
-
-#ifndef ANDROID_SERVICE_H_
-#define ANDROID_SERVICE_H_
-
-typedef struct android_service_t android_service_t;
-
-#include <bus/listeners/listener.h>
-
-#include "android_creds.h"
-
-/**
- * Service that interacts with the Android Settings frontend.
- */
-struct android_service_t {
-
-       /**
-        * Implements listener_t.
-        */
-       listener_t listener;
-
-       /**
-        * Destroy a android_service_t.
-        */
-       void (*destroy)(android_service_t *this);
-
-};
-
-/**
- * Create an Android service instance.
- *
- * @param creds                Android credentials
- */
-android_service_t *android_service_create(android_creds_t *creds);
-
-#endif /** ANDROID_SERVICE_H_ @}*/
diff --git a/src/libcharon/plugins/android_dns/Makefile.am b/src/libcharon/plugins/android_dns/Makefile.am
new file mode 100644 (file)
index 0000000..0d25f11
--- /dev/null
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+       -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-android-dns.la
+else
+plugin_LTLIBRARIES = libstrongswan-android-dns.la
+endif
+
+libstrongswan_android_dns_la_SOURCES = \
+       android_dns_plugin.c android_dns_plugin.h \
+       android_dns_handler.c android_dns_handler.h
+
+libstrongswan_android_dns_la_LDFLAGS = -module -avoid-version
+libstrongswan_android_dns_la_LIBADD  = -lcutils
\ No newline at end of file
diff --git a/src/libcharon/plugins/android_dns/android_dns_handler.c b/src/libcharon/plugins/android_dns/android_dns_handler.c
new file mode 100644 (file)
index 0000000..5268103
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2010-2013 Tobias Brunner
+ * Copyright (C) 2010 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "android_dns_handler.h"
+
+#include <networking/host.h>
+#include <collections/linked_list.h>
+
+#include <cutils/properties.h>
+
+typedef struct private_android_dns_handler_t private_android_dns_handler_t;
+
+/**
+ * Private data of an android_dns_handler_t object.
+ */
+struct private_android_dns_handler_t {
+
+       /**
+        * Public interface
+        */
+       android_dns_handler_t public;
+
+       /**
+        * List of registered DNS servers
+        */
+       linked_list_t *dns;
+};
+
+/**
+ * Prefix to be used when installing DNS servers
+ */
+#define DNS_PREFIX_DEFAULT  "net"
+
+/**
+ * Struct to store a pair of old and installed DNS servers
+ */
+typedef struct {
+       /** installed dns server */
+       host_t *dns;
+       /** old dns server */
+       host_t *old;
+} dns_pair_t;
+
+/**
+ * Destroy a pair of old and installed DNS servers
+ */
+static void destroy_dns_pair(dns_pair_t *this)
+{
+       DESTROY_IF(this->dns);
+       DESTROY_IF(this->old);
+       free(this);
+}
+
+/**
+ * Filter pairs of DNS servers
+ */
+static bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out)
+{
+       *out = (*in)->dns;
+       return TRUE;
+}
+
+/**
+ * Read DNS server property with a given index
+ */
+static host_t *get_dns_server(private_android_dns_handler_t *this, int index)
+{
+       host_t *dns = NULL;
+       char key[10], value[PROPERTY_VALUE_MAX],
+                *prefix = DNS_PREFIX_DEFAULT;
+
+       if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key))
+       {
+               return NULL;
+       }
+
+       if (property_get(key, value, NULL) > 0)
+       {
+               dns = host_create_from_string(value, 0);
+       }
+       return dns;
+}
+
+/**
+ * Set DNS server property with a given index
+ */
+static bool set_dns_server(private_android_dns_handler_t *this, int index,
+                                                  host_t *dns)
+{
+       char key[10], value[PROPERTY_VALUE_MAX],
+                *prefix = DNS_PREFIX_DEFAULT;
+
+       if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key))
+       {
+               return FALSE;
+       }
+
+       if (dns)
+       {
+               if (snprintf(value, sizeof(value), "%H", dns) >= sizeof(value))
+               {
+                       return FALSE;
+               }
+       }
+       else
+       {
+               value[0] = '\0';
+       }
+
+       if (property_set(key, value) != 0)
+       {
+               return FALSE;
+       }
+       return TRUE;
+}
+
+METHOD(attribute_handler_t, handle, bool,
+       private_android_dns_handler_t *this, identification_t *id,
+       configuration_attribute_type_t type, chunk_t data)
+{
+       switch (type)
+       {
+               case INTERNAL_IP4_DNS:
+               {
+                       host_t *dns;
+                       dns_pair_t *pair;
+                       int index;
+
+                       dns = host_create_from_chunk(AF_INET, data, 0);
+                       if (dns)
+                       {
+                               pair = malloc_thing(dns_pair_t);
+                               pair->dns = dns;
+                               index = this->dns->get_count(this->dns) + 1;
+                               pair->old = get_dns_server(this, index);
+                               set_dns_server(this, index, dns);
+                               this->dns->insert_last(this->dns, pair);
+                               return TRUE;
+                       }
+                       return FALSE;
+               }
+               default:
+                       return FALSE;
+       }
+}
+
+METHOD(attribute_handler_t, release, void,
+       private_android_dns_handler_t *this, identification_t *server,
+       configuration_attribute_type_t type, chunk_t data)
+{
+       if (type == INTERNAL_IP4_DNS)
+       {
+               enumerator_t *enumerator;
+               dns_pair_t *pair;
+               int index;
+
+               enumerator = this->dns->create_enumerator(this->dns);
+               for (index = 1; enumerator->enumerate(enumerator, &pair); index++)
+               {
+                       if (chunk_equals(pair->dns->get_address(pair->dns), data))
+                       {
+                               this->dns->remove_at(this->dns, enumerator);
+                               set_dns_server(this, index, pair->old);
+                               destroy_dns_pair(pair);
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
+}
+
+METHOD(enumerator_t, enumerate_dns, bool,
+       enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data)
+{
+       *type = INTERNAL_IP4_DNS;
+       *data = chunk_empty;
+       /* stop enumeration */
+       this->enumerate = (void*)return_false;
+       return TRUE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
+       private_android_dns_handler_t *this, identification_t *id,
+       linked_list_t *vips)
+{
+       enumerator_t *enumerator;
+
+       INIT(enumerator,
+               .enumerate = (void*)_enumerate_dns,
+               .destroy = (void*)free,
+       );
+       return enumerator;
+}
+
+METHOD(android_dns_handler_t, destroy, void,
+       private_android_dns_handler_t *this)
+{
+       this->dns->destroy_function(this->dns, (void*)destroy_dns_pair);
+       free(this);
+}
+
+/**
+ * See header
+ */
+android_dns_handler_t *android_dns_handler_create()
+{
+       private_android_dns_handler_t *this;
+
+       INIT(this,
+               .public = {
+                       .handler = {
+                               .handle = _handle,
+                               .release = _release,
+                               .create_attribute_enumerator = _create_attribute_enumerator,
+                       },
+                       .destroy = _destroy,
+               },
+               .dns = linked_list_create(),
+       );
+
+       return &this->public;
+}
+
diff --git a/src/libcharon/plugins/android_dns/android_dns_handler.h b/src/libcharon/plugins/android_dns/android_dns_handler.h
new file mode 100644 (file)
index 0000000..d7b089d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010-2011 Tobias Brunner
+ * Copyright (C) 2010 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup android_dns_handler android_dns_handler
+ * @{ @ingroup android_dns
+ */
+
+#ifndef ANDROID_DNS_HANDLER_H_
+#define ANDROID_DNS_HANDLER_H_
+
+#include <attributes/attribute_handler.h>
+
+typedef struct android_dns_handler_t android_dns_handler_t;
+
+/**
+ * Android specific DNS attribute handler.
+ */
+struct android_dns_handler_t {
+
+       /**
+        * Implements attribute_handler_t.
+        */
+       attribute_handler_t handler;
+
+       /**
+        * Destroy a android_dns_handler_t.
+        */
+       void (*destroy)(android_dns_handler_t *this);
+};
+
+/**
+ * Create an android_dns_handler_t instance.
+ */
+android_dns_handler_t *android_dns_handler_create();
+
+#endif /** ANDROID_DNS_HANDLER_H_ @}*/
diff --git a/src/libcharon/plugins/android_dns/android_dns_plugin.c b/src/libcharon/plugins/android_dns/android_dns_plugin.c
new file mode 100644 (file)
index 0000000..4e2b5f5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010-2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "android_dns_plugin.h"
+#include "android_dns_handler.h"
+
+#include <hydra.h>
+#include <daemon.h>
+
+typedef struct private_android_dns_plugin_t private_android_dns_plugin_t;
+
+/**
+ * Private data of an android_dns_plugin_t object.
+ */
+struct private_android_dns_plugin_t {
+
+       /**
+        * Public interface
+        */
+       android_dns_plugin_t public;
+
+       /**
+        * Android specific DNS handler
+        */
+       android_dns_handler_t *handler;
+};
+
+METHOD(plugin_t, get_name, char*,
+       private_android_dns_plugin_t *this)
+{
+       return "android-dns";
+}
+
+METHOD(plugin_t, destroy, void,
+       private_android_dns_plugin_t *this)
+{
+       hydra->attributes->remove_handler(hydra->attributes,
+                                                                         &this->handler->handler);
+       this->handler->destroy(this->handler);
+       free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *android_dns_plugin_create()
+{
+       private_android_dns_plugin_t *this;
+
+       INIT(this,
+               .public = {
+                       .plugin = {
+                               .get_name = _get_name,
+                               .reload = (void*)return_false,
+                               .destroy = _destroy,
+                       },
+               },
+               .handler = android_dns_handler_create(),
+       );
+
+       hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+
+       return &this->public.plugin;
+}
diff --git a/src/libcharon/plugins/android_dns/android_dns_plugin.h b/src/libcharon/plugins/android_dns/android_dns_plugin.h
new file mode 100644 (file)
index 0000000..e9e57dc
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup android_dns android_dns
+ * @ingroup cplugins
+ *
+ * @defgroup android_dns_plugin android_dns_plugin
+ * @{ @ingroup android_dns
+ */
+
+#ifndef ANDROID_DNS_PLUGIN_H_
+#define ANDROID_DNS_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct android_dns_plugin_t android_dns_plugin_t;
+
+/**
+ * Plugin providing an Android-specific handler for DNS servers.
+ */
+struct android_dns_plugin_t {
+
+       /**
+        * Implements plugin interface.
+        */
+       plugin_t plugin;
+};
+
+#endif /** ANDROID_DNS_PLUGIN_H_ @}*/