Pass a list instead of a single virtual IP to attribute enumerators
authorMartin Willi <martin@revosec.ch>
Mon, 27 Aug 2012 12:09:47 +0000 (14:09 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 30 Aug 2012 14:43:42 +0000 (16:43 +0200)
15 files changed:
src/charon-nm/nm/nm_handler.c
src/frontends/android/jni/libandroidbridge/backend/android_attr.c
src/libcharon/plugins/android/android_handler.c
src/libcharon/plugins/dhcp/dhcp_provider.c
src/libcharon/plugins/stroke/stroke_attribute.c
src/libcharon/plugins/stroke/stroke_handler.c
src/libcharon/sa/ikev1/tasks/mode_config.c
src/libcharon/sa/ikev2/tasks/ike_config.c
src/libhydra/attributes/attribute_handler.h
src/libhydra/attributes/attribute_manager.c
src/libhydra/attributes/attribute_manager.h
src/libhydra/attributes/attribute_provider.h
src/libhydra/plugins/attr/attr_provider.c
src/libhydra/plugins/attr_sql/sql_attribute.c
src/libhydra/plugins/resolve/resolve_handler.c

index 408129e..28aa04b 100644 (file)
@@ -92,15 +92,17 @@ static bool enumerate_dns(enumerator_t *this,
 }
 
 METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
-       private_nm_handler_t *this, identification_t *server, host_t *vip)
+       private_nm_handler_t *this, identification_t *server, linked_list_t *vips)
 {
-       if (vip && vip->get_family(vip) == AF_INET)
-       {       /* no IPv6 attributes yet */
-               enumerator_t *enumerator = malloc_thing(enumerator_t);
-               /* enumerate DNS attribute first ... */
-               enumerator->enumerate = (void*)enumerate_dns;
-               enumerator->destroy = (void*)free;
+       if (vips->get_count(vips))
+       {
+               enumerator_t *enumerator;
 
+               INIT(enumerator,
+                       /* enumerate DNS attribute first ... */
+                       .enumerate = (void*)enumerate_dns,
+                       .destroy = (void*)free,
+               );
                return enumerator;
        }
        return enumerator_create_empty();
index e8c5069..f9e96a7 100644 (file)
@@ -80,7 +80,7 @@ METHOD(enumerator_t, enumerate_dns, bool,
 }
 
 METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
-       private_android_attr_t *this, identification_t *server, host_t *vip)
+       private_android_attr_t *this, identification_t *server, linked_list_t *vips)
 {
        enumerator_t *enumerator;
 
index a53962f..f1d3045 100644 (file)
@@ -196,7 +196,7 @@ METHOD(enumerator_t, enumerate_dns, bool,
 }
 
 METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
-       android_handler_t *this, identification_t *id, host_t *vip)
+       android_handler_t *this, identification_t *id, linked_list_t *vips)
 {
        enumerator_t *enumerator;
 
index a6a8877..7050634 100644 (file)
@@ -130,17 +130,24 @@ METHOD(attribute_provider_t, release_address, bool,
 
 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
        private_dhcp_provider_t *this, char *pool, identification_t *id,
-       host_t *vip)
+       linked_list_t *vips)
 {
-       dhcp_transaction_t *transaction;
+       dhcp_transaction_t *transaction = NULL;
+       enumerator_t *enumerator;
+       host_t *vip;
 
-       if (!vip)
+       this->mutex->lock(this->mutex);
+       enumerator = vips->create_enumerator(vips);
+       while (enumerator->enumerate(enumerator, &vip))
        {
-               return NULL;
+               transaction = this->transactions->get(this->transactions,
+                                                                                         (void*)hash_id_host(id, vip));
+               if (transaction)
+               {
+                       break;
+               }
        }
-       this->mutex->lock(this->mutex);
-       transaction = this->transactions->get(this->transactions,
-                                                                                 (void*)hash_id_host(id, vip));
+       enumerator->destroy(enumerator);
        if (!transaction)
        {
                this->mutex->unlock(this->mutex);
index ebae6fc..cec6334 100644 (file)
@@ -149,7 +149,7 @@ static bool attr_filter(void *lock, host_t **in,
 
 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
        private_stroke_attribute_t *this, char *pool, identification_t *id,
-       host_t *vip)
+       linked_list_t *vips)
 {
        ike_sa_t *ike_sa;
        peer_cfg_t *peer_cfg;
index e15daf4..523151e 100644 (file)
@@ -94,7 +94,8 @@ static bool attr_filter(void *lock, host_t **in,
 }
 
 METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
-       private_stroke_handler_t *this, identification_t *server, host_t *vip)
+       private_stroke_handler_t *this, identification_t *server,
+       linked_list_t *vips)
 {
        ike_sa_t *ike_sa;
        peer_cfg_t *peer_cfg;
index bad599b..6b8ed07 100644 (file)
@@ -239,30 +239,44 @@ METHOD(task_t, build_i, status_t,
        peer_cfg_t *config;
        configuration_attribute_type_t type;
        chunk_t data;
-       host_t *vip;
+       linked_list_t *vips;
+       host_t *host;
+
+       vips = linked_list_create();
 
        /* reuse virtual IP if we already have one */
        enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
-       if (!enumerator->enumerate(enumerator, &vip))
+       while (enumerator->enumerate(enumerator, &host))
+       {
+               vips->insert_last(vips, host);
+       }
+       enumerator->destroy(enumerator);
+
+       if (vips->get_count(vips) == 0)
        {
-               enumerator->destroy(enumerator);
                config = this->ike_sa->get_peer_cfg(this->ike_sa);
                enumerator = config->create_virtual_ip_enumerator(config);
-               if (!enumerator->enumerate(enumerator, &vip))
+               while (enumerator->enumerate(enumerator, &host))
                {
-                       vip = NULL;
+                       vips->insert_last(vips, host);
                }
+               enumerator->destroy(enumerator);
        }
-       enumerator->destroy(enumerator);
 
-       if (vip)
+       if (vips->get_count(vips))
        {
                cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
-               cp->add_attribute(cp, build_vip(vip));
+               enumerator = vips->create_enumerator(vips);
+               while (enumerator->enumerate(enumerator, &host))
+               {
+                       cp->add_attribute(cp, build_vip(host));
+               }
+               enumerator->destroy(enumerator);
        }
 
-       enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
-                                                       this->ike_sa->get_other_id(this->ike_sa), vip);
+       enumerator = hydra->attributes->create_initiator_enumerator(
+                                                               hydra->attributes,
+                                                               this->ike_sa->get_other_id(this->ike_sa), vips);
        while (enumerator->enumerate(enumerator, &handler, &type, &data))
        {
                configuration_attribute_t *ca;
@@ -286,6 +300,8 @@ METHOD(task_t, build_i, status_t,
        }
        enumerator->destroy(enumerator);
 
+       vips->destroy(vips);
+
        if (cp)
        {
                message->add_payload(message, (payload_t*)cp);
@@ -310,6 +326,7 @@ METHOD(task_t, build_r, status_t,
        cp_payload_t *cp = NULL;
        peer_cfg_t *config;
        identification_t *id;
+       linked_list_t *vips;
        char *pool;
 
        id = this->ike_sa->get_other_eap_id(this->ike_sa);
@@ -342,8 +359,14 @@ METHOD(task_t, build_r, status_t,
                }
        }
        /* query registered providers for additional attributes to include */
+       vips = linked_list_create();
+       /* TODO: use list with all assigned VIPs */
+       if (vip)
+       {
+               vips->insert_last(vips, vip);
+       }
        enumerator = hydra->attributes->create_responder_enumerator(
-                                                                                       hydra->attributes, pool, id, vip);
+                                                                                       hydra->attributes, pool, id, vips);
        while (enumerator->enumerate(enumerator, &type, &value))
        {
                if (!cp)
@@ -357,6 +380,7 @@ METHOD(task_t, build_r, status_t,
                                                                                                 type, value));
        }
        enumerator->destroy(enumerator);
+       vips->destroy(vips);
 
        if (cp)
        {
index 5b0871f..f3c0c2f 100644 (file)
@@ -242,30 +242,45 @@ METHOD(task_t, build_i, status_t,
                peer_cfg_t *config;
                configuration_attribute_type_t type;
                chunk_t data;
-               host_t *vip;
+               linked_list_t *vips;
+               host_t *host;
+
+               vips = linked_list_create();
 
                /* reuse virtual IP if we already have one */
                enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
                                                                                                                                TRUE);
-               if (!enumerator->enumerate(enumerator, &vip))
+               while (enumerator->enumerate(enumerator, &host))
+               {
+                       vips->insert_last(vips, host);
+               }
+               enumerator->destroy(enumerator);
+
+               if (vips->get_count(vips) == 0)
                {
-                       enumerator->destroy(enumerator);
                        config = this->ike_sa->get_peer_cfg(this->ike_sa);
                        enumerator = config->create_virtual_ip_enumerator(config);
-                       if (!enumerator->enumerate(enumerator, &vip))
+                       while (enumerator->enumerate(enumerator, &host))
                        {
-                               vip = NULL;
+                               vips->insert_last(vips, host);
                        }
+                       enumerator->destroy(enumerator);
                }
-               enumerator->destroy(enumerator);
-               if (vip)
+
+               if (vips->get_count(vips))
                {
                        cp = cp_payload_create_type(CONFIGURATION, CFG_REQUEST);
-                       cp->add_attribute(cp, build_vip(vip));
+                       enumerator = vips->create_enumerator(vips);
+                       while (enumerator->enumerate(enumerator, &host))
+                       {
+                               cp->add_attribute(cp, build_vip(host));
+                       }
+                       enumerator->destroy(enumerator);
                }
 
-               enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
-                                                               this->ike_sa->get_other_id(this->ike_sa), vip);
+               enumerator = hydra->attributes->create_initiator_enumerator(
+                                                               hydra->attributes,
+                                                               this->ike_sa->get_other_id(this->ike_sa), vips);
                while (enumerator->enumerate(enumerator, &handler, &type, &data))
                {
                        configuration_attribute_t *ca;
@@ -291,6 +306,8 @@ METHOD(task_t, build_i, status_t,
                }
                enumerator->destroy(enumerator);
 
+               vips->destroy(vips);
+
                if (cp)
                {
                        message->add_payload(message, (payload_t*)cp);
@@ -321,6 +338,7 @@ METHOD(task_t, build_r, status_t,
                cp_payload_t *cp = NULL;
                peer_cfg_t *config;
                identification_t *id;
+               linked_list_t *vips;
                char *pool;
 
                id = this->ike_sa->get_other_eap_id(this->ike_sa);
@@ -357,8 +375,14 @@ METHOD(task_t, build_r, status_t,
                }
 
                /* query registered providers for additional attributes to include */
+               vips = linked_list_create();
+               /* TODO: use list with all assigned VIPs */
+               if (vip)
+               {
+                       vips->insert_last(vips, vip);
+               }
                enumerator = hydra->attributes->create_responder_enumerator(
-                                                                                       hydra->attributes, pool, id, vip);
+                                                                                       hydra->attributes, pool, id, vips);
                while (enumerator->enumerate(enumerator, &type, &value))
                {
                        if (!cp)
@@ -372,6 +396,7 @@ METHOD(task_t, build_r, status_t,
                                                                                                         type, value));
                }
                enumerator->destroy(enumerator);
+               vips->destroy(vips);
 
                if (cp)
                {
index d042f47..6014ef0 100644 (file)
@@ -22,8 +22,8 @@
 #define ATTRIBUTE_HANDLER_H_
 
 #include <chunk.h>
-#include <utils/host.h>
 #include <utils/identification.h>
+#include <utils/linked_list.h>
 
 #include "attributes.h"
 
@@ -62,11 +62,11 @@ struct attribute_handler_t {
         * Enumerate attributes to request from a server.
         *
         * @param server                server identity to request attributes from
-        * @param vip                   virtual IP we are requesting, if any
+        * @param vips                  list of virtual IPs (host_t*) we are requesting
         * @return                              enumerator (configuration_attribute_type_t, chunk_t)
         */
        enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this,
-                                                                               identification_t *server, host_t *vip);
+                                                               identification_t *server, linked_list_t *vips);
 };
 
 #endif /** ATTRIBUTE_HANDLER_H_ @}*/
index 2503023..b1c2c95 100644 (file)
@@ -55,8 +55,8 @@ typedef struct {
        char *pool;
        /** server/peer identity */
        identification_t *id;
-       /** requesting/assigned virtual IP */
-       host_t *vip;
+       /** requesting/assigned virtual IPs */
+       linked_list_t *vips;
 } enum_data_t;
 
 METHOD(attribute_manager_t, acquire_address, host_t*,
@@ -118,18 +118,20 @@ static enumerator_t *responder_enum_create(attribute_provider_t *provider,
                                                                                   enum_data_t *data)
 {
        return provider->create_attribute_enumerator(provider, data->pool,
-                                                                                                data->id, data->vip);
+                                                                                                data->id, data->vips);
 }
 
 METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
        private_attribute_manager_t *this, char *pool, identification_t *id,
-       host_t *vip)
+       linked_list_t *vips)
 {
-       enum_data_t *data = malloc_thing(enum_data_t);
+       enum_data_t *data;
 
-       data->pool = pool;
-       data->id = id;
-       data->vip = vip;
+       INIT(data,
+               .pool = pool,
+               .id = id,
+               .vips = vips,
+       );
        this->lock->read_lock(this->lock);
        return enumerator_create_cleaner(
                                enumerator_create_nested(
@@ -235,8 +237,8 @@ typedef struct {
        enumerator_t *inner;
        /** server ID we want attributes for */
        identification_t *id;
-       /** virtual IP we are requesting along with attriubutes */
-       host_t *vip;
+       /** virtual IPs we are requesting along with attriubutes */
+       linked_list_t *vips;
 } initiator_enumerator_t;
 
 /**
@@ -256,7 +258,7 @@ static bool initiator_enumerate(initiator_enumerator_t *this,
                }
                DESTROY_IF(this->inner);
                this->inner = this->handler->create_attribute_enumerator(this->handler,
-                                                                                                               this->id, this->vip);
+                                                                                                               this->id, this->vips);
        }
        /* inject the handler as additional attribute */
        *handler = this->handler;
@@ -275,20 +277,22 @@ static void initiator_destroy(initiator_enumerator_t *this)
 }
 
 METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
-       private_attribute_manager_t *this, identification_t *id, host_t *vip)
+       private_attribute_manager_t *this, identification_t *id, linked_list_t *vips)
 {
-       initiator_enumerator_t *enumerator = malloc_thing(initiator_enumerator_t);
+       initiator_enumerator_t *enumerator;
 
        this->lock->read_lock(this->lock);
-       enumerator->public.enumerate = (void*)initiator_enumerate;
-       enumerator->public.destroy = (void*)initiator_destroy;
-       enumerator->this = this;
-       enumerator->id = id;
-       enumerator->vip = vip;
-       enumerator->outer = this->handlers->create_enumerator(this->handlers);
-       enumerator->inner = NULL;
-       enumerator->handler = NULL;
 
+       INIT(enumerator,
+               .public = {
+                       .enumerate = (void*)initiator_enumerate,
+                       .destroy = (void*)initiator_destroy,
+               },
+               .this = this,
+               .id = id,
+               .vips = vips,
+               .outer = this->handlers->create_enumerator(this->handlers),
+       );
        return &enumerator->public;
 }
 
index 37e872a..385580e 100644 (file)
@@ -64,11 +64,11 @@ struct attribute_manager_t {
         *
         * @param pool                  pool name to get attributes from
         * @param id                    peer identity to hand out attributes to
-        * @param vip                   virtual IP to assign to peer, if any
+        * @param vip                   list of virtual IPs (host_t*) to assign to peer
         * @return                              enumerator (configuration_attribute_type_t, chunk_t)
         */
        enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
-                                                               char *pool, identification_t *id, host_t *vip);
+                                               char *pool, identification_t *id, linked_list_t *vips);
 
        /**
         * Register an attribute provider to the manager.
@@ -115,11 +115,11 @@ struct attribute_manager_t {
         * Create an enumerator over attributes to request from server.
         *
         * @param id                    server identity to hand out attributes to
-        * @param vip                   virtual IP going to request, if any
+        * @param vip                   list of virtual IPs (host_t*) going to request
         * @return                              enumerator (attribute_handler_t, ca_type_t, chunk_t)
         */
        enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this,
-                                                                                       identification_t *id, host_t *vip);
+                                                                       identification_t *id, linked_list_t *vips);
 
        /**
         * Register an attribute handler to the manager.
index e4b4e13..104e5ca 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <utils/host.h>
 #include <utils/identification.h>
+#include <utils/linked_list.h>
 
 typedef struct attribute_provider_t attribute_provider_t;
 
@@ -58,11 +59,11 @@ struct attribute_provider_t {
         *
         * @param pool                  pool name to get attributes from
         * @param id                    peer ID
-        * @param vip                   virtual IP to assign to peer, if any
+        * @param vip                   list of virtual IPs (host_t*) to assign to peer
         * @return                              enumerator (configuration_attribute_type_t, chunk_t)
         */
        enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
-                                                       char *pool, identification_t *id, host_t *vip);
+                                               char *pool, identification_t *id, linked_list_t *vips);
 };
 
 #endif /** ATTRIBUTE_PROVIDER_H_ @}*/
index 6af8b47..f81f643 100644 (file)
@@ -78,9 +78,9 @@ static bool attr_enum_filter(void *null, attribute_entry_t **in,
 
 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
        private_attr_provider_t *this, char *pool,
-       identification_t *id, host_t *vip)
+       identification_t *id, linked_list_t *vips)
 {
-       if (vip)
+       if (vips->get_count(vips))
        {
                this->lock->read_lock(this->lock);
                return enumerator_create_filter(
index 714bbcd..b0f8c16 100644 (file)
@@ -340,11 +340,11 @@ METHOD(attribute_provider_t, release_address, bool,
 
 METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
        private_sql_attribute_t *this, char *names, identification_t *id,
-       host_t *vip)
+       linked_list_t *vips)
 {
        enumerator_t *attr_enumerator = NULL;
 
-       if (vip)
+       if (vips->get_count(vips))
        {
                enumerator_t *names_enumerator;
                u_int count;
index 011ebba..2bee45d 100644 (file)
@@ -267,46 +267,71 @@ METHOD(attribute_handler_t, release, void,
 typedef struct {
        /** implements enumerator_t interface */
        enumerator_t public;
-       /** virtual IP we are requesting */
-       host_t *vip;
+       /** request IPv4 DNS? */
+       bool v4;
+       /** request IPv6 DNS? */
+       bool v6;
 } attribute_enumerator_t;
 
 static bool attribute_enumerate(attribute_enumerator_t *this,
                                                                configuration_attribute_type_t *type,
                                                                chunk_t *data)
 {
-       switch (this->vip->get_family(this->vip))
+       if (this->v4)
        {
-               case AF_INET:
-                       *type = INTERNAL_IP4_DNS;
-                       break;
-               case AF_INET6:
-                       *type = INTERNAL_IP6_DNS;
-                       break;
-               default:
-                       return FALSE;
+               *type = INTERNAL_IP4_DNS;
+               *data = chunk_empty;
+               this->v4 = FALSE;
+               return TRUE;
        }
-       *data = chunk_empty;
-       /* enumerate only once */
-       this->public.enumerate = (void*)return_false;
-       return TRUE;
+       if (this->v6)
+       {
+               *type = INTERNAL_IP6_DNS;
+               *data = chunk_empty;
+               this->v6 = FALSE;
+               return TRUE;
+       }
+       return FALSE;
 }
 
-METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
-       private_resolve_handler_t *this, identification_t *server, host_t *vip)
+/**
+ * Check if a list has a host of given family
+ */
+static bool has_host_family(linked_list_t *list, int family)
 {
-       if (vip)
+       enumerator_t *enumerator;
+       host_t *host;
+       bool found = FALSE;
+
+       enumerator = list->create_enumerator(list);
+       while (enumerator->enumerate(enumerator, &host))
        {
-               attribute_enumerator_t *enumerator;
+               if (host->get_family(host) == family)
+               {
+                       found = TRUE;
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
 
-               enumerator = malloc_thing(attribute_enumerator_t);
-               enumerator->public.enumerate = (void*)attribute_enumerate;
-               enumerator->public.destroy = (void*)free;
-               enumerator->vip = vip;
+       return found;
+}
 
-               return &enumerator->public;
-       }
-       return enumerator_create_empty();
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+       private_resolve_handler_t *this, identification_t *server,
+       linked_list_t *vips)
+{
+       attribute_enumerator_t *enumerator;
+
+       INIT(enumerator,
+               .public = {
+                       .enumerate = (void*)attribute_enumerate,
+                       .destroy = (void*)free,
+               },
+               .v4 = has_host_family(vips, AF_INET),
+               .v6 = has_host_family(vips, AF_INET6),
+       );
+       return &enumerator->public;
 }
 
 METHOD(resolve_handler_t, destroy, void,