aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/charon/encoding/payloads/configuration_attribute.c156
-rw-r--r--src/charon/encoding/payloads/configuration_attribute.h59
-rw-r--r--src/charon/encoding/payloads/cp_payload.c103
-rw-r--r--src/charon/encoding/payloads/cp_payload.h49
-rw-r--r--src/charon/plugins/attr/attr_provider.c12
-rw-r--r--src/charon/plugins/nm/nm_handler.c45
-rw-r--r--src/charon/plugins/resolve/resolve_handler.c54
-rw-r--r--src/charon/plugins/stroke/stroke_attribute.c2
-rw-r--r--src/charon/sa/ike_sa.c20
-rw-r--r--src/charon/sa/ike_sa.h1
-rw-r--r--src/charon/sa/tasks/ike_config.c184
-rw-r--r--src/libstrongswan/attributes/attribute_handler.h11
-rw-r--r--src/libstrongswan/attributes/attribute_manager.c84
-rw-r--r--src/libstrongswan/attributes/attribute_manager.h20
-rw-r--r--src/libstrongswan/attributes/attribute_provider.h3
-rw-r--r--src/libstrongswan/plugins/attr_sql/sql_attribute.c2
16 files changed, 503 insertions, 302 deletions
diff --git a/src/charon/encoding/payloads/configuration_attribute.c b/src/charon/encoding/payloads/configuration_attribute.c
index caba34a6c..9094fd44d 100644
--- a/src/charon/encoding/payloads/configuration_attribute.c
+++ b/src/charon/encoding/payloads/configuration_attribute.c
@@ -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));
-}
diff --git a/src/charon/encoding/payloads/configuration_attribute.h b/src/charon/encoding/payloads/configuration_attribute.h
index f30fbfa72..6e4b018bb 100644
--- a/src/charon/encoding/payloads/configuration_attribute.h
+++ b/src/charon/encoding/payloads/configuration_attribute.h
@@ -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_ @}*/
diff --git a/src/charon/encoding/payloads/cp_payload.c b/src/charon/encoding/payloads/cp_payload.c
index 8dc4b69f2..f0a26eee2 100644
--- a/src/charon/encoding/payloads/cp_payload.c
+++ b/src/charon/encoding/payloads/cp_payload.c
@@ -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;
}
+
diff --git a/src/charon/encoding/payloads/cp_payload.h b/src/charon/encoding/payloads/cp_payload.h
index 11f5061b9..c0760885a 100644
--- a/src/charon/encoding/payloads/cp_payload.h
+++ b/src/charon/encoding/payloads/cp_payload.h
@@ -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_ @}*/
diff --git a/src/charon/plugins/attr/attr_provider.c b/src/charon/plugins/attr/attr_provider.c
index 88c5ed4c0..00fcbf6ef 100644
--- a/src/charon/plugins/attr/attr_provider.c
+++ b/src/charon/plugins/attr/attr_provider.c
@@ -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();
diff --git a/src/charon/plugins/nm/nm_handler.c b/src/charon/plugins/nm/nm_handler.c
index 7756b8e7a..eacb54dda 100644
--- a/src/charon/plugins/nm/nm_handler.c
+++ b/src/charon/plugins/nm/nm_handler.c
@@ -68,6 +68,50 @@ static bool handle(private_nm_handler_t *this, identification_t *server,
}
/**
+ * 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
*/
static bool filter_chunks(void* null, char **in, chunk_t *out)
@@ -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;
diff --git a/src/charon/plugins/resolve/resolve_handler.c b/src/charon/plugins/resolve/resolve_handler.c
index 7c7d52a05..ff0e5943e 100644
--- a/src/charon/plugins/resolve/resolve_handler.c
+++ b/src/charon/plugins/resolve/resolve_handler.c
@@ -164,6 +164,59 @@ static void release(private_resolve_handler_t *this, identification_t *server,
}
/**
+ * 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.
*/
static void destroy(private_resolve_handler_t *this)
@@ -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);
diff --git a/src/charon/plugins/stroke/stroke_attribute.c b/src/charon/plugins/stroke/stroke_attribute.c
index 5c24d346b..db8b53e96 100644
--- a/src/charon/plugins/stroke/stroke_attribute.c
+++ b/src/charon/plugins/stroke/stroke_attribute.c
@@ -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;
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index c681b0180..a6bae454f 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -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;
diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h
index 525e80b0a..5e6378b82 100644
--- a/src/charon/sa/ike_sa.h
+++ b/src/charon/sa/ike_sa.h
@@ -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);
/**
diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c
index 0e2340a6a..1c222fa8c 100644
--- a/src/charon/sa/tasks/ike_config.c
+++ b/src/charon/sa/tasks/ike_config.c
@@ -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)
{
diff --git a/src/libstrongswan/attributes/attribute_handler.h b/src/libstrongswan/attributes/attribute_handler.h
index c9b668cc3..d042f47ef 100644
--- a/src/libstrongswan/attributes/attribute_handler.h
+++ b/src/libstrongswan/attributes/attribute_handler.h
@@ -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_ @}*/
diff --git a/src/libstrongswan/attributes/attribute_manager.c b/src/libstrongswan/attributes/attribute_manager.c
index e09c211dc..0615316f9 100644
--- a/src/libstrongswan/attributes/attribute_manager.c
+++ b/src/libstrongswan/attributes/attribute_manager.c
@@ -48,6 +48,16 @@ struct private_attribute_manager_t {
};
/**
+ * 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.
*/
static host_t* acquire_address(private_attribute_manager_t *this,
@@ -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)
@@ -210,6 +238,33 @@ static void release(private_attribute_manager_t *this,
}
/**
+ * 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
*/
static void add_handler(private_attribute_manager_t *this,
@@ -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;
diff --git a/src/libstrongswan/attributes/attribute_manager.h b/src/libstrongswan/attributes/attribute_manager.h
index ba194b563..642662366 100644
--- a/src/libstrongswan/attributes/attribute_manager.h
+++ b/src/libstrongswan/attributes/attribute_manager.h
@@ -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.
@@ -108,6 +110,16 @@ struct attribute_manager_t {
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.
*
* @param handler attribute handler to register
diff --git a/src/libstrongswan/attributes/attribute_provider.h b/src/libstrongswan/attributes/attribute_provider.h
index 14721d921..f8485cc6c 100644
--- a/src/libstrongswan/attributes/attribute_provider.h
+++ b/src/libstrongswan/attributes/attribute_provider.h
@@ -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_ @}*/
diff --git a/src/libstrongswan/plugins/attr_sql/sql_attribute.c b/src/libstrongswan/plugins/attr_sql/sql_attribute.c
index ab6a799e8..2dd909981 100644
--- a/src/libstrongswan/plugins/attr_sql/sql_attribute.c
+++ b/src/libstrongswan/plugins/attr_sql/sql_attribute.c
@@ -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;