Give plugins more control of which configuration attributes to request, and pass received attributes back to the requesting handler

This commit is contained in:
Martin Willi 2009-11-17 14:51:50 +01:00
parent e6cf060275
commit b5a2055fb1
16 changed files with 503 additions and 302 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@ -38,17 +38,17 @@ struct private_configuration_attribute_t {
/** /**
* Type of the attribute. * Type of the attribute.
*/ */
u_int16_t attribute_type; u_int16_t type;
/** /**
* Length of the attribute. * Length of the attribute.
*/ */
u_int16_t attribute_length; u_int16_t length;
/** /**
* Attribute value as chunk. * 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 * The defined offsets are the positions in a object of type
* private_configuration_attribute_t. * private_configuration_attribute_t.
*
*/ */
encoding_rule_t configuration_attribute_encodings[] = { encoding_rule_t configuration_attribute_encodings[] = {
{ RESERVED_BIT, 0 }, { RESERVED_BIT, 0 },
/* type of the attribute as 15 bit unsigned integer */ /* 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 */ /* 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 */ /* 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; bool failed = FALSE;
if (this->attribute_length != this->attribute_value.len) if (this->length != this->value.len)
{ {
DBG1(DBG_ENC, "invalid attribute length"); DBG1(DBG_ENC, "invalid attribute length");
return FAILED; return FAILED;
} }
switch (this->attribute_type) switch (this->type)
{ {
case INTERNAL_IP4_ADDRESS: case INTERNAL_IP4_ADDRESS:
case INTERNAL_IP4_NETMASK: case INTERNAL_IP4_NETMASK:
@ -102,20 +101,20 @@ static status_t verify(private_configuration_attribute_t *this)
case INTERNAL_IP4_NBNS: case INTERNAL_IP4_NBNS:
case INTERNAL_ADDRESS_EXPIRY: case INTERNAL_ADDRESS_EXPIRY:
case INTERNAL_IP4_DHCP: case INTERNAL_IP4_DHCP:
if (this->attribute_length != 0 && this->attribute_length != 4) if (this->length != 0 && this->length != 4)
{ {
failed = TRUE; failed = TRUE;
} }
break; break;
case INTERNAL_IP4_SUBNET: case INTERNAL_IP4_SUBNET:
if (this->attribute_length != 0 && this->attribute_length != 8) if (this->length != 0 && this->length != 8)
{ {
failed = TRUE; failed = TRUE;
} }
break; break;
case INTERNAL_IP6_ADDRESS: case INTERNAL_IP6_ADDRESS:
case INTERNAL_IP6_SUBNET: case INTERNAL_IP6_SUBNET:
if (this->attribute_length != 0 && this->attribute_length != 17) if (this->length != 0 && this->length != 17)
{ {
failed = TRUE; failed = TRUE;
} }
@ -123,13 +122,13 @@ static status_t verify(private_configuration_attribute_t *this)
case INTERNAL_IP6_DNS: case INTERNAL_IP6_DNS:
case INTERNAL_IP6_NBNS: case INTERNAL_IP6_NBNS:
case INTERNAL_IP6_DHCP: case INTERNAL_IP6_DHCP:
if (this->attribute_length != 0 && this->attribute_length != 16) if (this->length != 0 && this->length != 16)
{ {
failed = TRUE; failed = TRUE;
} }
break; break;
case SUPPORTED_ATTRIBUTES: case SUPPORTED_ATTRIBUTES:
if (this->attribute_length % 2) if (this->length % 2)
{ {
failed = TRUE; failed = TRUE;
} }
@ -139,15 +138,14 @@ static status_t verify(private_configuration_attribute_t *this)
break; break;
default: default:
DBG1(DBG_ENC, "unknown attribute type %N", DBG1(DBG_ENC, "unknown attribute type %N",
configuration_attribute_type_names, this->attribute_type); configuration_attribute_type_names, this->type);
break; break;
} }
if (failed) if (failed)
{ {
DBG1(DBG_ENC, "invalid attribute length %d for %N", DBG1(DBG_ENC, "invalid attribute length %d for %N",
this->attribute_length, configuration_attribute_type_names, this->length, configuration_attribute_type_names, this->type);
this->attribute_type);
return FAILED; return FAILED;
} }
return SUCCESS; return SUCCESS;
@ -156,7 +154,8 @@ static status_t verify(private_configuration_attribute_t *this)
/** /**
* Implementation of payload_t.get_encoding_rules. * 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; *rules = configuration_attribute_encodings;
*rule_count = sizeof(configuration_attribute_encodings) / sizeof(encoding_rule_t); *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) 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. * 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,68 +190,32 @@ static void set_next_type(private_configuration_attribute_t *this,payload_type_t
*/ */
static size_t get_length(private_configuration_attribute_t *this) 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.
*/
static void set_value(private_configuration_attribute_t *this, chunk_t value)
{
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;
}
/**
* Implementation of configuration_attribute_t.get_value.
*/
static chunk_t get_value (private_configuration_attribute_t *this)
{
return this->attribute_value;
}
/**
* Implementation of configuration_attribute_t.set_type.
*/
static void set_attribute_type (private_configuration_attribute_t *this, u_int16_t type)
{
this->attribute_type = type & 0x7FFF;
} }
/** /**
* Implementation of configuration_attribute_t.get_type. * Implementation of configuration_attribute_t.get_type.
*/ */
static u_int16_t get_attribute_type (private_configuration_attribute_t *this) static configuration_attribute_type_t get_configuration_attribute_type(
private_configuration_attribute_t *this)
{ {
return this->attribute_type; return this->type;
} }
/** /**
* Implementation of configuration_attribute_t.get_length. * Implementation of configuration_attribute_t.get_value.
*/ */
static u_int16_t get_attribute_length (private_configuration_attribute_t *this) static chunk_t get_value(private_configuration_attribute_t *this)
{ {
return this->attribute_length; return this->value;
} }
/** /**
* Implementation of configuration_attribute_t.destroy and payload_t.destroy. * Implementation of configuration_attribute_t.destroy and payload_t.destroy.
*/ */
static void destroy(private_configuration_attribute_t *this) static void destroy(private_configuration_attribute_t *this)
{ {
if (this->attribute_value.ptr != NULL) free(this->value.ptr);
{
free(this->attribute_value.ptr);
}
free(this); free(this);
} }
@ -260,29 +224,41 @@ static void destroy(private_configuration_attribute_t *this)
*/ */
configuration_attribute_t *configuration_attribute_create() configuration_attribute_t *configuration_attribute_create()
{ {
private_configuration_attribute_t *this = malloc_thing(private_configuration_attribute_t); private_configuration_attribute_t *this;
/* payload interface */ this = malloc_thing(private_configuration_attribute_t);
this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; 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_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_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.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.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.get_type = (payload_type_t(*)(payload_t *))get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; this->public.payload_interface.destroy = (void(*)(payload_t*))destroy;
/* public functions */ this->public.get_value = (chunk_t(*)(configuration_attribute_t *))get_value;
this->public.set_value = (void (*) (configuration_attribute_t *,chunk_t)) set_value; this->public.get_type = (configuration_attribute_type_t(*)(configuration_attribute_t *))get_configuration_attribute_type;
this->public.get_value = (chunk_t (*) (configuration_attribute_t *)) get_value; this->public.destroy = (void (*)(configuration_attribute_t*))destroy;
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->type = 0;
this->attribute_type = 0; this->value = chunk_empty;
this->attribute_value = chunk_empty; this->length = 0;
this->attribute_length = 0;
return (&(this->public)); return &this->public;
} }
/*
* Described in header.
*/
configuration_attribute_t *configuration_attribute_create_value(
configuration_attribute_type_t type, chunk_t value)
{
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;
return &this->public;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@ -28,7 +28,6 @@ typedef struct configuration_attribute_t configuration_attribute_t;
#include <attributes/attributes.h> #include <attributes/attributes.h>
#include <encoding/payloads/payload.h> #include <encoding/payloads/payload.h>
/** /**
* Configuration attribute header length in bytes. * Configuration attribute header length in bytes.
*/ */
@ -40,50 +39,26 @@ typedef struct configuration_attribute_t configuration_attribute_t;
* The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1. * The CONFIGURATION ATTRIBUTE format is described in RFC section 3.15.1.
*/ */
struct configuration_attribute_t { struct configuration_attribute_t {
/** /**
* The payload_t interface. * Implements payload_t interface.
*/ */
payload_t payload_interface; payload_t payload_interface;
/** /**
* Returns the currently set value of the attribute. * Get the type of the attribute.
* *
* @warning Returned data are not copied. * @return type of the configuration attribute
*/
configuration_attribute_type_t (*get_type)(configuration_attribute_t *this);
/**
* Returns the value of the attribute.
* *
* @return chunk_t pointing to the value * @return chunk_t pointing to the internal value
*/ */
chunk_t (*get_value) (configuration_attribute_t *this); 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)
*/
void (*set_type) (configuration_attribute_t *this, u_int16_t type);
/**
* get the type of the attribute.
*
* @return type of the value
*/
u_int16_t (*get_type) (configuration_attribute_t *this);
/**
* get the length of an attribute.
*
* @return type of the value
*/
u_int16_t (*get_length) (configuration_attribute_t *this);
/** /**
* Destroys an configuration_attribute_t object. * 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_t object * @return created configuration attribute
*/ */
configuration_attribute_t *configuration_attribute_create(void); configuration_attribute_t *configuration_attribute_create();
/**
* Creates a configuration attribute with type and value.
*
* @param type type of configuration attribute
* @param value value, gets cloned
* @return created configuration attribute
*/
configuration_attribute_t *configuration_attribute_create_value(
configuration_attribute_type_t type, chunk_t value);
#endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/ #endif /** CONFIGURATION_ATTRIBUTE_H_ @}*/

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@ -56,14 +56,14 @@ struct private_cp_payload_t {
u_int16_t payload_length; 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. * 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) }, { PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure, /* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */ 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 }, { 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) static status_t verify(private_cp_payload_t *this)
{ {
status_t status = SUCCESS; status_t status = SUCCESS;
iterator_t *iterator; enumerator_t *enumerator;
configuration_attribute_t *attribute; payload_t *attribute;
iterator = this->attributes->create_iterator(this->attributes,TRUE); enumerator = this->attributes->create_enumerator(this->attributes);
while(iterator->iterate(iterator, (void**)&attribute)) while (enumerator->enumerate(enumerator, &attribute))
{ {
status = attribute->payload_interface.verify(&attribute->payload_interface); status = attribute->verify(attribute);
if (status != SUCCESS) if (status != SUCCESS)
{ {
break; break;
} }
} }
iterator->destroy(iterator); enumerator->destroy(enumerator);
return status; return status;
} }
/** /**
* Implementation of payload_t.get_encoding_rules. * 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; *rules = cp_payload_encodings;
*rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t); *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) 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) static void compute_length(private_cp_payload_t *this)
{ {
iterator_t *iterator; enumerator_t *enumerator;
payload_t *current_attribute; payload_t *attribute;
size_t length = CP_PAYLOAD_HEADER_LENGTH;
iterator = this->attributes->create_iterator(this->attributes,TRUE); this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
while (iterator->iterate(iterator, (void**)&current_attribute))
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); enumerator->destroy(enumerator);
this->payload_length = length;
} }
/** /**
@ -190,41 +190,33 @@ static void compute_length(private_cp_payload_t *this)
*/ */
static size_t get_length(private_cp_payload_t *this) static size_t get_length(private_cp_payload_t *this)
{ {
compute_length(this);
return this->payload_length; 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); compute_length(this);
} }
/** /**
* Implementation of cp_payload_t.set_config_type. * Implementation of cp_payload_t.get_type.
*/ */
static void set_config_type (private_cp_payload_t *this,config_type_t config_type) static config_type_t get_config_type(private_cp_payload_t *this)
{ {
this->config_type = config_type; return this->type;
}
/**
* Implementation of cp_payload_t.get_config_type.
*/
static config_type_t get_config_type (private_cp_payload_t *this)
{
return this->config_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) static void destroy(private_cp_payload_t *this)
{ {
this->attributes->destroy_offset(this->attributes, this->attributes->destroy_offset(this->attributes,
offsetof(configuration_attribute_t, destroy)); offsetof(configuration_attribute_t, destroy));
free(this); free(this);
} }
@ -244,7 +236,6 @@ cp_payload_t *cp_payload_create()
{ {
private_cp_payload_t *this = malloc_thing(private_cp_payload_t); 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.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_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_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.get_type = (payload_type_t (*) (payload_t *)) get_type;
this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
/* public functions */ this->public.create_attribute_enumerator = (enumerator_t*(*)(cp_payload_t *))create_attribute_enumerator;
this->public.create_attribute_iterator = (iterator_t* (*) (cp_payload_t *)) create_attribute_iterator; this->public.add_attribute = (void (*) (cp_payload_t *,configuration_attribute_t*))add_attribute;
this->public.add_configuration_attribute = (void (*) (cp_payload_t *,configuration_attribute_t *)) add_configuration_attribute; this->public.get_type = (config_type_t (*) (cp_payload_t *))get_config_type;
this->public.set_config_type = (void (*) (cp_payload_t *, config_type_t)) set_config_type; this->public.destroy = (void (*)(cp_payload_t *))destroy;
this->public.get_config_type = (config_type_t (*) (cp_payload_t *)) get_config_type;
this->public.destroy = (void (*) (cp_payload_t *)) destroy;
/* set default values of the fields */ /* set default values of the fields */
this->critical = FALSE; this->critical = FALSE;
this->next_payload = NO_PAYLOAD; this->next_payload = NO_PAYLOAD;
this->payload_length = CP_PAYLOAD_HEADER_LENGTH; this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
this->attributes = linked_list_create(); 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;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@ -28,7 +28,7 @@ typedef struct cp_payload_t cp_payload_t;
#include <library.h> #include <library.h>
#include <encoding/payloads/payload.h> #include <encoding/payloads/payload.h>
#include <encoding/payloads/configuration_attribute.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. * 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. * The CP Payload format is described in RFC section 3.15.
*/ */
struct cp_payload_t { struct cp_payload_t {
/** /**
* The payload_t interface. * The payload_t interface.
*/ */
@ -64,36 +65,24 @@ struct cp_payload_t {
/** /**
* Creates an iterator of stored configuration_attribute_t objects. * Creates an iterator of stored configuration_attribute_t objects.
* *
* When deleting an attribute using this iterator, the length of this * @return enumerator over configration_attribute_T
* configuration_attribute_t has to be refreshed by calling get_length()!
*
* @return created iterator_t object
*/ */
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. * Adds a configuration attribute to the configuration payload.
* *
* The added configuration_attribute_t object is getting destroyed in * @param attribute attribute to add
* destroy function of cp_payload_t.
*
* @param attribute configuration_attribute_t object 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); config_type_t (*get_type) (cp_payload_t *this);
/**
* Get the config type.
*
* @return config_type_t
*/
config_type_t (*get_config_type) (cp_payload_t *this);
/** /**
* Destroys an cp_payload_t object. * 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 cp_payload_t object * @return empty configuration payload
*/ */
cp_payload_t *cp_payload_create(void); cp_payload_t *cp_payload_create();
/**
* Creates an cp_payload_t with type and value
*
* @param type type of configuration payload to create
* @return created configuration payload
*/
cp_payload_t *cp_payload_create_type(config_type_t config_type);
#endif /** CP_PAYLOAD_H_ @}*/ #endif /** CP_PAYLOAD_H_ @}*/

View File

@ -61,12 +61,16 @@ static bool attr_enum_filter(void *null, attribute_entry_t **in,
/** /**
* Implementation of attribute_provider_t.create_attribute_enumerator * Implementation of attribute_provider_t.create_attribute_enumerator
*/ */
static enumerator_t* create_attribute_enumerator( static enumerator_t* create_attribute_enumerator(private_attr_provider_t *this,
private_attr_provider_t *this, identification_t *id) identification_t *id, host_t *vip)
{ {
return enumerator_create_filter( if (vip)
{
return enumerator_create_filter(
this->attributes->create_enumerator(this->attributes), this->attributes->create_enumerator(this->attributes),
(void*)attr_enum_filter, NULL, NULL); (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.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.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->public.destroy = (void(*)(attr_provider_t*))destroy;
this->attributes = linked_list_create(); this->attributes = linked_list_create();

View File

@ -67,6 +67,50 @@ static bool handle(private_nm_handler_t *this, identification_t *server,
return TRUE; 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 * 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.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.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.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator;
this->public.reset = (void(*)(nm_handler_t*))reset; this->public.reset = (void(*)(nm_handler_t*))reset;
this->public.destroy = (void(*)(nm_handler_t*))destroy; this->public.destroy = (void(*)(nm_handler_t*))destroy;

View File

@ -163,6 +163,59 @@ static void release(private_resolve_handler_t *this, identification_t *server,
this->mutex->unlock(this->mutex); 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. * 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.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.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->public.destroy = (void(*)(resolve_handler_t*))destroy;
this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);

View 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.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.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.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.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; this->public.create_pool_enumerator = (enumerator_t*(*)(stroke_attribute_t*))create_pool_enumerator;

View File

@ -1843,22 +1843,16 @@ static status_t roam(private_ike_sa_t *this, bool address)
* Implementation of ike_sa_t.add_configuration_attribute * Implementation of ike_sa_t.add_configuration_attribute
*/ */
static void add_configuration_attribute(private_ike_sa_t *this, static void add_configuration_attribute(private_ike_sa_t *this,
attribute_handler_t *handler,
configuration_attribute_type_t type, chunk_t data) configuration_attribute_type_t type, chunk_t data)
{ {
attribute_entry_t *entry; attribute_entry_t *entry = malloc_thing(attribute_entry_t);
attribute_handler_t *handler;
handler = lib->attributes->handle(lib->attributes, this->other_id, entry->handler = handler;
type, data); entry->type = type;
if (handler) entry->data = chunk_clone(data);
{
entry = malloc_thing(attribute_entry_t);
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.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.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.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; this->public.set_kmaddress = (void (*)(ike_sa_t*,host_t*,host_t*))set_kmaddress;
#ifdef ME #ifdef ME
this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server; this->public.act_as_mediation_server = (void (*)(ike_sa_t*)) act_as_mediation_server;

View File

@ -855,6 +855,7 @@ struct ike_sa_t {
* @param data associated attribute data * @param data associated attribute data
*/ */
void (*add_configuration_attribute)(ike_sa_t *this, void (*add_configuration_attribute)(ike_sa_t *this,
attribute_handler_t *handler,
configuration_attribute_type_t type, chunk_t data); configuration_attribute_type_t type, chunk_t data);
/** /**

View File

@ -19,9 +19,6 @@
#include <daemon.h> #include <daemon.h>
#include <encoding/payloads/cp_payload.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; typedef struct private_ike_config_t private_ike_config_t;
/** /**
@ -48,21 +45,34 @@ struct private_ike_config_t {
* virtual ip * virtual ip
*/ */
host_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
*/ */
static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp) typedef struct {
{ /** attribute requested */
configuration_attribute_t *ca; configuration_attribute_type_t type;
chunk_t chunk, prefix; /** handler requesting this attribute */
attribute_handler_t *handler;
} entry_t;
ca = configuration_attribute_create(); /**
* build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
*/
static configuration_attribute_t *build_vip(host_t *vip)
{
configuration_attribute_type_t type;
chunk_t chunk, prefix;
if (vip->get_family(vip) == AF_INET) if (vip->get_family(vip) == AF_INET)
{ {
ca->set_type(ca, INTERNAL_IP4_ADDRESS); type = INTERNAL_IP4_ADDRESS;
if (vip->is_anyaddr(vip)) if (vip->is_anyaddr(vip))
{ {
chunk = chunk_empty; chunk = chunk_empty;
@ -74,7 +84,7 @@ static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
} }
else else
{ {
ca->set_type(ca, INTERNAL_IP6_ADDRESS); type = INTERNAL_IP6_ADDRESS;
if (vip->is_anyaddr(vip)) if (vip->is_anyaddr(vip))
{ {
chunk = chunk_empty; 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); chunk = chunk_cata("cc", chunk, prefix);
} }
} }
ca->set_value(ca, chunk); return configuration_attribute_create_value(type, chunk);
cp->add_configuration_attribute(cp, ca); }
/**
* 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; break;
} }
default: default:
{
if (this->initiator) if (this->initiator)
{ {
this->ike_sa->add_configuration_attribute(this->ike_sa, handle_attribute(this, ca);
ca->get_type(ca), ca->get_value(ca));
}
else
{
/* we do not handle attribute requests other than for VIPs */
} }
}
} }
} }
@ -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) static void process_payloads(private_ike_config_t *this, message_t *message)
{ {
enumerator_t *enumerator; enumerator_t *enumerator, *attributes;
iterator_t *attributes;
payload_t *payload; payload_t *payload;
enumerator = message->create_payload_enumerator(message); 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; cp_payload_t *cp = (cp_payload_t*)payload;
configuration_attribute_t *ca; configuration_attribute_t *ca;
switch (cp->get_config_type(cp))
switch (cp->get_type(cp))
{ {
case CFG_REQUEST: case CFG_REQUEST:
case CFG_REPLY: case CFG_REPLY:
{ {
attributes = cp->create_attribute_iterator(cp); attributes = cp->create_attribute_enumerator(cp);
while (attributes->iterate(attributes, (void**)&ca)) while (attributes->enumerate(attributes, &ca))
{ {
process_attribute(this, ca); process_attribute(this, ca);
} }
@ -173,7 +213,7 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
} }
default: default:
DBG1(DBG_IKE, "ignoring %N config payload", DBG1(DBG_IKE, "ignoring %N config payload",
config_type_names, cp->get_config_type(cp)); config_type_names, cp->get_type(cp));
break; 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) if (message->get_message_id(message) == 1)
{ /* in first IKE_AUTH only */ { /* in first IKE_AUTH only */
cp_payload_t *cp = NULL;
enumerator_t *enumerator;
attribute_handler_t *handler;
peer_cfg_t *config; peer_cfg_t *config;
configuration_attribute_type_t type;
chunk_t data;
host_t *vip; host_t *vip;
/* reuse virtual IP if we already have one */ /* reuse virtual IP if we already have one */
@ -199,26 +244,37 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
vip = config->get_virtual_ip(config); vip = config->get_virtual_ip(config);
} }
if (vip) if (vip)
{
cp = cp_payload_create_type(CFG_REQUEST);
cp->add_attribute(cp, build_vip(vip));
}
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; configuration_attribute_t *ca;
cp_payload_t *cp; entry_t *entry;
cp = cp_payload_create(); /* create configuration attribute */
cp->set_config_type(cp, CFG_REQUEST); ca = configuration_attribute_create_value(type, data);
if (!cp)
build_vip(this, vip, cp);
/* 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); cp = cp_payload_create_type(CFG_REQUEST);
} }
else cp->add_attribute(cp, ca);
{
ca->set_type(ca, INTERNAL_IP6_DNS); /* save handler along with requested type */
} entry = malloc_thing(entry_t);
cp->add_configuration_attribute(cp, ca); 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); 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) if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */ { /* 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) 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); DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
if (config->get_pool(config)) 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); DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip); this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
cp = cp_payload_create(); cp = cp_payload_create_type(CFG_REPLY);
cp->set_config_type(cp, CFG_REPLY); cp->add_attribute(cp, build_vip(vip));
}
build_vip(this, vip, cp); /* query registered providers for additional attributes to include */
vip->destroy(vip); enumerator = lib->attributes->create_responder_enumerator(
lib->attributes, this->ike_sa->get_other_id(this->ike_sa), vip);
/* if we add an IP, we also look for other attributes */ while (enumerator->enumerate(enumerator, &type, &value))
enumerator = lib->attributes->create_attribute_enumerator( {
lib->attributes, this->ike_sa->get_other_id(this->ike_sa)); if (!cp)
while (enumerator->enumerate(enumerator, &type, &value))
{ {
ca = configuration_attribute_create(); cp = cp_payload_create_type(CFG_REPLY);
ca->set_type(ca, type);
ca->set_value(ca, value);
cp->add_configuration_attribute(cp, ca);
} }
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); message->add_payload(message, (payload_t*)cp);
} }
DESTROY_IF(vip);
return SUCCESS; return SUCCESS;
} }
return NEED_MORE; 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->ike_sa = ike_sa;
this->virtual_ip = NULL; 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) static void destroy(private_ike_config_t *this)
{ {
DESTROY_IF(this->virtual_ip); DESTROY_IF(this->virtual_ip);
this->requested->destroy_function(this->requested, free);
free(this); free(this);
} }
@ -360,6 +421,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
this->initiator = initiator; this->initiator = initiator;
this->ike_sa = ike_sa; this->ike_sa = ike_sa;
this->virtual_ip = NULL; this->virtual_ip = NULL;
this->requested = linked_list_create();
if (initiator) if (initiator)
{ {

View File

@ -22,6 +22,7 @@
#define ATTRIBUTE_HANDLER_H_ #define ATTRIBUTE_HANDLER_H_
#include <chunk.h> #include <chunk.h>
#include <utils/host.h>
#include <utils/identification.h> #include <utils/identification.h>
#include "attributes.h" #include "attributes.h"
@ -56,6 +57,16 @@ struct attribute_handler_t {
*/ */
void (*release)(attribute_handler_t *this, identification_t *server, void (*release)(attribute_handler_t *this, identification_t *server,
configuration_attribute_type_t type, chunk_t data); 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_ @}*/ #endif /** ATTRIBUTE_HANDLER_H_ @}*/

View File

@ -47,6 +47,16 @@ struct private_attribute_manager_t {
rwlock_t *lock; 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. * 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, static enumerator_t *responder_enum_create(attribute_provider_t *provider,
identification_t *id) 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( static enumerator_t* create_responder_enumerator(
private_attribute_manager_t *this, identification_t *id) 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); this->lock->read_lock(this->lock);
return enumerator_create_cleaner( return enumerator_create_cleaner(
enumerator_create_nested( enumerator_create_nested(
this->providers->create_enumerator(this->providers), this->providers->create_enumerator(this->providers),
(void*)attrib_enum_create, id, NULL), (void*)responder_enum_create, data, free),
(void*)this->lock->unlock, this->lock); (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 * Implementation of attribute_manager_t.handle
*/ */
static attribute_handler_t* handle(private_attribute_manager_t *this, static attribute_handler_t* handle(private_attribute_manager_t *this,
identification_t *server, identification_t *server, attribute_handler_t *handler,
configuration_attribute_type_t type, configuration_attribute_type_t type, chunk_t data)
chunk_t data)
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
attribute_handler_t *current, *handled = NULL; attribute_handler_t *current, *handled = NULL;
this->lock->read_lock(this->lock); this->lock->read_lock(this->lock);
/* try to find the passed handler */
enumerator = this->handlers->create_enumerator(this->handlers); enumerator = this->handlers->create_enumerator(this->handlers);
while (enumerator->enumerate(enumerator, &current)) while (enumerator->enumerate(enumerator, &current))
{ {
if (current->handle(current, server, type, data)) if (current == handler && current->handle(current, server, type, data))
{ {
handled = current; handled = current;
break; break;
} }
} }
enumerator->destroy(enumerator); 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); this->lock->unlock(this->lock);
if (!handled) if (!handled)
@ -209,6 +237,33 @@ static void release(private_attribute_manager_t *this,
this->lock->unlock(this->lock); 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 * 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.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.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.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.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.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.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.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))remove_handler;
this->public.destroy = (void(*)(attribute_manager_t*))destroy; this->public.destroy = (void(*)(attribute_manager_t*))destroy;

View File

@ -62,10 +62,11 @@ struct attribute_manager_t {
* Create an enumerator over attributes to hand out to a peer. * Create an enumerator over attributes to hand out to a peer.
* *
* @param id peer identity to hand out attributes to * @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) * @return enumerator (configuration_attribute_type_t, chunk_t)
*/ */
enumerator_t* (*create_attribute_enumerator)(attribute_manager_t *this, enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
identification_t *id); identification_t *id, host_t *vip);
/** /**
* Register an attribute provider to the manager. * 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. * Handle a configuration attribute by passing them to the handlers.
* *
* @param server server from which the attribute was received * @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 type type of configuration attribute
* @param data associated attribute data * @param data associated attribute data
* @return handler which handled this attribute, NULL if none * @return handler which handled this attribute, NULL if none
*/ */
attribute_handler_t* (*handle)(attribute_manager_t *this, attribute_handler_t* (*handle)(attribute_manager_t *this,
identification_t *server, identification_t *server, attribute_handler_t *handler,
configuration_attribute_type_t type, chunk_t data); configuration_attribute_type_t type, chunk_t data);
/** /**
* Release an attribute previously handle()d by a handler. * Release an attribute previously handle()d by a handler.
@ -107,6 +109,16 @@ struct attribute_manager_t {
configuration_attribute_type_t type, configuration_attribute_type_t type,
chunk_t data); 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. * Register an attribute handler to the manager.
* *

View File

@ -57,10 +57,11 @@ struct attribute_provider_t {
* Create an enumerator over attributes to hand out to a peer. * Create an enumerator over attributes to hand out to a peer.
* *
* @param id peer ID * @param id peer ID
* @param vip virtual IP to assign to peer, if any
* @return enumerator (configuration_attribute_type_t, chunk_t) * @return enumerator (configuration_attribute_type_t, chunk_t)
*/ */
enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this, enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
identification_t *id); identification_t *id, host_t *vip);
}; };
#endif /** ATTRIBUTE_PROVIDER_H_ @}*/ #endif /** ATTRIBUTE_PROVIDER_H_ @}*/

View 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.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.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->public.destroy = (void(*)(sql_attribute_t*))destroy;
this->db = db; this->db = db;