ikev1: implement mode config push mode
This commit is contained in:
@@ -539,23 +539,40 @@ static bool mode_config_expected(private_task_manager_t *this)
|
|||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
peer_cfg_t *peer_cfg;
|
peer_cfg_t *peer_cfg;
|
||||||
char *pool;
|
char *pool;
|
||||||
|
bool local;
|
||||||
host_t *host;
|
host_t *host;
|
||||||
|
|
||||||
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
if (peer_cfg)
|
if (peer_cfg)
|
||||||
{
|
{
|
||||||
enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
|
if (peer_cfg->use_pull_mode(peer_cfg))
|
||||||
if (!enumerator->enumerate(enumerator, &pool))
|
{
|
||||||
{ /* no pool configured */
|
enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
|
||||||
|
if (!enumerator->enumerate(enumerator, &pool))
|
||||||
|
{ /* no pool configured */
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
|
|
||||||
|
local = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
|
||||||
|
if (!enumerator->enumerate(enumerator, &host))
|
||||||
|
{ /* not requesting a vip */
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
local = TRUE;
|
||||||
|
}
|
||||||
enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
|
enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
|
||||||
FALSE);
|
local);
|
||||||
if (!enumerator->enumerate(enumerator, &host))
|
if (!enumerator->enumerate(enumerator, &host))
|
||||||
{ /* have a pool, but no VIP assigned yet */
|
{ /* expecting a VIP exchange, but no VIP assigned yet */
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1087,7 +1104,8 @@ static status_t process_request(private_task_manager_t *this,
|
|||||||
case TRANSACTION:
|
case TRANSACTION:
|
||||||
if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
|
if (this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING)
|
||||||
{
|
{
|
||||||
task = (task_t *)mode_config_create(this->ike_sa, FALSE);
|
task = (task_t *)mode_config_create(this->ike_sa,
|
||||||
|
FALSE, TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -196,6 +196,17 @@ static status_t send_delete(private_aggressive_mode_t *this)
|
|||||||
return ALREADY_DONE;
|
return ALREADY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a timeout for the IKE_SA should it not establish
|
||||||
|
*/
|
||||||
|
static void schedule_timeout(ike_sa_t *ike_sa)
|
||||||
|
{
|
||||||
|
job_t *job;
|
||||||
|
|
||||||
|
job = (job_t*)delete_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE);
|
||||||
|
lib->scheduler->schedule_job(lib->scheduler, job, HALF_OPEN_IKE_SA_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(task_t, build_i, status_t,
|
METHOD(task_t, build_i, status_t,
|
||||||
private_aggressive_mode_t *this, message_t *message)
|
private_aggressive_mode_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
@@ -300,20 +311,15 @@ METHOD(task_t, build_i, status_t,
|
|||||||
case AUTH_XAUTH_INIT_PSK:
|
case AUTH_XAUTH_INIT_PSK:
|
||||||
case AUTH_XAUTH_INIT_RSA:
|
case AUTH_XAUTH_INIT_RSA:
|
||||||
case AUTH_HYBRID_INIT_RSA:
|
case AUTH_HYBRID_INIT_RSA:
|
||||||
{ /* wait for XAUTH request, since this may never come,
|
/* wait for XAUTH request */
|
||||||
* we queue a timeout */
|
schedule_timeout(this->ike_sa);
|
||||||
job_t *job = (job_t*)delete_ike_sa_job_create(
|
|
||||||
this->ike_sa->get_id(this->ike_sa), FALSE);
|
|
||||||
lib->scheduler->schedule_job(lib->scheduler, job,
|
|
||||||
HALF_OPEN_IKE_SA_TIMEOUT);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case AUTH_XAUTH_RESP_PSK:
|
case AUTH_XAUTH_RESP_PSK:
|
||||||
case AUTH_XAUTH_RESP_RSA:
|
case AUTH_XAUTH_RESP_RSA:
|
||||||
case AUTH_HYBRID_RESP_RSA:
|
case AUTH_HYBRID_RESP_RSA:
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
(task_t*)xauth_create(this->ike_sa, TRUE));
|
(task_t*)xauth_create(this->ike_sa, TRUE));
|
||||||
return SUCCESS;
|
break;
|
||||||
default:
|
default:
|
||||||
if (charon->ike_sa_manager->check_uniqueness(
|
if (charon->ike_sa_manager->check_uniqueness(
|
||||||
charon->ike_sa_manager, this->ike_sa, FALSE))
|
charon->ike_sa_manager, this->ike_sa, FALSE))
|
||||||
@@ -328,10 +334,30 @@ METHOD(task_t, build_i, status_t,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* check for and prepare mode config push/pull */
|
||||||
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
||||||
{
|
{
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
(task_t*)mode_config_create(this->ike_sa, TRUE));
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
schedule_timeout(this->ike_sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
|
||||||
|
{
|
||||||
|
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
|
{
|
||||||
|
schedule_timeout(this->ike_sa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -482,7 +508,7 @@ METHOD(task_t, process_r, status_t,
|
|||||||
case AUTH_HYBRID_INIT_RSA:
|
case AUTH_HYBRID_INIT_RSA:
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
(task_t*)xauth_create(this->ike_sa, TRUE));
|
(task_t*)xauth_create(this->ike_sa, TRUE));
|
||||||
return SUCCESS;
|
break;
|
||||||
case AUTH_XAUTH_RESP_PSK:
|
case AUTH_XAUTH_RESP_PSK:
|
||||||
case AUTH_XAUTH_RESP_RSA:
|
case AUTH_XAUTH_RESP_RSA:
|
||||||
case AUTH_HYBRID_RESP_RSA:
|
case AUTH_HYBRID_RESP_RSA:
|
||||||
@@ -505,11 +531,22 @@ METHOD(task_t, process_r, status_t,
|
|||||||
this->ike_sa->get_id(this->ike_sa)));
|
this->ike_sa->get_id(this->ike_sa)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
|
/* check for and prepare mode config push/pull */
|
||||||
this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
||||||
{
|
{
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
(task_t*)mode_config_create(this->ike_sa, TRUE));
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
|
||||||
|
{
|
||||||
|
if (!this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -504,7 +504,7 @@ METHOD(task_t, build_r, status_t,
|
|||||||
case AUTH_HYBRID_INIT_RSA:
|
case AUTH_HYBRID_INIT_RSA:
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
(task_t*)xauth_create(this->ike_sa, TRUE));
|
(task_t*)xauth_create(this->ike_sa, TRUE));
|
||||||
return SUCCESS;
|
break;
|
||||||
case AUTH_XAUTH_RESP_PSK:
|
case AUTH_XAUTH_RESP_PSK:
|
||||||
case AUTH_XAUTH_RESP_RSA:
|
case AUTH_XAUTH_RESP_RSA:
|
||||||
case AUTH_HYBRID_RESP_RSA:
|
case AUTH_HYBRID_RESP_RSA:
|
||||||
@@ -527,11 +527,21 @@ METHOD(task_t, build_r, status_t,
|
|||||||
this->ike_sa->get_id(this->ike_sa)));
|
this->ike_sa->get_id(this->ike_sa)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
|
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
||||||
this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
|
||||||
{
|
{
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
(task_t*)mode_config_create(this->ike_sa, TRUE));
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
|
||||||
|
{
|
||||||
|
if (!this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -540,6 +550,17 @@ METHOD(task_t, build_r, status_t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a timeout for the IKE_SA should it not establish
|
||||||
|
*/
|
||||||
|
static void schedule_timeout(ike_sa_t *ike_sa)
|
||||||
|
{
|
||||||
|
job_t *job;
|
||||||
|
|
||||||
|
job = (job_t*)delete_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE);
|
||||||
|
lib->scheduler->schedule_job(lib->scheduler, job, HALF_OPEN_IKE_SA_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(task_t, process_i, status_t,
|
METHOD(task_t, process_i, status_t,
|
||||||
private_main_mode_t *this, message_t *message)
|
private_main_mode_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
@@ -639,20 +660,15 @@ METHOD(task_t, process_i, status_t,
|
|||||||
case AUTH_XAUTH_INIT_PSK:
|
case AUTH_XAUTH_INIT_PSK:
|
||||||
case AUTH_XAUTH_INIT_RSA:
|
case AUTH_XAUTH_INIT_RSA:
|
||||||
case AUTH_HYBRID_INIT_RSA:
|
case AUTH_HYBRID_INIT_RSA:
|
||||||
{ /* wait for XAUTH request, since this may never come,
|
/* wait for XAUTH request */
|
||||||
* we queue a timeout */
|
schedule_timeout(this->ike_sa);
|
||||||
job_t *job = (job_t*)delete_ike_sa_job_create(
|
|
||||||
this->ike_sa->get_id(this->ike_sa), FALSE);
|
|
||||||
lib->scheduler->schedule_job(lib->scheduler, job,
|
|
||||||
HALF_OPEN_IKE_SA_TIMEOUT);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case AUTH_XAUTH_RESP_PSK:
|
case AUTH_XAUTH_RESP_PSK:
|
||||||
case AUTH_XAUTH_RESP_RSA:
|
case AUTH_XAUTH_RESP_RSA:
|
||||||
case AUTH_HYBRID_RESP_RSA:
|
case AUTH_HYBRID_RESP_RSA:
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
(task_t*)xauth_create(this->ike_sa, TRUE));
|
(task_t*)xauth_create(this->ike_sa, TRUE));
|
||||||
return SUCCESS;
|
break;
|
||||||
default:
|
default:
|
||||||
if (charon->ike_sa_manager->check_uniqueness(
|
if (charon->ike_sa_manager->check_uniqueness(
|
||||||
charon->ike_sa_manager, this->ike_sa, FALSE))
|
charon->ike_sa_manager, this->ike_sa, FALSE))
|
||||||
@@ -667,10 +683,30 @@ METHOD(task_t, process_i, status_t,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* check for and prepare mode config push/pull */
|
||||||
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
|
||||||
{
|
{
|
||||||
this->ike_sa->queue_task(this->ike_sa,
|
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
(task_t*)mode_config_create(this->ike_sa, TRUE));
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, TRUE));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
schedule_timeout(this->ike_sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->ph1->has_pool(this->ph1, this->peer_cfg))
|
||||||
|
{
|
||||||
|
if (this->peer_cfg->use_pull_mode(this->peer_cfg))
|
||||||
|
{
|
||||||
|
schedule_timeout(this->ike_sa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->ike_sa->queue_task(this->ike_sa,
|
||||||
|
(task_t*)mode_config_create(this->ike_sa, TRUE, FALSE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,15 +41,20 @@ struct private_mode_config_t {
|
|||||||
*/
|
*/
|
||||||
bool initiator;
|
bool initiator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use pull (CFG_REQUEST/RESPONSE) or push (CFG_SET/ACK)?
|
||||||
|
*/
|
||||||
|
bool pull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Received list of virtual IPs, host_t*
|
* Received list of virtual IPs, host_t*
|
||||||
*/
|
*/
|
||||||
linked_list_t *vips;
|
linked_list_t *vips;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list of attributes requested and its handler, entry_t
|
* Requested/received list of attributes, entry_t
|
||||||
*/
|
*/
|
||||||
linked_list_t *requested;
|
linked_list_t *attributes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifier to include in response
|
* Identifier to include in response
|
||||||
@@ -58,12 +63,12 @@ struct private_mode_config_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry for a requested attribute and the requesting handler
|
* Entry for a attribute and associated handler
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/** attribute requested */
|
/** attribute type */
|
||||||
configuration_attribute_type_t type;
|
configuration_attribute_type_t type;
|
||||||
/** handler requesting this attribute */
|
/** handler for this attribute */
|
||||||
attribute_handler_t *handler;
|
attribute_handler_t *handler;
|
||||||
} entry_t;
|
} entry_t;
|
||||||
|
|
||||||
@@ -117,13 +122,13 @@ static void handle_attribute(private_mode_config_t *this,
|
|||||||
entry_t *entry;
|
entry_t *entry;
|
||||||
|
|
||||||
/* find the handler which requested this attribute */
|
/* find the handler which requested this attribute */
|
||||||
enumerator = this->requested->create_enumerator(this->requested);
|
enumerator = this->attributes->create_enumerator(this->attributes);
|
||||||
while (enumerator->enumerate(enumerator, &entry))
|
while (enumerator->enumerate(enumerator, &entry))
|
||||||
{
|
{
|
||||||
if (entry->type == ca->get_type(ca))
|
if (entry->type == ca->get_type(ca))
|
||||||
{
|
{
|
||||||
handler = entry->handler;
|
handler = entry->handler;
|
||||||
this->requested->remove_at(this->requested, enumerator);
|
this->attributes->remove_at(this->attributes, enumerator);
|
||||||
free(entry);
|
free(entry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -180,7 +185,7 @@ static void process_attribute(private_mode_config_t *this,
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (this->initiator)
|
if (this->initiator == this->pull)
|
||||||
{
|
{
|
||||||
handle_attribute(this, ca);
|
handle_attribute(this, ca);
|
||||||
}
|
}
|
||||||
@@ -188,6 +193,24 @@ static void process_attribute(private_mode_config_t *this,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if config allows push mode when acting as task responder
|
||||||
|
*/
|
||||||
|
static bool accept_push(private_mode_config_t *this)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
peer_cfg_t *config;
|
||||||
|
bool vip;
|
||||||
|
host_t *host;
|
||||||
|
|
||||||
|
config = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
|
enumerator = config->create_virtual_ip_enumerator(config);
|
||||||
|
vip = enumerator->enumerate(enumerator, &host);
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
return vip && !config->use_pull_mode(config);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan for configuration payloads and attributes
|
* Scan for configuration payloads and attributes
|
||||||
*/
|
*/
|
||||||
@@ -206,6 +229,15 @@ static void process_payloads(private_mode_config_t *this, message_t *message)
|
|||||||
|
|
||||||
switch (cp->get_type(cp))
|
switch (cp->get_type(cp))
|
||||||
{
|
{
|
||||||
|
case CFG_SET:
|
||||||
|
/* when acting as a responder, we detect the mode using
|
||||||
|
* the type of configuration payload. But we should double
|
||||||
|
* check the peer is allowed to use push mode on us. */
|
||||||
|
if (!this->initiator && accept_push(this))
|
||||||
|
{
|
||||||
|
this->pull = FALSE;
|
||||||
|
}
|
||||||
|
/* FALL */
|
||||||
case CFG_REQUEST:
|
case CFG_REQUEST:
|
||||||
this->identifier = cp->get_identifier(cp);
|
this->identifier = cp->get_identifier(cp);
|
||||||
/* FALL */
|
/* FALL */
|
||||||
@@ -219,6 +251,8 @@ static void process_payloads(private_mode_config_t *this, message_t *message)
|
|||||||
}
|
}
|
||||||
attributes->destroy(attributes);
|
attributes->destroy(attributes);
|
||||||
break;
|
break;
|
||||||
|
case CFG_ACK:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DBG1(DBG_IKE, "ignoring %N config payload",
|
DBG1(DBG_IKE, "ignoring %N config payload",
|
||||||
config_type_names, cp->get_type(cp));
|
config_type_names, cp->get_type(cp));
|
||||||
@@ -229,8 +263,29 @@ static void process_payloads(private_mode_config_t *this, message_t *message)
|
|||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(task_t, build_i, status_t,
|
/**
|
||||||
private_mode_config_t *this, message_t *message)
|
* Add an attribute to a configuration payload, and store it in task
|
||||||
|
*/
|
||||||
|
static void add_attribute(private_mode_config_t *this, cp_payload_t *cp,
|
||||||
|
configuration_attribute_type_t type, chunk_t data,
|
||||||
|
attribute_handler_t *handler)
|
||||||
|
{
|
||||||
|
entry_t *entry;
|
||||||
|
|
||||||
|
cp->add_attribute(cp,
|
||||||
|
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
|
||||||
|
type, data));
|
||||||
|
INIT(entry,
|
||||||
|
.type = type,
|
||||||
|
.handler = handler,
|
||||||
|
);
|
||||||
|
this->attributes->insert_last(this->attributes, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a CFG_REQUEST as initiator
|
||||||
|
*/
|
||||||
|
static status_t build_request(private_mode_config_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
cp_payload_t *cp;
|
cp_payload_t *cp;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
@@ -279,18 +334,7 @@ METHOD(task_t, build_i, status_t,
|
|||||||
this->ike_sa->get_other_id(this->ike_sa), vips);
|
this->ike_sa->get_other_id(this->ike_sa), vips);
|
||||||
while (enumerator->enumerate(enumerator, &handler, &type, &data))
|
while (enumerator->enumerate(enumerator, &handler, &type, &data))
|
||||||
{
|
{
|
||||||
entry_t *entry;
|
add_attribute(this, cp, type, data, handler);
|
||||||
|
|
||||||
DBG2(DBG_IKE, "building %N attribute",
|
|
||||||
configuration_attribute_type_names, type);
|
|
||||||
cp->add_attribute(cp,
|
|
||||||
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
|
|
||||||
type, data));
|
|
||||||
INIT(entry,
|
|
||||||
.type = type,
|
|
||||||
.handler = handler,
|
|
||||||
);
|
|
||||||
this->requested->insert_last(this->requested, entry);
|
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
@@ -301,15 +345,121 @@ METHOD(task_t, build_i, status_t,
|
|||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a CFG_SET as initiator
|
||||||
|
*/
|
||||||
|
static status_t build_set(private_mode_config_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
configuration_attribute_type_t type;
|
||||||
|
chunk_t value;
|
||||||
|
cp_payload_t *cp;
|
||||||
|
peer_cfg_t *config;
|
||||||
|
identification_t *id;
|
||||||
|
linked_list_t *pools;
|
||||||
|
host_t *any4, *any6, *found;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_SET);
|
||||||
|
|
||||||
|
id = this->ike_sa->get_other_eap_id(this->ike_sa);
|
||||||
|
config = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||||
|
any4 = host_create_any(AF_INET);
|
||||||
|
any6 = host_create_any(AF_INET6);
|
||||||
|
|
||||||
|
this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
|
||||||
|
|
||||||
|
/* in push mode, we ask each configured pool for an address */
|
||||||
|
enumerator = config->create_pool_enumerator(config);
|
||||||
|
while (enumerator->enumerate(enumerator, &name))
|
||||||
|
{
|
||||||
|
pools = linked_list_create_with_items(name, NULL);
|
||||||
|
/* try IPv4, then IPv6 */
|
||||||
|
found = hydra->attributes->acquire_address(hydra->attributes,
|
||||||
|
pools, id, any4);
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
found = hydra->attributes->acquire_address(hydra->attributes,
|
||||||
|
pools, id, any6);
|
||||||
|
}
|
||||||
|
pools->destroy(pools);
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
|
||||||
|
this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
|
||||||
|
cp->add_attribute(cp, build_vip(found));
|
||||||
|
this->vips->insert_last(this->vips, found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
any4->destroy(any4);
|
||||||
|
any6->destroy(any6);
|
||||||
|
|
||||||
|
/* query registered providers for additional attributes to include */
|
||||||
|
pools = linked_list_create_from_enumerator(
|
||||||
|
config->create_pool_enumerator(config));
|
||||||
|
enumerator = hydra->attributes->create_responder_enumerator(
|
||||||
|
hydra->attributes, pools, id, this->vips);
|
||||||
|
while (enumerator->enumerate(enumerator, &type, &value))
|
||||||
|
{
|
||||||
|
add_attribute(this, cp, type, value, NULL);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
pools->destroy(pools);
|
||||||
|
|
||||||
|
message->add_payload(message, (payload_t*)cp);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(task_t, build_i, status_t,
|
||||||
|
private_mode_config_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
if (this->pull)
|
||||||
|
{
|
||||||
|
return build_request(this, message);
|
||||||
|
}
|
||||||
|
return build_set(this, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store received virtual IPs to the IKE_SA, install them
|
||||||
|
*/
|
||||||
|
static void install_vips(private_mode_config_t *this)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
host_t *host;
|
||||||
|
|
||||||
|
this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
|
||||||
|
|
||||||
|
enumerator = this->vips->create_enumerator(this->vips);
|
||||||
|
while (enumerator->enumerate(enumerator, &host))
|
||||||
|
{
|
||||||
|
if (!host->is_anyaddr(host))
|
||||||
|
{
|
||||||
|
this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(task_t, process_r, status_t,
|
METHOD(task_t, process_r, status_t,
|
||||||
private_mode_config_t *this, message_t *message)
|
private_mode_config_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
process_payloads(this, message);
|
process_payloads(this, message);
|
||||||
|
|
||||||
|
if (!this->pull)
|
||||||
|
{
|
||||||
|
install_vips(this);
|
||||||
|
}
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(task_t, build_r, status_t,
|
/**
|
||||||
private_mode_config_t *this, message_t *message)
|
* Build CFG_REPLY message after receiving CFG_REQUEST
|
||||||
|
*/
|
||||||
|
static status_t build_reply(private_mode_config_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
configuration_attribute_type_t type;
|
configuration_attribute_type_t type;
|
||||||
@@ -360,8 +510,6 @@ METHOD(task_t, build_r, status_t,
|
|||||||
hydra->attributes, pools, id, vips);
|
hydra->attributes, pools, id, vips);
|
||||||
while (enumerator->enumerate(enumerator, &type, &value))
|
while (enumerator->enumerate(enumerator, &type, &value))
|
||||||
{
|
{
|
||||||
DBG2(DBG_IKE, "building %N attribute",
|
|
||||||
configuration_attribute_type_names, type);
|
|
||||||
cp->add_attribute(cp,
|
cp->add_attribute(cp,
|
||||||
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
|
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
|
||||||
type, value));
|
type, value));
|
||||||
@@ -376,26 +524,72 @@ METHOD(task_t, build_r, status_t,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(task_t, process_i, status_t,
|
/**
|
||||||
private_mode_config_t *this, message_t *message)
|
* Build CFG_ACK for a received CFG_SET
|
||||||
|
*/
|
||||||
|
static status_t build_ack(private_mode_config_t *this, message_t *message)
|
||||||
{
|
{
|
||||||
|
cp_payload_t *cp;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
host_t *host;
|
host_t *host;
|
||||||
|
configuration_attribute_type_t type;
|
||||||
|
entry_t *entry;
|
||||||
|
|
||||||
process_payloads(this, message);
|
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_ACK);
|
||||||
|
|
||||||
this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE);
|
/* return empty attributes for installed IPs */
|
||||||
|
|
||||||
enumerator = this->vips->create_enumerator(this->vips);
|
enumerator = this->vips->create_enumerator(this->vips);
|
||||||
while (enumerator->enumerate(enumerator, &host))
|
while (enumerator->enumerate(enumerator, &host))
|
||||||
{
|
{
|
||||||
if (!host->is_anyaddr(host))
|
type = INTERNAL_IP6_ADDRESS;
|
||||||
|
if (host->get_family(host) == AF_INET6)
|
||||||
{
|
{
|
||||||
this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
|
type = INTERNAL_IP6_ADDRESS;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = INTERNAL_IP4_ADDRESS;
|
||||||
|
}
|
||||||
|
cp->add_attribute(cp, configuration_attribute_create_chunk(
|
||||||
|
CONFIGURATION_ATTRIBUTE_V1, type, chunk_empty));
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
enumerator = this->attributes->create_enumerator(this->attributes);
|
||||||
|
while (enumerator->enumerate(enumerator, &entry))
|
||||||
|
{
|
||||||
|
cp->add_attribute(cp,
|
||||||
|
configuration_attribute_create_chunk(CONFIGURATION_ATTRIBUTE_V1,
|
||||||
|
entry->type, chunk_empty));
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
cp->set_identifier(cp, this->identifier);
|
||||||
|
message->add_payload(message, (payload_t*)cp);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(task_t, build_r, status_t,
|
||||||
|
private_mode_config_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
if (this->pull)
|
||||||
|
{
|
||||||
|
return build_reply(this, message);
|
||||||
|
}
|
||||||
|
return build_ack(this, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(task_t, process_i, status_t,
|
||||||
|
private_mode_config_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
process_payloads(this, message);
|
||||||
|
|
||||||
|
if (this->pull)
|
||||||
|
{
|
||||||
|
install_vips(this);
|
||||||
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,22 +605,22 @@ METHOD(task_t, migrate, void,
|
|||||||
this->ike_sa = ike_sa;
|
this->ike_sa = ike_sa;
|
||||||
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
|
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
|
||||||
this->vips = linked_list_create();
|
this->vips = linked_list_create();
|
||||||
this->requested->destroy_function(this->requested, free);
|
this->attributes->destroy_function(this->attributes, free);
|
||||||
this->requested = linked_list_create();
|
this->attributes = linked_list_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(task_t, destroy, void,
|
METHOD(task_t, destroy, void,
|
||||||
private_mode_config_t *this)
|
private_mode_config_t *this)
|
||||||
{
|
{
|
||||||
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
|
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
|
||||||
this->requested->destroy_function(this->requested, free);
|
this->attributes->destroy_function(this->attributes, free);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
|
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator, bool pull)
|
||||||
{
|
{
|
||||||
private_mode_config_t *this;
|
private_mode_config_t *this;
|
||||||
|
|
||||||
@@ -439,8 +633,9 @@ mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
.initiator = initiator,
|
.initiator = initiator,
|
||||||
|
.pull = initiator ? pull : TRUE,
|
||||||
.ike_sa = ike_sa,
|
.ike_sa = ike_sa,
|
||||||
.requested = linked_list_create(),
|
.attributes = linked_list_create(),
|
||||||
.vips = linked_list_create(),
|
.vips = linked_list_create(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ struct mode_config_t {
|
|||||||
*
|
*
|
||||||
* @param ike_sa IKE_SA this task works for
|
* @param ike_sa IKE_SA this task works for
|
||||||
* @param initiator TRUE for initiator
|
* @param initiator TRUE for initiator
|
||||||
|
* @param pull TRUE to pull, FALSE to push (applies if initiator only)
|
||||||
* @return mode_config task to handle by the task_manager
|
* @return mode_config task to handle by the task_manager
|
||||||
*/
|
*/
|
||||||
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator);
|
mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator, bool pull);
|
||||||
|
|
||||||
#endif /** MODE_CONFIG_H_ @}*/
|
#endif /** MODE_CONFIG_H_ @}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user