diff options
author | Martin Willi <martin@revosec.ch> | 2013-07-17 17:28:18 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-07-17 17:28:18 +0200 |
commit | 20ea35679e23171cf53f2f39cb29af7227392cca (patch) | |
tree | 45f9c0732e45ad29f8dd1a25321b72f744bd7436 /src/libcharon | |
parent | f067348134109b1896c39724fc8cd8cba0fe60f8 (diff) | |
parent | c6f1d0de94a0e33785b7ed7670c7d41f0b1c4e3b (diff) | |
download | strongswan-20ea35679e23171cf53f2f39cb29af7227392cca.tar.bz2 strongswan-20ea35679e23171cf53f2f39cb29af7227392cca.tar.xz |
Merge branch 'array'
Introduces a new lightweight array collection having minimal memory overhead.
The new class replaces various linked lists that are used during the full
lifetime of an SA, reducing memory requirements by about 5KB or more per tunnel.
Diffstat (limited to 'src/libcharon')
-rw-r--r-- | src/libcharon/config/proposal.c | 477 | ||||
-rw-r--r-- | src/libcharon/plugins/farp/farp_listener.c | 24 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_child.c | 16 | ||||
-rw-r--r-- | src/libcharon/plugins/smp/smp.c | 4 | ||||
-rw-r--r-- | src/libcharon/plugins/stroke/stroke_list.c | 13 | ||||
-rw-r--r-- | src/libcharon/plugins/uci/uci_control.c | 8 | ||||
-rw-r--r-- | src/libcharon/sa/child_sa.c | 143 | ||||
-rw-r--r-- | src/libcharon/sa/child_sa.h | 13 | ||||
-rw-r--r-- | src/libcharon/sa/ike_sa.c | 214 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/task_manager_v1.c | 36 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/quick_delete.c | 14 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/tasks/quick_mode.c | 14 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 146 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 34 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_delete.c | 14 |
15 files changed, 525 insertions, 645 deletions
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index 4803c7be2..a927a1f75 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -19,7 +19,7 @@ #include "proposal.h" #include <daemon.h> -#include <collections/linked_list.h> +#include <collections/array.h> #include <utils/identification.h> #include <crypto/transform.h> @@ -36,7 +36,6 @@ ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP, ); typedef struct private_proposal_t private_proposal_t; -typedef struct algorithm_t algorithm_t; /** * Private data of an proposal_t object @@ -54,29 +53,9 @@ struct private_proposal_t { protocol_id_t protocol; /** - * priority ordered list of encryption algorithms + * Priority ordered list of transforms, as entry_t */ - linked_list_t *encryption_algos; - - /** - * priority ordered list of integrity algorithms - */ - linked_list_t *integrity_algos; - - /** - * priority ordered list of pseudo random functions - */ - linked_list_t *prf_algos; - - /** - * priority ordered list of dh groups - */ - linked_list_t *dh_groups; - - /** - * priority ordered list of extended sequence number flags - */ - linked_list_t *esns; + array_t *transforms; /** * senders SPI @@ -92,68 +71,47 @@ struct private_proposal_t { /** * Struct used to store different kinds of algorithms. */ -struct algorithm_t { - /** - * Value from an encryption_algorithm_t/integrity_algorithm_t/... - */ - u_int16_t algorithm; - - /** - * the associated key size in bits, or zero if not needed - */ +typedef struct { + /** Type of the transform */ + transform_type_t type; + /** algorithm identifier */ + u_int16_t alg; + /** key size in bits, or zero if not needed */ u_int16_t key_size; -}; - -/** - * Add algorithm/keysize to a algorithm list - */ -static void add_algo(linked_list_t *list, u_int16_t algo, u_int16_t key_size) -{ - algorithm_t *algo_key; - - algo_key = malloc_thing(algorithm_t); - algo_key->algorithm = algo; - algo_key->key_size = key_size; - list->insert_last(list, (void*)algo_key); -} +} entry_t; METHOD(proposal_t, add_algorithm, void, private_proposal_t *this, transform_type_t type, - u_int16_t algo, u_int16_t key_size) + u_int16_t alg, u_int16_t key_size) { - switch (type) - { - case ENCRYPTION_ALGORITHM: - add_algo(this->encryption_algos, algo, key_size); - break; - case INTEGRITY_ALGORITHM: - add_algo(this->integrity_algos, algo, key_size); - break; - case PSEUDO_RANDOM_FUNCTION: - add_algo(this->prf_algos, algo, key_size); - break; - case DIFFIE_HELLMAN_GROUP: - add_algo(this->dh_groups, algo, 0); - break; - case EXTENDED_SEQUENCE_NUMBERS: - add_algo(this->esns, algo, 0); - break; - default: - break; - } + entry_t entry = { + .type = type, + .alg = alg, + .key_size = key_size, + }; + + array_insert(this->transforms, ARRAY_TAIL, &entry); } /** * filter function for peer configs */ -static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg, +static bool alg_filter(uintptr_t type, entry_t **in, u_int16_t *alg, void **unused, u_int16_t *key_size) { - algorithm_t *algo = *in; - *alg = algo->algorithm; + entry_t *entry = *in; + + if (entry->type != type) + { + return FALSE; + } + if (alg) + { + *alg = entry->alg; + } if (key_size) { - *key_size = algo->key_size; + *key_size = entry->key_size; } return TRUE; } @@ -161,30 +119,9 @@ static bool alg_filter(void *null, algorithm_t **in, u_int16_t *alg, METHOD(proposal_t, create_enumerator, enumerator_t*, private_proposal_t *this, transform_type_t type) { - linked_list_t *list; - - switch (type) - { - case ENCRYPTION_ALGORITHM: - list = this->encryption_algos; - break; - case INTEGRITY_ALGORITHM: - list = this->integrity_algos; - break; - case PSEUDO_RANDOM_FUNCTION: - list = this->prf_algos; - break; - case DIFFIE_HELLMAN_GROUP: - list = this->dh_groups; - break; - case EXTENDED_SEQUENCE_NUMBERS: - list = this->esns; - break; - default: - return NULL; - } - return enumerator_create_filter(list->create_enumerator(list), - (void*)alg_filter, NULL, NULL); + return enumerator_create_filter( + array_create_enumerator(this->transforms), + (void*)alg_filter, (void*)(uintptr_t)type, NULL); } METHOD(proposal_t, get_algorithm, bool, @@ -200,84 +137,91 @@ METHOD(proposal_t, get_algorithm, bool, found = TRUE; } enumerator->destroy(enumerator); + return found; } METHOD(proposal_t, has_dh_group, bool, private_proposal_t *this, diffie_hellman_group_t group) { - bool result = FALSE; + bool found = FALSE, any = FALSE; + enumerator_t *enumerator; + u_int16_t current; - if (this->dh_groups->get_count(this->dh_groups)) + enumerator = create_enumerator(this, DIFFIE_HELLMAN_GROUP); + while (enumerator->enumerate(enumerator, ¤t, NULL)) { - algorithm_t *current; - enumerator_t *enumerator; - - enumerator = this->dh_groups->create_enumerator(this->dh_groups); - while (enumerator->enumerate(enumerator, (void**)¤t)) + any = TRUE; + if (current == group) { - if (current->algorithm == group) - { - result = TRUE; - break; - } + found = TRUE; + break; } - enumerator->destroy(enumerator); } - else if (group == MODP_NONE) + enumerator->destroy(enumerator); + + if (!any && group == MODP_NONE) { - result = TRUE; + found = TRUE; } - return result; + return found; } METHOD(proposal_t, strip_dh, void, private_proposal_t *this, diffie_hellman_group_t keep) { enumerator_t *enumerator; - algorithm_t *alg; + entry_t *entry; - enumerator = this->dh_groups->create_enumerator(this->dh_groups); - while (enumerator->enumerate(enumerator, (void**)&alg)) + enumerator = array_create_enumerator(this->transforms); + while (enumerator->enumerate(enumerator, &entry)) { - if (alg->algorithm != keep) + if (entry->type == DIFFIE_HELLMAN_GROUP && + entry->alg != keep) { - this->dh_groups->remove_at(this->dh_groups, enumerator); - free(alg); + array_remove_at(this->transforms, enumerator); } } enumerator->destroy(enumerator); } /** - * Find a matching alg/keysize in two linked lists + * Select a matching proposal from this and other, insert into selected. */ -static bool select_algo(linked_list_t *first, linked_list_t *second, bool priv, - bool *add, u_int16_t *alg, size_t *key_size) +static bool select_algo(private_proposal_t *this, proposal_t *other, + proposal_t *selected, transform_type_t type, bool priv) { enumerator_t *e1, *e2; - algorithm_t *alg1, *alg2; + u_int16_t alg1, alg2, ks1, ks2; + bool found = FALSE; - /* if in both are zero algorithms specified, we HAVE a match */ - if (first->get_count(first) == 0 && second->get_count(second) == 0) + if (type == INTEGRITY_ALGORITHM && + selected->get_algorithm(selected, ENCRYPTION_ALGORITHM, &alg1, NULL) && + encryption_algorithm_is_aead(alg1)) { - *add = FALSE; + /* no integrity algorithm required, we have an AEAD */ return TRUE; } - e1 = first->create_enumerator(first); - e2 = second->create_enumerator(second); + e1 = create_enumerator(this, type); + e2 = other->create_enumerator(other, type); + if (!e1->enumerate(e1, NULL, NULL) && !e2->enumerate(e2, NULL, NULL)) + { + found = TRUE; + } + + e1->destroy(e1); + e1 = create_enumerator(this, type); /* compare algs, order of algs in "first" is preferred */ - while (e1->enumerate(e1, &alg1)) + while (!found && e1->enumerate(e1, &alg1, &ks1)) { e2->destroy(e2); - e2 = second->create_enumerator(second); - while (e2->enumerate(e2, &alg2)) + e2 = other->create_enumerator(other, type); + while (e2->enumerate(e2, &alg2, &ks2)) { - if (alg1->algorithm == alg2->algorithm && - alg1->key_size == alg2->key_size) + if (alg1 == alg2 && ks1 == ks2) { - if (!priv && alg1->algorithm >= 1024) + if (!priv && alg1 >= 1024) { /* accept private use algorithms only if requested */ DBG1(DBG_CFG, "an algorithm from private space would match, " @@ -285,132 +229,52 @@ static bool select_algo(linked_list_t *first, linked_list_t *second, bool priv, continue; } /* ok, we have an algorithm */ - *alg = alg1->algorithm; - *key_size = alg1->key_size; - *add = TRUE; - e1->destroy(e1); - e2->destroy(e2); - return TRUE; + selected->add_algorithm(selected, type, alg1, ks1); + found = TRUE; + break; } } } /* no match in all comparisons */ e1->destroy(e1); e2->destroy(e2); - return FALSE; + + if (!found) + { + DBG2(DBG_CFG, " no acceptable %N found", transform_type_names, type); + } + return found; } METHOD(proposal_t, select_proposal, proposal_t*, - private_proposal_t *this, proposal_t *other_pub, bool private) + private_proposal_t *this, proposal_t *other, bool private) { - private_proposal_t *other = (private_proposal_t*)other_pub; proposal_t *selected; - u_int16_t algo; - size_t key_size; - bool add; DBG2(DBG_CFG, "selecting proposal:"); - /* check protocol */ - if (this->protocol != other->protocol) + if (this->protocol != other->get_protocol(other)) { DBG2(DBG_CFG, " protocol mismatch, skipping"); return NULL; } - selected = proposal_create(this->protocol, other->number); + selected = proposal_create(this->protocol, other->get_number(other)); - /* select encryption algorithm */ - if (select_algo(this->encryption_algos, other->encryption_algos, private, - &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, ENCRYPTION_ALGORITHM, - algo, key_size); - } - } - else - { - selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable %N found", - transform_type_names, ENCRYPTION_ALGORITHM); - return NULL; - } - /* select integrity algorithm */ - if (!encryption_algorithm_is_aead(algo)) - { - if (select_algo(this->integrity_algos, other->integrity_algos, private, - &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, INTEGRITY_ALGORITHM, - algo, key_size); - } - } - else - { - selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable %N found", - transform_type_names, INTEGRITY_ALGORITHM); - return NULL; - } - } - /* select prf algorithm */ - if (select_algo(this->prf_algos, other->prf_algos, private, - &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, PSEUDO_RANDOM_FUNCTION, - algo, key_size); - } - } - else - { - selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable %N found", - transform_type_names, PSEUDO_RANDOM_FUNCTION); - return NULL; - } - /* select a DH-group */ - if (select_algo(this->dh_groups, other->dh_groups, private, - &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, DIFFIE_HELLMAN_GROUP, algo, 0); - } - } - else + if (!select_algo(this, other, selected, ENCRYPTION_ALGORITHM, private) || + !select_algo(this, other, selected, PSEUDO_RANDOM_FUNCTION, private) || + !select_algo(this, other, selected, INTEGRITY_ALGORITHM, private) || + !select_algo(this, other, selected, DIFFIE_HELLMAN_GROUP, private) || + !select_algo(this, other, selected, EXTENDED_SEQUENCE_NUMBERS, private)) { selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable %N found", - transform_type_names, DIFFIE_HELLMAN_GROUP); - return NULL; - } - /* select if we use ESNs (has no private use space) */ - if (select_algo(this->esns, other->esns, TRUE, &add, &algo, &key_size)) - { - if (add) - { - selected->add_algorithm(selected, EXTENDED_SEQUENCE_NUMBERS, algo, 0); - } - } - else - { - selected->destroy(selected); - DBG2(DBG_CFG, " no acceptable %N found", - transform_type_names, EXTENDED_SEQUENCE_NUMBERS); return NULL; } + DBG2(DBG_CFG, " proposal matches"); - /* apply SPI from "other" */ - selected->set_spi(selected, other->spi); + selected->set_spi(selected, other->get_spi(other)); - /* everything matched, return new proposal */ return selected; } @@ -433,50 +297,39 @@ METHOD(proposal_t, get_spi, u_int64_t, } /** - * Clone a algorithm list - */ -static void clone_algo_list(linked_list_t *list, linked_list_t *clone_list) -{ - algorithm_t *algo, *clone_algo; - enumerator_t *enumerator; - - enumerator = list->create_enumerator(list); - while (enumerator->enumerate(enumerator, &algo)) - { - clone_algo = malloc_thing(algorithm_t); - memcpy(clone_algo, algo, sizeof(algorithm_t)); - clone_list->insert_last(clone_list, (void*)clone_algo); - } - enumerator->destroy(enumerator); -} - -/** - * check if an algorithm list equals + * Check if two proposals have the same algorithms for a given transform type */ -static bool algo_list_equals(linked_list_t *l1, linked_list_t *l2) +static bool algo_list_equals(private_proposal_t *this, proposal_t *other, + transform_type_t type) { enumerator_t *e1, *e2; - algorithm_t *alg1, *alg2; + u_int16_t alg1, alg2, ks1, ks2; bool equals = TRUE; - if (l1->get_count(l1) != l2->get_count(l2)) + e1 = create_enumerator(this, type); + e2 = other->create_enumerator(other, type); + while (e1->enumerate(e1, &alg1, &ks1)) { - return FALSE; - } - - e1 = l1->create_enumerator(l1); - e2 = l2->create_enumerator(l2); - while (e1->enumerate(e1, &alg1) && e2->enumerate(e2, &alg2)) - { - if (alg1->algorithm != alg2->algorithm || - alg1->key_size != alg2->key_size) + if (!e2->enumerate(e2, &alg2, &ks2)) { + /* this has more algs */ equals = FALSE; break; } + if (alg1 != alg2 || ks1 != ks2) + { + equals = FALSE; + break; + } + } + if (e2->enumerate(e2, &alg2, ks2)) + { + /* other has more algs */ + equals = FALSE; } e1->destroy(e1); e2->destroy(e2); + return equals; } @@ -487,33 +340,35 @@ METHOD(proposal_t, get_number, u_int, } METHOD(proposal_t, equals, bool, - private_proposal_t *this, proposal_t *other_pub) + private_proposal_t *this, proposal_t *other) { - private_proposal_t *other = (private_proposal_t*)other_pub; - - if (this == other) + if (&this->public == other) { return TRUE; } return ( - algo_list_equals(this->encryption_algos, other->encryption_algos) && - algo_list_equals(this->integrity_algos, other->integrity_algos) && - algo_list_equals(this->prf_algos, other->prf_algos) && - algo_list_equals(this->dh_groups, other->dh_groups) && - algo_list_equals(this->esns, other->esns)); + algo_list_equals(this, other, ENCRYPTION_ALGORITHM) && + algo_list_equals(this, other, INTEGRITY_ALGORITHM) && + algo_list_equals(this, other, PSEUDO_RANDOM_FUNCTION) && + algo_list_equals(this, other, DIFFIE_HELLMAN_GROUP) && + algo_list_equals(this, other, EXTENDED_SEQUENCE_NUMBERS)); } METHOD(proposal_t, clone_, proposal_t*, private_proposal_t *this) { private_proposal_t *clone; + enumerator_t *enumerator; + entry_t *entry; clone = (private_proposal_t*)proposal_create(this->protocol, 0); - clone_algo_list(this->encryption_algos, clone->encryption_algos); - clone_algo_list(this->integrity_algos, clone->integrity_algos); - clone_algo_list(this->prf_algos, clone->prf_algos); - clone_algo_list(this->dh_groups, clone->dh_groups); - clone_algo_list(this->esns, clone->esns); + + enumerator = array_create_enumerator(this->transforms); + while (enumerator->enumerate(enumerator, &entry)) + { + array_insert(clone->transforms, ARRAY_TAIL, entry); + } + enumerator->destroy(enumerator); clone->spi = this->spi; clone->number = this->number; @@ -544,34 +399,40 @@ static const struct { static void check_proposal(private_proposal_t *this) { enumerator_t *e; - algorithm_t *alg; + entry_t *entry; + u_int16_t alg, ks; bool all_aead = TRUE; int i; - if (this->protocol == PROTO_IKE && - this->prf_algos->get_count(this->prf_algos) == 0) - { /* No explicit PRF found. We assume the same algorithm as used - * for integrity checking */ - e = this->integrity_algos->create_enumerator(this->integrity_algos); - while (e->enumerate(e, &alg)) + if (this->protocol == PROTO_IKE) + { + e = create_enumerator(this, PSEUDO_RANDOM_FUNCTION); + if (!e->enumerate(e, &alg, &ks)) { - for (i = 0; i < countof(integ_prf_map); i++) + /* No explicit PRF found. We assume the same algorithm as used + * for integrity checking */ + e->destroy(e); + e = create_enumerator(this, INTEGRITY_ALGORITHM); + while (e->enumerate(e, &alg, &ks)) { - if (alg->algorithm == integ_prf_map[i].integ) + for (i = 0; i < countof(integ_prf_map); i++) { - add_algorithm(this, PSEUDO_RANDOM_FUNCTION, - integ_prf_map[i].prf, 0); - break; + if (alg == integ_prf_map[i].integ) + { + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, + integ_prf_map[i].prf, 0); + break; + } } } } e->destroy(e); } - e = this->encryption_algos->create_enumerator(this->encryption_algos); - while (e->enumerate(e, &alg)) + e = create_enumerator(this, ENCRYPTION_ALGORITHM); + while (e->enumerate(e, &alg, &ks)) { - if (!encryption_algorithm_is_aead(alg->algorithm)) + if (!encryption_algorithm_is_aead(alg)) { all_aead = FALSE; break; @@ -581,24 +442,30 @@ static void check_proposal(private_proposal_t *this) if (all_aead) { - /* if all encryption algorithms in the proposal are authenticated encryption - * algorithms we MUST NOT propose any integrity algorithms */ - while (this->integrity_algos->remove_last(this->integrity_algos, - (void**)&alg) == SUCCESS) + /* if all encryption algorithms in the proposal are AEADs, + * we MUST NOT propose any integrity algorithms */ + e = array_create_enumerator(this->transforms); + while (e->enumerate(e, &entry)) { - free(alg); + if (entry->type == INTEGRITY_ALGORITHM) + { + array_remove_at(this->transforms, e); + } } + e->destroy(e); } if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP) { - e = this->esns->create_enumerator(this->esns); - if (!e->enumerate(e, &alg)) + e = create_enumerator(this, EXTENDED_SEQUENCE_NUMBERS); + if (!e->enumerate(e, NULL, NULL)) { /* ESN not specified, assume not supported */ add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0); } e->destroy(e); } + + array_compress(this->transforms); } /** @@ -704,11 +571,7 @@ int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, METHOD(proposal_t, destroy, void, private_proposal_t *this) { - this->encryption_algos->destroy_function(this->encryption_algos, free); - this->integrity_algos->destroy_function(this->integrity_algos, free); - this->prf_algos->destroy_function(this->prf_algos, free); - this->dh_groups->destroy_function(this->dh_groups, free); - this->esns->destroy_function(this->esns, free); + array_destroy(this->transforms); free(this); } @@ -737,11 +600,7 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number) }, .protocol = protocol, .number = number, - .encryption_algos = linked_list_create(), - .integrity_algos = linked_list_create(), - .prf_algos = linked_list_create(), - .dh_groups = linked_list_create(), - .esns = linked_list_create(), + .transforms = array_create(sizeof(entry_t), 0), ); return &this->public; diff --git a/src/libcharon/plugins/farp/farp_listener.c b/src/libcharon/plugins/farp/farp_listener.c index 81d5d2405..87c84359c 100644 --- a/src/libcharon/plugins/farp/farp_listener.c +++ b/src/libcharon/plugins/farp/farp_listener.c @@ -58,19 +58,30 @@ METHOD(listener_t, child_updown, bool, bool up) { enumerator_t *enumerator; + traffic_selector_t *ts; entry_t *entry; if (up) { INIT(entry, - .local = child_sa->get_traffic_selectors(child_sa, TRUE), - .remote = child_sa->get_traffic_selectors(child_sa, FALSE), + .local = linked_list_create(), + .remote = linked_list_create(), .reqid = child_sa->get_reqid(child_sa), ); - entry->local = entry->local->clone_offset(entry->local, - offsetof(traffic_selector_t, clone)); - entry->remote = entry->remote->clone_offset(entry->remote, - offsetof(traffic_selector_t, clone)); + + enumerator = child_sa->create_ts_enumerator(child_sa, TRUE); + while (enumerator->enumerate(enumerator, &ts)) + { + entry->local->insert_last(entry->local, ts->clone(ts)); + } + enumerator->destroy(enumerator); + + enumerator = child_sa->create_ts_enumerator(child_sa, FALSE); + while (enumerator->enumerate(enumerator, &ts)) + { + entry->remote->insert_last(entry->remote, ts->clone(ts)); + } + enumerator->destroy(enumerator); this->lock->write_lock(this->lock); this->entries->insert_last(this->entries, entry); @@ -160,4 +171,3 @@ farp_listener_t *farp_listener_create() return &this->public; } - diff --git a/src/libcharon/plugins/ha/ha_child.c b/src/libcharon/plugins/ha/ha_child.c index 707add94d..c166d72ac 100644 --- a/src/libcharon/plugins/ha/ha_child.c +++ b/src/libcharon/plugins/ha/ha_child.c @@ -103,18 +103,22 @@ METHOD(listener_t, child_keys, bool, chunk_clear(&secret); } - local_ts = child_sa->get_traffic_selectors(child_sa, TRUE); - enumerator = local_ts->create_enumerator(local_ts); + local_ts = linked_list_create(); + remote_ts = linked_list_create(); + + enumerator = child_sa->create_ts_enumerator(child_sa, TRUE); while (enumerator->enumerate(enumerator, &ts)) { m->add_attribute(m, HA_LOCAL_TS, ts); + local_ts->insert_last(local_ts, ts); } enumerator->destroy(enumerator); - remote_ts = child_sa->get_traffic_selectors(child_sa, FALSE); - enumerator = remote_ts->create_enumerator(remote_ts); + + enumerator = child_sa->create_ts_enumerator(child_sa, FALSE); while (enumerator->enumerate(enumerator, &ts)) { m->add_attribute(m, HA_REMOTE_TS, ts); + remote_ts->insert_last(remote_ts, ts); } enumerator->destroy(enumerator); @@ -128,6 +132,9 @@ METHOD(listener_t, child_keys, bool, seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "", seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : ""); + local_ts->destroy(local_ts); + remote_ts->destroy(remote_ts); + this->socket->push(this->socket, m); m->destroy(m); @@ -195,4 +202,3 @@ ha_child_t *ha_child_create(ha_socket_t *socket, ha_tunnel_t *tunnel, return &this->public; } - diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c index d13b82216..123608819 100644 --- a/src/libcharon/plugins/smp/smp.c +++ b/src/libcharon/plugins/smp/smp.c @@ -165,8 +165,10 @@ static void write_childend(xmlTextWriterPtr writer, child_sa_t *child, bool loca xmlTextWriterWriteFormatElement(writer, "spi", "%x", htonl(child->get_spi(child, local))); - list = child->get_traffic_selectors(child, local); + list = linked_list_create_from_enumerator( + child->create_ts_enumerator(child, local)); write_networks(writer, "networks", list); + list->destroy(list); } /** diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index e76afec68..e81f3fc32 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -207,8 +207,10 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) time_t use_in, use_out, rekey, now; u_int64_t bytes_in, bytes_out, packets_in, packets_out; proposal_t *proposal; - child_cfg_t *config = child_sa->get_config(child_sa); + linked_list_t *my_ts, *other_ts; + child_cfg_t *config; + config = child_sa->get_config(child_sa); now = time_monotonic(NULL); fprintf(out, "%12s{%d}: %N, %N%s", @@ -319,10 +321,15 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) fprintf(out, ", expires in %V", &now, &rekey); } + my_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, TRUE)); + other_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, FALSE)); fprintf(out, "\n%12s{%d}: %#R=== %#R\n", child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); + my_ts, other_ts); + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); } /** diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c index 53221b786..cebc389e7 100644 --- a/src/libcharon/plugins/uci/uci_control.c +++ b/src/libcharon/plugins/uci/uci_control.c @@ -72,6 +72,7 @@ static void write_fifo(private_uci_control_t *this, char *format, ...) static void status(private_uci_control_t *this, char *name) { enumerator_t *configs, *sas, *children; + linked_list_t *list; ike_sa_t *ike_sa; child_sa_t *child_sa; peer_cfg_t *peer_cfg; @@ -108,8 +109,10 @@ static void status(private_uci_control_t *this, char *name) children = ike_sa->create_child_sa_enumerator(ike_sa); while (children->enumerate(children, (void**)&child_sa)) { - fprintf(out, "%#R", - child_sa->get_traffic_selectors(child_sa, FALSE)); + list = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, FALSE)); + fprintf(out, "%#R", list); + list->destroy(list); } children->destroy(children); fprintf(out, "\n"); @@ -296,4 +299,3 @@ uci_control_t *uci_control_create() } return &this->public; } - diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index 1069b2d91..46e4b6f7b 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -25,6 +25,7 @@ #include <hydra.h> #include <daemon.h> +#include <collections/array.h> ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING, "CREATED", @@ -79,14 +80,14 @@ struct private_child_sa_t { u_int16_t other_cpi; /** - * List for local traffic selectors + * Array for local traffic selectors */ - linked_list_t *my_ts; + array_t *my_ts; /** - * List for remote traffic selectors + * Array for remote traffic selectors */ - linked_list_t *other_ts; + array_t *other_ts; /** * Protocol used to protect this SA, ESP|AH @@ -331,10 +332,14 @@ METHOD(child_sa_t, set_proposal, void, this->proposal = proposal->clone(proposal); } -METHOD(child_sa_t, get_traffic_selectors, linked_list_t*, - private_child_sa_t *this, bool local) +METHOD(child_sa_t, create_ts_enumerator, enumerator_t*, + private_child_sa_t *this, bool local) { - return local ? this->my_ts : this->other_ts; + if (local) + { + return array_create_enumerator(this->my_ts); + } + return array_create_enumerator(this->other_ts); } typedef struct policy_enumerator_t policy_enumerator_t; @@ -349,8 +354,8 @@ struct policy_enumerator_t { enumerator_t *mine; /** enumerator over others TS */ enumerator_t *other; - /** list of others TS, to recreate enumerator */ - linked_list_t *list; + /** array of others TS, to recreate enumerator */ + array_t *array; /** currently enumerating TS for "me" side */ traffic_selector_t *ts; }; @@ -366,7 +371,7 @@ METHOD(enumerator_t, policy_enumerate, bool, if (!this->other->enumerate(this->other, &other_ts)) { /* end of others list, restart with new of mine */ this->other->destroy(this->other); - this->other = this->list->create_enumerator(this->list); + this->other = array_create_enumerator(this->array); this->ts = NULL; continue; } @@ -405,9 +410,9 @@ METHOD(child_sa_t, create_policy_enumerator, enumerator_t*, .enumerate = (void*)_policy_enumerate, .destroy = _policy_destroy, }, - .mine = this->my_ts->create_enumerator(this->my_ts), - .other = this->other_ts->create_enumerator(this->other_ts), - .list = this->other_ts, + .mine = array_create_enumerator(this->my_ts), + .other = array_create_enumerator(this->other_ts), + .array = this->other_ts, .ts = NULL, ); @@ -772,13 +777,13 @@ METHOD(child_sa_t, add_policies, status_t, enumerator = my_ts_list->create_enumerator(my_ts_list); while (enumerator->enumerate(enumerator, &my_ts)) { - this->my_ts->insert_last(this->my_ts, my_ts->clone(my_ts)); + array_insert(this->my_ts, ARRAY_TAIL, my_ts->clone(my_ts)); } enumerator->destroy(enumerator); enumerator = other_ts_list->create_enumerator(other_ts_list); while (enumerator->enumerate(enumerator, &other_ts)) { - this->other_ts->insert_last(this->other_ts, other_ts->clone(other_ts)); + array_insert(this->other_ts, ARRAY_TAIL, other_ts->clone(other_ts)); } enumerator->destroy(enumerator); @@ -1069,8 +1074,8 @@ METHOD(child_sa_t, destroy, void, enumerator->destroy(enumerator); } - this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy)); - this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy)); + array_destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy)); + array_destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy)); this->my_addr->destroy(this->my_addr); this->other_addr->destroy(this->other_addr); DESTROY_IF(this->proposal); @@ -1079,6 +1084,41 @@ METHOD(child_sa_t, destroy, void, } /** + * Get proxy address for one side, if any + */ +static host_t* get_proxy_addr(child_cfg_t *config, host_t *ike, bool local) +{ + host_t *host = NULL; + u_int8_t mask; + enumerator_t *enumerator; + linked_list_t *ts_list, *list; + traffic_selector_t *ts; + + list = linked_list_create_with_items(ike, NULL); + ts_list = config->get_traffic_selectors(config, local, NULL, list); + list->destroy(list); + + enumerator = ts_list->create_enumerator(ts_list); + while (enumerator->enumerate(enumerator, &ts)) + { + if (ts->is_host(ts, NULL) && ts->to_subnet(ts, &host, &mask)) + { + DBG1(DBG_CHD, "%s address: %H is a transport mode proxy for %H", + local ? "my" : "other", ike, host); + break; + } + } + enumerator->destroy(enumerator); + ts_list->destroy_offset(ts_list, offsetof(traffic_selector_t, destroy)); + + if (!host) + { + host = ike->clone(ike); + } + return host; +} + +/** * Described in header. */ child_sa_t * child_sa_create(host_t *me, host_t* other, @@ -1117,17 +1157,15 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, .install = _install, .update = _update, .add_policies = _add_policies, - .get_traffic_selectors = _get_traffic_selectors, + .create_ts_enumerator = _create_ts_enumerator, .create_policy_enumerator = _create_policy_enumerator, .destroy = _destroy, }, - .my_addr = me->clone(me), - .other_addr = other->clone(other), .encap = encap, .ipcomp = IPCOMP_NONE, .state = CHILD_CREATED, - .my_ts = linked_list_create(), - .other_ts = linked_list_create(), + .my_ts = array_create(0, 0), + .other_ts = array_create(0, 0), .protocol = PROTO_NONE, .mode = MODE_TUNNEL, .close_action = config->get_close_action(config), @@ -1170,62 +1208,15 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, if (config->get_mode(config) == MODE_TRANSPORT && config->use_proxy_mode(config)) { - ts_type_t type; - int family; - chunk_t addr; - host_t *host; - enumerator_t *enumerator; - linked_list_t *my_ts_list, *other_ts_list, *list; - traffic_selector_t *my_ts, *other_ts; - this->mode = MODE_TRANSPORT; - list = linked_list_create_with_items(me, NULL); - my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, list); - list->destroy(list); - enumerator = my_ts_list->create_enumerator(my_ts_list); - if (enumerator->enumerate(enumerator, &my_ts)) - { - if (my_ts->is_host(my_ts, NULL) && - !my_ts->is_host(my_ts, this->my_addr)) - { - type = my_ts->get_type(my_ts); - family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6; - addr = my_ts->get_from_address(my_ts); - host = host_create_from_chunk(family, addr, 0); - free(addr.ptr); - DBG1(DBG_CHD, "my address: %H is a transport mode proxy for %H", - this->my_addr, host); - this->my_addr->destroy(this->my_addr); - this->my_addr = host; - } - } - enumerator->destroy(enumerator); - my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy)); - - list = linked_list_create_with_items(other, NULL); - other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, list); - list->destroy(list); - enumerator = other_ts_list->create_enumerator(other_ts_list); - if (enumerator->enumerate(enumerator, &other_ts)) - { - if (other_ts->is_host(other_ts, NULL) && - !other_ts->is_host(other_ts, this->other_addr)) - { - type = other_ts->get_type(other_ts); - family = (type == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6; - addr = other_ts->get_from_address(other_ts); - host = host_create_from_chunk(family, addr, 0); - free(addr.ptr); - DBG1(DBG_CHD, "other address: %H is a transport mode proxy for %H", - this->other_addr, host); - this->other_addr->destroy(this->other_addr); - this->other_addr = host; - } - } - enumerator->destroy(enumerator); - other_ts_list->destroy_offset(other_ts_list, offsetof(traffic_selector_t, destroy)); + this->my_addr = get_proxy_addr(config, me, TRUE); + this->other_addr = get_proxy_addr(config, other, FALSE); + } + else + { + this->my_addr = me->clone(me); + this->other_addr = other->clone(other); } - return &this->public; } diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h index aa44dbfad..44c529391 100644 --- a/src/libcharon/sa/child_sa.h +++ b/src/libcharon/sa/child_sa.h @@ -284,17 +284,20 @@ struct child_sa_t { mark_t (*get_mark)(child_sa_t *this, bool inbound); /** - * Get the traffic selectors list added for one side. + * Create an enumerator over traffic selectors of one side. * - * @param local TRUE for own traffic selectors, FALSE for remote - * @return list of traffic selectors + * @param local TRUE for own traffic selectors, FALSE for remote. + * @return enumerator over traffic_selector_t* */ - linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local); + enumerator_t* (*create_ts_enumerator)(child_sa_t *this, bool local); /** * Create an enumerator over installed policies. * - * @return enumerator over pairs of traffic selectors. + * The enumerated traffic selectors is a full mesh of compatible local + * and remote traffic selectors. + * + * @return enumerator over a pair of traffic_selector_t* */ enumerator_t* (*create_policy_enumerator)(child_sa_t *this); diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 19c6248ec..50d969430 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -26,7 +26,7 @@ #include <library.h> #include <hydra.h> #include <daemon.h> -#include <collections/linked_list.h> +#include <collections/array.h> #include <utils/lexparser.h> #include <processing/jobs/retransmit_job.h> #include <processing/jobs/delete_ike_sa_job.h> @@ -95,24 +95,24 @@ struct private_ike_sa_t { peer_cfg_t *peer_cfg; /** - * currently used authentication ruleset, local (as auth_cfg_t) + * currently used authentication ruleset, local */ auth_cfg_t *my_auth; /** - * list of completed local authentication rounds + * currently used authentication constraints, remote */ - linked_list_t *my_auths; + auth_cfg_t *other_auth; /** - * list of completed remote authentication rounds + * Array of completed local authentication rounds (as auth_cfg_t) */ - linked_list_t *other_auths; + array_t *my_auths; /** - * currently used authentication constraints, remote (as auth_cfg_t) + * Array of completed remote authentication rounds (as auth_cfg_t) */ - auth_cfg_t *other_auth; + array_t *other_auths; /** * Selected IKE proposal @@ -172,9 +172,9 @@ struct private_ike_sa_t { ike_condition_t conditions; /** - * Linked List containing the child sa's of the current IKE_SA. + * Array containing the child sa's of the current IKE_SA. */ - linked_list_t *child_sas; + array_t *child_sas; /** * keymat of this IKE_SA @@ -184,22 +184,22 @@ struct private_ike_sa_t { /** * Virtual IPs on local host */ - linked_list_t *my_vips; + array_t *my_vips; /** * Virtual IPs on remote host */ - linked_list_t *other_vips; + array_t *other_vips; /** * List of configuration attributes (attribute_entry_t) */ - linked_list_t *attributes; + array_t *attributes; /** * list of peer's addresses, additional ones transmitted via MOBIKE */ - linked_list_t *peer_addresses; + array_t *peer_addresses; /** * previously value of received DESTINATION_IP hash @@ -282,7 +282,8 @@ static time_t get_use_time(private_ike_sa_t* this, bool inbound) { use_time = this->stats[STAT_OUTBOUND]; } - enumerator = this->child_sas->create_enumerator(this->child_sas); + + enumerator = array_create_enumerator(this->child_sas); while (enumerator->enumerate(enumerator, &child_sa)) { child_sa->get_usestats(child_sa, inbound, ¤t, NULL, NULL); @@ -389,11 +390,11 @@ METHOD(ike_sa_t, add_auth_cfg, void, { if (local) { - this->my_auths->insert_last(this->my_auths, cfg); + array_insert(this->my_auths, ARRAY_TAIL, cfg); } else { - this->other_auths->insert_last(this->other_auths, cfg); + array_insert(this->other_auths, ARRAY_TAIL, cfg); } } @@ -402,9 +403,9 @@ METHOD(ike_sa_t, create_auth_cfg_enumerator, enumerator_t*, { if (local) { - return this->my_auths->create_enumerator(this->my_auths); + return array_create_enumerator(this->my_auths); } - return this->other_auths->create_enumerator(this->other_auths); + return array_create_enumerator(this->other_auths); } /** @@ -417,13 +418,11 @@ static void flush_auth_cfgs(private_ike_sa_t *this) this->my_auth->purge(this->my_auth, FALSE); this->other_auth->purge(this->other_auth, FALSE); - while (this->my_auths->remove_last(this->my_auths, - (void**)&cfg) == SUCCESS) + while (array_remove(this->my_auths, ARRAY_TAIL, &cfg)) { cfg->destroy(cfg); } - while (this->other_auths->remove_last(this->other_auths, - (void**)&cfg) == SUCCESS) + while (array_remove(this->other_auths, ARRAY_TAIL, &cfg)) { cfg->destroy(cfg); } @@ -750,7 +749,7 @@ METHOD(ike_sa_t, add_virtual_ip, void, if (hydra->kernel_interface->add_ip(hydra->kernel_interface, ip, -1, iface) == SUCCESS) { - this->my_vips->insert_last(this->my_vips, ip->clone(ip)); + array_insert_create(&this->my_vips, ARRAY_TAIL, ip->clone(ip)); } else { @@ -765,7 +764,7 @@ METHOD(ike_sa_t, add_virtual_ip, void, } else { - this->other_vips->insert_last(this->other_vips, ip->clone(ip)); + array_insert_create(&this->other_vips, ARRAY_TAIL, ip->clone(ip)); } } @@ -773,14 +772,15 @@ 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; + array_t *vips; host_t *vip; - if (!local && vips->get_count(vips)) + vips = local ? this->my_vips : this->other_vips; + if (!local && array_count(vips)) { charon->bus->assign_vips(charon->bus, &this->public, FALSE); } - while (vips->remove_first(vips, (void**)&vip) == SUCCESS) + while (array_remove(vips, ARRAY_HEAD, &vip)) { if (local) { @@ -796,23 +796,23 @@ METHOD(ike_sa_t, create_virtual_ip_enumerator, enumerator_t*, { if (local) { - return this->my_vips->create_enumerator(this->my_vips); + return array_create_enumerator(this->my_vips); } - return this->other_vips->create_enumerator(this->other_vips); + return array_create_enumerator(this->other_vips); } METHOD(ike_sa_t, add_peer_address, void, private_ike_sa_t *this, host_t *host) { - this->peer_addresses->insert_last(this->peer_addresses, host); + array_insert_create(&this->peer_addresses, ARRAY_TAIL, host); } METHOD(ike_sa_t, create_peer_address_enumerator, enumerator_t*, private_ike_sa_t *this) { - if (this->peer_addresses->get_count(this->peer_addresses)) + if (this->peer_addresses) { - return this->peer_addresses->create_enumerator(this->peer_addresses); + return array_create_enumerator(this->peer_addresses); } /* in case we don't have MOBIKE */ return enumerator_create_single(this->other_host, NULL); @@ -821,17 +821,8 @@ METHOD(ike_sa_t, create_peer_address_enumerator, enumerator_t*, METHOD(ike_sa_t, clear_peer_addresses, void, private_ike_sa_t *this) { - enumerator_t *enumerator; - host_t *host; - - enumerator = this->peer_addresses->create_enumerator(this->peer_addresses); - while (enumerator->enumerate(enumerator, (void**)&host)) - { - this->peer_addresses->remove_at(this->peer_addresses, - enumerator); - host->destroy(host); - } - enumerator->destroy(enumerator); + array_destroy_offset(this->peer_addresses, offsetof(host_t, destroy)); + this->peer_addresses = NULL; } METHOD(ike_sa_t, has_mapping_changed, bool, @@ -927,13 +918,16 @@ METHOD(ike_sa_t, update_hosts, void, { enumerator_t *enumerator; child_sa_t *child_sa; + linked_list_t *vips; - enumerator = this->child_sas->create_enumerator(this->child_sas); - while (enumerator->enumerate(enumerator, (void**)&child_sa)) + vips = linked_list_create_from_enumerator( + array_create_enumerator(this->my_vips)); + + enumerator = array_create_enumerator(this->child_sas); + while (enumerator->enumerate(enumerator, &child_sa)) { - if (child_sa->update(child_sa, this->my_host, - this->other_host, this->my_vips, - has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED) + if (child_sa->update(child_sa, this->my_host, this->other_host, + vips, has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED) { this->public.rekey_child_sa(&this->public, child_sa->get_protocol(child_sa), @@ -941,6 +935,8 @@ METHOD(ike_sa_t, update_hosts, void, } } enumerator->destroy(enumerator); + + vips->destroy(vips); } } @@ -1326,7 +1322,7 @@ METHOD(ike_sa_t, get_other_eap_id, identification_t*, enumerator_t *enumerator; auth_cfg_t *cfg; - enumerator = this->other_auths->create_enumerator(this->other_auths); + enumerator = array_create_enumerator(this->other_auths); while (enumerator->enumerate(enumerator, &cfg)) { /* prefer EAP-Identity of last round */ @@ -1363,7 +1359,7 @@ METHOD(ike_sa_t, set_other_id, void, METHOD(ike_sa_t, add_child_sa, void, private_ike_sa_t *this, child_sa_t *child_sa) { - this->child_sas->insert_last(this->child_sas, child_sa); + array_insert_create(&this->child_sas, ARRAY_TAIL, child_sa); } METHOD(ike_sa_t, get_child_sa, child_sa_t*, @@ -1372,7 +1368,7 @@ METHOD(ike_sa_t, get_child_sa, child_sa_t*, enumerator_t *enumerator; child_sa_t *current, *found = NULL; - enumerator = this->child_sas->create_enumerator(this->child_sas); + enumerator = array_create_enumerator(this->child_sas); while (enumerator->enumerate(enumerator, (void**)¤t)) { if (current->get_spi(current, inbound) == spi && @@ -1388,19 +1384,19 @@ METHOD(ike_sa_t, get_child_sa, child_sa_t*, METHOD(ike_sa_t, get_child_count, int, private_ike_sa_t *this) { - return this->child_sas->get_count(this->child_sas); + return array_count(this->child_sas); } METHOD(ike_sa_t, create_child_sa_enumerator, enumerator_t*, private_ike_sa_t *this) { - return this->child_sas->create_enumerator(this->child_sas); + return array_create_enumerator(this->child_sas); } METHOD(ike_sa_t, remove_child_sa, void, private_ike_sa_t *this, enumerator_t *enumerator) { - this->child_sas->remove_at(this->child_sas, enumerator); + array_remove_at(this->child_sas, enumerator); } METHOD(ike_sa_t, rekey_child_sa, status_t, @@ -1433,13 +1429,13 @@ METHOD(ike_sa_t, destroy_child_sa, status_t, child_sa_t *child_sa; status_t status = NOT_FOUND; - enumerator = this->child_sas->create_enumerator(this->child_sas); + enumerator = array_create_enumerator(this->child_sas); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { if (child_sa->get_protocol(child_sa) == protocol && child_sa->get_spi(child_sa, TRUE) == spi) { - this->child_sas->remove_at(this->child_sas, enumerator); + array_remove_at(this->child_sas, enumerator); child_sa->destroy(child_sa); status = SUCCESS; break; @@ -1506,7 +1502,7 @@ METHOD(ike_sa_t, reauth, status_t, if (!has_condition(this, COND_ORIGINAL_INITIATOR)) { DBG1(DBG_IKE, "initiator did not reauthenticate as requested"); - if (this->other_vips->get_count(this->other_vips) != 0 || + if (array_count(this->other_vips) != 0 || has_condition(this, COND_XAUTH_AUTHENTICATED) || has_condition(this, COND_EAP_AUTHENTICATED) #ifdef ME @@ -1553,7 +1549,7 @@ METHOD(ike_sa_t, reestablish, status_t, if (has_condition(this, COND_REAUTHENTICATING)) { /* only reauthenticate if we have children */ - if (this->child_sas->get_count(this->child_sas) == 0 + if (array_count(this->child_sas) == 0 #ifdef ME /* allow reauth of mediation connections without CHILD_SAs */ && !this->peer_cfg->is_mediation(this->peer_cfg) @@ -1570,7 +1566,7 @@ METHOD(ike_sa_t, reestablish, status_t, } else { /* check if we have children to keep up at all */ - enumerator = this->child_sas->create_enumerator(this->child_sas); + enumerator = array_create_enumerator(this->child_sas); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { if (this->state == IKE_DELETING) @@ -1611,7 +1607,7 @@ METHOD(ike_sa_t, reestablish, status_t, /* check if we are able to reestablish this IKE_SA */ if (!has_condition(this, COND_ORIGINAL_INITIATOR) && - (this->other_vips->get_count(this->other_vips) != 0 || + (array_count(this->other_vips) != 0 || has_condition(this, COND_EAP_AUTHENTICATED) #ifdef ME || this->is_mediation_server @@ -1634,7 +1630,7 @@ METHOD(ike_sa_t, reestablish, status_t, host = this->my_host; new->set_my_host(new, host->clone(host)); /* if we already have a virtual IP, we reuse it */ - enumerator = this->my_vips->create_enumerator(this->my_vips); + enumerator = array_create_enumerator(this->my_vips); while (enumerator->enumerate(enumerator, &host)) { new->add_virtual_ip(new, TRUE, host); @@ -1649,7 +1645,7 @@ METHOD(ike_sa_t, reestablish, status_t, else #endif /* ME */ { - enumerator = this->child_sas->create_enumerator(this->child_sas); + enumerator = array_create_enumerator(this->child_sas); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { if (has_condition(this, COND_REAUTHENTICATING)) @@ -1658,7 +1654,7 @@ METHOD(ike_sa_t, reestablish, status_t, { case CHILD_ROUTED: { /* move routed child directly */ - this->child_sas->remove_at(this->child_sas, enumerator); + array_remove_at(this->child_sas, enumerator); new->add_child_sa(new, child_sa); action = ACTION_NONE; break; @@ -1789,7 +1785,7 @@ METHOD(ike_sa_t, set_auth_lifetime, status_t, * We send the notify in IKE_AUTH if not yet ESTABLISHED. */ send_update = this->state == IKE_ESTABLISHED && this->version == IKEV2 && !has_condition(this, COND_ORIGINAL_INITIATOR) && - (this->other_vips->get_count(this->other_vips) != 0 || + (array_count(this->other_vips) != 0 || has_condition(this, COND_EAP_AUTHENTICATED)); if (lifetime < diff) @@ -1963,13 +1959,12 @@ METHOD(ike_sa_t, add_configuration_attribute, void, private_ike_sa_t *this, attribute_handler_t *handler, configuration_attribute_type_t type, chunk_t data) { - attribute_entry_t *entry = malloc_thing(attribute_entry_t); - - entry->handler = handler; - entry->type = type; - entry->data = chunk_clone(data); - - this->attributes->insert_last(this->attributes, entry); + attribute_entry_t entry = { + .handler = handler, + .type = type, + .data = chunk_clone(data), + }; + array_insert(this->attributes, ARRAY_TAIL, &entry); } METHOD(ike_sa_t, create_task_enumerator, enumerator_t*, @@ -1995,8 +1990,8 @@ METHOD(ike_sa_t, inherit, void, { private_ike_sa_t *other = (private_ike_sa_t*)other_public; child_sa_t *child_sa; - attribute_entry_t *entry; enumerator_t *enumerator; + attribute_entry_t entry; auth_cfg_t *cfg; host_t *vip; @@ -2011,35 +2006,33 @@ METHOD(ike_sa_t, inherit, void, this->other_id = other->other_id->clone(other->other_id); /* apply assigned virtual IPs... */ - while (other->my_vips->remove_last(other->my_vips, (void**)&vip) == SUCCESS) + while (array_remove(other->my_vips, ARRAY_HEAD, &vip)) { - this->my_vips->insert_first(this->my_vips, vip); + array_insert_create(&this->my_vips, ARRAY_TAIL, vip); } - while (other->other_vips->remove_last(other->other_vips, - (void**)&vip) == SUCCESS) + while (array_remove(other->other_vips, ARRAY_HEAD, &vip)) { - this->other_vips->insert_first(this->other_vips, vip); + array_insert_create(&this->other_vips, ARRAY_TAIL, vip); } /* authentication information */ - enumerator = other->my_auths->create_enumerator(other->my_auths); + enumerator = array_create_enumerator(other->my_auths); while (enumerator->enumerate(enumerator, &cfg)) { - this->my_auths->insert_last(this->my_auths, cfg->clone(cfg)); + array_insert(this->my_auths, ARRAY_TAIL, cfg->clone(cfg)); } enumerator->destroy(enumerator); - enumerator = other->other_auths->create_enumerator(other->other_auths); + enumerator = array_create_enumerator(other->other_auths); while (enumerator->enumerate(enumerator, &cfg)) { - this->other_auths->insert_last(this->other_auths, cfg->clone(cfg)); + array_insert(this->other_auths, ARRAY_TAIL, cfg->clone(cfg)); } enumerator->destroy(enumerator); /* ... and configuration attributes */ - while (other->attributes->remove_last(other->attributes, - (void**)&entry) == SUCCESS) + while (array_remove(other->attributes, ARRAY_HEAD, &entry)) { - this->attributes->insert_first(this->attributes, entry); + array_insert(this->attributes, ARRAY_TAIL, &entry); } /* inherit all conditions */ @@ -2062,10 +2055,9 @@ METHOD(ike_sa_t, inherit, void, #endif /* ME */ /* adopt all children */ - while (other->child_sas->remove_last(other->child_sas, - (void**)&child_sa) == SUCCESS) + while (array_remove(other->child_sas, ARRAY_HEAD, &child_sa)) { - this->child_sas->insert_first(this->child_sas, (void*)child_sa); + array_insert_create(&this->child_sas, ARRAY_TAIL, child_sa); } /* move pending tasks to the new IKE_SA */ @@ -2092,7 +2084,7 @@ METHOD(ike_sa_t, inherit, void, METHOD(ike_sa_t, destroy, void, private_ike_sa_t *this) { - attribute_entry_t *entry; + attribute_entry_t entry; host_t *vip; charon->bus->set_sa(charon->bus, &this->public); @@ -2101,25 +2093,22 @@ METHOD(ike_sa_t, destroy, void, DESTROY_IF(this->task_manager); /* remove attributes first, as we pass the IKE_SA to the handler */ - while (this->attributes->remove_last(this->attributes, - (void**)&entry) == SUCCESS) + while (array_remove(this->attributes, ARRAY_TAIL, &entry)) { - hydra->attributes->release(hydra->attributes, entry->handler, - this->other_id, entry->type, entry->data); - free(entry->data.ptr); - free(entry); + hydra->attributes->release(hydra->attributes, entry.handler, + this->other_id, entry.type, entry.data); + free(entry.data.ptr); } - while (this->my_vips->remove_last(this->my_vips, (void**)&vip) == SUCCESS) + while (array_remove(this->my_vips, ARRAY_TAIL, &vip)) { hydra->kernel_interface->del_ip(hydra->kernel_interface, vip, -1, TRUE); vip->destroy(vip); } - if (this->other_vips->get_count(this->other_vips)) + if (array_count(this->other_vips)) { charon->bus->assign_vips(charon->bus, &this->public, FALSE); } - while (this->other_vips->remove_last(this->other_vips, - (void**)&vip) == SUCCESS) + while (array_remove(this->other_vips, ARRAY_TAIL, &vip)) { if (this->peer_cfg) { @@ -2138,13 +2127,12 @@ METHOD(ike_sa_t, destroy, void, /* unset SA after here to avoid usage by the listeners */ charon->bus->set_sa(charon->bus, NULL); - this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy)); + array_destroy_offset(this->child_sas, offsetof(child_sa_t, destroy)); DESTROY_IF(this->keymat); - this->attributes->destroy(this->attributes); - this->my_vips->destroy(this->my_vips); - this->other_vips->destroy(this->other_vips); - this->peer_addresses->destroy_offset(this->peer_addresses, - offsetof(host_t, destroy)); + array_destroy(this->attributes); + array_destroy(this->my_vips); + array_destroy(this->other_vips); + array_destroy_offset(this->peer_addresses, offsetof(host_t, destroy)); #ifdef ME if (this->is_mediation_server) { @@ -2168,10 +2156,8 @@ METHOD(ike_sa_t, destroy, void, DESTROY_IF(this->proposal); this->my_auth->destroy(this->my_auth); this->other_auth->destroy(this->other_auth); - this->my_auths->destroy_offset(this->my_auths, - offsetof(auth_cfg_t, destroy)); - this->other_auths->destroy_offset(this->other_auths, - offsetof(auth_cfg_t, destroy)); + array_destroy_offset(this->my_auths, offsetof(auth_cfg_t, destroy)); + array_destroy_offset(this->other_auths, offsetof(auth_cfg_t, destroy)); this->ike_sa_id->destroy(this->ike_sa_id); free(this); @@ -2283,7 +2269,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, }, .ike_sa_id = ike_sa_id->clone(ike_sa_id), .version = version, - .child_sas = linked_list_create(), .my_host = host_create_any(AF_INET), .other_host = host_create_any(AF_INET), .my_id = identification_create_from_encoding(ID_ANY, chunk_empty), @@ -2294,13 +2279,10 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, .stats[STAT_OUTBOUND] = time_monotonic(NULL), .my_auth = auth_cfg_create(), .other_auth = auth_cfg_create(), - .my_auths = linked_list_create(), - .other_auths = linked_list_create(), + .my_auths = array_create(0, 0), + .other_auths = array_create(0, 0), + .attributes = array_create(sizeof(attribute_entry_t), 0), .unique_id = ref_get(&unique_id), - .peer_addresses = linked_list_create(), - .my_vips = linked_list_create(), - .other_vips = linked_list_create(), - .attributes = linked_list_create(), .keepalive_interval = lib->settings->get_time(lib->settings, "%s.keep_alive", KEEPALIVE_INTERVAL, charon->name), .retry_initiate_interval = lib->settings->get_time(lib->settings, diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 709033cb5..bfa6fc81e 100644 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -1753,21 +1753,22 @@ METHOD(task_manager_t, queue_child, void, /** * Check if two CHILD_SAs have the same traffic selector */ -static bool have_equal_ts(child_sa_t *a, child_sa_t *b, bool local) +static bool have_equal_ts(child_sa_t *child1, child_sa_t *child2, bool local) { - linked_list_t *list; - traffic_selector_t *ts_a, *ts_b; + enumerator_t *e1, *e2; + traffic_selector_t *ts1, *ts2; + bool equal = FALSE; - list = a->get_traffic_selectors(a, local); - if (list->get_first(list, (void**)&ts_a) == SUCCESS) + e1 = child1->create_ts_enumerator(child1, local); + e2 = child2->create_ts_enumerator(child2, local); + if (e1->enumerate(e1, &ts1) && e2->enumerate(e2, &ts2)) { - list = b->get_traffic_selectors(b, local); - if (list->get_first(list, (void**)&ts_b) == SUCCESS) - { - return ts_a->equals(ts_a, ts_b); - } + equal = ts1->equals(ts1, ts2); } - return FALSE; + e1->destroy(e1); + e1->destroy(e1); + + return equal; } /** @@ -1806,14 +1807,13 @@ static bool is_redundant(private_task_manager_t *this, child_sa_t *child_sa) static traffic_selector_t* get_first_ts(child_sa_t *child_sa, bool local) { traffic_selector_t *ts = NULL; - linked_list_t *list; + enumerator_t *enumerator; - list = child_sa->get_traffic_selectors(child_sa, local); - if (list->get_first(list, (void**)&ts) == SUCCESS) - { - return ts; - } - return NULL; + enumerator = child_sa->create_ts_enumerator(child_sa, local); + enumerator->enumerate(enumerator, &ts); + enumerator->destroy(enumerator); + + return ts; } METHOD(task_manager_t, queue_child_rekey, void, diff --git a/src/libcharon/sa/ikev1/tasks/quick_delete.c b/src/libcharon/sa/ikev1/tasks/quick_delete.c index e9f06cbe3..5b3e35ed3 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_delete.c +++ b/src/libcharon/sa/ikev1/tasks/quick_delete.c @@ -69,6 +69,7 @@ static bool delete_child(private_quick_delete_t *this, { u_int64_t bytes_in, bytes_out; child_sa_t *child_sa; + linked_list_t *my_ts, *other_ts; bool rekeyed; child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE); @@ -85,15 +86,17 @@ static bool delete_child(private_quick_delete_t *this, rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYING; child_sa->set_state(child_sa, CHILD_DELETING); + my_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, TRUE)); + other_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, FALSE)); if (this->expired) { DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), - ntohl(child_sa->get_spi(child_sa, FALSE)), - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); + ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts); } else { @@ -105,9 +108,10 @@ static bool delete_child(private_quick_delete_t *this, child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); + my_ts, other_ts); } + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); if (!rekeyed) { diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index 52ea34b1a..92df0f0f8 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -259,7 +259,7 @@ static bool install(private_quick_mode_t *this) { status_t status, status_i, status_o; chunk_t encr_i, encr_r, integ_i, integ_r; - linked_list_t *tsi, *tsr; + linked_list_t *tsi, *tsr, *my_ts, *other_ts; child_sa_t *old = NULL; this->child_sa->set_proposal(this->child_sa, this->proposal); @@ -362,14 +362,20 @@ static bool install(private_quick_mode_t *this) this->child_sa->set_state(this->child_sa, CHILD_INSTALLED); this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); + my_ts = linked_list_create_from_enumerator( + this->child_sa->create_ts_enumerator(this->child_sa, TRUE)); + other_ts = linked_list_create_from_enumerator( + this->child_sa->create_ts_enumerator(this->child_sa, FALSE)); + DBG0(DBG_IKE, "CHILD_SA %s{%d} established " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", this->child_sa->get_name(this->child_sa), this->child_sa->get_reqid(this->child_sa), ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), - ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), - this->child_sa->get_traffic_selectors(this->child_sa, TRUE), - this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); + ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts); + + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); if (this->rekey) { diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index 839bdb990..79a9aa5a0 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -18,6 +18,7 @@ #include <math.h> +#include <collections/array.h> #include <daemon.h> #include <sa/ikev2/tasks/ike_init.h> #include <sa/ikev2/tasks/ike_natd.h> @@ -122,19 +123,19 @@ struct private_task_manager_t { } initiating; /** - * List of queued tasks not yet in action + * Array of queued tasks not yet in action */ - linked_list_t *queued_tasks; + array_t *queued_tasks; /** - * List of active tasks, initiated by ourselve + * Array of active tasks, initiated by ourselve */ - linked_list_t *active_tasks; + array_t *active_tasks; /** - * List of tasks initiated by peer + * Array of tasks initiated by peer */ - linked_list_t *passive_tasks; + array_t *passive_tasks; /** * the task manager has been reset @@ -160,24 +161,24 @@ struct private_task_manager_t { METHOD(task_manager_t, flush_queue, void, private_task_manager_t *this, task_queue_t queue) { - linked_list_t *list; + array_t *array; task_t *task; switch (queue) { case TASK_QUEUE_ACTIVE: - list = this->active_tasks; + array = this->active_tasks; break; case TASK_QUEUE_PASSIVE: - list = this->passive_tasks; + array = this->passive_tasks; break; case TASK_QUEUE_QUEUED: - list = this->queued_tasks; + array = this->queued_tasks; break; default: return; } - while (list->remove_last(list, (void**)&task) == SUCCESS) + while (array_remove(array, ARRAY_TAIL, &task)) { task->destroy(task); } @@ -202,14 +203,14 @@ static bool activate_task(private_task_manager_t *this, task_type_t type) task_t *task; bool found = FALSE; - enumerator = this->queued_tasks->create_enumerator(this->queued_tasks); + enumerator = array_create_enumerator(this->queued_tasks); while (enumerator->enumerate(enumerator, (void**)&task)) { if (task->get_type(task) == type) { DBG2(DBG_IKE, " activating %N task", task_type_names, type); - this->queued_tasks->remove_at(this->queued_tasks, enumerator); - this->active_tasks->insert_last(this->active_tasks, task); + array_remove_at(this->queued_tasks, enumerator); + array_insert(this->active_tasks, ARRAY_TAIL, task); found = TRUE; break; } @@ -231,7 +232,7 @@ METHOD(task_manager_t, retransmit, status_t, ike_mobike_t *mobike = NULL; /* check if we are retransmitting a MOBIKE routability check */ - enumerator = this->active_tasks->create_enumerator(this->active_tasks); + enumerator = array_create_enumerator(this->active_tasks); while (enumerator->enumerate(enumerator, (void*)&task)) { if (task->get_type(task) == TASK_IKE_MOBIKE) @@ -319,7 +320,7 @@ METHOD(task_manager_t, initiate, status_t, return SUCCESS; } - if (this->active_tasks->get_count(this->active_tasks) == 0) + if (array_count(this->active_tasks) == 0) { DBG2(DBG_IKE, "activating new tasks"); switch (this->ike_sa->get_state(this->ike_sa)) @@ -414,8 +415,8 @@ METHOD(task_manager_t, initiate, status_t, else { DBG2(DBG_IKE, "reinitiating already active tasks"); - enumerator = this->active_tasks->create_enumerator(this->active_tasks); - while (enumerator->enumerate(enumerator, (void**)&task)) + enumerator = array_create_enumerator(this->active_tasks); + while (enumerator->enumerate(enumerator, &task)) { DBG2(DBG_IKE, " %N task", task_type_names, task->get_type(task)); switch (task->get_type(task)) @@ -460,14 +461,14 @@ METHOD(task_manager_t, initiate, status_t, this->initiating.type = exchange; this->initiating.retransmitted = 0; - enumerator = this->active_tasks->create_enumerator(this->active_tasks); - while (enumerator->enumerate(enumerator, (void*)&task)) + enumerator = array_create_enumerator(this->active_tasks); + while (enumerator->enumerate(enumerator, &task)) { switch (task->build(task, message)) { case SUCCESS: /* task completed, remove it */ - this->active_tasks->remove_at(this->active_tasks, enumerator); + array_remove_at(this->active_tasks, enumerator); task->destroy(task); break; case NEED_MORE: @@ -507,6 +508,9 @@ METHOD(task_manager_t, initiate, status_t, } message->destroy(message); + array_compress(this->active_tasks); + array_compress(this->queued_tasks); + return retransmit(this, this->initiating.mid); } @@ -530,14 +534,14 @@ static status_t process_response(private_task_manager_t *this, /* catch if we get resetted while processing */ this->reset = FALSE; - enumerator = this->active_tasks->create_enumerator(this->active_tasks); - while (enumerator->enumerate(enumerator, (void*)&task)) + enumerator = array_create_enumerator(this->active_tasks); + while (enumerator->enumerate(enumerator, &task)) { switch (task->process(task, message)) { case SUCCESS: /* task completed, remove it */ - this->active_tasks->remove_at(this->active_tasks, enumerator); + array_remove_at(this->active_tasks, enumerator); task->destroy(task); break; case NEED_MORE: @@ -549,7 +553,7 @@ static status_t process_response(private_task_manager_t *this, /* FALL */ case DESTROY_ME: /* critical failure, destroy IKE_SA */ - this->active_tasks->remove_at(this->active_tasks, enumerator); + array_remove_at(this->active_tasks, enumerator); enumerator->destroy(enumerator); task->destroy(task); return DESTROY_ME; @@ -568,6 +572,8 @@ static status_t process_response(private_task_manager_t *this, this->initiating.packet->destroy(this->initiating.packet); this->initiating.packet = NULL; + array_compress(this->active_tasks); + return initiate(this); } @@ -588,8 +594,8 @@ static bool handle_collisions(private_task_manager_t *this, task_t *task) type == TASK_IKE_REAUTH) { /* find an exchange collision, and notify these tasks */ - enumerator = this->active_tasks->create_enumerator(this->active_tasks); - while (enumerator->enumerate(enumerator, (void**)&active)) + enumerator = array_create_enumerator(this->active_tasks); + while (enumerator->enumerate(enumerator, &active)) { switch (active->get_type(active)) { @@ -646,14 +652,14 @@ static status_t build_response(private_task_manager_t *this, message_t *request) message->set_message_id(message, this->responding.mid); message->set_request(message, FALSE); - enumerator = this->passive_tasks->create_enumerator(this->passive_tasks); + enumerator = array_create_enumerator(this->passive_tasks); while (enumerator->enumerate(enumerator, (void*)&task)) { switch (task->build(task, message)) { case SUCCESS: /* task completed, remove it */ - this->passive_tasks->remove_at(this->passive_tasks, enumerator); + array_remove_at(this->passive_tasks, enumerator); if (!handle_collisions(this, task)) { task->destroy(task); @@ -663,8 +669,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) /* processed, but task needs another exchange */ if (handle_collisions(this, task)) { - this->passive_tasks->remove_at(this->passive_tasks, - enumerator); + array_remove_at(this->passive_tasks, enumerator); } break; case FAILED: @@ -721,6 +726,9 @@ static status_t build_response(private_task_manager_t *this, message_t *request) } return DESTROY_ME; } + + array_compress(this->passive_tasks); + return SUCCESS; } @@ -736,37 +744,37 @@ static status_t process_request(private_task_manager_t *this, notify_payload_t *notify; delete_payload_t *delete; - if (this->passive_tasks->get_count(this->passive_tasks) == 0) + if (array_count(this->passive_tasks) == 0) { /* create tasks depending on request type, if not already some queued */ switch (message->get_exchange_type(message)) { case IKE_SA_INIT: { task = (task_t*)ike_vendor_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)ike_init_create(this->ike_sa, FALSE, NULL); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)ike_natd_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)ike_cert_pre_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); #ifdef ME task = (task_t*)ike_me_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); #endif /* ME */ task = (task_t*)ike_auth_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)ike_cert_post_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)ike_config_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)child_create_create(this->ike_sa, NULL, FALSE, NULL, NULL); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)ike_auth_lifetime_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); task = (task_t*)ike_mobike_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); break; } case CREATE_CHILD_SA: @@ -817,7 +825,7 @@ static status_t process_request(private_task_manager_t *this, { task = (task_t*)ike_rekey_create(this->ike_sa, FALSE); } - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); break; } case INFORMATIONAL: @@ -889,14 +897,14 @@ static status_t process_request(private_task_manager_t *this, { task = (task_t*)ike_dpd_create(FALSE); } - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); break; } #ifdef ME case ME_CONNECT: { task = (task_t*)ike_me_create(this->ike_sa, FALSE); - this->passive_tasks->insert_last(this->passive_tasks, task); + array_insert(this->passive_tasks, ARRAY_TAIL, task); } #endif /* ME */ default: @@ -905,14 +913,14 @@ static status_t process_request(private_task_manager_t *this, } /* let the tasks process the message */ - enumerator = this->passive_tasks->create_enumerator(this->passive_tasks); + enumerator = array_create_enumerator(this->passive_tasks); while (enumerator->enumerate(enumerator, (void*)&task)) { switch (task->process(task, message)) { case SUCCESS: /* task completed, remove it */ - this->passive_tasks->remove_at(this->passive_tasks, enumerator); + array_remove_at(this->passive_tasks, enumerator); task->destroy(task); break; case NEED_MORE: @@ -924,7 +932,7 @@ static status_t process_request(private_task_manager_t *this, /* FALL */ case DESTROY_ME: /* critical failure, destroy IKE_SA */ - this->passive_tasks->remove_at(this->passive_tasks, enumerator); + array_remove_at(this->passive_tasks, enumerator); enumerator->destroy(enumerator); task->destroy(task); return DESTROY_ME; @@ -1230,8 +1238,8 @@ METHOD(task_manager_t, queue_task, void, enumerator_t *enumerator; task_t *current; - enumerator = this->queued_tasks->create_enumerator(this->queued_tasks); - while (enumerator->enumerate(enumerator, (void**)¤t)) + enumerator = array_create_enumerator(this->queued_tasks); + while (enumerator->enumerate(enumerator, ¤t)) { if (current->get_type(current) == TASK_IKE_MOBIKE) { @@ -1243,7 +1251,7 @@ METHOD(task_manager_t, queue_task, void, enumerator->destroy(enumerator); } DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task)); - this->queued_tasks->insert_last(this->queued_tasks, task); + array_insert(this->queued_tasks, ARRAY_TAIL, task); } /** @@ -1255,7 +1263,7 @@ static bool has_queued(private_task_manager_t *this, task_type_t type) bool found = FALSE; task_t *task; - enumerator = this->queued_tasks->create_enumerator(this->queued_tasks); + enumerator = array_create_enumerator(this->queued_tasks); while (enumerator->enumerate(enumerator, &task)) { if (task->get_type(task) == type) @@ -1410,19 +1418,18 @@ METHOD(task_manager_t, adopt_tasks, void, task_t *task; /* move queued tasks from other to this */ - while (other->queued_tasks->remove_last(other->queued_tasks, - (void**)&task) == SUCCESS) + while (array_remove(other->queued_tasks, ARRAY_TAIL, &task)) { DBG2(DBG_IKE, "migrating %N task", task_type_names, task->get_type(task)); task->migrate(task, this->ike_sa); - this->queued_tasks->insert_first(this->queued_tasks, task); + array_insert(this->queued_tasks, ARRAY_HEAD, task); } } METHOD(task_manager_t, busy, bool, private_task_manager_t *this) { - return (this->active_tasks->get_count(this->active_tasks) > 0); + return array_count(this->active_tasks) > 0; } METHOD(task_manager_t, reset, void, @@ -1447,7 +1454,7 @@ METHOD(task_manager_t, reset, void, this->initiating.type = EXCHANGE_TYPE_UNDEFINED; /* reset queued tasks */ - enumerator = this->queued_tasks->create_enumerator(this->queued_tasks); + enumerator = array_create_enumerator(this->queued_tasks); while (enumerator->enumerate(enumerator, &task)) { task->migrate(task, this->ike_sa); @@ -1455,11 +1462,10 @@ METHOD(task_manager_t, reset, void, enumerator->destroy(enumerator); /* reset active tasks */ - while (this->active_tasks->remove_last(this->active_tasks, - (void**)&task) == SUCCESS) + while (array_remove(this->active_tasks, ARRAY_TAIL, &task)) { task->migrate(task, this->ike_sa); - this->queued_tasks->insert_first(this->queued_tasks, task); + array_insert(this->queued_tasks, ARRAY_HEAD, task); } this->reset = TRUE; @@ -1471,11 +1477,11 @@ METHOD(task_manager_t, create_task_enumerator, enumerator_t*, switch (queue) { case TASK_QUEUE_ACTIVE: - return this->active_tasks->create_enumerator(this->active_tasks); + return array_create_enumerator(this->active_tasks); case TASK_QUEUE_PASSIVE: - return this->passive_tasks->create_enumerator(this->passive_tasks); + return array_create_enumerator(this->passive_tasks); case TASK_QUEUE_QUEUED: - return this->queued_tasks->create_enumerator(this->queued_tasks); + return array_create_enumerator(this->queued_tasks); default: return enumerator_create_empty(); } @@ -1486,9 +1492,9 @@ METHOD(task_manager_t, destroy, void, { flush(this); - this->active_tasks->destroy(this->active_tasks); - this->queued_tasks->destroy(this->queued_tasks); - this->passive_tasks->destroy(this->passive_tasks); + array_destroy(this->active_tasks); + array_destroy(this->queued_tasks); + array_destroy(this->passive_tasks); DESTROY_IF(this->responding.packet); DESTROY_IF(this->initiating.packet); @@ -1529,9 +1535,9 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa) }, .ike_sa = ike_sa, .initiating.type = EXCHANGE_TYPE_UNDEFINED, - .queued_tasks = linked_list_create(), - .active_tasks = linked_list_create(), - .passive_tasks = linked_list_create(), + .queued_tasks = array_create(0, 0), + .active_tasks = array_create(0, 0), + .passive_tasks = array_create(0, 0), .retransmit_tries = lib->settings->get_int(lib->settings, "%s.retransmit_tries", RETRANSMIT_TRIES, charon->name), .retransmit_timeout = lib->settings->get_double(lib->settings, diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index dd3813e85..8ae36af84 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -673,6 +673,22 @@ static status_t select_and_install(private_child_create_t *this, { /* a rekeyed SA uses the same reqid, no need for a new job */ schedule_inactivity_timeout(this); } + + my_ts = linked_list_create_from_enumerator( + this->child_sa->create_ts_enumerator(this->child_sa, TRUE)); + other_ts = linked_list_create_from_enumerator( + this->child_sa->create_ts_enumerator(this->child_sa, FALSE)); + + DBG0(DBG_IKE, "CHILD_SA %s{%d} established " + "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", + this->child_sa->get_name(this->child_sa), + this->child_sa->get_reqid(this->child_sa), + ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), + ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts); + + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); + return SUCCESS; } @@ -1245,15 +1261,6 @@ METHOD(task_t, build_r, status_t, build_payloads(this, message); - DBG0(DBG_IKE, "CHILD_SA %s{%d} established " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), - ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), - ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), - this->child_sa->get_traffic_selectors(this->child_sa, TRUE), - this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); - if (!this->rekey) { /* invoke the child_up() hook if we are not rekeying */ charon->bus->child_updown(charon->bus, this->child_sa, TRUE); @@ -1431,15 +1438,6 @@ METHOD(task_t, process_i, status_t, if (select_and_install(this, no_dh, ike_auth) == SUCCESS) { - DBG0(DBG_IKE, "CHILD_SA %s{%d} established " - "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", - this->child_sa->get_name(this->child_sa), - this->child_sa->get_reqid(this->child_sa), - ntohl(this->child_sa->get_spi(this->child_sa, TRUE)), - ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), - this->child_sa->get_traffic_selectors(this->child_sa, TRUE), - this->child_sa->get_traffic_selectors(this->child_sa, FALSE)); - if (!this->rekey) { /* invoke the child_up() hook if we are not rekeying */ charon->bus->child_updown(charon->bus, this->child_sa, TRUE); diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c index 9f12d7385..eaaca2039 100644 --- a/src/libcharon/sa/ikev2/tasks/child_delete.c +++ b/src/libcharon/sa/ikev2/tasks/child_delete.c @@ -249,6 +249,7 @@ static status_t destroy_and_reestablish(private_child_delete_t *this) */ static void log_children(private_child_delete_t *this) { + linked_list_t *my_ts, *other_ts; enumerator_t *enumerator; child_sa_t *child_sa; u_int64_t bytes_in, bytes_out; @@ -256,15 +257,17 @@ static void log_children(private_child_delete_t *this) enumerator = this->child_sas->create_enumerator(this->child_sas); while (enumerator->enumerate(enumerator, (void**)&child_sa)) { + my_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, TRUE)); + other_ts = linked_list_create_from_enumerator( + child_sa->create_ts_enumerator(child_sa, FALSE)); if (this->expired) { DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} " "with SPIs %.8x_i %.8x_o and TS %#R=== %#R", child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), - ntohl(child_sa->get_spi(child_sa, FALSE)), - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); + ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts); } else { @@ -276,9 +279,10 @@ static void log_children(private_child_delete_t *this) child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in, ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out, - child_sa->get_traffic_selectors(child_sa, TRUE), - child_sa->get_traffic_selectors(child_sa, FALSE)); + my_ts, other_ts); } + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); } enumerator->destroy(enumerator); } |