From d2e8f20d949dde98d5c42e5d7da9dae5771b56f1 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 5 Sep 2012 13:16:31 +0200 Subject: [PATCH] Clear virtual IPs before storing assigned ones on the IKE_SA Otherwise we'll end up with duplicate or invalid VIPs stored on the IKE_SA. --- src/libcharon/plugins/ha/ha_dispatcher.c | 11 ++++++++++- src/libcharon/sa/ike_sa.c | 18 ++++++++++++++++++ src/libcharon/sa/ike_sa.h | 7 +++++++ src/libcharon/sa/ikev1/tasks/mode_config.c | 4 ++++ src/libcharon/sa/ikev2/tasks/ike_config.c | 4 ++++ 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index f07b4ea21..97ed13111 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -310,7 +310,7 @@ static void process_ike_update(private_ha_dispatcher_t *this, ike_sa_t *ike_sa = NULL; peer_cfg_t *peer_cfg = NULL; auth_cfg_t *auth; - bool received_vip = FALSE, first_peer_addr = TRUE; + bool received_vip = FALSE, first_local_vip = TRUE, first_peer_addr = TRUE; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -344,9 +344,18 @@ static void process_ike_update(private_ha_dispatcher_t *this, ike_sa->set_other_host(ike_sa, value.host->clone(value.host)); break; case HA_LOCAL_VIP: + if (first_local_vip) + { + ike_sa->clear_virtual_ips(ike_sa, TRUE); + first_local_vip = FALSE; + } ike_sa->add_virtual_ip(ike_sa, TRUE, value.host); break; case HA_REMOTE_VIP: + if (!received_vip) + { + ike_sa->clear_virtual_ips(ike_sa, FALSE); + } ike_sa->add_virtual_ip(ike_sa, FALSE, value.host); received_vip = TRUE; break; diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 7672accc4..e3744b6c0 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -757,6 +757,23 @@ METHOD(ike_sa_t, add_virtual_ip, void, } } + +METHOD(ike_sa_t, clear_virtual_ips, void, + private_ike_sa_t *this, bool local) +{ + linked_list_t *vips = local ? this->my_vips : this->other_vips; + host_t *vip; + + while (vips->remove_first(vips, (void**)&vip) == SUCCESS) + { + if (local) + { + hydra->kernel_interface->del_ip(hydra->kernel_interface, vip); + } + vip->destroy(vip); + } +} + METHOD(ike_sa_t, create_virtual_ip_enumerator, enumerator_t*, private_ike_sa_t *this, bool local) { @@ -2193,6 +2210,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, .reset = _reset, .get_unique_id = _get_unique_id, .add_virtual_ip = _add_virtual_ip, + .clear_virtual_ips = _clear_virtual_ips, .create_virtual_ip_enumerator = _create_virtual_ip_enumerator, .add_configuration_attribute = _add_configuration_attribute, .set_kmaddress = _set_kmaddress, diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index d2a394b6c..d9ee6b876 100644 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -941,6 +941,13 @@ struct ike_sa_t { */ void (*add_virtual_ip) (ike_sa_t *this, bool local, host_t *ip); + /** + * Clear all virtual IPs stored on this IKE_SA. + * + * @param local TRUE to clear local addresses, FALSE for remote + */ + void (*clear_virtual_ips) (ike_sa_t *this, bool local); + /** * Create an enumerator over virtual IPs. * diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c index 03072a2a7..a134ad562 100644 --- a/src/libcharon/sa/ikev1/tasks/mode_config.c +++ b/src/libcharon/sa/ikev1/tasks/mode_config.c @@ -332,6 +332,8 @@ METHOD(task_t, build_r, status_t, vips = linked_list_create(); pools = linked_list_create(); + this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE); + enumerator = this->vips->create_enumerator(this->vips); while (enumerator->enumerate(enumerator, &requested)) { @@ -411,6 +413,8 @@ METHOD(task_t, process_i, status_t, process_payloads(this, message); + this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE); + enumerator = this->vips->create_enumerator(this->vips); while (enumerator->enumerate(enumerator, &host)) { diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c index e788bb5f9..fbfcb0ea9 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_config.c +++ b/src/libcharon/sa/ikev2/tasks/ike_config.c @@ -344,6 +344,8 @@ METHOD(task_t, build_r, status_t, vips = linked_list_create(); pools = linked_list_create(); + this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE); + enumerator = this->vips->create_enumerator(this->vips); while (enumerator->enumerate(enumerator, &requested)) { @@ -437,6 +439,8 @@ METHOD(task_t, process_i, status_t, process_payloads(this, message); + this->ike_sa->clear_virtual_ips(this->ike_sa, TRUE); + enumerator = this->vips->create_enumerator(this->vips); while (enumerator->enumerate(enumerator, &host)) {