]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Give plugins more control of which configuration attributes to request, and pass...
authorMartin Willi <martin@strongswan.org>
Tue, 17 Nov 2009 13:51:50 +0000 (14:51 +0100)
committerMartin Willi <martin@strongswan.org>
Tue, 17 Nov 2009 13:51:50 +0000 (14:51 +0100)
16 files changed:
src/charon/encoding/payloads/configuration_attribute.c
src/charon/encoding/payloads/configuration_attribute.h
src/charon/encoding/payloads/cp_payload.c
src/charon/encoding/payloads/cp_payload.h
src/charon/plugins/attr/attr_provider.c
src/charon/plugins/nm/nm_handler.c
src/charon/plugins/resolve/resolve_handler.c
src/charon/plugins/stroke/stroke_attribute.c
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/tasks/ike_config.c
src/libstrongswan/attributes/attribute_handler.h
src/libstrongswan/attributes/attribute_manager.c
src/libstrongswan/attributes/attribute_manager.h
src/libstrongswan/attributes/attribute_provider.h
src/libstrongswan/plugins/attr_sql/sql_attribute.c

index caba34a6c41bfc3ba9c401793dfef07861c1a108..9094fd44d82d9b952e948b70d5db92457bcf831a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
@@ -38,17 +38,17 @@ struct private_configuration_attribute_t {
        /**
         * Type of the attribute.
         */
-       u_int16_t attribute_type;
+       u_int16_t type;
 
        /**
         * Length of the attribute.
         */
-       u_int16_t attribute_length;
+       u_int16_t length;
 
        /**
         * Attribute value as chunk.
         */
-       chunk_t attribute_value;
+       chunk_t value;
 };
 
 /**
@@ -56,17 +56,16 @@ struct private_configuration_attribute_t {
  *
  * The defined offsets are the positions in a object of type
  * private_configuration_attribute_t.
- *
  */
 encoding_rule_t configuration_attribute_encodings[] = {
 
-       { RESERVED_BIT, 0                                                                                                                                                                       },
+       { RESERVED_BIT,                                         0                                                                                                       },
        /* type of the attribute as 15 bit unsigned integer */
-       { ATTRIBUTE_TYPE,                       offsetof(private_configuration_attribute_t, attribute_type)                             },
+       { ATTRIBUTE_TYPE,                                       offsetof(private_configuration_attribute_t, type)       },
        /* Length of attribute value */
-       { CONFIGURATION_ATTRIBUTE_LENGTH,               offsetof(private_configuration_attribute_t, attribute_length)},
+       { CONFIGURATION_ATTRIBUTE_LENGTH,       offsetof(private_configuration_attribute_t, length)     },
        /* Value of attribute if attribute format flag is zero */
-       { CONFIGURATION_ATTRIBUTE_VALUE,                offsetof(private_configuration_attribute_t, attribute_value)}
+       { CONFIGURATION_ATTRIBUTE_VALUE,        offsetof(private_configuration_attribute_t, value)      }
 };
 
 /*
@@ -88,13 +87,13 @@ static status_t verify(private_configuration_attribute_t *this)
 {
        bool failed = FALSE;
 
-       if (this->attribute_length != this->attribute_value.len)
+       if (this->length != this->value.len)
        {
                DBG1(DBG_ENC, "invalid attribute length");
                return FAILED;
        }
 
-       switch (this->attribute_type)
+       switch (this->type)
        {
                 case INTERNAL_IP4_ADDRESS:
                 case INTERNAL_IP4_NETMASK:
@@ -102,20 +101,20 @@ static status_t verify(private_configuration_attribute_t *this)
                 case INTERNAL_IP4_NBNS:
                 case INTERNAL_ADDRESS_EXPIRY:
                 case INTERNAL_IP4_DHCP:
-                       if (this->attribute_length != 0 && this->attribute_length != 4)
+                       if (this->length != 0 && this->length != 4)
                        {
                                failed = TRUE;
                        }
                        break;
                 case INTERNAL_IP4_SUBNET:
-                       if (this->attribute_length != 0 && this->attribute_length != 8)
+                       if (this->length != 0 && this->length != 8)
                        {
                                failed = TRUE;
                        }
                        break;
                 case INTERNAL_IP6_ADDRESS:
                 case INTERNAL_IP6_SUBNET:
-                       if (this->attribute_length != 0 && this->attribute_length != 17)
+                       if (this->length != 0 && this->length != 17)
                        {
                                failed = TRUE;
                        }
@@ -123,13 +122,13 @@ static status_t verify(private_configuration_attribute_t *this)
                 case INTERNAL_IP6_DNS:
                 case INTERNAL_IP6_NBNS:
                 case INTERNAL_IP6_DHCP:
-                       if (this->attribute_length != 0 && this->attribute_length != 16)
+                       if (this->length != 0 && this->length != 16)
                        {
                                failed = TRUE;
                        }
                        break;
                 case SUPPORTED_ATTRIBUTES:
-                       if (this->attribute_length % 2)
+                       if (this->length % 2)
                        {
                                failed = TRUE;
                        }
@@ -139,15 +138,14 @@ static status_t verify(private_configuration_attribute_t *this)
                        break;
                 default:
                        DBG1(DBG_ENC, "unknown attribute type %N",
-                                configuration_attribute_type_names, this->attribute_type);
+                                configuration_attribute_type_names, this->type);
                        break;
        }
 
        if (failed)
        {
                DBG1(DBG_ENC, "invalid attribute length %d for %N",
-                        this->attribute_length, configuration_attribute_type_names,
-                        this->attribute_type);
+                        this->length, configuration_attribute_type_names, this->type);
                return FAILED;
        }
        return SUCCESS;
@@ -156,7 +154,8 @@ static status_t verify(private_configuration_attribute_t *this)
 /**
  * Implementation of payload_t.get_encoding_rules.
  */
-static void get_encoding_rules(private_configuration_attribute_t *this, encoding_rule_t **rules, size_t *rule_count)
+static void get_encoding_rules(private_configuration_attribute_t *this,
+                                                          encoding_rule_t **rules, size_t *rule_count)
 {
        *rules = configuration_attribute_encodings;
        *rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t);
@@ -175,13 +174,14 @@ static payload_type_t get_type(private_configuration_attribute_t *this)
  */
 static payload_type_t get_next_type(private_configuration_attribute_t *this)
 {
-       return (NO_PAYLOAD);
+       return NO_PAYLOAD;
 }
 
 /**
  * Implementation of payload_t.set_next_type.
  */
-static void set_next_type(private_configuration_attribute_t *this,payload_type_t type)
+static void set_next_type(private_configuration_attribute_t *this,
+                                                 payload_type_t type)
 {
 }
 
@@ -190,99 +190,75 @@ static void set_next_type(private_configuration_attribute_t *this,payload_type_t
  */
 static size_t get_length(private_configuration_attribute_t *this)
 {
-       return (this->attribute_value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH);
+       return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
 }
 
 /**
- * Implementation of configuration_attribute_t.set_value.
+ * Implementation of configuration_attribute_t.get_type.
  */
-static void set_value(private_configuration_attribute_t *this, chunk_t value)
+static configuration_attribute_type_t get_configuration_attribute_type(
+                                                                       private_configuration_attribute_t *this)
 {
-       if (this->attribute_value.ptr != NULL)
-       {
-               /* free existing value */
-               chunk_free(&(this->attribute_value));
-       }
-
-       this->attribute_value.ptr = clalloc(value.ptr,value.len);
-       this->attribute_value.len = value.len;
-
-       this->attribute_length = this->attribute_value.len;
+       return this->type;
 }
 
 /**
  * Implementation of configuration_attribute_t.get_value.
  */
-static chunk_t get_value (private_configuration_attribute_t *this)
+static chunk_t get_value(private_configuration_attribute_t *this)
 {
-       return this->attribute_value;
+       return this->value;
 }
 
 /**
- * Implementation of configuration_attribute_t.set_type.
+ * Implementation of configuration_attribute_t.destroy and payload_t.destroy.
  */
-static void set_attribute_type (private_configuration_attribute_t *this, u_int16_t type)
+static void destroy(private_configuration_attribute_t *this)
 {
-       this->attribute_type = type & 0x7FFF;
+       free(this->value.ptr);
+       free(this);
 }
 
-/**
- * Implementation of configuration_attribute_t.get_type.
+/*
+ * Described in header.
  */
-static u_int16_t get_attribute_type (private_configuration_attribute_t *this)
+configuration_attribute_t *configuration_attribute_create()
 {
-       return this->attribute_type;
+       private_configuration_attribute_t *this;
+
+       this = malloc_thing(private_configuration_attribute_t);
+       this->public.payload_interface.verify = (status_t(*)(payload_t *))verify;
+       this->public.payload_interface.get_encoding_rules = (void(*)(payload_t *, encoding_rule_t **, size_t *) )get_encoding_rules;
+       this->public.payload_interface.get_length = (size_t(*)(payload_t *))get_length;
+       this->public.payload_interface.get_next_type = (payload_type_t(*)(payload_t *))get_next_type;
+       this->public.payload_interface.set_next_type = (void(*)(payload_t *,payload_type_t))set_next_type;
+       this->public.payload_interface.get_type = (payload_type_t(*)(payload_t *))get_type;
+       this->public.payload_interface.destroy = (void(*)(payload_t*))destroy;
+
+       this->public.get_value = (chunk_t(*)(configuration_attribute_t *))get_value;
+       this->public.get_type = (configuration_attribute_type_t(*)(configuration_attribute_t *))get_configuration_attribute_type;
+       this->public.destroy = (void (*)(configuration_attribute_t*))destroy;
+
+       this->type = 0;
+       this->value = chunk_empty;
+       this->length = 0;
+
+       return &this->public;
 }
 
-/**
- * Implementation of configuration_attribute_t.get_length.
+/*
+ * Described in header.
  */
-static u_int16_t get_attribute_length (private_configuration_attribute_t *this)
+configuration_attribute_t *configuration_attribute_create_value(
+                                                       configuration_attribute_type_t type, chunk_t value)
 {
-       return this->attribute_length;
-}
+       private_configuration_attribute_t *this;
 
+       this = (private_configuration_attribute_t*)configuration_attribute_create();
+       this->type = ((u_int16_t)type) & 0x7FFF;
+       this->value = chunk_clone(value);
+       this->length = value.len;
 
-/**
- * Implementation of configuration_attribute_t.destroy and payload_t.destroy.
- */
-static void destroy(private_configuration_attribute_t *this)
-{
-       if (this->attribute_value.ptr != NULL)
-       {
-               free(this->attribute_value.ptr);
-       }
-       free(this);
+       return &this->public;
 }
 
-/*
- * Described in header.
- */
-configuration_attribute_t *configuration_attribute_create()
-{
-       private_configuration_attribute_t *this = malloc_thing(private_configuration_attribute_t);
-
-       /* payload interface */
-       this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
-       this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
-       this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
-       this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
-       this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
-       this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
-       this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
-
-       /* public functions */
-       this->public.set_value = (void (*) (configuration_attribute_t *,chunk_t)) set_value;
-       this->public.get_value = (chunk_t (*) (configuration_attribute_t *)) get_value;
-       this->public.set_type = (void (*) (configuration_attribute_t *,u_int16_t type)) set_attribute_type;
-       this->public.get_type = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_type;
-       this->public.get_length = (u_int16_t (*) (configuration_attribute_t *)) get_attribute_length;
-       this->public.destroy = (void (*) (configuration_attribute_t *)) destroy;
-
-       /* set default values of the fields */
-       this->attribute_type = 0;
-       this->attribute_value = chunk_empty;
-       this->attribute_length = 0;
-
-       return (&(this->public));
-}
index f30fbfa7247a88ffdc7309d83e117123a121a5cd..6e4b018bb8f263c30f96a35971ab2e3a50928ed3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
@@ -28,7 +28,6 @@ typedef struct configuration_attribute_t configuration_attribute_t;
 #include <attributes/attributes.h>
 #include <encoding/payloads/payload.h>
 
-
 /**
  * Configuration attribute header length in bytes.
  */
@@ -40,49 +39,25 @@ typedef struct configuration_attribute_t configuration_attribute_t;
  * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
  */
 struct configuration_attribute_t {
-       /**
-        * The payload_t interface.
-        */
-       payload_t payload_interface;
-
-       /**
-        * Returns the currently set value of the attribute.
-        *
-        * @warning Returned data are not copied.
-        *
-        * @return              chunk_t pointing to the value
-        */
-       chunk_t (*get_value) (configuration_attribute_t *this);
-
-       /**
-        * Sets the value of the attribute.
-        *
-        * Value is getting copied.
-        *
-        * @param value chunk_t pointing to the value to set
-        */
-       void (*set_value) (configuration_attribute_t *this, chunk_t value);
 
        /**
-        * Sets the type of the attribute.
-        *
-        * @param type  type to set (most significant bit is set to zero)
+        * Implements payload_t interface.
         */
-       void (*set_type) (configuration_attribute_t *this, u_int16_t type);
+       payload_t payload_interface;
 
        /**
-        * get the type of the attribute.
+        * Get the type of the attribute.
         *
-        * @return              type of the value
+        * @return              type of the configuration attribute
         */
-       u_int16_t (*get_type) (configuration_attribute_t *this);
+       configuration_attribute_type_t (*get_type)(configuration_attribute_t *this);
 
        /**
-        * get the length of an attribute.
+        * Returns the value of the attribute.
         *
-        * @return              type of the value
+        * @return              chunk_t pointing to the internal value
         */
-       u_int16_t (*get_length) (configuration_attribute_t *this);
+       chunk_t (*get_value) (configuration_attribute_t *this);
 
        /**
         * Destroys an configuration_attribute_t object.
@@ -91,10 +66,20 @@ struct configuration_attribute_t {
 };
 
 /**
- * Creates an empty configuration_attribute_t object.
+ * Creates an empty configuration attribute.
+ *
+ * @return             created configuration attribute
+ */
+configuration_attribute_t *configuration_attribute_create();
+
+/**
+ * Creates a configuration attribute with type and value.
  *
- * @return                     created configuration_attribute_t object
+ * @param type type of configuration attribute
+ * @param value        value, gets cloned
+ * @return             created configuration attribute
  */
-configuration_attribute_t *configuration_attribute_create(void);
+configuration_attribute_t *configuration_attribute_create_value(
+                                                       configuration_attribute_type_t type, chunk_t value);
 
 #endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/
index 8dc4b69f225e809953fc3b569d538df1e89a3c7f..f0a26eee245b16a7c8898e1ba9dc63d374b45461 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
@@ -56,14 +56,14 @@ struct private_cp_payload_t {
        u_int16_t payload_length;
 
        /**
-        * Configuration Attributes in this payload are stored in a linked_list_t.
+        * List of attributes, as configuration_attribute_t
         */
-       linked_list_t * attributes;
+       linked_list_t *attributes;
 
        /**
         * Config Type.
         */
-       u_int8_t config_type;
+       u_int8_t type;
 };
 
 /**
@@ -90,7 +90,7 @@ encoding_rule_t cp_payload_encodings[] = {
        { PAYLOAD_LENGTH,               offsetof(private_cp_payload_t, payload_length)  },
        /* Proposals are stored in a proposal substructure,
           offset points to a linked_list_t pointer */
-       { U_INT_8,              offsetof(private_cp_payload_t, config_type)                             },
+       { U_INT_8,                              offsetof(private_cp_payload_t, type)                    },
        { RESERVED_BYTE,0                                                                                                               },
        { RESERVED_BYTE,0                                                                                                               },
        { RESERVED_BYTE,0                                                                                                               },
@@ -117,26 +117,27 @@ encoding_rule_t cp_payload_encodings[] = {
 static status_t verify(private_cp_payload_t *this)
 {
        status_t status = SUCCESS;
-       iterator_t *iterator;
-       configuration_attribute_t *attribute;
+       enumerator_t *enumerator;
+       payload_t *attribute;
 
-       iterator = this->attributes->create_iterator(this->attributes,TRUE);
-       while(iterator->iterate(iterator, (void**)&attribute))
+       enumerator = this->attributes->create_enumerator(this->attributes);
+       while (enumerator->enumerate(enumerator, &attribute))
        {
-               status = attribute->payload_interface.verify(&attribute->payload_interface);
+               status = attribute->verify(attribute);
                if (status != SUCCESS)
                {
                        break;
                }
        }
-       iterator->destroy(iterator);
+       enumerator->destroy(enumerator);
        return status;
 }
 
 /**
  * Implementation of payload_t.get_encoding_rules.
  */
-static void get_encoding_rules(private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
+static void get_encoding_rules(private_cp_payload_t *this,
+                                                          encoding_rule_t **rules, size_t *rule_count)
 {
        *rules = cp_payload_encodings;
        *rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t);
@@ -155,7 +156,7 @@ static payload_type_t get_type(private_cp_payload_t *this)
  */
 static payload_type_t get_next_type(private_cp_payload_t *this)
 {
-       return (this->next_payload);
+       return this->next_payload;
 }
 
 /**
@@ -171,18 +172,17 @@ static void set_next_type(private_cp_payload_t *this,payload_type_t type)
  */
 static void compute_length(private_cp_payload_t *this)
 {
-       iterator_t *iterator;
-       payload_t *current_attribute;
-       size_t length = CP_PAYLOAD_HEADER_LENGTH;
+       enumerator_t *enumerator;
+       payload_t *attribute;
 
-       iterator = this->attributes->create_iterator(this->attributes,TRUE);
-       while (iterator->iterate(iterator, (void**)&current_attribute))
+       this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
+
+       enumerator = this->attributes->create_enumerator(this->attributes);
+       while (enumerator->enumerate(enumerator, &attribute))
        {
-               length += current_attribute->get_length(current_attribute);
+               this->payload_length += attribute->get_length(attribute);
        }
-       iterator->destroy(iterator);
-
-       this->payload_length = length;
+       enumerator->destroy(enumerator);
 }
 
 /**
@@ -190,41 +190,33 @@ static void compute_length(private_cp_payload_t *this)
  */
 static size_t get_length(private_cp_payload_t *this)
 {
-       compute_length(this);
        return this->payload_length;
 }
 
 /**
- * Implementation of cp_payload_t.create_configuration_attribute_iterator.
+ * Implementation of cp_payload_t.create_attribute_enumerator.
  */
-static iterator_t *create_attribute_iterator (private_cp_payload_t *this)
+static enumerator_t *create_attribute_enumerator(private_cp_payload_t *this)
 {
-       return this->attributes->create_iterator(this->attributes, TRUE);
+       return this->attributes->create_enumerator(this->attributes);
 }
 
 /**
- * Implementation of cp_payload_t.add_proposal_substructure.
+ * Implementation of cp_payload_t.add_attribute.
  */
-static void add_configuration_attribute (private_cp_payload_t *this,configuration_attribute_t *attribute)
+static void add_attribute(private_cp_payload_t *this,
+                                                 configuration_attribute_t *attribute)
 {
-       this->attributes->insert_last(this->attributes,(void *) attribute);
+       this->attributes->insert_last(this->attributes, attribute);
        compute_length(this);
 }
 
 /**
- * Implementation of cp_payload_t.set_config_type.
- */
-static void set_config_type (private_cp_payload_t *this,config_type_t config_type)
-{
-       this->config_type = config_type;
-}
-
-/**
- * Implementation of cp_payload_t.get_config_type.
+ * Implementation of cp_payload_t.get_type.
  */
-static config_type_t get_config_type (private_cp_payload_t *this)
+static config_type_t get_config_type(private_cp_payload_t *this)
 {
-       return this->config_type;
+       return this->type;
 }
 
 /**
@@ -233,7 +225,7 @@ static config_type_t get_config_type (private_cp_payload_t *this)
 static void destroy(private_cp_payload_t *this)
 {
        this->attributes->destroy_offset(this->attributes,
-                                                                        offsetof(configuration_attribute_t, destroy));
+                                                               offsetof(configuration_attribute_t, destroy));
        free(this);
 }
 
@@ -244,7 +236,6 @@ cp_payload_t *cp_payload_create()
 {
        private_cp_payload_t *this = malloc_thing(private_cp_payload_t);
 
-       /* public interface */
        this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
        this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
        this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
@@ -253,18 +244,30 @@ cp_payload_t *cp_payload_create()
        this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
        this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
 
-       /* public functions */
-       this->public.create_attribute_iterator = (iterator_t* (*) (cp_payload_t *)) create_attribute_iterator;
-       this->public.add_configuration_attribute = (void (*) (cp_payload_t *,configuration_attribute_t *)) add_configuration_attribute;
-       this->public.set_config_type = (void (*) (cp_payload_t *, config_type_t)) set_config_type;
-       this->public.get_config_type = (config_type_t (*) (cp_payload_t *)) get_config_type;
-       this->public.destroy = (void (*) (cp_payload_t *)) destroy;
+       this->public.create_attribute_enumerator = (enumerator_t*(*)(cp_payload_t *))create_attribute_enumerator;
+       this->public.add_attribute = (void (*) (cp_payload_t *,configuration_attribute_t*))add_attribute;
+       this->public.get_type = (config_type_t (*) (cp_payload_t *))get_config_type;
+       this->public.destroy = (void (*)(cp_payload_t *))destroy;
 
        /* set default values of the fields */
        this->critical = FALSE;
        this->next_payload = NO_PAYLOAD;
        this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
-
        this->attributes = linked_list_create();
-       return (&(this->public));
+       this->type = CFG_REQUEST;
+
+       return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+cp_payload_t *cp_payload_create_type(config_type_t type)
+{
+       private_cp_payload_t *this = (private_cp_payload_t*)cp_payload_create();
+
+       this->type = type;
+
+       return &this->public;
 }
+
index 11f5061b9f7d0a3a2b72ca73329db6dff042fcdf..c0760885ac229700e80cc65db98cdf7cc1c23ef4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
  *
@@ -28,7 +28,7 @@ typedef struct cp_payload_t cp_payload_t;
 #include <library.h>
 #include <encoding/payloads/payload.h>
 #include <encoding/payloads/configuration_attribute.h>
-#include <utils/linked_list.h>
+#include <utils/enumerator.h>
 
 /**
  * CP_PAYLOAD length in bytes without any proposal substructure.
@@ -56,6 +56,7 @@ extern enum_name_t *config_type_names;
  * The CP Payload format is described in RFC section 3.15.
  */
 struct cp_payload_t {
+
        /**
         * The payload_t interface.
         */
@@ -64,36 +65,24 @@ struct cp_payload_t {
        /**
         * Creates an iterator of stored configuration_attribute_t objects.
         *
-        * When deleting an attribute using this iterator, the length of this
-        * configuration_attribute_t has to be refreshed by calling get_length()!
-        *
-        * @return                              created iterator_t object
+        * @return                      enumerator over configration_attribute_T
         */
-       iterator_t *(*create_attribute_iterator) (cp_payload_t *this);
+       enumerator_t *(*create_attribute_enumerator) (cp_payload_t *this);
 
        /**
-        * Adds a configuration_attribute_t object to this object.
-        *
-        * The added configuration_attribute_t object is getting destroyed in
-        * destroy function of cp_payload_t.
+        * Adds a configuration attribute to the configuration payload.
         *
-        * @param attribute             configuration_attribute_t object to add
+        * @param attribute     attribute to add
         */
-       void (*add_configuration_attribute) (cp_payload_t *this, configuration_attribute_t *attribute);
+       void (*add_attribute)(cp_payload_t *this,
+                                                 configuration_attribute_t *attribute);
 
        /**
-        * Set the config type.
+        * Get the configuration payload type.
         *
-        * @param config_type   config_type_t to set
+        * @return                      type of configuration payload
         */
-       void (*set_config_type) (cp_payload_t *this,config_type_t config_type);
-
-       /**
-        * Get the config type.
-        *
-        * @return                              config_type_t
-        */
-       config_type_t (*get_config_type) (cp_payload_t *this);
+       config_type_t (*get_type) (cp_payload_t *this);
 
        /**
         * Destroys an cp_payload_t object.
@@ -102,10 +91,18 @@ struct cp_payload_t {
 };
 
 /**
- * Creates an empty cp_payload_t object
+ * Creates an empty configuration payload
+ *
+ * @return             empty configuration payload
+ */
+cp_payload_t *cp_payload_create();
+
+/**
+ * Creates an cp_payload_t with type and value
  *
- * @return cp_payload_t object
+ * @param type type of configuration payload to create
+ * @return             created configuration payload
  */
-cp_payload_t *cp_payload_create(void);
+cp_payload_t *cp_payload_create_type(config_type_t config_type);
 
 #endif /** CP_PAYLOAD_H_ @}*/
index 88c5ed4c02666a13cf29dea512cddc15342bf09d..00fcbf6ef223afc8340d01dbab0346f0e22063ab 100644 (file)
@@ -61,12 +61,16 @@ static bool attr_enum_filter(void *null, attribute_entry_t **in,
 /**
  * Implementation of attribute_provider_t.create_attribute_enumerator
  */
-static enumerator_t* create_attribute_enumerator(
-                                       private_attr_provider_t *this, identification_t *id)
+static enumerator_t* create_attribute_enumerator(private_attr_provider_t *this,
+                                                                                       identification_t *id, host_t *vip)
 {
-       return enumerator_create_filter(
+       if (vip)
+       {
+               return enumerator_create_filter(
                                                this->attributes->create_enumerator(this->attributes),
                                                (void*)attr_enum_filter, NULL, NULL);
+       }
+       return enumerator_create_empty();
 }
 
 /**
@@ -138,7 +142,7 @@ attr_provider_t *attr_provider_create(database_t *db)
 
        this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))return_null;
        this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))return_false;
-       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id))create_attribute_enumerator;
+       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *vip))create_attribute_enumerator;
        this->public.destroy = (void(*)(attr_provider_t*))destroy;
 
        this->attributes = linked_list_create();
index 7756b8e7afc104d7fda4d186017aeccf50d00a71..eacb54dda1444e93f28fd8402fe5333d4749d578 100644 (file)
@@ -67,6 +67,50 @@ static bool handle(private_nm_handler_t *this, identification_t *server,
        return TRUE;
 }
 
+/**
+ * Implementation of create_attribute_enumerator().enumerate() for WINS
+ */
+static bool enumerate_nbns(enumerator_t *this,
+                                                  configuration_attribute_type_t *type, chunk_t *data)
+{
+       *type = INTERNAL_IP4_NBNS;
+       *data = chunk_empty;
+       /* done */
+       this->enumerate = (void*)return_false;
+       return TRUE;
+}
+
+/**
+ * Implementation of create_attribute_enumerator().enumerate() for DNS
+ */
+static bool enumerate_dns(enumerator_t *this,
+                                                 configuration_attribute_type_t *type, chunk_t *data)
+{
+       *type = INTERNAL_IP4_DNS;
+       *data = chunk_empty;
+       /* enumerate WINS server as next attribute ... */
+       this->enumerate = (void*)enumerate_nbns;
+       return TRUE;
+}
+
+/**
+ * Implementation of attribute_handler_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_nm_handler_t *this,
+                                                                               identification_t *server, host_t *vip)
+{
+       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;
+
+               return enumerator;
+       }
+       return enumerator_create_empty();
+}
+
 /**
  * convert plain byte ptrs to handy chunk during enumeration
  */
@@ -136,6 +180,7 @@ nm_handler_t *nm_handler_create()
 
        this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
        this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))nop;
+       this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
        this->public.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator;
        this->public.reset = (void(*)(nm_handler_t*))reset;
        this->public.destroy = (void(*)(nm_handler_t*))destroy;
index 7c7d52a05fb5cee11471e93769036f661dddbace..ff0e5943e14354ffbfb84278202e97b413203525 100644 (file)
@@ -163,6 +163,59 @@ static void release(private_resolve_handler_t *this, identification_t *server,
        this->mutex->unlock(this->mutex);
 }
 
+/**
+ * Attribute enumerator implementation
+ */
+typedef struct {
+       /** implements enumerator_t interface */
+       enumerator_t public;
+       /** virtual IP we are requesting */
+       host_t *vip;
+} attribute_enumerator_t;
+
+/**
+ * Implementation of create_attribute_enumerator().enumerate()
+ */
+static bool attribute_enumerate(attribute_enumerator_t *this,
+                                               configuration_attribute_type_t *type, chunk_t *data)
+{
+       switch (this->vip->get_family(this->vip))
+       {
+               case AF_INET:
+                       *type = INTERNAL_IP4_DNS;
+                       break;
+               case AF_INET6:
+                       *type = INTERNAL_IP6_DNS;
+                       break;
+               default:
+                       return FALSE;
+       }
+       *data = chunk_empty;
+       /* enumerate only once */
+       this->public.enumerate = (void*)return_false;
+       return TRUE;
+}
+
+/**
+ * Implementation of attribute_handler_t.create_attribute_enumerator
+ */
+static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this,
+                                                                               identification_t *server, host_t *vip)
+{
+       if (vip)
+       {
+               attribute_enumerator_t *enumerator;
+
+               enumerator = malloc_thing(attribute_enumerator_t);
+               enumerator->public.enumerate = (void*)attribute_enumerate;
+               enumerator->public.destroy = (void*)free;
+               enumerator->vip = vip;
+
+               return &enumerator->public;
+       }
+       return enumerator_create_empty();
+}
+
 /**
  * Implementation of resolve_handler_t.destroy.
  */
@@ -181,6 +234,7 @@ resolve_handler_t *resolve_handler_create()
 
        this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
        this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
+       this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
        this->public.destroy = (void(*)(resolve_handler_t*))destroy;
 
        this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
index 5c24d346b1d7332692e38c4dac94dafead0ee34d..db8b53e961cd7f828821e2224f442fed6b64c5b3 100644 (file)
@@ -531,7 +531,7 @@ stroke_attribute_t *stroke_attribute_create()
 
        this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,host_t *))acquire_address;
        this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
-       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id))enumerator_create_empty;
+       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *vip))enumerator_create_empty;
        this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool;
        this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool;
        this->public.create_pool_enumerator = (enumerator_t*(*)(stroke_attribute_t*))create_pool_enumerator;
index c681b0180da61b6c0f6a61cde83a8262545d2e28..a6bae454f6b928e5b34f7205598cd695fb2cbc76 100644 (file)
@@ -1843,22 +1843,16 @@ static status_t roam(private_ike_sa_t *this, bool address)
  * Implementation of ike_sa_t.add_configuration_attribute
  */
 static void add_configuration_attribute(private_ike_sa_t *this,
+                                                       attribute_handler_t *handler,
                                                        configuration_attribute_type_t type, chunk_t data)
 {
-       attribute_entry_t *entry;
-       attribute_handler_t *handler;
+       attribute_entry_t *entry = malloc_thing(attribute_entry_t);
 
-       handler = lib->attributes->handle(lib->attributes, this->other_id,
-                                                                         type, data);
-       if (handler)
-       {
-               entry = malloc_thing(attribute_entry_t);
-               entry->handler = handler;
-               entry->type = type;
-               entry->data = chunk_clone(data);
+       entry->handler = handler;
+       entry->type = type;
+       entry->data = chunk_clone(data);
 
-               this->attributes->insert_last(this->attributes, entry);
-       }
+       this->attributes->insert_last(this->attributes, entry);
 }
 
 /**
@@ -2091,7 +2085,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->public.get_unique_id = (u_int32_t (*)(ike_sa_t*))get_unique_id;
        this->public.set_virtual_ip = (void (*)(ike_sa_t*,bool,host_t*))set_virtual_ip;
        this->public.get_virtual_ip = (host_t* (*)(ike_sa_t*,bool))get_virtual_ip;
-       this->public.add_configuration_attribute = (void(*)(ike_sa_t*, configuration_attribute_type_t type, chunk_t data))add_configuration_attribute;
+       this->public.add_configuration_attribute = (void(*)(ike_sa_t*, attribute_handler_t *handler,configuration_attribute_type_t type, chunk_t data))add_configuration_attribute;
        this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
 #ifdef ME
        this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;
index 525e80b0a5e4670c53b6353704eaf49585acfb3d..5e6378b827861e5eb04388238a48f7a1beadfeda 100644 (file)
@@ -855,6 +855,7 @@ struct ike_sa_t {
         * @param data                  associated attribute data
         */
        void (*add_configuration_attribute)(ike_sa_t *this,
+                                                       attribute_handler_t *handler,
                                                        configuration_attribute_type_t type, chunk_t data);
 
        /**
index 0e2340a6a1aabd57f82436f7b0f75e5d5a401726..1c222fa8cfa14786f2156af334b740a11bffa5f1 100644 (file)
@@ -19,9 +19,6 @@
 #include <daemon.h>
 #include <encoding/payloads/cp_payload.h>
 
-#define DNS_SERVER_MAX         2
-#define NBNS_SERVER_MAX                2
-
 typedef struct private_ike_config_t private_ike_config_t;
 
 /**
@@ -48,21 +45,34 @@ struct private_ike_config_t {
         * virtual ip
         */
        host_t *virtual_ip;
+
+       /**
+        * list of attributes requested and its handler, entry_t
+        */
+       linked_list_t *requested;
 };
 
 /**
- * build INTERNAL_IPV4/6_ADDRESS from virtual ip
+ * Entry for a requested attribute and the requesting handler
+ */
+typedef struct {
+       /** attribute requested */
+       configuration_attribute_type_t type;
+       /** handler requesting this attribute */
+       attribute_handler_t *handler;
+} entry_t;
+
+/**
+ * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
  */
-static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
+static configuration_attribute_t *build_vip(host_t *vip)
 {
-       configuration_attribute_t *ca;
+       configuration_attribute_type_t type;
        chunk_t chunk, prefix;
 
-       ca = configuration_attribute_create();
-
        if (vip->get_family(vip) == AF_INET)
        {
-               ca->set_type(ca, INTERNAL_IP4_ADDRESS);
+               type = INTERNAL_IP4_ADDRESS;
                if (vip->is_anyaddr(vip))
                {
                        chunk = chunk_empty;
@@ -74,7 +84,7 @@ static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
        }
        else
        {
-               ca->set_type(ca, INTERNAL_IP6_ADDRESS);
+               type = INTERNAL_IP6_ADDRESS;
                if (vip->is_anyaddr(vip))
                {
                        chunk = chunk_empty;
@@ -87,8 +97,41 @@ static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
                        chunk = chunk_cata("cc", chunk, prefix);
                }
        }
-       ca->set_value(ca, chunk);
-       cp->add_configuration_attribute(cp, ca);
+       return configuration_attribute_create_value(type, chunk);
+}
+
+/**
+ * Handle a received attribute as initiator
+ */
+static void handle_attribute(private_ike_config_t *this,
+                                                        configuration_attribute_t *ca)
+{
+       attribute_handler_t *handler = NULL;
+       enumerator_t *enumerator;
+       entry_t *entry;
+
+       /* find the handler which requested this attribute */
+       enumerator = this->requested->create_enumerator(this->requested);
+       while (enumerator->enumerate(enumerator, &entry))
+       {
+               if (entry->type == ca->get_type(ca))
+               {
+                       handler = entry->handler;
+                       this->requested->remove_at(this->requested, enumerator);
+                       free(entry);
+                       break;
+               }
+       }
+
+       /* and pass it to the handle function */
+       handler = lib->attributes->handle(lib->attributes,
+                                                       this->ike_sa->get_other_id(this->ike_sa), handler,
+                                                       ca->get_type(ca), ca->get_value(ca));
+       if (handler)
+       {
+               this->ike_sa->add_configuration_attribute(this->ike_sa,
+                               handler, ca->get_type(ca), ca->get_value(ca));
+       }
 }
 
 /**
@@ -130,15 +173,12 @@ static void process_attribute(private_ike_config_t *this,
                        break;
                }
                default:
+               {
                        if (this->initiator)
                        {
-                               this->ike_sa->add_configuration_attribute(this->ike_sa,
-                                                                               ca->get_type(ca), ca->get_value(ca));
-                       }
-                       else
-                       {
-                               /* we do not handle attribute requests other than for VIPs */
+                               handle_attribute(this, ca);
                        }
+               }
        }
 }
 
@@ -147,8 +187,7 @@ static void process_attribute(private_ike_config_t *this,
  */
 static void process_payloads(private_ike_config_t *this, message_t *message)
 {
-       enumerator_t *enumerator;
-       iterator_t *attributes;
+       enumerator_t *enumerator, *attributes;
        payload_t *payload;
 
        enumerator = message->create_payload_enumerator(message);
@@ -158,13 +197,14 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
                {
                        cp_payload_t *cp = (cp_payload_t*)payload;
                        configuration_attribute_t *ca;
-                       switch (cp->get_config_type(cp))
+
+                       switch (cp->get_type(cp))
                        {
                                case CFG_REQUEST:
                                case CFG_REPLY:
                                {
-                                       attributes = cp->create_attribute_iterator(cp);
-                                       while (attributes->iterate(attributes, (void**)&ca))
+                                       attributes = cp->create_attribute_enumerator(cp);
+                                       while (attributes->enumerate(attributes, &ca))
                                        {
                                                process_attribute(this, ca);
                                        }
@@ -173,7 +213,7 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
                                }
                                default:
                                        DBG1(DBG_IKE, "ignoring %N config payload",
-                                                config_type_names, cp->get_config_type(cp));
+                                                config_type_names, cp->get_type(cp));
                                        break;
                        }
                }
@@ -188,7 +228,12 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
 {
        if (message->get_message_id(message) == 1)
        {       /* in first IKE_AUTH only */
+               cp_payload_t *cp = NULL;
+               enumerator_t *enumerator;
+               attribute_handler_t *handler;
                peer_cfg_t *config;
+               configuration_attribute_type_t type;
+               chunk_t data;
                host_t *vip;
 
                /* reuse virtual IP if we already have one */
@@ -200,25 +245,36 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
                }
                if (vip)
                {
-                       configuration_attribute_t *ca;
-                       cp_payload_t *cp;
-
-                       cp = cp_payload_create();
-                       cp->set_config_type(cp, CFG_REQUEST);
+                       cp = cp_payload_create_type(CFG_REQUEST);
+                       cp->add_attribute(cp, build_vip(vip));
+               }
 
-                       build_vip(this, vip, cp);
+               enumerator = lib->attributes->create_initiator_enumerator(lib->attributes,
+                                                               this->ike_sa->get_other_id(this->ike_sa), vip);
+               while (enumerator->enumerate(enumerator, &handler, &type, &data))
+               {
+                       configuration_attribute_t *ca;
+                       entry_t *entry;
 
-                       /* we currently always add a DNS request if we request an IP */
-                       ca = configuration_attribute_create();
-                       if (vip->get_family(vip) == AF_INET)
-                       {
-                               ca->set_type(ca, INTERNAL_IP4_DNS);
-                       }
-                       else
+                       /* create configuration attribute */
+                       ca = configuration_attribute_create_value(type, data);
+                       if (!cp)
                        {
-                               ca->set_type(ca, INTERNAL_IP6_DNS);
+                               cp = cp_payload_create_type(CFG_REQUEST);
                        }
-                       cp->add_configuration_attribute(cp, ca);
+                       cp->add_attribute(cp, ca);
+
+                       /* save handler along with requested type */
+                       entry = malloc_thing(entry_t);
+                       entry->type = type;
+                       entry->handler = handler;
+
+                       this->requested->insert_last(this->requested, entry);
+               }
+               enumerator->destroy(enumerator);
+
+               if (cp)
+               {
                        message->add_payload(message, (payload_t*)cp);
                }
        }
@@ -244,17 +300,16 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
 {
        if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
        {       /* in last IKE_AUTH exchange */
-               peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
+               enumerator_t *enumerator;
+               configuration_attribute_type_t type;
+               chunk_t value;
+               host_t *vip = NULL;
+               cp_payload_t *cp = NULL;
+               peer_cfg_t *config;
 
+               config = this->ike_sa->get_peer_cfg(this->ike_sa);
                if (config && this->virtual_ip)
                {
-                       enumerator_t *enumerator;
-                       configuration_attribute_type_t type;
-                       configuration_attribute_t *ca;
-                       chunk_t value;
-                       cp_payload_t *cp;
-                       host_t *vip = NULL;
-
                        DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
                        if (config->get_pool(config))
                        {
@@ -274,26 +329,29 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
                        DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
                        this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
 
-                       cp = cp_payload_create();
-                       cp->set_config_type(cp, CFG_REPLY);
-
-                       build_vip(this, vip, cp);
-                       vip->destroy(vip);
+                       cp = cp_payload_create_type(CFG_REPLY);
+                       cp->add_attribute(cp, build_vip(vip));
+               }
 
-                       /* if we add an IP, we also look for other attributes */
-                       enumerator = lib->attributes->create_attribute_enumerator(
-                                       lib->attributes, this->ike_sa->get_other_id(this->ike_sa));
-                       while (enumerator->enumerate(enumerator, &type, &value))
+               /* query registered providers for additional attributes to include */
+               enumerator = lib->attributes->create_responder_enumerator(
+                               lib->attributes, this->ike_sa->get_other_id(this->ike_sa), vip);
+               while (enumerator->enumerate(enumerator, &type, &value))
+               {
+                       if (!cp)
                        {
-                               ca = configuration_attribute_create();
-                               ca->set_type(ca, type);
-                               ca->set_value(ca, value);
-                               cp->add_configuration_attribute(cp, ca);
+                               cp = cp_payload_create_type(CFG_REPLY);
                        }
-                       enumerator->destroy(enumerator);
+                       cp->add_attribute(cp,
+                                               configuration_attribute_create_value(type, value));
+               }
+               enumerator->destroy(enumerator);
 
+               if (cp)
+               {
                        message->add_payload(message, (payload_t*)cp);
                }
+               DESTROY_IF(vip);
                return SUCCESS;
        }
        return NEED_MORE;
@@ -335,6 +393,8 @@ static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
 
        this->ike_sa = ike_sa;
        this->virtual_ip = NULL;
+       this->requested->destroy_function(this->requested, free);
+       this->requested = linked_list_create();
 }
 
 /**
@@ -343,6 +403,7 @@ static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
 static void destroy(private_ike_config_t *this)
 {
        DESTROY_IF(this->virtual_ip);
+       this->requested->destroy_function(this->requested, free);
        free(this);
 }
 
@@ -360,6 +421,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
        this->initiator = initiator;
        this->ike_sa = ike_sa;
        this->virtual_ip = NULL;
+       this->requested = linked_list_create();
 
        if (initiator)
        {
index c9b668cc3ab32591978ca1be69e8bee273fb18a5..d042f47ef9ab858d004ee0e9a3e0723e08651cd6 100644 (file)
@@ -22,6 +22,7 @@
 #define ATTRIBUTE_HANDLER_H_
 
 #include <chunk.h>
+#include <utils/host.h>
 #include <utils/identification.h>
 
 #include "attributes.h"
@@ -56,6 +57,16 @@ struct attribute_handler_t {
         */
        void (*release)(attribute_handler_t *this, identification_t *server,
                                        configuration_attribute_type_t type, chunk_t data);
+
+       /**
+        * Enumerate attributes to request from a server.
+        *
+        * @param server                server identity to request attributes from
+        * @param vip                   virtual IP we are requesting, if any
+        * @return                              enumerator (configuration_attribute_type_t, chunk_t)
+        */
+       enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this,
+                                                                               identification_t *server, host_t *vip);
 };
 
 #endif /** ATTRIBUTE_HANDLER_H_ @}*/
index e09c211dc45ae84048b9f0c5fce2025f2d0ed8e0..0615316f92cf7dd9033e1eb3db7fbbc5b18288fb 100644 (file)
@@ -47,6 +47,16 @@ struct private_attribute_manager_t {
        rwlock_t *lock;
 };
 
+/**
+ * Data to pass to enumerator filters
+ */
+typedef struct {
+       /** server/peer identity */
+       identification_t *id;
+       /** requesting/assigned virtual IP */
+       host_t *vip;
+} enum_data_t;
+
 /**
  * Implementation of attribute_manager_t.acquire_address.
  */
@@ -108,25 +118,29 @@ static void release_address(private_attribute_manager_t *this,
 }
 
 /**
- * inner enumerator constructor for attributes
+ * inner enumerator constructor for responder attributes
  */
-static enumerator_t *attrib_enum_create(attribute_provider_t *provider,
-                                                                               identification_t *id)
+static enumerator_t *responder_enum_create(attribute_provider_t *provider,
+                                                                                  enum_data_t *data)
 {
-       return provider->create_attribute_enumerator(provider, id);
+       return provider->create_attribute_enumerator(provider, data->id, data->vip);
 }
 
 /**
- * Implementation of attribute_manager_t.create_attribute_enumerator
+ * Implementation of attribute_manager_t.create_responder_enumerator
  */
-static enumerator_t* create_attribute_enumerator(
-                                               private_attribute_manager_t *this, identification_t *id)
+static enumerator_t* create_responder_enumerator(
+                       private_attribute_manager_t *this, identification_t *id, host_t *vip)
 {
+       enum_data_t *data = malloc_thing(enum_data_t);
+
+       data->id = id;
+       data->vip = vip;
        this->lock->read_lock(this->lock);
        return enumerator_create_cleaner(
                                enumerator_create_nested(
                                        this->providers->create_enumerator(this->providers),
-                                       (void*)attrib_enum_create, id, NULL),
+                                       (void*)responder_enum_create, data, free),
                                (void*)this->lock->unlock, this->lock);
 }
 
@@ -156,24 +170,38 @@ static void remove_provider(private_attribute_manager_t *this,
  * Implementation of attribute_manager_t.handle
  */
 static attribute_handler_t* handle(private_attribute_manager_t *this,
-                                                                  identification_t *server,
-                                                                  configuration_attribute_type_t type,
-                                                                  chunk_t data)
+                                               identification_t *server, attribute_handler_t *handler,
+                                               configuration_attribute_type_t type, chunk_t data)
 {
        enumerator_t *enumerator;
        attribute_handler_t *current, *handled = NULL;
 
        this->lock->read_lock(this->lock);
+
+       /* try to find the passed handler */
        enumerator = this->handlers->create_enumerator(this->handlers);
        while (enumerator->enumerate(enumerator, &current))
        {
-               if (current->handle(current, server, type, data))
+               if (current == handler && current->handle(current, server, type, data))
                {
                        handled = current;
                        break;
                }
        }
        enumerator->destroy(enumerator);
+       if (!handled)
+       {       /* handler requesting this attribute not found, try any other */
+               enumerator = this->handlers->create_enumerator(this->handlers);
+               while (enumerator->enumerate(enumerator, &current))
+               {
+                       if (current->handle(current, server, type, data))
+                       {
+                               handled = current;
+                               break;
+                       }
+               }
+               enumerator->destroy(enumerator);
+       }
        this->lock->unlock(this->lock);
 
        if (!handled)
@@ -209,6 +237,33 @@ static void release(private_attribute_manager_t *this,
        this->lock->unlock(this->lock);
 }
 
+/**
+ * inner enumerator constructor for initiator attributes
+ */
+static enumerator_t *initiator_enum_create(attribute_handler_t *handler,
+                                                                                  enum_data_t *data)
+{
+       return handler->create_attribute_enumerator(handler, data->id, data->vip);
+}
+
+/**
+ * Implementation of attribute_manager_t.create_initiator_enumerator
+ */
+static enumerator_t* create_initiator_enumerator(
+               private_attribute_manager_t *this, identification_t *id, host_t *vip)
+{
+       enum_data_t *data = malloc_thing(enum_data_t);
+
+       data->id = id;
+       data->vip = vip;
+       this->lock->read_lock(this->lock);
+       return enumerator_create_cleaner(
+                               enumerator_create_nested(
+                                       this->handlers->create_enumerator(this->handlers),
+                                       (void*)initiator_enum_create, data, free),
+                               (void*)this->lock->unlock, this->lock);
+}
+
 /**
  * Implementation of attribute_manager_t.add_handler
  */
@@ -251,11 +306,12 @@ attribute_manager_t *attribute_manager_create()
 
        this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
        this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address;
-       this->public.create_attribute_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*))create_attribute_enumerator;
+       this->public.create_responder_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_responder_enumerator;
        this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider;
        this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider;
-       this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
+       this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*,identification_t*, attribute_handler_t*, configuration_attribute_type_t, chunk_t))handle;
        this->public.release = (void(*)(attribute_manager_t*, attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
+       this->public.create_initiator_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_initiator_enumerator;
        this->public.add_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))add_handler;
        this->public.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))remove_handler;
        this->public.destroy = (void(*)(attribute_manager_t*))destroy;
index ba194b5630be4b22f7c68ec6fc0a897221a2d003..64266236627b280417d1fc8d87e17a47a0b5ce61 100644 (file)
@@ -62,10 +62,11 @@ struct attribute_manager_t {
         * Create an enumerator over attributes to hand out to a peer.
         *
         * @param id                    peer identity to hand out attributes to
+        * @param vip                   virtual IP to assign to peer, if any
         * @return                              enumerator (configuration_attribute_type_t, chunk_t)
         */
-       enumerator_t* (*create_attribute_enumerator)(attribute_manager_t *this,
-                                                                                                identification_t *id);
+       enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
+                                                                                       identification_t *id, host_t *vip);
 
        /**
         * Register an attribute provider to the manager.
@@ -86,13 +87,14 @@ struct attribute_manager_t {
         * Handle a configuration attribute by passing them to the handlers.
         *
         * @param server                server from which the attribute was received
+        * @param handler               handler we requested the attribute for, if any
         * @param type                  type of configuration attribute
         * @param data                  associated attribute data
         * @return                              handler which handled this attribute, NULL if none
         */
        attribute_handler_t* (*handle)(attribute_manager_t *this,
-                                                       identification_t *server,
-                                                       configuration_attribute_type_t type, chunk_t data);
+                                               identification_t *server, attribute_handler_t *handler,
+                                               configuration_attribute_type_t type, chunk_t data);
 
        /**
         * Release an attribute previously handle()d by a handler.
@@ -107,6 +109,16 @@ struct attribute_manager_t {
                                                configuration_attribute_type_t type,
                                                chunk_t data);
 
+       /**
+        * 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
+        * @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);
+
        /**
         * Register an attribute handler to the manager.
         *
index 14721d9214fd877b821dd77ebd4a7928b127765b..f8485cc6c46eb3f1df9ebf48cd67841b03eb1318 100644 (file)
@@ -57,10 +57,11 @@ struct attribute_provider_t {
         * Create an enumerator over attributes to hand out to a peer.
         *
         * @param id                    peer ID
+        * @param vip                   virtual IP to assign to peer, if any
         * @return                              enumerator (configuration_attribute_type_t, chunk_t)
         */
        enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
-                                                                                                identification_t *id);
+                                                                                       identification_t *id, host_t *vip);
 };
 
 #endif /** ATTRIBUTE_PROVIDER_H_ @}*/
index ab6a799e8b0f690f8e6c10a8a00a782cb4985ade..2dd909981109290035c6fa3fb5e972ba2d2e6c00 100644 (file)
@@ -341,7 +341,7 @@ sql_attribute_t *sql_attribute_create(database_t *db)
 
        this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address;
        this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
-       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id))enumerator_create_empty;
+       this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *host))enumerator_create_empty;
        this->public.destroy = (void(*)(sql_attribute_t*))destroy;
 
        this->db = db;