segment = put_entry(this, entry);
}
- /* apply identities for duplicate test (only as responder) */
- if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
- ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ /* apply identities for duplicate test */
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
entry->my_id == NULL && entry->other_id == NULL)
{
entry->my_id = my_id->clone(my_id);
{
remove_half_open(this, entry);
}
- if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
- entry->my_id && entry->other_id)
+ if (entry->my_id && entry->other_id)
{
remove_connected_peers(this, entry);
}
return cancel;
}
+METHOD(ike_sa_manager_t, has_contact, bool,
+ private_ike_sa_manager_t *this, identification_t *me,
+ identification_t *other, int family)
+{
+ linked_list_t *list;
+ u_int row, segment;
+ rwlock_t *lock;
+ bool found = FALSE;
+
+ row = chunk_hash_inc(other->get_encoding(other),
+ chunk_hash(me->get_encoding(me))) & this->table_mask;
+ segment = row & this->segment_mask;
+ lock = this->connected_peers_segments[segment & this->segment_mask].lock;
+ lock->read_lock(lock);
+ list = this->connected_peers_table[row];
+ if (list)
+ {
+ if (list->find_first(list, (linked_list_match_t)connected_peers_match,
+ NULL, me, other, family) == SUCCESS)
+ {
+ found = TRUE;
+ }
+ }
+ lock->unlock(lock);
+
+ return found;
+}
+
METHOD(ike_sa_manager_t, get_half_open_count, int,
private_ike_sa_manager_t *this, host_t *ip)
{
{
remove_half_open(this, entry);
}
- if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
- entry->my_id && entry->other_id)
+ if (entry->my_id && entry->other_id)
{
remove_connected_peers(this, entry);
}
.checkout_by_id = _checkout_by_id,
.checkout_by_name = _checkout_by_name,
.check_uniqueness = _check_uniqueness,
+ .has_contact = _has_contact,
.create_enumerator = _create_enumerator,
.checkin = _checkin,
.checkin_and_destroy = _checkin_and_destroy,
*/
bool (*check_uniqueness)(ike_sa_manager_t *this, ike_sa_t *ike_sa);
+ /**
+ * Check if we already have a connected IKE_SA between two identities.
+ *
+ * @param me own identity
+ * @param other remote identity
+ * @param family address family to include in uniqueness check
+ * @return TRUE if we have a connected IKE_SA
+ */
+ bool (*has_contact)(ike_sa_manager_t *this, identification_t *me,
+ identification_t *other, int family);
+
/**
* Check out an IKE_SA a unique ID.
*
/* check if an authenticator is in progress */
if (this->my_auth == NULL)
{
- identification_t *id;
+ identification_t *idi, *idr = NULL;
id_payload_t *id_payload;
/* clean up authentication config from a previous round */
cfg = get_auth_cfg(this, FALSE);
if (cfg)
{
- id = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (id && !id->contains_wildcards(id))
+ idr = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (idr && !idr->contains_wildcards(idr))
{
- this->ike_sa->set_other_id(this->ike_sa, id->clone(id));
+ this->ike_sa->set_other_id(this->ike_sa, idr->clone(idr));
id_payload = id_payload_create_from_identification(
- ID_RESPONDER, id);
+ ID_RESPONDER, idr);
message->add_payload(message, (payload_t*)id_payload);
}
}
/* add IDi */
cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
cfg->merge(cfg, get_auth_cfg(this, TRUE), TRUE);
- id = cfg->get(cfg, AUTH_RULE_IDENTITY);
- if (!id)
+ idi = cfg->get(cfg, AUTH_RULE_IDENTITY);
+ if (!idi)
{
DBG1(DBG_CFG, "configuration misses IDi");
return FAILED;
}
- this->ike_sa->set_my_id(this->ike_sa, id->clone(id));
- id_payload = id_payload_create_from_identification(ID_INITIATOR, id);
+ this->ike_sa->set_my_id(this->ike_sa, idi->clone(idi));
+ id_payload = id_payload_create_from_identification(ID_INITIATOR, idi);
get_reserved_id_bytes(this, id_payload);
message->add_payload(message, (payload_t*)id_payload);
+ if (idr && message->get_message_id(message) == 1 &&
+ this->peer_cfg->get_unique_policy(this->peer_cfg) != UNIQUE_NO)
+ {
+ host_t *host;
+
+ host = this->ike_sa->get_other_host(this->ike_sa);
+ if (!charon->ike_sa_manager->has_contact(charon->ike_sa_manager,
+ idi, idr, host->get_family(host)))
+ {
+ message->add_notify(message, FALSE, INITIAL_CONTACT, chunk_empty);
+ }
+ }
+
/* build authentication data */
this->my_auth = authenticator_create_builder(this->ike_sa, cfg,
this->other_nonce, this->my_nonce,