Added an IKE_SA manager method to enumerate IKE_SA IDs filtered by identities

This commit is contained in:
Martin Willi
2012-03-20 17:31:33 +01:00
parent beab4a90ae
commit cb1a145ce2
2 changed files with 59 additions and 34 deletions
+47 -34
View File
@@ -266,7 +266,7 @@ static bool connected_peers_match(connected_peers_t *connected_peers,
{ {
return my_id->equals(my_id, connected_peers->my_id) && return my_id->equals(my_id, connected_peers->my_id) &&
other_id->equals(other_id, connected_peers->other_id) && other_id->equals(other_id, connected_peers->other_id) &&
family == connected_peers->family; (!family || family == connected_peers->family);
} }
typedef struct segment_t segment_t; typedef struct segment_t segment_t;
@@ -1444,29 +1444,23 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void,
charon->bus->set_sa(charon->bus, NULL); charon->bus->set_sa(charon->bus, NULL);
} }
METHOD(ike_sa_manager_t, check_uniqueness, bool, /**
private_ike_sa_manager_t *this, ike_sa_t *ike_sa, bool force_replace) * Cleanup function for create_id_enumerator
*/
static void id_enumerator_cleanup(linked_list_t *ids)
{ {
bool cancel = FALSE; ids->destroy_offset(ids, offsetof(ike_sa_id_t, destroy));
peer_cfg_t *peer_cfg; }
unique_policy_t policy;
linked_list_t *list, *duplicate_ids = NULL; METHOD(ike_sa_manager_t, create_id_enumerator, enumerator_t*,
enumerator_t *enumerator; private_ike_sa_manager_t *this, identification_t *me,
ike_sa_id_t *duplicate_id = NULL; identification_t *other, int family)
identification_t *me, *other; {
linked_list_t *list, *ids = NULL;
connected_peers_t *current;
u_int row, segment; u_int row, segment;
rwlock_t *lock; rwlock_t *lock;
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
policy = peer_cfg->get_unique_policy(peer_cfg);
if (policy == UNIQUE_NO && !force_replace)
{
return FALSE;
}
me = ike_sa->get_my_id(ike_sa);
other = ike_sa->get_other_id(ike_sa);
row = chunk_hash_inc(other->get_encoding(other), row = chunk_hash_inc(other->get_encoding(other),
chunk_hash(me->get_encoding(me))) & this->table_mask; chunk_hash(me->get_encoding(me))) & this->table_mask;
segment = row & this->segment_mask; segment = row & this->segment_mask;
@@ -1476,33 +1470,52 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool,
list = this->connected_peers_table[row]; list = this->connected_peers_table[row];
if (list) if (list)
{ {
connected_peers_t *current;
host_t *other_host;
other_host = ike_sa->get_other_host(ike_sa);
if (list->find_first(list, (linked_list_match_t)connected_peers_match, if (list->find_first(list, (linked_list_match_t)connected_peers_match,
(void**)&current, me, other, (void**)&current, me, other, (uintptr_t)family) == SUCCESS)
(uintptr_t)other_host->get_family(other_host)) == SUCCESS)
{ {
/* clone the list, so we can release the lock */ ids = current->sas->clone_offset(current->sas,
duplicate_ids = current->sas->clone_offset(current->sas, offsetof(ike_sa_id_t, clone));
offsetof(ike_sa_id_t, clone));
} }
} }
lock->unlock(lock); lock->unlock(lock);
if (!duplicate_ids) if (!ids)
{
return enumerator_create_empty();
}
return enumerator_create_cleaner(ids->create_enumerator(ids),
(void*)id_enumerator_cleanup, ids);
}
METHOD(ike_sa_manager_t, check_uniqueness, bool,
private_ike_sa_manager_t *this, ike_sa_t *ike_sa, bool force_replace)
{
bool cancel = FALSE;
peer_cfg_t *peer_cfg;
unique_policy_t policy;
enumerator_t *enumerator;
ike_sa_id_t *id = NULL;
identification_t *me, *other;
host_t *other_host;
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
policy = peer_cfg->get_unique_policy(peer_cfg);
if (policy == UNIQUE_NO && !force_replace)
{ {
return FALSE; return FALSE;
} }
me = ike_sa->get_my_id(ike_sa);
other = ike_sa->get_other_id(ike_sa);
other_host = ike_sa->get_other_host(ike_sa);
enumerator = duplicate_ids->create_enumerator(duplicate_ids); enumerator = create_id_enumerator(this, me, other,
while (enumerator->enumerate(enumerator, &duplicate_id)) other_host->get_family(other_host));
while (enumerator->enumerate(enumerator, &id))
{ {
status_t status = SUCCESS; status_t status = SUCCESS;
ike_sa_t *duplicate; ike_sa_t *duplicate;
duplicate = checkout(this, duplicate_id); duplicate = checkout(this, id);
if (!duplicate) if (!duplicate)
{ {
continue; continue;
@@ -1552,7 +1565,6 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
duplicate_ids->destroy_offset(duplicate_ids, offsetof(ike_sa_id_t, destroy));
/* reset thread's current IKE_SA after checkin */ /* reset thread's current IKE_SA after checkin */
charon->bus->set_sa(charon->bus, ike_sa); charon->bus->set_sa(charon->bus, ike_sa);
return cancel; return cancel;
@@ -1789,6 +1801,7 @@ ike_sa_manager_t *ike_sa_manager_create()
.check_uniqueness = _check_uniqueness, .check_uniqueness = _check_uniqueness,
.has_contact = _has_contact, .has_contact = _has_contact,
.create_enumerator = _create_enumerator, .create_enumerator = _create_enumerator,
.create_id_enumerator = _create_id_enumerator,
.checkin = _checkin, .checkin = _checkin,
.checkin_and_destroy = _checkin_and_destroy, .checkin_and_destroy = _checkin_and_destroy,
.get_count = _get_count, .get_count = _get_count,
+12
View File
@@ -169,6 +169,18 @@ struct ike_sa_manager_t {
*/ */
enumerator_t *(*create_enumerator) (ike_sa_manager_t* this, bool wait); enumerator_t *(*create_enumerator) (ike_sa_manager_t* this, bool wait);
/**
* Create an enumerator over ike_sa_id_t*, matching peer identities.
*
* @param me local peer identity to match
* @param other remote peer identity to match
* @param family address family to match, 0 for any
* @return enumerator over ike_sa_id_t*
*/
enumerator_t* (*create_id_enumerator)(ike_sa_manager_t *this,
identification_t *me, identification_t *other,
int family);
/** /**
* Checkin the SA after usage. * Checkin the SA after usage.
* *