diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-04-12 20:30:08 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-04-12 20:30:08 +0000 |
commit | b0d8ed94fe9e74afb49fdf5f11e4add29879c65c (patch) | |
tree | b20167235628771046e940a82a906a6d0991ee4a /src/charon/config/policies/local_policy_store.c | |
parent | ea939d07c84d2a8e51215458063fc05e9c399290 (diff) | |
download | vyos-strongswan-b0d8ed94fe9e74afb49fdf5f11e4add29879c65c.tar.gz vyos-strongswan-b0d8ed94fe9e74afb49fdf5f11e4add29879c65c.zip |
[svn-upgrade] Integrating new upstream version, strongswan (4.1.1)
Diffstat (limited to 'src/charon/config/policies/local_policy_store.c')
-rw-r--r-- | src/charon/config/policies/local_policy_store.c | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/src/charon/config/policies/local_policy_store.c b/src/charon/config/policies/local_policy_store.c new file mode 100644 index 000000000..dd22b43a0 --- /dev/null +++ b/src/charon/config/policies/local_policy_store.c @@ -0,0 +1,282 @@ +/** + * @file local_policy_store.c + * + * @brief Implementation of local_policy_store_t. + * + */ + +/* + * Copyright (C) 2006 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <string.h> + +#include "local_policy_store.h" + +#include <daemon.h> +#include <utils/linked_list.h> + + +typedef struct private_local_policy_store_t private_local_policy_store_t; + +/** + * Private data of an local_policy_store_t object + */ +struct private_local_policy_store_t { + + /** + * Public part + */ + local_policy_store_t public; + + /** + * list of policy_t's + */ + linked_list_t *policies; + + /** + * Mutex to exclusivly access list + */ + pthread_mutex_t mutex; +}; + +/** + * Implementation of policy_store_t.add_policy. + */ +static void add_policy(private_local_policy_store_t *this, policy_t *policy) +{ + pthread_mutex_lock(&(this->mutex)); + this->policies->insert_last(this->policies, (void*)policy); + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * Check if a policy contains traffic selectors + */ +static bool contains_traffic_selectors(policy_t *policy, bool mine, + linked_list_t *ts, host_t *host) +{ + linked_list_t *selected; + bool contains = FALSE; + + if (mine) + { + selected = policy->select_my_traffic_selectors(policy, ts, host); + } + else + { + selected = policy->select_other_traffic_selectors(policy, ts, host); + } + if (selected->get_count(selected)) + { + contains = TRUE; + } + selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy)); + return contains; +} + +/** + * Implementation of policy_store_t.get_policy. + */ +static policy_t *get_policy(private_local_policy_store_t *this, + identification_t *my_id, identification_t *other_id, + linked_list_t *my_ts, linked_list_t *other_ts, + host_t *my_host, host_t *other_host) +{ + typedef enum { + PRIO_UNDEFINED = 0x00, + PRIO_TS_MISMATCH = 0x01, + PRIO_ID_ANY = 0x02, + PRIO_ID_MATCH = PRIO_ID_ANY + MAX_WILDCARDS, + } prio_t; + + prio_t best_prio = PRIO_UNDEFINED; + + iterator_t *iterator; + policy_t *candidate; + policy_t *found = NULL; + traffic_selector_t *ts; + + DBG1(DBG_CFG, "searching policy for '%D'...'%D'", my_id, other_id); + iterator = my_ts->create_iterator(my_ts, TRUE); + while (iterator->iterate(iterator, (void**)&ts)) + { + DBG1(DBG_CFG, " local TS: %R", ts); + } + iterator->destroy(iterator); + iterator = other_ts->create_iterator(other_ts, TRUE); + while (iterator->iterate(iterator, (void**)&ts)) + { + DBG1(DBG_CFG, " remote TS: %R", ts); + } + iterator->destroy(iterator); + + pthread_mutex_lock(&(this->mutex)); + iterator = this->policies->create_iterator(this->policies, TRUE); + + /* determine closest matching policy */ + while (iterator->iterate(iterator, (void**)&candidate)) + { + identification_t *candidate_my_id; + identification_t *candidate_other_id; + int wildcards; + + candidate_my_id = candidate->get_my_id(candidate); + candidate_other_id = candidate->get_other_id(candidate); + + /* my_id is either %any or if set must match exactly */ + if (candidate_my_id->matches(candidate_my_id, my_id, &wildcards)) + { + prio_t prio = PRIO_UNDEFINED; + + /* wildcard match for other_id */ + if (!other_id->matches(other_id, candidate_other_id, &wildcards)) + { + continue; + } + prio = PRIO_ID_MATCH - wildcards; + + /* only accept if traffic selectors match */ + if (!contains_traffic_selectors(candidate, TRUE, my_ts, my_host) || + !contains_traffic_selectors(candidate, FALSE, other_ts, other_host)) + { + DBG2(DBG_CFG, "candidate '%s' inacceptable due traffic " + "selector mismatch", candidate->get_name(candidate)); + prio = PRIO_TS_MISMATCH; + } + + DBG2(DBG_CFG, "candidate policy '%s': '%D'...'%D' (prio=%d)", + candidate->get_name(candidate), + candidate_my_id, candidate_other_id, prio); + + if (prio > best_prio) + { + found = candidate; + best_prio = prio; + } + } + } + iterator->destroy(iterator); + + if (found) + { + DBG1(DBG_CFG, "found matching policy '%s': '%D'...'%D' (prio=%d)", + found->get_name(found), found->get_my_id(found), + found->get_other_id(found), best_prio); + /* give out a new reference to it */ + found->get_ref(found); + } + pthread_mutex_unlock(&(this->mutex)); + return found; +} + +/** + * Implementation of policy_store_t.get_policy_by_name. + */ +static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *name) +{ + iterator_t *iterator; + policy_t *current, *found = NULL; + + DBG2(DBG_CFG, "looking for policy '%s'", name); + + pthread_mutex_lock(&(this->mutex)); + iterator = this->policies->create_iterator(this->policies, TRUE); + while (iterator->iterate(iterator, (void **)¤t)) + { + if (strcmp(current->get_name(current), name) == 0) + { + found = current; + } + } + iterator->destroy(iterator); + pthread_mutex_unlock(&(this->mutex)); + + /* give out a new reference */ + found->get_ref(found); + return found; +} + +/** + * Implementation of policy_store_t.delete_policy. + */ +static status_t delete_policy(private_local_policy_store_t *this, char *name) +{ + iterator_t *iterator; + policy_t *current; + bool found = FALSE; + + pthread_mutex_lock(&(this->mutex)); + iterator = this->policies->create_iterator(this->policies, TRUE); + while (iterator->iterate(iterator, (void **)¤t)) + { + if (strcmp(current->get_name(current), name) == 0) + { + /* remove policy from list, and destroy it */ + iterator->remove(iterator); + current->destroy(current); + found = TRUE; + /* we do not break here, as there may be multipe policies */ + } + } + iterator->destroy(iterator); + pthread_mutex_unlock(&(this->mutex)); + if (found) + { + return SUCCESS; + } + return NOT_FOUND; +} + +/** + * Implementation of policy_store_t.create_iterator. + */ +static iterator_t* create_iterator(private_local_policy_store_t *this) +{ + return this->policies->create_iterator_locked(this->policies, + &this->mutex); +} + +/** + * Implementation of policy_store_t.destroy. + */ +static void destroy(private_local_policy_store_t *this) +{ + pthread_mutex_lock(&(this->mutex)); + this->policies->destroy_offset(this->policies, offsetof(policy_t, destroy)); + pthread_mutex_unlock(&(this->mutex)); + free(this); +} + +/** + * Described in header. + */ +local_policy_store_t *local_policy_store_create(void) +{ + private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t); + + this->public.policy_store.add_policy = (void (*) (policy_store_t*,policy_t*))add_policy; + this->public.policy_store.get_policy = (policy_t* (*) (policy_store_t*,identification_t*,identification_t*, + linked_list_t*,linked_list_t*,host_t*,host_t*))get_policy; + this->public.policy_store.get_policy_by_name = (policy_t* (*) (policy_store_t*,char*))get_policy_by_name; + this->public.policy_store.delete_policy = (status_t (*) (policy_store_t*,char*))delete_policy; + this->public.policy_store.create_iterator = (iterator_t* (*) (policy_store_t*))create_iterator; + this->public.policy_store.destroy = (void (*) (policy_store_t*))destroy; + + /* private variables */ + this->policies = linked_list_create(); + pthread_mutex_init(&(this->mutex), NULL); + + return (&this->public); +} |