diff options
Diffstat (limited to 'src/charon/config/backend_manager.c')
-rw-r--r-- | src/charon/config/backend_manager.c | 183 |
1 files changed, 101 insertions, 82 deletions
diff --git a/src/charon/config/backend_manager.c b/src/charon/config/backend_manager.c index d77c05fd7..c2b408ca9 100644 --- a/src/charon/config/backend_manager.c +++ b/src/charon/config/backend_manager.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: backend_manager.c 4044 2008-06-06 15:05:54Z martin $ + * $Id: backend_manager.c 4134 2008-07-01 11:10:37Z martin $ */ #include "backend_manager.h" @@ -49,6 +49,16 @@ struct private_backend_manager_t { }; /** + * match of an ike_cfg + */ +typedef enum ike_cfg_match_t { + MATCH_NONE = 0x00, + MATCH_ANY = 0x01, + MATCH_ME = 0x04, + MATCH_OTHER = 0x08, +} ike_cfg_match_t; + +/** * data to pass nested IKE enumerator */ typedef struct { @@ -108,6 +118,48 @@ static enumerator_t *peer_enum_create_all(backend_t *backend) } /** + * get a match of a candidate ike_cfg for two hosts + */ +static ike_cfg_match_t get_match(ike_cfg_t *cand, host_t *me, host_t *other) +{ + host_t *me_cand, *other_cand; + ike_cfg_match_t match = MATCH_NONE; + + me_cand = host_create_from_dns(cand->get_my_addr(cand), + me->get_family(me), 0); + if (!me_cand) + { + return MATCH_NONE; + } + if (me_cand->ip_equals(me_cand, me)) + { + match += MATCH_ME; + } + else if (me_cand->is_anyaddr(me_cand)) + { + match += MATCH_ANY; + } + me_cand->destroy(me_cand); + + other_cand = host_create_from_dns(cand->get_other_addr(cand), + other->get_family(other), 0); + if (!other_cand) + { + return MATCH_NONE; + } + if (other_cand->ip_equals(other_cand, other)) + { + match += MATCH_OTHER; + } + else if (other_cand->is_anyaddr(other_cand)) + { + match += MATCH_ANY; + } + other_cand->destroy(other_cand); + return match; +} + +/** * implements backend_manager_t.get_ike_cfg. */ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, @@ -115,14 +167,8 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, { ike_cfg_t *current, *found = NULL; enumerator_t *enumerator; - host_t *my_candidate, *other_candidate; + ike_cfg_match_t match, best = MATCH_ANY; ike_data_t *data; - enum { - MATCH_NONE = 0x00, - MATCH_ANY = 0x01, - MATCH_ME = 0x04, - MATCH_OTHER = 0x08, - } prio, best = MATCH_ANY; data = malloc_thing(ike_data_t); data->this = this; @@ -137,51 +183,20 @@ static ike_cfg_t *get_ike_cfg(private_backend_manager_t *this, (void*)ike_enum_create, data, (void*)ike_enum_destroy); while (enumerator->enumerate(enumerator, (void**)¤t)) { - prio = MATCH_NONE; - - my_candidate = host_create_from_dns(current->get_my_addr(current), - me->get_family(me), 0); - if (!my_candidate) - { - continue; - } - if (my_candidate->ip_equals(my_candidate, me)) - { - prio += MATCH_ME; - } - else if (my_candidate->is_anyaddr(my_candidate)) - { - prio += MATCH_ANY; - } - my_candidate->destroy(my_candidate); - - other_candidate = host_create_from_dns(current->get_other_addr(current), - other->get_family(other), 0); - if (!other_candidate) - { - continue; - } - if (other_candidate->ip_equals(other_candidate, other)) - { - prio += MATCH_OTHER; - } - else if (other_candidate->is_anyaddr(other_candidate)) - { - prio += MATCH_ANY; - } - other_candidate->destroy(other_candidate); - - DBG2(DBG_CFG, " candidate: %s...%s, prio %d", - current->get_my_addr(current), current->get_other_addr(current), - prio); - - /* we require at least two MATCH_ANY */ - if (prio > best) + match = get_match(current, me, other); + + if (match) { - best = prio; - DESTROY_IF(found); - found = current; - found->get_ref(found); + DBG2(DBG_CFG, " candidate: %s...%s, prio %d", + current->get_my_addr(current), current->get_other_addr(current), + match); + if (match > best) + { + DESTROY_IF(found); + found = current; + found->get_ref(found); + best = match; + } } } enumerator->destroy(enumerator); @@ -202,22 +217,23 @@ static enumerator_t *create_peer_cfg_enumerator(private_backend_manager_t *this) /** * implements backend_manager_t.get_peer_cfg. */ -static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, - identification_t *me, identification_t *other, - auth_info_t *auth) +static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, host_t *me, + host_t *other, identification_t *my_id, + identification_t *other_id, auth_info_t *auth) { peer_cfg_t *current, *found = NULL; enumerator_t *enumerator; - identification_t *my_candidate, *other_candidate; - id_match_t best = ID_MATCH_NONE; + id_match_t best_peer = ID_MATCH_NONE; + ike_cfg_match_t best_ike = MATCH_NONE; peer_data_t *data; - DBG2(DBG_CFG, "looking for a config for %D...%D", me, other); + DBG2(DBG_CFG, "looking for a config for %H[%D]...%H[%D]", + me, my_id, other, other_id); data = malloc_thing(peer_data_t); data->this = this; - data->me = me; - data->other = other; + data->me = my_id; + data->other = other_id; this->mutex->lock(this->mutex); enumerator = enumerator_create_nested( @@ -225,42 +241,45 @@ static peer_cfg_t *get_peer_cfg(private_backend_manager_t *this, (void*)peer_enum_create, data, (void*)peer_enum_destroy); while (enumerator->enumerate(enumerator, ¤t)) { - id_match_t m1, m2, sum; + identification_t *my_cand, *other_cand; + id_match_t m1, m2, match_peer; + ike_cfg_match_t match_ike; - my_candidate = current->get_my_id(current); - other_candidate = current->get_other_id(current); + my_cand = current->get_my_id(current); + other_cand = current->get_other_id(current); /* own ID may have wildcards in both, config and request (missing IDr) */ - m1 = my_candidate->matches(my_candidate, me); + m1 = my_cand->matches(my_cand, my_id); if (!m1) { - m1 = me->matches(me, my_candidate); + m1 = my_id->matches(my_id, my_cand); } - m2 = other->matches(other, other_candidate); - sum = m1 + m2; + m2 = other_id->matches(other_id, other_cand); + + match_peer = m1 + m2; + match_ike = get_match(current->get_ike_cfg(current), me, other); - if (m1 && m2) + if (m1 && m2 && match_ike && + auth->complies(auth, current->get_auth(current))) { - if (auth->complies(auth, current->get_auth(current))) + DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d.%d", + current->get_name(current), my_cand, other_cand, + match_peer, match_ike); + if (match_peer >= best_peer && match_ike > best_ike) { - DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d", - current->get_name(current), my_candidate, - other_candidate, sum); - if (sum > best) - { - DESTROY_IF(found); - found = current; - found->get_ref(found); - best = sum; - } + DESTROY_IF(found); + found = current; + found->get_ref(found); + best_peer = match_peer; + best_ike = match_ike; } } } if (found) { - DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d", + DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d.%d", found->get_name(found), found->get_my_id(found), - found->get_other_id(found), best); + found->get_other_id(found), best_peer, best_ike); } enumerator->destroy(enumerator); this->mutex->unlock(this->mutex); @@ -325,7 +344,7 @@ backend_manager_t *backend_manager_create() private_backend_manager_t *this = malloc_thing(private_backend_manager_t); this->public.get_ike_cfg = (ike_cfg_t* (*)(backend_manager_t*, host_t*, host_t*))get_ike_cfg; - this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,identification_t*,identification_t*,auth_info_t*))get_peer_cfg; + this->public.get_peer_cfg = (peer_cfg_t* (*)(backend_manager_t*,host_t*,host_t*,identification_t*,identification_t*,auth_info_t*))get_peer_cfg; this->public.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_manager_t*,char*))get_peer_cfg_by_name; this->public.create_peer_cfg_enumerator = (enumerator_t* (*)(backend_manager_t*))create_peer_cfg_enumerator; this->public.add_backend = (void(*)(backend_manager_t*, backend_t *backend))add_backend; |