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
* 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,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)
{
return (this->attribute_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;
return this->value.len + CONFIGURATION_ATTRIBUTE_HEADER_LENGTH;
}
/**
* 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.
*/
static void destroy(private_configuration_attribute_t *this)
{
if (this->attribute_value.ptr != NULL)
{
free(this->attribute_value.ptr);
}
free(this->value.ptr);
free(this);
}
@ -260,29 +224,41 @@ static void destroy(private_configuration_attribute_t *this)
*/
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->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 = 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;
/* 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;
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;
/* set default values of the fields */
this->attribute_type = 0;
this->attribute_value = chunk_empty;
this->attribute_length = 0;
this->type = 0;
this->value = chunk_empty;
this->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
* 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,50 +39,26 @@ 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.
* Implements payload_t 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);
/**
* 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.
*/
@ -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_ @}*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@ -56,14 +56,14 @@ struct private_cp_payload_t {
u_int16_t payload_length;
/**
* Configuration Attributes in this payload are stored in a linked_list_t.
* List of attributes, as configuration_attribute_t
*/
linked_list_t * attributes;
linked_list_t *attributes;
/**
* Config Type.
*/
u_int8_t config_type;
u_int8_t type;
};
/**
@ -90,7 +90,7 @@ encoding_rule_t cp_payload_encodings[] = {
{ PAYLOAD_LENGTH, offsetof(private_cp_payload_t, payload_length) },
/* Proposals are stored in a proposal substructure,
offset points to a linked_list_t pointer */
{ U_INT_8, offsetof(private_cp_payload_t, config_type) },
{ U_INT_8, offsetof(private_cp_payload_t, type) },
{ RESERVED_BYTE,0 },
{ RESERVED_BYTE,0 },
{ RESERVED_BYTE,0 },
@ -117,26 +117,27 @@ encoding_rule_t cp_payload_encodings[] = {
static status_t verify(private_cp_payload_t *this)
{
status_t status = SUCCESS;
iterator_t *iterator;
configuration_attribute_t *attribute;
enumerator_t *enumerator;
payload_t *attribute;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while(iterator->iterate(iterator, (void**)&attribute))
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
status = attribute->payload_interface.verify(&attribute->payload_interface);
status = attribute->verify(attribute);
if (status != SUCCESS)
{
break;
}
}
iterator->destroy(iterator);
enumerator->destroy(enumerator);
return status;
}
/**
* Implementation of payload_t.get_encoding_rules.
*/
static void get_encoding_rules(private_cp_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
static void get_encoding_rules(private_cp_payload_t *this,
encoding_rule_t **rules, size_t *rule_count)
{
*rules = cp_payload_encodings;
*rule_count = sizeof(cp_payload_encodings) / sizeof(encoding_rule_t);
@ -155,7 +156,7 @@ static payload_type_t get_type(private_cp_payload_t *this)
*/
static payload_type_t get_next_type(private_cp_payload_t *this)
{
return (this->next_payload);
return this->next_payload;
}
/**
@ -171,18 +172,17 @@ static void set_next_type(private_cp_payload_t *this,payload_type_t type)
*/
static void compute_length(private_cp_payload_t *this)
{
iterator_t *iterator;
payload_t *current_attribute;
size_t length = CP_PAYLOAD_HEADER_LENGTH;
enumerator_t *enumerator;
payload_t *attribute;
iterator = this->attributes->create_iterator(this->attributes,TRUE);
while (iterator->iterate(iterator, (void**)&current_attribute))
this->payload_length = CP_PAYLOAD_HEADER_LENGTH;
enumerator = this->attributes->create_enumerator(this->attributes);
while (enumerator->enumerate(enumerator, &attribute))
{
length += current_attribute->get_length(current_attribute);
this->payload_length += attribute->get_length(attribute);
}
iterator->destroy(iterator);
this->payload_length = length;
enumerator->destroy(enumerator);
}
/**
@ -190,41 +190,33 @@ static void compute_length(private_cp_payload_t *this)
*/
static size_t get_length(private_cp_payload_t *this)
{
compute_length(this);
return this->payload_length;
}
/**
* Implementation of cp_payload_t.create_configuration_attribute_iterator.
* Implementation of cp_payload_t.create_attribute_enumerator.
*/
static iterator_t *create_attribute_iterator (private_cp_payload_t *this)
static enumerator_t *create_attribute_enumerator(private_cp_payload_t *this)
{
return this->attributes->create_iterator(this->attributes, TRUE);
return this->attributes->create_enumerator(this->attributes);
}
/**
* Implementation of cp_payload_t.add_proposal_substructure.
* Implementation of cp_payload_t.add_attribute.
*/
static void add_configuration_attribute (private_cp_payload_t *this,configuration_attribute_t *attribute)
static void add_attribute(private_cp_payload_t *this,
configuration_attribute_t *attribute)
{
this->attributes->insert_last(this->attributes,(void *) attribute);
this->attributes->insert_last(this->attributes, attribute);
compute_length(this);
}
/**
* Implementation of cp_payload_t.set_config_type.
* 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;
}
/**
* Implementation of cp_payload_t.get_config_type.
*/
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;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@ -28,7 +28,7 @@ typedef struct cp_payload_t cp_payload_t;
#include <library.h>
#include <encoding/payloads/payload.h>
#include <encoding/payloads/configuration_attribute.h>
#include <utils/linked_list.h>
#include <utils/enumerator.h>
/**
* CP_PAYLOAD length in bytes without any proposal substructure.
@ -56,6 +56,7 @@ extern enum_name_t *config_type_names;
* The CP Payload format is described in RFC section 3.15.
*/
struct cp_payload_t {
/**
* The payload_t interface.
*/
@ -64,36 +65,24 @@ struct cp_payload_t {
/**
* Creates an iterator of stored configuration_attribute_t objects.
*
* When deleting an attribute using this iterator, the length of this
* configuration_attribute_t has to be refreshed by calling get_length()!
*
* @return created iterator_t object
* @return enumerator over configration_attribute_T
*/
iterator_t *(*create_attribute_iterator) (cp_payload_t *this);
enumerator_t *(*create_attribute_enumerator) (cp_payload_t *this);
/**
* Adds a configuration_attribute_t object to this object.
* Adds a configuration attribute to the configuration payload.
*
* The added configuration_attribute_t object is getting destroyed in
* destroy function of cp_payload_t.
*
* @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 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_ @}*/

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
*/
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();

View File

@ -67,6 +67,50 @@ static bool handle(private_nm_handler_t *this, identification_t *server,
return TRUE;
}
/**
* Implementation of create_attribute_enumerator().enumerate() for WINS
*/
static bool enumerate_nbns(enumerator_t *this,
configuration_attribute_type_t *type, chunk_t *data)
{
*type = INTERNAL_IP4_NBNS;
*data = chunk_empty;
/* done */
this->enumerate = (void*)return_false;
return TRUE;
}
/**
* Implementation of create_attribute_enumerator().enumerate() for DNS
*/
static bool enumerate_dns(enumerator_t *this,
configuration_attribute_type_t *type, chunk_t *data)
{
*type = INTERNAL_IP4_DNS;
*data = chunk_empty;
/* enumerate WINS server as next attribute ... */
this->enumerate = (void*)enumerate_nbns;
return TRUE;
}
/**
* Implementation of attribute_handler_t.create_attribute_enumerator
*/
static enumerator_t* create_attribute_enumerator(private_nm_handler_t *this,
identification_t *server, host_t *vip)
{
if (vip && vip->get_family(vip) == AF_INET)
{ /* no IPv6 attributes yet */
enumerator_t *enumerator = malloc_thing(enumerator_t);
/* enumerate DNS attribute first ... */
enumerator->enumerate = (void*)enumerate_dns;
enumerator->destroy = (void*)free;
return enumerator;
}
return enumerator_create_empty();
}
/**
* convert plain byte ptrs to handy chunk during enumeration
*/
@ -136,6 +180,7 @@ nm_handler_t *nm_handler_create()
this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))nop;
this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
this->public.create_enumerator = (enumerator_t*(*)(nm_handler_t*, configuration_attribute_type_t type))create_enumerator;
this->public.reset = (void(*)(nm_handler_t*))reset;
this->public.destroy = (void(*)(nm_handler_t*))destroy;

View File

@ -163,6 +163,59 @@ static void release(private_resolve_handler_t *this, identification_t *server,
this->mutex->unlock(this->mutex);
}
/**
* Attribute enumerator implementation
*/
typedef struct {
/** implements enumerator_t interface */
enumerator_t public;
/** virtual IP we are requesting */
host_t *vip;
} attribute_enumerator_t;
/**
* Implementation of create_attribute_enumerator().enumerate()
*/
static bool attribute_enumerate(attribute_enumerator_t *this,
configuration_attribute_type_t *type, chunk_t *data)
{
switch (this->vip->get_family(this->vip))
{
case AF_INET:
*type = INTERNAL_IP4_DNS;
break;
case AF_INET6:
*type = INTERNAL_IP6_DNS;
break;
default:
return FALSE;
}
*data = chunk_empty;
/* enumerate only once */
this->public.enumerate = (void*)return_false;
return TRUE;
}
/**
* Implementation of attribute_handler_t.create_attribute_enumerator
*/
static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this,
identification_t *server, host_t *vip)
{
if (vip)
{
attribute_enumerator_t *enumerator;
enumerator = malloc_thing(attribute_enumerator_t);
enumerator->public.enumerate = (void*)attribute_enumerate;
enumerator->public.destroy = (void*)free;
enumerator->vip = vip;
return &enumerator->public;
}
return enumerator_create_empty();
}
/**
* Implementation of resolve_handler_t.destroy.
*/
@ -181,6 +234,7 @@ resolve_handler_t *resolve_handler_create()
this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator;
this->public.destroy = (void(*)(resolve_handler_t*))destroy;
this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);

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.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;

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
*/
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;

View File

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

View File

@ -19,9 +19,6 @@
#include <daemon.h>
#include <encoding/payloads/cp_payload.h>
#define DNS_SERVER_MAX 2
#define NBNS_SERVER_MAX 2
typedef struct private_ike_config_t private_ike_config_t;
/**
@ -48,21 +45,34 @@ struct private_ike_config_t {
* virtual ip
*/
host_t *virtual_ip;
/**
* list of attributes requested and its handler, entry_t
*/
linked_list_t *requested;
};
/**
* build INTERNAL_IPV4/6_ADDRESS from virtual ip
* Entry for a requested attribute and the requesting handler
*/
static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
{
configuration_attribute_t *ca;
chunk_t chunk, prefix;
typedef struct {
/** attribute requested */
configuration_attribute_type_t type;
/** 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)
{
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 */
@ -199,26 +244,37 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
vip = config->get_virtual_ip(config);
}
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;
cp_payload_t *cp;
entry_t *entry;
cp = cp_payload_create();
cp->set_config_type(cp, CFG_REQUEST);
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)
/* create configuration attribute */
ca = configuration_attribute_create_value(type, data);
if (!cp)
{
ca->set_type(ca, INTERNAL_IP4_DNS);
cp = cp_payload_create_type(CFG_REQUEST);
}
else
{
ca->set_type(ca, INTERNAL_IP6_DNS);
}
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);
cp = cp_payload_create_type(CFG_REPLY);
cp->add_attribute(cp, build_vip(vip));
}
build_vip(this, vip, cp);
vip->destroy(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)
{

View File

@ -22,6 +22,7 @@
#define ATTRIBUTE_HANDLER_H_
#include <chunk.h>
#include <utils/host.h>
#include <utils/identification.h>
#include "attributes.h"
@ -56,6 +57,16 @@ struct attribute_handler_t {
*/
void (*release)(attribute_handler_t *this, identification_t *server,
configuration_attribute_type_t type, chunk_t data);
/**
* Enumerate attributes to request from a server.
*
* @param server server identity to request attributes from
* @param vip virtual IP we are requesting, if any
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this,
identification_t *server, host_t *vip);
};
#endif /** ATTRIBUTE_HANDLER_H_ @}*/

View File

@ -47,6 +47,16 @@ struct private_attribute_manager_t {
rwlock_t *lock;
};
/**
* Data to pass to enumerator filters
*/
typedef struct {
/** server/peer identity */
identification_t *id;
/** requesting/assigned virtual IP */
host_t *vip;
} enum_data_t;
/**
* Implementation of attribute_manager_t.acquire_address.
*/
@ -108,25 +118,29 @@ static void release_address(private_attribute_manager_t *this,
}
/**
* inner enumerator constructor for attributes
* inner enumerator constructor for responder attributes
*/
static enumerator_t *attrib_enum_create(attribute_provider_t *provider,
identification_t *id)
static enumerator_t *responder_enum_create(attribute_provider_t *provider,
enum_data_t *data)
{
return provider->create_attribute_enumerator(provider, id);
return provider->create_attribute_enumerator(provider, data->id, data->vip);
}
/**
* Implementation of attribute_manager_t.create_attribute_enumerator
* Implementation of attribute_manager_t.create_responder_enumerator
*/
static enumerator_t* create_attribute_enumerator(
private_attribute_manager_t *this, identification_t *id)
static enumerator_t* create_responder_enumerator(
private_attribute_manager_t *this, identification_t *id, host_t *vip)
{
enum_data_t *data = malloc_thing(enum_data_t);
data->id = id;
data->vip = vip;
this->lock->read_lock(this->lock);
return enumerator_create_cleaner(
enumerator_create_nested(
this->providers->create_enumerator(this->providers),
(void*)attrib_enum_create, id, NULL),
(void*)responder_enum_create, data, free),
(void*)this->lock->unlock, this->lock);
}
@ -156,24 +170,38 @@ static void remove_provider(private_attribute_manager_t *this,
* Implementation of attribute_manager_t.handle
*/
static attribute_handler_t* handle(private_attribute_manager_t *this,
identification_t *server,
configuration_attribute_type_t type,
chunk_t data)
identification_t *server, attribute_handler_t *handler,
configuration_attribute_type_t type, chunk_t data)
{
enumerator_t *enumerator;
attribute_handler_t *current, *handled = NULL;
this->lock->read_lock(this->lock);
/* try to find the passed handler */
enumerator = this->handlers->create_enumerator(this->handlers);
while (enumerator->enumerate(enumerator, &current))
{
if (current->handle(current, server, type, data))
if (current == handler && current->handle(current, server, type, data))
{
handled = current;
break;
}
}
enumerator->destroy(enumerator);
if (!handled)
{ /* handler requesting this attribute not found, try any other */
enumerator = this->handlers->create_enumerator(this->handlers);
while (enumerator->enumerate(enumerator, &current))
{
if (current->handle(current, server, type, data))
{
handled = current;
break;
}
}
enumerator->destroy(enumerator);
}
this->lock->unlock(this->lock);
if (!handled)
@ -209,6 +237,33 @@ static void release(private_attribute_manager_t *this,
this->lock->unlock(this->lock);
}
/**
* inner enumerator constructor for initiator attributes
*/
static enumerator_t *initiator_enum_create(attribute_handler_t *handler,
enum_data_t *data)
{
return handler->create_attribute_enumerator(handler, data->id, data->vip);
}
/**
* Implementation of attribute_manager_t.create_initiator_enumerator
*/
static enumerator_t* create_initiator_enumerator(
private_attribute_manager_t *this, identification_t *id, host_t *vip)
{
enum_data_t *data = malloc_thing(enum_data_t);
data->id = id;
data->vip = vip;
this->lock->read_lock(this->lock);
return enumerator_create_cleaner(
enumerator_create_nested(
this->handlers->create_enumerator(this->handlers),
(void*)initiator_enum_create, data, free),
(void*)this->lock->unlock, this->lock);
}
/**
* Implementation of attribute_manager_t.add_handler
*/
@ -251,11 +306,12 @@ attribute_manager_t *attribute_manager_create()
this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address;
this->public.create_attribute_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*))create_attribute_enumerator;
this->public.create_responder_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_responder_enumerator;
this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider;
this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider;
this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle;
this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*,identification_t*, attribute_handler_t*, configuration_attribute_type_t, chunk_t))handle;
this->public.release = (void(*)(attribute_manager_t*, attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release;
this->public.create_initiator_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_initiator_enumerator;
this->public.add_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))add_handler;
this->public.remove_handler = (void(*)(attribute_manager_t*, attribute_handler_t*))remove_handler;
this->public.destroy = (void(*)(attribute_manager_t*))destroy;

View File

@ -62,10 +62,11 @@ struct attribute_manager_t {
* Create an enumerator over attributes to hand out to a peer.
*
* @param id peer identity to hand out attributes to
* @param vip virtual IP to assign to peer, if any
* @return enumerator (configuration_attribute_type_t, chunk_t)
*/
enumerator_t* (*create_attribute_enumerator)(attribute_manager_t *this,
identification_t *id);
enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
identification_t *id, host_t *vip);
/**
* Register an attribute provider to the manager.
@ -86,13 +87,14 @@ struct attribute_manager_t {
* Handle a configuration attribute by passing them to the handlers.
*
* @param server server from which the attribute was received
* @param handler handler we requested the attribute for, if any
* @param type type of configuration attribute
* @param data associated attribute data
* @return handler which handled this attribute, NULL if none
*/
attribute_handler_t* (*handle)(attribute_manager_t *this,
identification_t *server,
configuration_attribute_type_t type, chunk_t data);
identification_t *server, attribute_handler_t *handler,
configuration_attribute_type_t type, chunk_t data);
/**
* Release an attribute previously handle()d by a handler.
@ -107,6 +109,16 @@ struct attribute_manager_t {
configuration_attribute_type_t type,
chunk_t data);
/**
* Create an enumerator over attributes to request from server.
*
* @param id server identity to hand out attributes to
* @param vip virtual IP going to request, if any
* @return enumerator (attribute_handler_t, ca_type_t, chunk_t)
*/
enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this,
identification_t *id, host_t *vip);
/**
* Register an attribute handler to the manager.
*

View File

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

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.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;