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:
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user