Merge branch 'multi-vip'

Brings support for multiple virtual IPs and multiple pools in
left/rigthsourceip definitions. Also introduces the new left/rightdns
options to configure requested DNS server address family and respond
with multiple connection specific servers.
This commit is contained in:
Martin Willi
2012-08-31 12:55:56 +02:00
71 changed files with 2004 additions and 760 deletions
+30
View File
@@ -609,6 +609,34 @@ METHOD(phase1_t, get_id, identification_t*,
return id;
}
METHOD(phase1_t, has_virtual_ip, bool,
private_phase1_t *this, peer_cfg_t *peer_cfg)
{
enumerator_t *enumerator;
bool found = FALSE;
host_t *host;
enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
found = enumerator->enumerate(enumerator, &host);
enumerator->destroy(enumerator);
return found;
}
METHOD(phase1_t, has_pool, bool,
private_phase1_t *this, peer_cfg_t *peer_cfg)
{
enumerator_t *enumerator;
bool found = FALSE;
char *pool;
enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
found = enumerator->enumerate(enumerator, &pool);
enumerator->destroy(enumerator);
return found;
}
METHOD(phase1_t, save_sa_payload, bool,
private_phase1_t *this, message_t *message)
{
@@ -748,6 +776,8 @@ phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
.get_auth_method = _get_auth_method,
.get_id = _get_id,
.select_config = _select_config,
.has_virtual_ip = _has_virtual_ip,
.has_pool = _has_pool,
.verify_auth = _verify_auth,
.build_auth = _build_auth,
.save_sa_payload = _save_sa_payload,
+16
View File
@@ -108,6 +108,22 @@ struct phase1_t {
*/
identification_t* (*get_id)(phase1_t *this, peer_cfg_t *peer_cfg, bool local);
/**
* Check if peer config has virtual IPs pool assigned.
*
* @param peer_cfg peer_config to check
* @return TRUE if peer config contains at least one pool
*/
bool (*has_pool)(phase1_t *this, peer_cfg_t *peer_cfg);
/**
* Check if peer config has virtual IPs to request
*
* @param peer_cfg peer_config to check
* @return TRUE if peer config contains at least one virtual IP
*/
bool (*has_virtual_ip)(phase1_t *this, peer_cfg_t *peer_cfg);
/**
* Extract and store SA payload bytes from encoded message.
*
+22 -6
View File
@@ -346,15 +346,30 @@ METHOD(task_manager_t, retransmit, status_t,
*/
static bool mode_config_expected(private_task_manager_t *this)
{
enumerator_t *enumerator;
peer_cfg_t *peer_cfg;
char *pool;
host_t *host;
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
if (peer_cfg && peer_cfg->get_pool(peer_cfg))
if (peer_cfg)
{
if (!this->ike_sa->get_virtual_ip(this->ike_sa, FALSE))
{
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 = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa,
FALSE);
if (!enumerator->enumerate(enumerator, &host))
{ /* have a pool, but no VIP assigned yet */
enumerator->destroy(enumerator);
return TRUE;
}
enumerator->destroy(enumerator);
}
return FALSE;
}
@@ -1309,11 +1324,12 @@ METHOD(task_manager_t, queue_ike_reauth, void,
new->set_other_host(new, host->clone(host));
host = this->ike_sa->get_my_host(this->ike_sa);
new->set_my_host(new, host->clone(host));
host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
if (host)
enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
while (enumerator->enumerate(enumerator, &host))
{
new->set_virtual_ip(new, TRUE, host);
new->add_virtual_ip(new, TRUE, host);
}
enumerator->destroy(enumerator);
enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
while (enumerator->enumerate(enumerator, &child_sa))
@@ -320,7 +320,7 @@ METHOD(task_t, build_i, status_t,
}
break;
}
if (this->peer_cfg->get_virtual_ip(this->peer_cfg))
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
@@ -497,8 +497,8 @@ METHOD(task_t, process_r, status_t,
this->ike_sa->get_id(this->ike_sa)));
break;
}
if (this->peer_cfg->get_pool(this->peer_cfg) == NULL &&
this->peer_cfg->get_virtual_ip(this->peer_cfg))
if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
+3 -3
View File
@@ -524,8 +524,8 @@ METHOD(task_t, build_r, status_t,
this->ike_sa->get_id(this->ike_sa)));
break;
}
if (this->peer_cfg->get_pool(this->peer_cfg) == NULL &&
this->peer_cfg->get_virtual_ip(this->peer_cfg))
if (!this->ph1->has_pool(this->ph1, this->peer_cfg) &&
this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
@@ -658,7 +658,7 @@ METHOD(task_t, process_i, status_t,
}
break;
}
if (this->peer_cfg->get_virtual_ip(this->peer_cfg))
if (this->ph1->has_virtual_ip(this->ph1, this->peer_cfg))
{
this->ike_sa->queue_task(this->ike_sa,
(task_t*)mode_config_create(this->ike_sa, TRUE));
+98 -39
View File
@@ -42,9 +42,9 @@ struct private_mode_config_t {
bool initiator;
/**
* virtual ip
* Received list of virtual IPs, host_t*
*/
host_t *virtual_ip;
linked_list_t *vips;
/**
* list of attributes requested and its handler, entry_t
@@ -174,8 +174,7 @@ static void process_attribute(private_mode_config_t *this,
}
if (ip)
{
DESTROY_IF(this->virtual_ip);
this->virtual_ip = ip;
this->vips->insert_last(this->vips, ip);
}
break;
}
@@ -239,23 +238,44 @@ METHOD(task_t, build_i, status_t,
peer_cfg_t *config;
configuration_attribute_type_t type;
chunk_t data;
host_t *vip;
linked_list_t *vips;
host_t *host;
vips = linked_list_create();
/* reuse virtual IP if we already have one */
vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
if (!vip)
enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
while (enumerator->enumerate(enumerator, &host))
{
vips->insert_last(vips, host);
}
enumerator->destroy(enumerator);
if (vips->get_count(vips) == 0)
{
config = this->ike_sa->get_peer_cfg(this->ike_sa);
vip = config->get_virtual_ip(config);
}
if (vip)
{
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
cp->add_attribute(cp, build_vip(vip));
enumerator = config->create_virtual_ip_enumerator(config);
while (enumerator->enumerate(enumerator, &host))
{
vips->insert_last(vips, host);
}
enumerator->destroy(enumerator);
}
enumerator = hydra->attributes->create_initiator_enumerator(hydra->attributes,
this->ike_sa->get_other_id(this->ike_sa), vip);
if (vips->get_count(vips))
{
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
enumerator = vips->create_enumerator(vips);
while (enumerator->enumerate(enumerator, &host))
{
cp->add_attribute(cp, build_vip(host));
}
enumerator->destroy(enumerator);
}
enumerator = hydra->attributes->create_initiator_enumerator(
hydra->attributes,
this->ike_sa->get_other_id(this->ike_sa), vips);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
configuration_attribute_t *ca;
@@ -279,6 +299,8 @@ METHOD(task_t, build_i, status_t,
}
enumerator->destroy(enumerator);
vips->destroy(vips);
if (cp)
{
message->add_payload(message, (payload_t*)cp);
@@ -299,37 +321,64 @@ METHOD(task_t, build_r, status_t,
enumerator_t *enumerator;
configuration_attribute_type_t type;
chunk_t value;
host_t *vip = NULL;
cp_payload_t *cp = NULL;
peer_cfg_t *config;
identification_t *id;
linked_list_t *vips, *pools;
host_t *requested;
id = this->ike_sa->get_other_eap_id(this->ike_sa);
config = this->ike_sa->get_peer_cfg(this->ike_sa);
if (this->virtual_ip)
vips = linked_list_create();
pools = linked_list_create();
enumerator = this->vips->create_enumerator(this->vips);
while (enumerator->enumerate(enumerator, &requested))
{
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
if (config->get_pool(config))
enumerator_t *poolenum;
char *pool;
host_t *found = NULL;
/* query all pools until we get an address */
DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
poolenum = config->create_pool_enumerator(config);
while (poolenum->enumerate(poolenum, &pool))
{
vip = hydra->attributes->acquire_address(hydra->attributes,
config->get_pool(config), id, this->virtual_ip);
found = hydra->attributes->acquire_address(hydra->attributes,
pool, id, requested);
if (!found)
{
continue;
}
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
if (!cp)
{
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
}
cp->add_attribute(cp, build_vip(found));
/* use pool to request other attributes */
if (pools->find_first(pools, NULL, (void**)&pool) == NOT_FOUND)
{
pools->insert_last(pools, pool);
}
vips->insert_last(vips, found);
break;
}
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
if (vip)
poolenum->destroy(poolenum);
if (!found)
{
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", vip, id);
this->ike_sa->set_virtual_ip(this->ike_sa, FALSE, vip);
cp->add_attribute(cp, build_vip(vip));
}
else
{
DBG1(DBG_IKE, "no virtual IP found, sending empty config payload");
DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
requested, id);
}
}
enumerator->destroy(enumerator);
/* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator(
hydra->attributes, config->get_pool(config), id, vip);
hydra->attributes, pools, id, vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
@@ -343,25 +392,35 @@ METHOD(task_t, build_r, status_t,
type, value));
}
enumerator->destroy(enumerator);
vips->destroy_offset(vips, offsetof(host_t, destroy));
vips->destroy(vips);
if (cp)
{
cp->set_identifier(cp, this->identifier);
message->add_payload(message, (payload_t*)cp);
}
DESTROY_IF(vip);
return SUCCESS;
}
METHOD(task_t, process_i, status_t,
private_mode_config_t *this, message_t *message)
{
enumerator_t *enumerator;
host_t *host;
process_payloads(this, message);
if (this->virtual_ip)
enumerator = this->vips->create_enumerator(this->vips);
while (enumerator->enumerate(enumerator, &host))
{
this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
if (!host->is_anyaddr(host))
{
this->ike_sa->add_virtual_ip(this->ike_sa, TRUE, host);
}
}
enumerator->destroy(enumerator);
return SUCCESS;
}
@@ -374,10 +433,9 @@ METHOD(task_t, get_type, task_type_t,
METHOD(task_t, migrate, void,
private_mode_config_t *this, ike_sa_t *ike_sa)
{
DESTROY_IF(this->virtual_ip);
this->ike_sa = ike_sa;
this->virtual_ip = NULL;
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->vips = linked_list_create();
this->requested->destroy_function(this->requested, free);
this->requested = linked_list_create();
}
@@ -385,7 +443,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void,
private_mode_config_t *this)
{
DESTROY_IF(this->virtual_ip);
this->vips->destroy_offset(this->vips, offsetof(host_t, destroy));
this->requested->destroy_function(this->requested, free);
free(this);
}
@@ -408,6 +466,7 @@ mode_config_t *mode_config_create(ike_sa_t *ike_sa, bool initiator)
.initiator = initiator,
.ike_sa = ike_sa,
.requested = linked_list_create(),
.vips = linked_list_create(),
);
if (initiator)
+30 -14
View File
@@ -398,11 +398,12 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
linked_list_t *supplied)
{
traffic_selector_t *ts;
enumerator_t *enumerator;
linked_list_t *list;
host_t *host;
host = this->ike_sa->get_virtual_ip(this->ike_sa, local);
if (!host)
enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, local);
if (!enumerator->enumerate(enumerator, &host))
{
if (local)
{
@@ -413,6 +414,7 @@ static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
host = this->ike_sa->get_other_host(this->ike_sa);
}
}
enumerator->destroy(enumerator);
list = this->config->get_traffic_selectors(this->config, local,
supplied, host);
if (list->get_first(list, (void**)&ts) == SUCCESS)
@@ -831,6 +833,30 @@ static void check_for_rekeyed_child(private_quick_mode_t *this)
enumerator->destroy(enumerator);
}
/**
* Get host to use for dynamic traffic selectors
*/
static host_t *get_dynamic_host(ike_sa_t *ike_sa, bool local)
{
enumerator_t *enumerator;
host_t *host;
enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
if (!enumerator->enumerate(enumerator, &host))
{
if (local)
{
host = ike_sa->get_my_host(ike_sa);
}
else
{
host = ike_sa->get_other_host(ike_sa);
}
}
enumerator->destroy(enumerator);
return host;
}
METHOD(task_t, process_r, status_t,
private_quick_mode_t *this, message_t *message)
{
@@ -841,7 +867,6 @@ METHOD(task_t, process_r, status_t,
sa_payload_t *sa_payload;
linked_list_t *tsi, *tsr, *list = NULL;
peer_cfg_t *peer_cfg;
host_t *me, *other;
u_int16_t group;
bool private;
@@ -849,16 +874,6 @@ METHOD(task_t, process_r, status_t,
{
return FAILED;
}
me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
if (!me)
{
me = this->ike_sa->get_my_host(this->ike_sa);
}
other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
if (!other)
{
other = this->ike_sa->get_other_host(this->ike_sa);
}
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
tsi = linked_list_create();
tsr = linked_list_create();
@@ -866,7 +881,8 @@ METHOD(task_t, process_r, status_t,
tsr->insert_last(tsr, this->tsr);
this->tsi = this->tsr = NULL;
this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
me, other);
get_dynamic_host(this->ike_sa, TRUE),
get_dynamic_host(this->ike_sa, FALSE));
if (this->config)
{
this->tsi = select_ts(this, FALSE, tsi);