aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/config
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2006-07-20 10:09:32 +0000
committerMartin Willi <martin@strongswan.org>2006-07-20 10:09:32 +0000
commit8dfbe71b34badd4a277b46e4bfd9a70cfa9db06b (patch)
treec85c7059d723cb76a0db9dd51f9cb984c3ad7f8f /src/charon/config
parent92ee45a0eedfa4b58d5814d7ffad0671165f3f06 (diff)
downloadstrongswan-8dfbe71b34badd4a277b46e4bfd9a70cfa9db06b.tar.bz2
strongswan-8dfbe71b34badd4a277b46e4bfd9a70cfa9db06b.tar.xz
introduced refcounting on policy and connections
aren't stored in the IKE_SA anymore, they are queried on the fly are immutable now, allows it to share them policy selection based on traffic selectors, leads to valid lookup results rekeying queries the policy based on its traffic selectors
Diffstat (limited to 'src/charon/config')
-rw-r--r--src/charon/config/connections/connection.c83
-rw-r--r--src/charon/config/connections/connection.h43
-rw-r--r--src/charon/config/connections/local_connection_store.c16
-rw-r--r--src/charon/config/policies/local_policy_store.c69
-rw-r--r--src/charon/config/policies/policy.c282
-rw-r--r--src/charon/config/policies/policy.h188
-rwxr-xr-xsrc/charon/config/policies/policy_store.h32
-rw-r--r--src/charon/config/traffic_selector.c17
8 files changed, 314 insertions, 416 deletions
diff --git a/src/charon/config/connections/connection.c b/src/charon/config/connections/connection.c
index 3de57ca80..e1ab0392d 100644
--- a/src/charon/config/connections/connection.c
+++ b/src/charon/config/connections/connection.c
@@ -59,6 +59,11 @@ struct private_connection_t {
* Public part
*/
connection_t public;
+
+ /**
+ * Number of references hold by others to this connection
+ */
+ u_int refcount;
/**
* Name of the connection
@@ -155,24 +160,6 @@ static host_t *get_other_host (private_connection_t *this)
}
/**
- * Implementation of connection_t.update_my_host.
- */
-static void update_my_host(private_connection_t *this, host_t *my_host)
-{
- this->my_host->destroy(this->my_host);
- this->my_host = my_host;
-}
-
-/**
- * Implementation of connection_t.update_other_host.
- */
-static void update_other_host(private_connection_t *this, host_t *other_host)
-{
- this->other_host->destroy(this->other_host);
- this->other_host = other_host;
-}
-
-/**
* Implementation of connection_t.get_proposals.
*/
static linked_list_t* get_proposals(private_connection_t *this)
@@ -288,31 +275,11 @@ static bool check_dh_group(private_connection_t *this, diffie_hellman_group_t dh
}
/**
- * Implementation of connection_t.clone.
+ * Implementation of connection_t.get_ref.
*/
-static connection_t *clone(private_connection_t *this)
+static void get_ref(private_connection_t *this)
{
- iterator_t *iterator;
- proposal_t *proposal;
- private_connection_t *clone = (private_connection_t*)connection_create(
- this->name, this->ikev2,
- this->cert_policy,
- this->certreq_policy,
- this->my_host->clone(this->my_host),
- this->other_host->clone(this->other_host),
- this->auth_method);
-
- /* clone all proposals */
- iterator = this->proposals->create_iterator(this->proposals, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&proposal);
- proposal = proposal->clone(proposal);
- clone->proposals->insert_last(clone->proposals, (void*)proposal);
- }
- iterator->destroy(iterator);
-
- return &clone->public;
+ this->refcount++;
}
/**
@@ -320,18 +287,21 @@ static connection_t *clone(private_connection_t *this)
*/
static void destroy(private_connection_t *this)
{
- proposal_t *proposal;
-
- while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
+ if (--this->refcount == 0)
{
- proposal->destroy(proposal);
+ proposal_t *proposal;
+
+ while (this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
+ {
+ proposal->destroy(proposal);
+ }
+ this->proposals->destroy(this->proposals);
+
+ this->my_host->destroy(this->my_host);
+ this->other_host->destroy(this->other_host);
+ free(this->name);
+ free(this);
}
- this->proposals->destroy(this->proposals);
-
- this->my_host->destroy(this->my_host);
- this->other_host->destroy(this->other_host);
- free(this->name);
- free(this);
}
/**
@@ -344,15 +314,13 @@ connection_t * connection_create(char *name, bool ikev2,
auth_method_t auth_method)
{
private_connection_t *this = malloc_thing(private_connection_t);
-
+
/* public functions */
this->public.get_name = (char*(*)(connection_t*))get_name;
this->public.is_ikev2 = (bool(*)(connection_t*))is_ikev2;
this->public.get_cert_policy = (cert_policy_t(*)(connection_t*))get_cert_policy;
this->public.get_certreq_policy = (cert_policy_t(*)(connection_t*))get_certreq_policy;
this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host;
- this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host;
- this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host;
this->public.get_other_host = (host_t*(*)(connection_t*))get_other_host;
this->public.get_proposals = (linked_list_t*(*)(connection_t*))get_proposals;
this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
@@ -360,10 +328,11 @@ connection_t * connection_create(char *name, bool ikev2,
this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method;
this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
- this->public.clone = (connection_t*(*)(connection_t*))clone;
+ this->public.get_ref = (void(*)(connection_t*))get_ref;
this->public.destroy = (void(*)(connection_t*))destroy;
/* private variables */
+ this->refcount = 1;
this->name = strdup(name);
this->ikev2 = ikev2;
this->cert_policy = cert_policy;
@@ -373,6 +342,6 @@ connection_t * connection_create(char *name, bool ikev2,
this->auth_method = auth_method;
this->proposals = linked_list_create();
-
- return (&this->public);
+
+ return &this->public;
}
diff --git a/src/charon/config/connections/connection.h b/src/charon/config/connections/connection.h
index dca570e05..111acd5e1 100644
--- a/src/charon/config/connections/connection.h
+++ b/src/charon/config/connections/connection.h
@@ -130,30 +130,6 @@ struct connection_t {
* @return host information as host_t object
*/
host_t *(*get_other_host) (connection_t *this);
-
- /**
- * @brief Update address of my host.
- *
- * It may be necessary to uptdate own address, as it
- * is set to the default route (0.0.0.0) in some cases.
- * Old host is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param my_host new host to set as my_host
- */
- void (*update_my_host) (connection_t *this, host_t *my_host);
-
- /**
- * @brief Update address of remote host.
- *
- * It may be necessary to uptdate remote address, as a
- * connection may define %any (0.0.0.0) or a subnet.
- * Old host is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param my_host new host to set as other_host
- */
- void (*update_other_host) (connection_t *this, host_t *other_host);
/**
* @brief Returns a list of all supported proposals.
@@ -227,7 +203,7 @@ struct connection_t {
* the peer. It should be ommited when CERT_SEND_NEVER, sended otherwise.
*
* @param this calling object
- * @return - TRUE, if certificate request should be sent
+ * @return certificate request sending policy
*/
cert_policy_t (*get_certreq_policy) (connection_t *this);
@@ -261,16 +237,21 @@ struct connection_t {
bool (*check_dh_group) (connection_t *this, diffie_hellman_group_t dh_group);
/**
- * @brief Clone a connection_t object.
- *
- * @param this connection to clone
- * @return clone of it
+ * @brief Get a new reference to this connection.
+ *
+ * Get a new reference to this connection by increasing
+ * it's internal reference counter.
+ *
+ * @param this calling object
*/
- connection_t *(*clone) (connection_t *this);
+ void (*get_ref) (connection_t *this);
/**
* @brief Destroys a connection_t object.
*
+ * Decrements the internal reference counter and
+ * destroys the connection when it reaches zero.
+ *
* @param this calling object
*/
void (*destroy) (connection_t *this);
@@ -278,7 +259,7 @@ struct connection_t {
/**
* @brief Creates a connection_t object.
- *
+ *
* Supplied hosts become owned by connection, so
* do not modify or destroy them after a call to
* connection_create(). Name gets cloned internally.
diff --git a/src/charon/config/connections/local_connection_store.c b/src/charon/config/connections/local_connection_store.c
index c6e982e23..1f961cbcc 100644
--- a/src/charon/config/connections/local_connection_store.c
+++ b/src/charon/config/connections/local_connection_store.c
@@ -116,7 +116,7 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t
{
found = candidate;
best_prio = prio;
- }
+ }
}
}
iterator->destroy(iterator);
@@ -132,13 +132,9 @@ static connection_t *get_connection_by_hosts(private_local_connection_store_t *t
found_my_host->get_string(found_my_host),
found_other_host->get_string(found_other_host),
best_prio);
-
- found = found->clone(found);
- if (best_prio & PRIO_ADDR_ANY)
- {
- /* replace %any by the peer's address */
- found->update_other_host(found, other_host->clone(other_host));
- }
+
+ /* give out a new reference to it */
+ found->get_ref(found);
}
pthread_mutex_unlock(&(this->mutex));
return found;
@@ -159,13 +155,15 @@ static connection_t *get_connection_by_name(private_local_connection_store_t *th
iterator->current(iterator, (void**)&current);
if (strcmp(name, current->get_name(current)) == 0)
{
- found = current->clone(current);
+ found = current;
break;
}
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
+ /* get a new reference for it */
+ found->get_ref(found);
return found;
}
diff --git a/src/charon/config/policies/local_policy_store.c b/src/charon/config/policies/local_policy_store.c
index 2054b9df5..0c3e0ee04 100644
--- a/src/charon/config/policies/local_policy_store.c
+++ b/src/charon/config/policies/local_policy_store.c
@@ -67,9 +67,42 @@ static void add_policy(private_local_policy_store_t *this, policy_t *policy)
}
/**
- * Implementation of policy_store_t.get_policy_by_ids.
+ * Check if a policy contains traffic selectors
*/
-static policy_t *get_policy_by_ids(private_local_policy_store_t *this, identification_t *my_id, identification_t *other_id)
+static bool contains_traffic_selectors(policy_t *policy, bool mine,
+ linked_list_t *ts, host_t *host)
+{
+ linked_list_t *selected;
+ bool contains = FALSE;
+ traffic_selector_t *to;
+
+ 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;
+ }
+ while (selected->remove_last(selected, (void**)&to) == SUCCESS)
+ {
+ to->destroy(to);
+ }
+ selected->destroy(selected);
+ 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,
@@ -111,9 +144,22 @@ static policy_t *get_policy_by_ids(private_local_policy_store_t *this, identific
{
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))
+ {
+ this->logger->log(this->logger, CONTROL|LEVEL2,
+ "candidate '%s' inacceptable due traffic selector mismatch",
+ candidate->get_name(candidate),
+ candidate_my_id->get_string(candidate_my_id),
+ candidate_other_id->get_string(candidate_other_id),
+ prio);
+ continue;
+ }
this->logger->log(this->logger, CONTROL|LEVEL2,
- "candidate policy \"%s\": %s...%s (prio=%d)",
+ "candidate policy '%s': %s...%s (prio=%d)",
candidate->get_name(candidate),
candidate_my_id->get_string(candidate_my_id),
candidate_other_id->get_string(candidate_other_id),
@@ -134,18 +180,13 @@ static policy_t *get_policy_by_ids(private_local_policy_store_t *this, identific
identification_t *found_other_id = found->get_other_id(found);
this->logger->log(this->logger, CONTROL|LEVEL1,
- "found matching policy \"%s\": %s...%s (prio=%d)",
+ "found matching policy '%s': %s...%s (prio=%d)",
found->get_name(found),
found_my_id->get_string(found_my_id),
found_other_id->get_string(found_other_id),
best_prio);
-
- found = found->clone(found);
- if (best_prio != PRIO_ID_MATCH)
- {
- /* replace %any/wildcards by the peer's address */
- found->update_other_id(found, other_id->clone(other_id));
- }
+ /* give out a new reference to it */
+ found->get_ref(found);
}
pthread_mutex_unlock(&(this->mutex));
return found;
@@ -168,12 +209,14 @@ static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *na
iterator->current(iterator, (void **)&current);
if (strcmp(current->get_name(current), name) == 0)
{
- found = current->clone(current);
+ found = current;
}
}
iterator->destroy(iterator);
pthread_mutex_unlock(&(this->mutex));
+ /* give out a new reference */
+ found->get_ref(found);
return found;
}
@@ -234,7 +277,7 @@ 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_by_ids = (policy_t*(*)(policy_store_t*,identification_t*,identification_t*))get_policy_by_ids;
+ 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.destroy = (void(*)(policy_store_t*))destroy;
diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c
index 152c157a8..a64af3271 100644
--- a/src/charon/config/policies/policy.c
+++ b/src/charon/config/policies/policy.c
@@ -44,6 +44,11 @@ struct private_policy_t {
policy_t public;
/**
+ * Number of references hold by others to this policy
+ */
+ u_int refcount;
+
+ /**
* Name of the policy, used to query it
*/
char *name;
@@ -135,76 +140,52 @@ static identification_t *get_other_id(private_policy_t *this)
}
/**
- * Implementation of policy_t.update_my_id
- */
-static void update_my_id(private_policy_t *this, identification_t *my_id)
-{
- this->my_id->destroy(this->my_id);
- this->my_id = my_id;
-}
-
-/**
- * Implementation of policy_t.update_other_id
- */
-static void update_other_id(private_policy_t *this, identification_t *other_id)
-{
- this->other_id->destroy(this->other_id);
- this->other_id = other_id;
-}
-
-/**
- * Helper function which does the work for policy_t.update_my_ts and update_other_ts
+ * Get traffic selectors, with wildcard-address update
*/
-static void update_ts(linked_list_t* list, host_t *new_host)
+static linked_list_t *get_traffic_selectors(private_policy_t *this, linked_list_t *list, host_t *host)
{
- traffic_selector_t *ts;
iterator_t *iterator;
-
+ traffic_selector_t *current;
+ linked_list_t *result = linked_list_create();
+
iterator = list->create_iterator(list, TRUE);
- while (iterator->has_next(iterator))
+
+ while (iterator->iterate(iterator, (void**)&current))
{
- iterator->current(iterator, (void**)&ts);
- ts->update_address_range(ts, new_host);
+ /* we make a copy of the TS, this allows us to update wildcard
+ * addresses in it. We won't pollute the shared policy. */
+ current = current->clone(current);
+ current->update_address_range(current, host);
+
+ result->insert_last(result, (void*)current);
}
iterator->destroy(iterator);
-}
-
-/**
- * Implementation of policy_t.update_my_id
- */
-static void update_my_ts(private_policy_t *this, host_t *my_host)
-{
- update_ts(this->my_ts, my_host);
-}
-
-/**
- * Implementation of policy_t.update_other_ts
- */
-static void update_other_ts(private_policy_t *this, host_t *my_host)
-{
- update_ts(this->other_ts, my_host);
+ return result;
}
/**
* Implementation of policy_t.get_my_traffic_selectors
*/
-static linked_list_t *get_my_traffic_selectors(private_policy_t *this)
+static linked_list_t *get_my_traffic_selectors(private_policy_t *this, host_t *me)
{
- return this->my_ts;
+ return get_traffic_selectors(this, this->my_ts, me);
}
/**
* Implementation of policy_t.get_other_traffic_selectors
*/
-static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[])
+static linked_list_t *get_other_traffic_selectors(private_policy_t *this, host_t *other)
{
- return this->other_ts;
+ return get_traffic_selectors(this, this->other_ts, other);
}
/**
- * Implementation of private_policy_t.select_traffic_selectors
+ * Narrow traffic selectors, with wildcard-address update in "stored".
*/
-static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied)
+static linked_list_t *select_traffic_selectors(private_policy_t *this,
+ linked_list_t *stored,
+ linked_list_t *supplied,
+ host_t *host)
{
iterator_t *supplied_iter, *stored_iter;
traffic_selector_t *supplied_ts, *stored_ts, *selected_ts;
@@ -218,16 +199,17 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
supplied_iter = supplied->create_iterator(supplied, TRUE);
/* iterate over all stored selectors */
- while (stored_iter->has_next(stored_iter))
+ while (stored_iter->iterate(stored_iter, (void**)&stored_ts))
{
- stored_iter->current(stored_iter, (void**)&stored_ts);
+ /* we make a copy of the TS, this allows us to update wildcard
+ * addresses in it. We won't pollute the shared policy. */
+ stored_ts = stored_ts->clone(stored_ts);
+ stored_ts->update_address_range(stored_ts, host);
supplied_iter->reset(supplied_iter);
/* iterate over all supplied traffic selectors */
- while (supplied_iter->has_next(supplied_iter))
+ while (supplied_iter->iterate(supplied_iter, (void**)&supplied_ts))
{
- supplied_iter->current(supplied_iter, (void**)&supplied_ts);
-
this->logger->log(this->logger, CONTROL|LEVEL2,
" stored %s <=> %s received",
stored_ts->get_string(stored_ts),
@@ -243,6 +225,7 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
selected_ts->get_string(selected_ts));
}
}
+ stored_ts->destroy(stored_ts);
}
stored_iter->destroy(stored_iter);
supplied_iter->destroy(supplied_iter);
@@ -253,17 +236,21 @@ static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_li
/**
* Implementation of private_policy_t.select_my_traffic_selectors
*/
-static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
+static linked_list_t *select_my_traffic_selectors(private_policy_t *this,
+ linked_list_t *supplied,
+ host_t *me)
{
- return select_traffic_selectors(this, this->my_ts, supplied);
+ return select_traffic_selectors(this, this->my_ts, supplied, me);
}
/**
* Implementation of private_policy_t.select_other_traffic_selectors
*/
-static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
+static linked_list_t *select_other_traffic_selectors(private_policy_t *this,
+ linked_list_t *supplied,
+ host_t* other)
{
- return select_traffic_selectors(this, this->other_ts, supplied);
+ return select_traffic_selectors(this, this->other_ts, supplied, other);
}
/**
@@ -322,11 +309,11 @@ static void add_authorities(private_policy_t *this, identification_t *my_ca, ide
}
/**
- * Implementation of policy_t.add_updown
+ * Implementation of policy_t.get_updown
*/
-static void add_updown(private_policy_t *this, char *updown)
+static char* get_updown(private_policy_t *this)
{
- this->updown = (updown == NULL)? NULL:strdup(updown);
+ return this->updown;
}
/**
@@ -375,118 +362,67 @@ static u_int32_t get_hard_lifetime(private_policy_t *this)
}
/**
- * Implements policy_t.clone.
+ * Implements policy_t.get_ref.
*/
-static policy_t *clone_(private_policy_t *this)
+static void get_ref(private_policy_t *this)
{
- private_policy_t *clone = (private_policy_t*)policy_create(this->name,
- this->my_id->clone(this->my_id),
- this->other_id->clone(this->other_id),
- this->hard_lifetime, this->soft_lifetime,
- this->jitter);
- iterator_t *iterator;
- proposal_t *proposal;
- traffic_selector_t *ts;
-
- /* clone the certification authorities */
- if (this->my_ca)
- {
- clone->my_ca = this->my_ca->clone(this->my_ca);
- }
- if (this->other_ca)
- {
- clone->other_ca = this->other_ca->clone(this->other_ca);
- }
-
- /* clone updown script */
- clone->updown = (this->updown == NULL)? NULL:strdup(this->updown);
-
- /* clone all proposals */
- iterator = this->proposals->create_iterator(this->proposals, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&proposal);
- proposal = proposal->clone(proposal);
- clone->proposals->insert_last(clone->proposals, (void*)proposal);
- }
- iterator->destroy(iterator);
-
- /* clone all local traffic selectors */
- iterator = this->my_ts->create_iterator(this->my_ts, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&ts);
- ts = ts->clone(ts);
- clone->my_ts->insert_last(clone->my_ts, (void*)ts);
- }
- iterator->destroy(iterator);
-
- /* clone all remote traffic selectors */
- iterator = this->other_ts->create_iterator(this->other_ts, TRUE);
- while (iterator->has_next(iterator))
- {
- iterator->current(iterator, (void**)&ts);
- ts = ts->clone(ts);
- clone->other_ts->insert_last(clone->other_ts, (void*)ts);
- }
- iterator->destroy(iterator);
-
- return &clone->public;
+ this->refcount++;
}
/**
* Implements policy_t.destroy.
*/
-static status_t destroy(private_policy_t *this)
-{
- proposal_t *proposal;
- traffic_selector_t *traffic_selector;
-
-
- /* delete proposals */
- while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
- {
- proposal->destroy(proposal);
- }
- this->proposals->destroy(this->proposals);
-
- /* delete traffic selectors */
- while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS)
- {
- traffic_selector->destroy(traffic_selector);
- }
- this->my_ts->destroy(this->my_ts);
-
- /* delete traffic selectors */
- while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS)
- {
- traffic_selector->destroy(traffic_selector);
- }
- this->other_ts->destroy(this->other_ts);
-
- /* delete certification authorities */
- if (this->my_ca)
- {
- this->my_ca->destroy(this->my_ca);
- }
- if (this->other_ca)
- {
- this->other_ca->destroy(this->other_ca);
- }
-
- /* delete updown script */
- if (this->updown)
+static void destroy(private_policy_t *this)
+{
+ if (--this->refcount == 0)
{
- free(this->updown);
+ proposal_t *proposal;
+ traffic_selector_t *traffic_selector;
+
+ /* delete proposals */
+ while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
+ {
+ proposal->destroy(proposal);
+ }
+ this->proposals->destroy(this->proposals);
+
+ /* delete traffic selectors */
+ while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS)
+ {
+ traffic_selector->destroy(traffic_selector);
+ }
+ this->my_ts->destroy(this->my_ts);
+
+ /* delete traffic selectors */
+ while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS)
+ {
+ traffic_selector->destroy(traffic_selector);
+ }
+ this->other_ts->destroy(this->other_ts);
+
+ /* delete certification authorities */
+ if (this->my_ca)
+ {
+ this->my_ca->destroy(this->my_ca);
+ }
+ if (this->other_ca)
+ {
+ this->other_ca->destroy(this->other_ca);
+ }
+
+ /* delete updown script */
+ if (this->updown)
+ {
+ free(this->updown);
+ }
+
+ /* delete ids */
+ this->my_id->destroy(this->my_id);
+ this->other_id->destroy(this->other_id);
+
+ free(this->name);
+ free(this);
}
-
- /* delete ids */
- this->my_id->destroy(this->my_id);
- this->other_id->destroy(this->other_id);
-
- free(this->name);
- free(this);
- return SUCCESS;
}
/*
@@ -494,7 +430,7 @@ static status_t destroy(private_policy_t *this)
*/
policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
u_int32_t hard_lifetime, u_int32_t soft_lifetime,
- u_int32_t jitter)
+ u_int32_t jitter, char *updown)
{
private_policy_t *this = malloc_thing(private_policy_t);
@@ -502,24 +438,20 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
this->public.get_name = (char *(*)(policy_t*))get_name;
this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id;
this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id;
- this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id;
- this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id;
- this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts;
- this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts;
- this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors;
- this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors;
- this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors;
- this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors;
+ this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*,host_t*))get_my_traffic_selectors;
+ this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*,host_t*))get_other_traffic_selectors;
+ this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*,host_t*))select_my_traffic_selectors;
+ this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*,host_t*))select_other_traffic_selectors;
this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals;
this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal;
this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector;
this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector;
this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal;
this->public.add_authorities = (void(*)(policy_t*,identification_t*, identification_t*))add_authorities;
- this->public.add_updown = (void(*)(policy_t*,char*))add_updown;
+ this->public.get_updown = (char*(*)(policy_t*))get_updown;
this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
- this->public.clone = (policy_t*(*)(policy_t*))clone_;
+ this->public.get_ref = (void(*)(policy_t*))get_ref;
this->public.destroy = (void(*)(policy_t*))destroy;
/* apply init values */
@@ -529,8 +461,10 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
this->hard_lifetime = hard_lifetime;
this->soft_lifetime = soft_lifetime;
this->jitter = jitter;
+ this->updown = (updown == NULL) ? NULL : strdup(updown);
/* initialize private members*/
+ this->refcount = 1;
this->my_ca = NULL;
this->other_ca = NULL;
this->proposals = linked_list_create();
@@ -538,5 +472,5 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
this->other_ts = linked_list_create();
this->logger = logger_manager->get_logger(logger_manager, CONFIG);
- return (&this->public);
+ return &this->public;
}
diff --git a/src/charon/config/policies/policy.h b/src/charon/config/policies/policy.h
index 329a48ff3..1a539f5bc 100644
--- a/src/charon/config/policies/policy.h
+++ b/src/charon/config/policies/policy.h
@@ -75,145 +75,103 @@ struct policy_t {
* @return other id
*/
identification_t *(*get_other_id) (policy_t *this);
-
- /**
- * @brief Update own ID.
- *
- * It may be necessary to uptdate own ID, as it
- * is set to %any or to e.g. *@strongswan.org in
- * some cases.
- * Old ID is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param my_id new ID to set as my_id
- */
- void (*update_my_id) (policy_t *this, identification_t *my_id);
-
- /**
- * @brief Update others ID.
- *
- * It may be necessary to uptdate others ID, as it
- * is set to %any or to e.g. *@strongswan.org in
- * some cases.
- * Old ID is destroyed, new one NOT cloned.
- *
- * @param this calling object
- * @param other_id new ID to set as other_id
- */
- void (*update_other_id) (policy_t *this, identification_t *other_id);
-
- /**
- * @brief Update own address in traffic selectors.
- *
- * Update own 0.0.0.0 address in traffic selectors
- * with supplied one. The size of the subnet will be
- * set to /32.
- *
- * @param this calling object
- * @param my_host new address to set in traffic selectors
- */
- void (*update_my_ts) (policy_t *this, host_t *my_host);
-
- /**
- * @brief Update others address in traffic selectors.
- *
- * Update remote 0.0.0.0 address in traffic selectors
- * with supplied one. The size of the subnet will be
- * set to /32.
- *
- * @param this calling object
- * @param other_host new address to set in traffic selectors
- */
- void (*update_other_ts) (policy_t *this, host_t *other_host);
/**
* @brief Get configured traffic selectors for our site.
*
* Returns a list with all traffic selectors for the local
- * site. List and items MUST NOT be freed nor modified.
+ * site. List and items must be destroyed after usage.
*
- * @param this calling object
- * @return list with traffic selectors
+ * @param this calling object
+ * @return list with traffic selectors
*/
- linked_list_t *(*get_my_traffic_selectors) (policy_t *this);
+ linked_list_t *(*get_my_traffic_selectors) (policy_t *this, host_t *me);
/**
* @brief Get configured traffic selectors for others site.
*
* Returns a list with all traffic selectors for the remote
- * site. List and items MUST NOT be freed nor modified.
+ * site. List and items must be destroyed after usage.
*
- * @param this calling object
- * @return list with traffic selectors
+ * @param this calling object
+ * @return list with traffic selectors
*/
- linked_list_t *(*get_other_traffic_selectors) (policy_t *this);
+ linked_list_t *(*get_other_traffic_selectors) (policy_t *this, host_t* other);
/**
* @brief Select traffic selectors from a supplied list for local site.
*
* Resulted list and traffic selectors must be destroyed after usage.
+ * As the traffic selectors may contain a wildcard address (0.0.0.0) for
+ * addresses we don't know in previous, an address may be supplied to
+ * replace these 0.0.0.0 addresses on-the-fly.
*
- * @param this calling object
- * @param supplied linked list with traffic selectors
- * @return list containing the selected traffic selectors
+ * @param this calling object
+ * @param supplied linked list with traffic selectors
+ * @param me host address used by us
+ * @return list containing the selected traffic selectors
*/
- linked_list_t *(*select_my_traffic_selectors) (policy_t *this, linked_list_t *supplied);
+ linked_list_t *(*select_my_traffic_selectors) (policy_t *this,
+ linked_list_t *supplied,
+ host_t *me);
/**
* @brief Select traffic selectors from a supplied list for remote site.
*
* Resulted list and traffic selectors must be destroyed after usage.
- *
- * @param this calling object
- * @param supplied linked list with traffic selectors
- * @return list containing the selected traffic selectors
+ * As the traffic selectors may contain a wildcard address (0.0.0.0) for
+ * addresses we don't know in previous, an address may be supplied to
+ * replace these 0.0.0.0 addresses on-the-fly.
+ *
+ * @param this calling object
+ * @param supplied linked list with traffic selectors
+ * @return list containing the selected traffic selectors
*/
- linked_list_t *(*select_other_traffic_selectors) (policy_t *this, linked_list_t *supplied);
+ linked_list_t *(*select_other_traffic_selectors) (policy_t *this,
+ linked_list_t *supplied,
+ host_t *other);
/**
* @brief Get the list of internally stored proposals.
*
- * Rembember: policy_t does store proposals for AH/ESP,
- * IKE proposals are in the connection_t
- *
- * @warning List and Items are still owned by policy and MUST NOT
- * be manipulated or freed!
- *
- * @param this calling object
- * @return lists with proposals
+ * policy_t does store proposals for AH/ESP, IKE proposals are in
+ * the connection_t.
+ * List and Items are still owned by policy and MUST NOT
+ * be manipulated or freed!
+ *
+ * @param this calling object
+ * @return lists with proposals
*/
linked_list_t *(*get_proposals) (policy_t *this);
/**
* @brief Select a proposal from a supplied list.
+ *
+ * Returned propsal is newly created and must be destroyed after usage.
*
- * @param this calling object
- * @param proposals list from from wich proposals are selected
- * @return selected proposal, or NULL if nothing matches
+ * @param this calling object
+ * @param proposals list from from wich proposals are selected
+ * @return selected proposal, or NULL if nothing matches
*/
proposal_t *(*select_proposal) (policy_t *this, linked_list_t *proposals);
/**
* @brief Add a traffic selector to the list for local site.
*
- * After add, proposal is owned by policy.
- *
- * @warning Do not add while other threads are reading.
+ * After add, traffic selector is owned by policy.
*
- * @param this calling object
- * @param traffic_selector traffic_selector to add
+ * @param this calling object
+ * @param traffic_selector traffic_selector to add
*/
void (*add_my_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
/**
* @brief Add a traffic selector to the list for remote site.
*
- * After add, proposal is owned by policy.
- *
- * @warning Do not add while other threads are reading.
+ * After add, traffic selector is owned by policy.
*
- * @param this calling object
- * @param traffic_selector traffic_selector to add
+ * @param this calling object
+ * @param traffic_selector traffic_selector to add
*/
void (*add_other_traffic_selector) (policy_t *this, traffic_selector_t *traffic_selector);
@@ -222,30 +180,29 @@ struct policy_t {
*
* The proposals are stored by priority, first added
* is the most prefered.
+ * After add, proposal is owned by policy.
*
- * @warning Do not add while other threads are reading.
- *
- * @param this calling object
- * @param proposal proposal to add
+ * @param this calling object
+ * @param proposal proposal to add
*/
void (*add_proposal) (policy_t *this, proposal_t *proposal);
/**
- * @brief Add certification authorities
+ * @brief Add certification authorities.
*
- * @param this calling object
- * @param my_ca issuer of my certificate
- * @param other_ca required issuer of the peer's certificate
+ * @param this calling object
+ * @param my_ca issuer of my certificate
+ * @param other_ca required issuer of the peer's certificate
*/
void (*add_authorities) (policy_t *this, identification_t *my_ca, identification_t *other_ca);
/**
- * @brief Add updown script
+ * @brief Get updown script
*
- * @param this calling object
- * @param updown updown script
+ * @param this calling object
+ * @return path to updown script
*/
- void (*add_updown) (policy_t *this, char *updown);
+ char* (*get_updown) (policy_t *this);
/**
* @brief Get the lifetime of a policy, before rekeying starts.
@@ -253,29 +210,34 @@ struct policy_t {
* A call to this function automatically adds a jitter to
* avoid simultanous rekeying.
*
- * @param this policy
- * @return lifetime in seconds
+ * @param this policy
+ * @return lifetime in seconds
*/
u_int32_t (*get_soft_lifetime) (policy_t *this);
/**
* @brief Get the lifetime of a policy, before SA gets deleted.
*
- * @param this policy
- * @return lifetime in seconds
+ * @param this policy
+ * @return lifetime in seconds
*/
u_int32_t (*get_hard_lifetime) (policy_t *this);
/**
- * @brief Clone a policy.
+ * @brief Get a new reference.
+ *
+ * Get a new reference to this policy by increasing
+ * it's internal reference counter.
*
- * @param this policy to clone
- * @return clone of it
+ * @param this calling object
*/
- policy_t *(*clone) (policy_t *this);
+ void (*get_ref) (policy_t *this);
/**
- * @brief Destroys the policy object
+ * @brief Destroys the policy object.
+ *
+ * Decrements the internal reference counter and
+ * destroys the policy when it reaches zero.
*
* @param this calling object
*/
@@ -291,6 +253,7 @@ struct policy_t {
* (soft_lifetime - random(0, jitter)). After a successful rekeying,
* the hard_lifetime limit counter is reset. You should specify
* hard_lifetime > soft_lifetime > jitter.
+ * After a call to create, a reference is obtained (refcount = 1).
*
* @param name name of the policy
* @param my_id identification_t for ourselves
@@ -298,11 +261,14 @@ struct policy_t {
* @param hard_lifetime lifetime before deleting an SA
* @param soft_lifetime lifetime before rekeying an SA
* @param jitter range of randomization time
+ * @param updown updown script to execute on up/down event
* @return policy_t object
*
* @ingroup config
*/
-policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
- u_int32_t hard_lifetime, u_int32_t soft_lifetime, u_int32_t jitter);
+policy_t *policy_create(char *name,
+ identification_t *my_id, identification_t *other_id,
+ u_int32_t hard_lifetime, u_int32_t soft_lifetime,
+ u_int32_t jitter, char *updown);
#endif /* POLICY_H_ */
diff --git a/src/charon/config/policies/policy_store.h b/src/charon/config/policies/policy_store.h
index 40cc87e2f..2ea57b8b4 100755
--- a/src/charon/config/policies/policy_store.h
+++ b/src/charon/config/policies/policy_store.h
@@ -25,13 +25,17 @@
#include <types.h>
#include <config/policies/policy.h>
+#include <utils/linked_list.h>
typedef struct policy_store_t policy_store_t;
/**
* @brief The interface for a store of policy_t's.
- *
+ *
+ * The store uses reference counting to manage their lifetime. Call
+ * destroy() for a policy which is returned from the store after usage.
+ *
* @b Constructors:
* - stroke_create()
*
@@ -40,28 +44,30 @@ typedef struct policy_store_t policy_store_t;
struct policy_store_t {
/**
- * @brief Returns a policy identified by two IDs.
+ * @brief Returns a policy identified by two IDs and a set of traffic selectors.
*
- * The returned policy gets created/cloned and therefore must be
- * destroyed by the caller.
* other_id must be fully qualified. my_id may be %any, as the
* other peer may not include an IDr Request.
*
- * @param this calling object
- * @param my_id own ID of the policy
- * @param other_id others ID of the policy
+ * @param this calling object
+ * @param my_id own ID of the policy
+ * @param other_id others ID of the policy
+ * @param my_ts traffic selectors requested for local host
+ * @param other_ts traffic selectors requested for remote host
+ * @param my_host host to use for wilcards in TS compare
+ * @param other_host host to use for wildcards in TS compare
* @return
- * - matching policy_t, if found
- * - NULL otherwise
+ * - matching policy_t, if found
+ * - NULL otherwise
*/
- policy_t *(*get_policy_by_ids) (policy_store_t *this, identification_t *my_id, identification_t *other_id);
+ policy_t *(*get_policy) (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);
/**
* @brief Returns a policy identified by a connection name.
*
- * The returned policy gets created/cloned and therefore must be
- * destroyed by the caller.
- *
* @param this calling object
* @param name name of the policy
* @return
diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c
index b0b0a13ce..3a9480f77 100644
--- a/src/charon/config/traffic_selector.c
+++ b/src/charon/config/traffic_selector.c
@@ -356,16 +356,18 @@ static void update_address_range(private_traffic_selector_t *this, host_t *host)
*/
static traffic_selector_t *clone_(private_traffic_selector_t *this)
{
- private_traffic_selector_t *clone = traffic_selector_create(this->protocol, this->type, this->from_port, this->to_port);
- clone->type = this->type;
- clone->string = strdup(this->string);
+ private_traffic_selector_t *clone;
+
+ clone = traffic_selector_create(this->protocol, this->type,
+ this->from_port, this->to_port);
switch (clone->type)
{
case TS_IPV4_ADDR_RANGE:
{
clone->from_addr_ipv4 = this->from_addr_ipv4;
clone->to_addr_ipv4 = this->to_addr_ipv4;
- return &(clone->public);
+ update_string(clone);
+ return &clone->public;
}
case TS_IPV6_ADDR_RANGE:
default:
@@ -391,8 +393,7 @@ static void destroy(private_traffic_selector_t *this)
traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from_addr, u_int16_t from_port, chunk_t to_addr, u_int16_t to_port)
{
private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
-
- this->type = type;
+
switch (type)
{
case TS_IPV4_ADDR_RANGE:
@@ -400,12 +401,12 @@ traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_typ
if (from_addr.len != 4 || to_addr.len != 4)
{
free(this);
- return NULL;
+ return NULL;
}
/* chunk contains network order, convert! */
this->from_addr_ipv4 = ntohl(*((u_int32_t*)from_addr.ptr));
this->to_addr_ipv4 = ntohl(*((u_int32_t*)to_addr.ptr));
- break;
+ break;
}
case TS_IPV6_ADDR_RANGE:
default: