aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/sa/tasks/ike_config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/sa/tasks/ike_config.c')
-rw-r--r--src/charon/sa/tasks/ike_config.c184
1 files changed, 123 insertions, 61 deletions
diff --git a/src/charon/sa/tasks/ike_config.c b/src/charon/sa/tasks/ike_config.c
index 0e2340a6a..1c222fa8c 100644
--- a/src/charon/sa/tasks/ike_config.c
+++ b/src/charon/sa/tasks/ike_config.c
@@ -19,9 +19,6 @@
#include <daemon.h>
#include <encoding/payloads/cp_payload.h>
-#define DNS_SERVER_MAX 2
-#define NBNS_SERVER_MAX 2
-
typedef struct private_ike_config_t private_ike_config_t;
/**
@@ -48,21 +45,34 @@ struct private_ike_config_t {
* virtual ip
*/
host_t *virtual_ip;
+
+ /**
+ * list of attributes requested and its handler, entry_t
+ */
+ linked_list_t *requested;
};
/**
- * build INTERNAL_IPV4/6_ADDRESS from virtual ip
+ * Entry for a requested attribute and the requesting handler
+ */
+typedef struct {
+ /** attribute requested */
+ configuration_attribute_type_t type;
+ /** handler requesting this attribute */
+ attribute_handler_t *handler;
+} entry_t;
+
+/**
+ * build INTERNAL_IPV4/6_ADDRESS attribute from virtual ip
*/
-static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
+static configuration_attribute_t *build_vip(host_t *vip)
{
- configuration_attribute_t *ca;
+ configuration_attribute_type_t type;
chunk_t chunk, prefix;
- ca = configuration_attribute_create();
-
if (vip->get_family(vip) == AF_INET)
{
- ca->set_type(ca, INTERNAL_IP4_ADDRESS);
+ type = INTERNAL_IP4_ADDRESS;
if (vip->is_anyaddr(vip))
{
chunk = chunk_empty;
@@ -74,7 +84,7 @@ static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
}
else
{
- ca->set_type(ca, INTERNAL_IP6_ADDRESS);
+ type = INTERNAL_IP6_ADDRESS;
if (vip->is_anyaddr(vip))
{
chunk = chunk_empty;
@@ -87,8 +97,41 @@ static void build_vip(private_ike_config_t *this, host_t *vip, cp_payload_t *cp)
chunk = chunk_cata("cc", chunk, prefix);
}
}
- ca->set_value(ca, chunk);
- cp->add_configuration_attribute(cp, ca);
+ return configuration_attribute_create_value(type, chunk);
+}
+
+/**
+ * Handle a received attribute as initiator
+ */
+static void handle_attribute(private_ike_config_t *this,
+ configuration_attribute_t *ca)
+{
+ attribute_handler_t *handler = NULL;
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ /* find the handler which requested this attribute */
+ enumerator = this->requested->create_enumerator(this->requested);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (entry->type == ca->get_type(ca))
+ {
+ handler = entry->handler;
+ this->requested->remove_at(this->requested, enumerator);
+ free(entry);
+ break;
+ }
+ }
+
+ /* and pass it to the handle function */
+ handler = lib->attributes->handle(lib->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), handler,
+ ca->get_type(ca), ca->get_value(ca));
+ if (handler)
+ {
+ this->ike_sa->add_configuration_attribute(this->ike_sa,
+ handler, ca->get_type(ca), ca->get_value(ca));
+ }
}
/**
@@ -130,15 +173,12 @@ static void process_attribute(private_ike_config_t *this,
break;
}
default:
+ {
if (this->initiator)
{
- this->ike_sa->add_configuration_attribute(this->ike_sa,
- ca->get_type(ca), ca->get_value(ca));
- }
- else
- {
- /* we do not handle attribute requests other than for VIPs */
+ handle_attribute(this, ca);
}
+ }
}
}
@@ -147,8 +187,7 @@ static void process_attribute(private_ike_config_t *this,
*/
static void process_payloads(private_ike_config_t *this, message_t *message)
{
- enumerator_t *enumerator;
- iterator_t *attributes;
+ enumerator_t *enumerator, *attributes;
payload_t *payload;
enumerator = message->create_payload_enumerator(message);
@@ -158,13 +197,14 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
{
cp_payload_t *cp = (cp_payload_t*)payload;
configuration_attribute_t *ca;
- switch (cp->get_config_type(cp))
+
+ switch (cp->get_type(cp))
{
case CFG_REQUEST:
case CFG_REPLY:
{
- attributes = cp->create_attribute_iterator(cp);
- while (attributes->iterate(attributes, (void**)&ca))
+ attributes = cp->create_attribute_enumerator(cp);
+ while (attributes->enumerate(attributes, &ca))
{
process_attribute(this, ca);
}
@@ -173,7 +213,7 @@ static void process_payloads(private_ike_config_t *this, message_t *message)
}
default:
DBG1(DBG_IKE, "ignoring %N config payload",
- config_type_names, cp->get_config_type(cp));
+ config_type_names, cp->get_type(cp));
break;
}
}
@@ -188,7 +228,12 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
{
if (message->get_message_id(message) == 1)
{ /* in first IKE_AUTH only */
+ cp_payload_t *cp = NULL;
+ enumerator_t *enumerator;
+ attribute_handler_t *handler;
peer_cfg_t *config;
+ configuration_attribute_type_t type;
+ chunk_t data;
host_t *vip;
/* reuse virtual IP if we already have one */
@@ -200,25 +245,36 @@ static status_t build_i(private_ike_config_t *this, message_t *message)
}
if (vip)
{
- configuration_attribute_t *ca;
- cp_payload_t *cp;
-
- cp = cp_payload_create();
- cp->set_config_type(cp, CFG_REQUEST);
+ cp = cp_payload_create_type(CFG_REQUEST);
+ cp->add_attribute(cp, build_vip(vip));
+ }
- build_vip(this, vip, cp);
+ enumerator = lib->attributes->create_initiator_enumerator(lib->attributes,
+ this->ike_sa->get_other_id(this->ike_sa), vip);
+ while (enumerator->enumerate(enumerator, &handler, &type, &data))
+ {
+ configuration_attribute_t *ca;
+ entry_t *entry;
- /* we currently always add a DNS request if we request an IP */
- ca = configuration_attribute_create();
- if (vip->get_family(vip) == AF_INET)
- {
- ca->set_type(ca, INTERNAL_IP4_DNS);
- }
- else
+ /* create configuration attribute */
+ ca = configuration_attribute_create_value(type, data);
+ if (!cp)
{
- ca->set_type(ca, INTERNAL_IP6_DNS);
+ cp = cp_payload_create_type(CFG_REQUEST);
}
- cp->add_configuration_attribute(cp, ca);
+ cp->add_attribute(cp, ca);
+
+ /* save handler along with requested type */
+ entry = malloc_thing(entry_t);
+ entry->type = type;
+ entry->handler = handler;
+
+ this->requested->insert_last(this->requested, entry);
+ }
+ enumerator->destroy(enumerator);
+
+ if (cp)
+ {
message->add_payload(message, (payload_t*)cp);
}
}
@@ -244,17 +300,16 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
{
if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
{ /* in last IKE_AUTH exchange */
- peer_cfg_t *config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ enumerator_t *enumerator;
+ configuration_attribute_type_t type;
+ chunk_t value;
+ host_t *vip = NULL;
+ cp_payload_t *cp = NULL;
+ peer_cfg_t *config;
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (config && this->virtual_ip)
{
- enumerator_t *enumerator;
- configuration_attribute_type_t type;
- configuration_attribute_t *ca;
- chunk_t value;
- cp_payload_t *cp;
- host_t *vip = NULL;
-
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
if (config->get_pool(config))
{
@@ -274,26 +329,29 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
DBG1(DBG_IKE, "assigning virtual IP %H to peer", vip);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
- cp = cp_payload_create();
- cp->set_config_type(cp, CFG_REPLY);
-
- build_vip(this, vip, cp);
- vip->destroy(vip);
+ cp = cp_payload_create_type(CFG_REPLY);
+ cp->add_attribute(cp, build_vip(vip));
+ }
- /* if we add an IP, we also look for other attributes */
- enumerator = lib->attributes->create_attribute_enumerator(
- lib->attributes, this->ike_sa->get_other_id(this->ike_sa));
- while (enumerator->enumerate(enumerator, &type, &value))
+ /* query registered providers for additional attributes to include */
+ enumerator = lib->attributes->create_responder_enumerator(
+ lib->attributes, this->ike_sa->get_other_id(this->ike_sa), vip);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ if (!cp)
{
- ca = configuration_attribute_create();
- ca->set_type(ca, type);
- ca->set_value(ca, value);
- cp->add_configuration_attribute(cp, ca);
+ cp = cp_payload_create_type(CFG_REPLY);
}
- enumerator->destroy(enumerator);
+ cp->add_attribute(cp,
+ configuration_attribute_create_value(type, value));
+ }
+ enumerator->destroy(enumerator);
+ if (cp)
+ {
message->add_payload(message, (payload_t*)cp);
}
+ DESTROY_IF(vip);
return SUCCESS;
}
return NEED_MORE;
@@ -335,6 +393,8 @@ static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
this->ike_sa = ike_sa;
this->virtual_ip = NULL;
+ this->requested->destroy_function(this->requested, free);
+ this->requested = linked_list_create();
}
/**
@@ -343,6 +403,7 @@ static void migrate(private_ike_config_t *this, ike_sa_t *ike_sa)
static void destroy(private_ike_config_t *this)
{
DESTROY_IF(this->virtual_ip);
+ this->requested->destroy_function(this->requested, free);
free(this);
}
@@ -360,6 +421,7 @@ ike_config_t *ike_config_create(ike_sa_t *ike_sa, bool initiator)
this->initiator = initiator;
this->ike_sa = ike_sa;
this->virtual_ip = NULL;
+ this->requested = linked_list_create();
if (initiator)
{