diff options
author | Martin Willi <martin@revosec.ch> | 2012-01-03 16:23:37 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-03-20 17:31:33 +0100 |
commit | cb1a145ce29e8ba39e73f8d314f788265498a66f (patch) | |
tree | 534cbb4139b6546b681c05b4208146411e2e169c /src | |
parent | beab4a90aef5aea018d2bb2159cae3dbfd760cee (diff) | |
download | strongswan-cb1a145ce29e8ba39e73f8d314f788265498a66f.tar.bz2 strongswan-cb1a145ce29e8ba39e73f8d314f788265498a66f.tar.xz |
Added an IKE_SA manager method to enumerate IKE_SA IDs filtered by identities
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.c | 81 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa_manager.h | 12 |
2 files changed, 59 insertions, 34 deletions
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 9ec0d34d8..2b4418f24 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -266,7 +266,7 @@ static bool connected_peers_match(connected_peers_t *connected_peers, { return my_id->equals(my_id, connected_peers->my_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; @@ -1444,29 +1444,23 @@ METHOD(ike_sa_manager_t, checkin_and_destroy, void, 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; - peer_cfg_t *peer_cfg; - unique_policy_t policy; - linked_list_t *list, *duplicate_ids = NULL; - enumerator_t *enumerator; - ike_sa_id_t *duplicate_id = NULL; - identification_t *me, *other; + ids->destroy_offset(ids, offsetof(ike_sa_id_t, destroy)); +} + +METHOD(ike_sa_manager_t, create_id_enumerator, enumerator_t*, + private_ike_sa_manager_t *this, identification_t *me, + identification_t *other, int family) +{ + linked_list_t *list, *ids = NULL; + connected_peers_t *current; u_int row, segment; 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), chunk_hash(me->get_encoding(me))) & this->table_mask; segment = row & this->segment_mask; @@ -1476,33 +1470,52 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool, list = this->connected_peers_table[row]; 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, - (void**)¤t, me, other, - (uintptr_t)other_host->get_family(other_host)) == SUCCESS) + (void**)¤t, me, other, (uintptr_t)family) == SUCCESS) { - /* clone the list, so we can release the lock */ - duplicate_ids = current->sas->clone_offset(current->sas, - offsetof(ike_sa_id_t, clone)); + ids = current->sas->clone_offset(current->sas, + offsetof(ike_sa_id_t, clone)); } } 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; } + 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); - while (enumerator->enumerate(enumerator, &duplicate_id)) + enumerator = create_id_enumerator(this, me, other, + other_host->get_family(other_host)); + while (enumerator->enumerate(enumerator, &id)) { status_t status = SUCCESS; ike_sa_t *duplicate; - duplicate = checkout(this, duplicate_id); + duplicate = checkout(this, id); if (!duplicate) { continue; @@ -1552,7 +1565,6 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool, } } enumerator->destroy(enumerator); - duplicate_ids->destroy_offset(duplicate_ids, offsetof(ike_sa_id_t, destroy)); /* reset thread's current IKE_SA after checkin */ charon->bus->set_sa(charon->bus, ike_sa); return cancel; @@ -1789,6 +1801,7 @@ ike_sa_manager_t *ike_sa_manager_create() .check_uniqueness = _check_uniqueness, .has_contact = _has_contact, .create_enumerator = _create_enumerator, + .create_id_enumerator = _create_id_enumerator, .checkin = _checkin, .checkin_and_destroy = _checkin_and_destroy, .get_count = _get_count, diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h index bf75b76bb..0f9a6d177 100644 --- a/src/libcharon/sa/ike_sa_manager.h +++ b/src/libcharon/sa/ike_sa_manager.h @@ -170,6 +170,18 @@ struct ike_sa_manager_t { 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. * * If the IKE_SA is not registered in the manager, a new entry is created. |