introduced refcounting on policy and connections
authorMartin Willi <martin@strongswan.org>
Thu, 20 Jul 2006 10:09:32 +0000 (10:09 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 20 Jul 2006 10:09:32 +0000 (10:09 -0000)
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

28 files changed:
src/charon/config/connections/connection.c
src/charon/config/connections/connection.h
src/charon/config/connections/local_connection_store.c
src/charon/config/policies/local_policy_store.c
src/charon/config/policies/policy.c
src/charon/config/policies/policy.h
src/charon/config/policies/policy_store.h
src/charon/config/traffic_selector.c
src/charon/queues/jobs/initiate_ike_sa_job.c
src/charon/queues/jobs/initiate_ike_sa_job.h
src/charon/sa/authenticator.c
src/charon/sa/authenticator.h
src/charon/sa/child_sa.c
src/charon/sa/child_sa.h
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/ike_sa_manager.c
src/charon/sa/transactions/create_child_sa.c
src/charon/sa/transactions/create_child_sa.h
src/charon/sa/transactions/dead_peer_detection.c
src/charon/sa/transactions/delete_child_sa.c
src/charon/sa/transactions/delete_ike_sa.c
src/charon/sa/transactions/ike_auth.c
src/charon/sa/transactions/ike_auth.h
src/charon/sa/transactions/ike_sa_init.c
src/charon/sa/transactions/ike_sa_init.h
src/charon/threads/stroke_interface.c
src/libstrongswan/definitions.h

index 3de57ca..e1ab039 100644 (file)
@@ -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;
 }
index dca570e..111acd5 100644 (file)
@@ -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.
index c6e982e..1f961cb 100644 (file)
@@ -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;
 }
 
index 2054b9d..0c3e0ee 100644 (file)
@@ -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;
index 152c157..a64af32 100644 (file)
@@ -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;
 }
index 329a48f..1a539f5 100644 (file)
@@ -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_ */
index 40cc87e..2ea57b8 100755 (executable)
 
 #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
index b0b0a13..3a9480f 100644 (file)
@@ -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:
index 6c753fd..38108ca 100644 (file)
@@ -41,11 +41,16 @@ struct private_initiate_ike_sa_job_t {
        initiate_ike_sa_job_t public;
        
        /**
-        * associated connection object to initiate
+        * associated connection to initiate
         */
        connection_t *connection;
        
        /**
+        * associated policy to initiate
+        */
+       policy_t *policy;
+       
+       /**
         * logger
         */
        logger_t *logger;
@@ -75,7 +80,9 @@ static status_t execute(private_initiate_ike_sa_job_t *this)
        this->logger->log(this->logger, CONTROL|LEVEL2, "Creating and checking out IKE SA");
        charon->ike_sa_manager->create_and_checkout(charon->ike_sa_manager, &ike_sa);
        
-       status = ike_sa->initiate(ike_sa, this->connection->clone(this->connection));
+       this->connection->get_ref(this->connection);
+       this->policy->get_ref(this->policy);
+       status = ike_sa->initiate(ike_sa, this->connection, this->policy);
        if (status != SUCCESS)
        {
                this->logger->log(this->logger, ERROR,
@@ -95,13 +102,14 @@ static status_t execute(private_initiate_ike_sa_job_t *this)
 static void destroy(private_initiate_ike_sa_job_t *this)
 {
        this->connection->destroy(this->connection);
+       this->policy->destroy(this->policy);
        free(this);
 }
 
 /*
  * Described in header
  */
-initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection)
+initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection, policy_t *policy)
 {
        private_initiate_ike_sa_job_t *this = malloc_thing(private_initiate_ike_sa_job_t);
        
@@ -112,7 +120,8 @@ initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection)
        
        /* private variables */
        this->connection = connection;
+       this->policy = policy;
        this->logger = logger_manager->get_logger(logger_manager, WORKER);
        
-       return &(this->public);
+       return &this->public;
 }
index fe81d31..c119cf3 100644 (file)
@@ -26,6 +26,7 @@
 #include <types.h>
 #include <queues/jobs/job.h>
 #include <config/connections/connection.h>
+#include <config/policies/policy.h>
 
 
 typedef struct initiate_ike_sa_job_t initiate_ike_sa_job_t;
@@ -33,8 +34,7 @@ typedef struct initiate_ike_sa_job_t initiate_ike_sa_job_t;
 /**
  * @brief Class representing an INITIATE_IKE_SA Job.
  * 
- * This job is created if an IKE_SA should be iniated. This 
- * happens via a user request, or via the kernel interface.
+ * This job is created if an IKE_SA should be iniated.
  * 
  * @b Constructors:
  * - initiate_ike_sa_job_create()
@@ -52,10 +52,12 @@ struct initiate_ike_sa_job_t {
  * @brief Creates a job of type INITIATE_IKE_SA.
  * 
  * @param connection   connection_t to initializes
+ * @param policy               policy to set up
  * @return                             initiate_ike_sa_job_t object
  * 
  * @ingroup jobs
  */
-initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection);
+initiate_ike_sa_job_t *initiate_ike_sa_job_create(connection_t *connection,
+                                                                                                 policy_t *policy);
 
 #endif /*INITIATE_IKE_SA_JOB_H_*/
index fb4bdde..8dcfc04 100644 (file)
@@ -51,6 +51,11 @@ struct private_authenticator_t {
        ike_sa_t *ike_sa;
        
        /**
+        * auth_method to create own signature/mac/whatever..
+        */
+       auth_method_t auth_method;
+       
+       /**
         * PRF taken from the IKE_SA.
         */
        prf_t *prf;
@@ -294,10 +299,8 @@ static status_t compute_auth_data (private_authenticator_t *this,
                                                                        chunk_t other_nonce,
                                                                        id_payload_t *my_id_payload,
                                                                        bool initiator)
-{
-       connection_t *connection = this->ike_sa->get_connection(this->ike_sa);
-       
-       switch(connection->get_auth_method(connection))
+{      
+       switch(this->auth_method)
        {
                case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
                {
@@ -405,7 +408,7 @@ static void destroy (private_authenticator_t *this)
 /*
  * Described in header.
  */
-authenticator_t *authenticator_create(ike_sa_t *ike_sa)
+authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method)
 {
        private_authenticator_t *this = malloc_thing(private_authenticator_t);
 
@@ -420,6 +423,7 @@ authenticator_t *authenticator_create(ike_sa_t *ike_sa)
        
        /* private data */
        this->ike_sa = ike_sa;
+       this->auth_method = auth_method;
        this->prf = this->ike_sa->get_prf(this->ike_sa);
        this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
        
index 99a56e2..645e39b 100644 (file)
@@ -122,11 +122,12 @@ struct authenticator_t {
  * @brief Creates an authenticator object.
  * 
  * @param ike_sa               associated ike_sa
+ * @param auth_method  authentication method to use for own signature/mac
  * 
  * @return                             authenticator_t object
  * 
  * @ingroup sa
  */
-authenticator_t *authenticator_create(ike_sa_t *ike_sa);
+authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_method);
 
 #endif /* AUTHENTICATOR_H_ */
index c9c6794..38b4fa8 100644 (file)
@@ -96,6 +96,16 @@ struct private_child_sa_t {
        linked_list_t *policies;
        
        /**
+        * Seperate list for local traffic selectors
+        */
+       linked_list_t *my_ts;
+       
+       /**
+        * Seperate list for remote traffic selectors
+        */
+       linked_list_t *other_ts;
+       
+       /**
         * reqid used for this child_sa
         */
        u_int32_t reqid;
@@ -473,6 +483,9 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
                        policy->my_ts = my_ts->clone(my_ts);
                        policy->other_ts = other_ts->clone(other_ts);
                        this->policies->insert_last(this->policies, (void*)policy);
+                       /* add to separate list to query them via get_*_traffic_selectors() */
+                       this->my_ts->insert_last(this->my_ts, (void*)policy->my_ts);
+                       this->other_ts->insert_last(this->other_ts, (void*)policy->other_ts);
                }
        }
        my_iter->destroy(my_iter);
@@ -481,6 +494,22 @@ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list
 }
 
 /**
+ * Implementation of child_sa_t.get_my_traffic_selectors.
+ */
+static linked_list_t *get_my_traffic_selectors(private_child_sa_t *this)
+{
+       return this->my_ts;
+}
+
+/**
+ * Implementation of child_sa_t.get_my_traffic_selectors.
+ */
+static linked_list_t *get_other_traffic_selectors(private_child_sa_t *this)
+{
+       return this->other_ts;
+}
+
+/**
  * Implementation of child_sa_t.set_rekeying_transaction.
  */
 static void set_rekeying_transaction(private_child_sa_t *this, void *transaction)
@@ -819,6 +848,8 @@ static void destroy(private_child_sa_t *this)
        }
        this->policies->destroy(this->policies);
        
+       this->my_ts->destroy(this->my_ts);
+       this->other_ts->destroy(this->other_ts);
        this->me.addr->destroy(this->me.addr);
        this->other.addr->destroy(this->other.addr);
        free(this);
@@ -843,6 +874,8 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
        this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update;
        this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_diff_t,host_diff_t))update_hosts;
        this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
+       this->public.get_my_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_my_traffic_selectors;
+       this->public.get_other_traffic_selectors = (linked_list_t*(*)(child_sa_t*))get_other_traffic_selectors;
        this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
        this->public.set_rekeying_transaction = (void (*)(child_sa_t*,void*))set_rekeying_transaction;
        this->public.get_rekeying_transaction = (void* (*)(child_sa_t*))get_rekeying_transaction;
@@ -866,6 +899,8 @@ child_sa_t * child_sa_create(u_int32_t rekey, host_t *me, host_t* other,
        /* reuse old reqid if we are rekeying an existing CHILD_SA */
        this->reqid = rekey ? rekey : ++reqid;
        this->policies = linked_list_create();
+       this->my_ts = linked_list_create();
+       this->other_ts = linked_list_create();
        this->protocol = PROTO_NONE;
        this->rekeying_transaction = NULL;
        
index 33d06a7..2a74a2a 100644 (file)
@@ -177,7 +177,7 @@ struct child_sa_t {
         * @return                              SUCCESS or FAILED
         */
        status_t (*update_hosts) (child_sa_t *this, host_t *new_me, host_t *new_other, 
-                                                         host_diff_t my_diff, host_diff_t other_diff);
+       host_diff_t my_diff, host_diff_t other_diff);
        
        /**
         * @brief Install the policies using some traffic selectors.
@@ -193,6 +193,22 @@ struct child_sa_t {
        status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list);
        
        /**
+        * @brief Get the traffic selectors of added policies of local host.
+        *
+        * @param this          calling object
+        * @return                      list of traffic selectors
+        */     
+       linked_list_t* (*get_my_traffic_selectors) (child_sa_t *this);
+       
+       /**
+        * @brief Get the traffic selectors of added policies of remote host.
+        *
+        * @param this          calling object
+        * @return                      list of traffic selectors
+        */     
+       linked_list_t* (*get_other_traffic_selectors) (child_sa_t *this);
+       
+       /**
         * @brief Get the time of this child_sa_t's last use (i.e. last use of any of its policies)
         * 
         * @param this          calling object
index c233afc..569d879 100644 (file)
@@ -86,24 +86,39 @@ struct private_ike_sa_t {
        ike_sa_id_t *ike_sa_id;
        
        /**
-        * Linked List containing the child sa's of the current IKE_SA.
+        * Current state of the IKE_SA
         */
-       linked_list_t *child_sas;
+       ike_sa_state_t state;
        
        /**
-        * Current state of the IKE_SA
+        * Name of the connection used by this IKE_SA
         */
-       ike_sa_state_t state;
+       char *name;
+       
+       /**
+        * Address of local host
+        */
+       host_t *my_host;
+       
+       /**
+        * Address of remote host
+        */
+       host_t *other_host;
+       
+       /**
+        * Identification used for us
+        */
+       identification_t *my_id;
        
        /**
-        * Connection definition used for this IKE_SA
+        * Identification used for other
         */
-       connection_t *connection;
+       identification_t *other_id;
        
        /**
-        * Policy definition used for this IKE_SA
+        * Linked List containing the child sa's of the current IKE_SA.
         */
-       policy_t *policy;
+       linked_list_t *child_sas;
        
        /**
         * crypter for inbound traffic
@@ -208,7 +223,7 @@ struct private_ike_sa_t {
 /**
  * get the time of the latest traffic processed by the kernel
  */
-static time_t get_esp_time(private_ike_sa_t* this, bool inbound)
+static time_t get_kernel_time(private_ike_sa_t* this, bool inbound)
 {
        iterator_t *iterator;
        child_sa_t *child_sa;
@@ -232,7 +247,7 @@ static time_t get_esp_time(private_ike_sa_t* this, bool inbound)
  */
 static time_t get_time_inbound(private_ike_sa_t *this)
 {
-       return max(this->time_inbound, get_esp_time(this, TRUE));
+       return max(this->time_inbound, get_kernel_time(this, TRUE));
 }
 
 /**
@@ -240,9 +255,41 @@ static time_t get_time_inbound(private_ike_sa_t *this)
  */
 static time_t get_time_outbound(private_ike_sa_t *this)
 {
-       return max(this->time_outbound, get_esp_time(this, FALSE));
+       return max(this->time_outbound, get_kernel_time(this, FALSE));
 }
 
+/**
+ * Implementation of ike_sa_t.get_name.
+ */
+static char *get_name(private_ike_sa_t *this)
+{
+       return this->name;
+}
+
+/**
+ * Implementation of ike_sa_t.set_name.
+ */
+static void set_name(private_ike_sa_t *this, char* name)
+{
+       free(this->name);
+       this->name = strdup(name);
+}
+
+/**
+ * Implementation of ike_sa_t.get_my_host.
+ */
+static host_t *get_my_host(private_ike_sa_t *this)
+{
+       return this->my_host;
+}
+
+/**
+ * Implementation of ike_sa_t.get_other_host.
+ */
+static host_t *get_other_host(private_ike_sa_t *this)
+{
+       return this->other_host;
+}
 
 /**
  * Update connection host, as addresses may change (NAT)
@@ -278,53 +325,58 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
         *    packet or any authenticated UDP-encapsulated ESP packet can be
         *    used to detect that the IP address or the port has changed.
         */
-       host_t *old_other = NULL;
        iterator_t *iterator = NULL;
        child_sa_t *child_sa = NULL;
-       int my_changes, other_changes;
-
-       my_changes = me->get_differences(me, this->connection->get_my_host(this->connection));
-
-       old_other = this->connection->get_other_host(this->connection);
-       other_changes = other->get_differences(other, old_other);
-
-       if (!my_changes && !other_changes) 
+       host_diff_t my_diff, other_diff;
+       
+       if (this->my_host == NULL || this->other_host == NULL)
+       {
+               /* on first received message */
+               this->my_host = me->clone(me);
+               this->other_host = other->clone(other);
+               return;
+       }
+       
+       my_diff = me->get_differences(me, this->my_host);
+       other_diff = other->get_differences(other, this->other_host);
+       
+       if (!my_diff && !other_diff)
        {
                return;
        }
        
-       if (my_changes)
+       if (my_diff)
        {
-               this->connection->update_my_host(this->connection, me->clone(me));
+               this->my_host->destroy(this->my_host);
+               this->my_host = me->clone(me);
        }
        
        if (!this->nat_here)
        {
                /* update without restrictions if we are not NATted */
-               if (other_changes)
+               if (other_diff)
                {
-                       this->connection->update_other_host(this->connection, other->clone(other));
+                       this->other_host->destroy(this->other_host);
+                       this->other_host = other->clone(other);
                }
        }
        else
        {
                /* if we are natted, only port may change */
-               if (other_changes & HOST_DIFF_ADDR)
+               if (other_diff & HOST_DIFF_ADDR)
                {
                        return;
                }
-               else if (other_changes & HOST_DIFF_PORT)
+               else if (other_diff & HOST_DIFF_PORT)
                {
-                       old_other->set_port(old_other, other->get_port(other));
+                       this->other_host->set_port(this->other_host, other->get_port(other));
                }
        }
        iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
        while (iterator->iterate(iterator, (void**)&child_sa))
        {
-               child_sa->update_hosts(child_sa,
-                                                          this->connection->get_my_host(this->connection),
-                                                          this->connection->get_other_host(this->connection),
-                                                          my_changes, other_changes);
+               child_sa->update_hosts(child_sa, this->my_host, this->other_host, 
+                                                          my_diff, other_diff);
                /* TODO: what to do if update fails? Delete CHILD_SA? */
        }
        iterator->destroy(iterator);
@@ -705,7 +757,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
        else
        {
                /* check if message is trustworthy, and update connection information */
-               if ((this->state == IKE_CREATED && this->connection) ||
+               if (this->state == IKE_CREATED ||
                        message->get_exchange_type(message) != IKE_SA_INIT)
                {
                        update_hosts(this, message->get_destination(message),
@@ -727,26 +779,60 @@ static status_t process_message(private_ike_sa_t *this, message_t *message)
 /**
  * Implementation of ike_sa_t.initiate.
  */
-static status_t initiate(private_ike_sa_t *this, connection_t *connection)
+static status_t initiate(private_ike_sa_t *this,
+                                                connection_t *connection, policy_t *policy)
 {
        ike_sa_init_t *ike_sa_init;
        
-       /* set connection and policy */
-       this->connection = connection;
-       this->policy = charon->policies->get_policy_by_name(charon->policies,
-                       this->connection->get_name(this->connection));
-       if (this->policy == NULL)
-       {
-               this->logger->log(this->logger, ERROR,
-                                                 "no policy found for connection %s, aborting",
-                                                 connection->get_name(connection));
-               return DESTROY_ME;
-       }
+       set_name(this, connection->get_name(connection));
+       
+       /* apply hosts from connection */
+       this->my_host = connection->get_my_host(connection);
+       this->my_host = this->my_host->clone(this->my_host);
+       this->other_host = connection->get_other_host(connection);
+       this->other_host = this->other_host->clone(this->other_host);
+       
        this->message_id_out = 1;
        ike_sa_init = ike_sa_init_create(&this->public);
+       ike_sa_init->set_config(ike_sa_init, connection, policy);
        return queue_transaction(this, (transaction_t*)ike_sa_init, TRUE);
 }
 
+
+/**
+ * Implementation of ike_sa_t.acquire.
+ */
+static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
+{
+       /* - get TS from child with reqid
+        * - get a policy from TS
+        * - get connection from policy
+        */
+       switch (this->state)
+       {
+               case IKE_CREATED:
+                       /* ike_sa_init */
+                       break;
+               case IKE_CONNECTING:
+               case IKE_ESTABLISHED:
+                       /* queue create_child_sa */
+                       break;
+               case IKE_DELETING:
+                       /* deny */
+                       break;
+       }
+       return FAILED;
+}
+
+/**
+ * Implementation of ike_sa_t.route.
+ */
+static status_t route(private_ike_sa_t *this, policy_t *policy)
+{
+       /* TODO: create CHILD_SA, add policy */
+       return FAILED;
+}
+
 /**
  * Implementation of ike_sa_t.send_dpd
  */
@@ -803,15 +889,12 @@ static void send_keepalive(private_ike_sa_t *this)
        
        if (diff >= interval)
        {
-               host_t *me, *other;
                packet_t *packet;
                chunk_t data;
                
                packet = packet_create();
-               me = this->connection->get_my_host(this->connection);
-               other = this->connection->get_other_host(this->connection);
-               packet->set_source(packet, me->clone(me));
-               packet->set_destination(packet, other->clone(other));
+               packet->set_source(packet, this->my_host->clone(this->my_host));
+               packet->set_destination(packet, this->other_host->clone(this->other_host));
                data.ptr = malloc(1);
                data.ptr[0] = 0xFF;
                data.len = 1;
@@ -843,17 +926,11 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
                                          mapping_find(ike_sa_state_m, state));
        if (state == IKE_ESTABLISHED)
        {
-               host_t *my_host, *other_host;
-               identification_t *my_id, *other_id;
-               my_host = this->connection->get_my_host(this->connection);
-               other_host = this->connection->get_other_host(this->connection);
-               my_id = this->policy->get_my_id(this->policy);
-               other_id = this->policy->get_other_id(this->policy);
                this->logger->log(this->logger, AUDIT, "IKE_SA established: %s[%s]...%s[%s]",
-                                                 my_host->get_string(my_host),
-                                                 my_id->get_string(my_id),
-                                                 other_host->get_string(other_host),
-                                                 other_id->get_string(other_id));
+                                                 this->my_host->get_string(this->my_host),
+                                                 this->my_id->get_string(this->my_id),
+                                                 this->other_host->get_string(this->other_host),
+                                                 this->other_id->get_string(this->other_id));
                
                send_dpd(this);
        }
@@ -861,74 +938,75 @@ static void set_state(private_ike_sa_t *this, ike_sa_state_t state)
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_connection.
+ * Implementation of protected_ike_sa_t.get_prf.
  */
-static connection_t *get_connection(private_ike_sa_t *this)
+static prf_t *get_prf(private_ike_sa_t *this)
 {
-       return this->connection;
+       return this->prf;
 }
 
 /**
- * Implementation of protected_ike_sa_t.set_connection.
+ * Implementation of protected_ike_sa_t.get_prf.
  */
-static void set_connection(private_ike_sa_t *this,connection_t * connection)
+static prf_t *get_child_prf(private_ike_sa_t *this)
 {
-       this->connection = connection;
+       return this->child_prf;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_policy.
+ * Implementation of protected_ike_sa_t.get_prf_auth_i.
  */
-static policy_t *get_policy(private_ike_sa_t *this)
+static prf_t *get_prf_auth_i(private_ike_sa_t *this)
 {
-       return this->policy;
+       return this->prf_auth_i;
 }
 
 /**
- * Implementation of protected_ike_sa_t.set_policy.
+ * Implementation of protected_ike_sa_t.get_prf_auth_r.
  */
-static void set_policy(private_ike_sa_t *this,policy_t * policy)
+static prf_t *get_prf_auth_r(private_ike_sa_t *this)
 {
-       this->policy = policy;
+       return this->prf_auth_r;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_prf.
+ * Implementation of ike_sa_t.get_id.
  */
-static prf_t *get_prf(private_ike_sa_t *this)
+static ike_sa_id_t* get_id(private_ike_sa_t *this)
 {
-       return this->prf;
+       return this->ike_sa_id;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_prf.
+ * Implementation of ike_sa_t.get_my_id.
  */
-static prf_t *get_child_prf(private_ike_sa_t *this)
+static identification_t* get_my_id(private_ike_sa_t *this)
 {
-       return this->child_prf;
+       return this->my_id;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_prf_auth_i.
+ * Implementation of ike_sa_t.set_my_id.
  */
-static prf_t *get_prf_auth_i(private_ike_sa_t *this)
+static void set_my_id(private_ike_sa_t *this, identification_t *me)
 {
-       return this->prf_auth_i;
+       this->my_id = me;
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_prf_auth_r.
+ * Implementation of ike_sa_t.get_other_id.
  */
-static prf_t *get_prf_auth_r(private_ike_sa_t *this)
+static identification_t* get_other_id(private_ike_sa_t *this)
 {
-       return this->prf_auth_r;
+       return this->other_id;
 }
+
 /**
- * Implementation of ike_sa_t.get_id.
+ * Implementation of ike_sa_t.set_other_id.
  */
-static ike_sa_id_t* get_id(private_ike_sa_t *this)
+static void set_other_id(private_ike_sa_t *this, identification_t *other)
 {
-       return this->ike_sa_id;
+       this->other_id = other;
 }
 
 /**
@@ -1201,55 +1279,41 @@ static void log_status(private_ike_sa_t *this, logger_t *logger, char *name)
 {
        iterator_t *iterator;
        child_sa_t *child_sa;
-       host_t *my_host, *other_host;
-       identification_t *my_id = NULL, *other_id = NULL;
+       char *my_host, *other_host, *my_id, *other_id;
        
-       /* only log if name == NULL or name == connection_name */
-       if (name)
+       if (name == NULL || streq(name, this->name))
        {
-               if (streq(this->connection->get_name(this->connection), name))
+               if (logger == NULL)
                {
-                       return;
+                       logger = this->logger;
                }
+               
+               my_host = this->my_host ?
+                               this->my_host->get_string(this->my_host) : "(unknown)";
+               other_host = this->other_host ?
+                               this->other_host->get_string(this->other_host) : "(unknown)";
+               my_id = this->my_id ?
+                               this->my_id->get_string(this->my_id) : "(unknown)";
+               other_id = this->other_id ?
+                               this->other_id->get_string(this->other_id) : "(unknown)";
+               
+               logger->log(logger, CONTROL|LEVEL1, 
+                                       "  \"%s\": IKE_SA in state %s, SPIs: 0x%.16llx 0x%.16llx",
+                                       this->name,
+                                       mapping_find(ike_sa_state_m, this->state),
+                                       this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
+                                       this->ike_sa_id->get_responder_spi(this->ike_sa_id));
+               logger->log(logger, CONTROL, "  \"%s\": %s[%s]...%s[%s]",
+                                       this->name, my_host, my_id, other_host, other_id);
+               
+               iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
+               while (iterator->has_next(iterator))
+               {
+                       iterator->current(iterator, (void**)&child_sa);
+                       child_sa->log_status(child_sa, logger, this->name);
+               }
+               iterator->destroy(iterator);
        }
-       my_host = this->connection->get_my_host(this->connection);
-       other_host = this->connection->get_other_host(this->connection);
-
-       /* use policy information, if available */
-       if (this->policy)
-       {
-               my_id = this->policy->get_my_id(this->policy);
-               other_id = this->policy->get_other_id(this->policy);
-               name = this->policy->get_name(this->policy);
-       }
-       else
-       {
-               name = this->connection->get_name(this->connection);
-       }
-       
-       if (logger == NULL)
-       {
-               logger = this->logger;
-       }
-       logger->log(logger, CONTROL|LEVEL1, "  \"%s\": IKE_SA in state %s, SPIs: 0x%.16llx 0x%.16llx",
-                               name,
-                               mapping_find(ike_sa_state_m, this->state),
-                               this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
-                               this->ike_sa_id->get_responder_spi(this->ike_sa_id));
-       logger->log(logger, CONTROL, "  \"%s\": %s[%s]...%s[%s]",
-                               name,
-                               my_host->get_string(my_host),
-                               my_id ? my_id->get_string(my_id) : "(unknown)",
-                               other_host->get_string(other_host),
-                               other_id ? other_id->get_string(other_id) : "(unknown)");
-       
-       iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
-       while (iterator->has_next(iterator))
-       {
-               iterator->current(iterator, (void**)&child_sa);
-               child_sa->log_status(child_sa, logger, name);
-       }
-       iterator->destroy(iterator);
 }
 
 /**
@@ -1313,6 +1377,7 @@ static void destroy(private_ike_sa_t *this)
 {
        child_sa_t *child_sa;
        transaction_t *transaction;
+       char *my_host, *other_host, *my_id, *other_id;
        
        this->logger->log(this->logger, CONTROL|LEVEL2, "going to destroy IKE SA %llu:%llu, role %s", 
                                          this->ike_sa_id->get_initiator_spi(this->ike_sa_id),
@@ -1336,73 +1401,38 @@ static void destroy(private_ike_sa_t *this)
                transaction->destroy(transaction);
        }
        this->transaction_queue->destroy(this->transaction_queue);
-       if (this->transaction_in)
-       {
-               this->transaction_in->destroy(this->transaction_in);
-       }
-       if (this->transaction_in_next)
-       {
-               this->transaction_in_next->destroy(this->transaction_in_next);
-       }
-       if (this->transaction_out)
-       {
-               this->transaction_out->destroy(this->transaction_out);
-       }
-       if (this->crypter_in)
-       {
-               this->crypter_in->destroy(this->crypter_in);
-       }
-       if (this->crypter_out)
-       {
-               this->crypter_out->destroy(this->crypter_out);
-       }
-       if (this->signer_in)
-       {
-               this->signer_in->destroy(this->signer_in);
-       }
-       if (this->signer_out)
-       {
-               this->signer_out->destroy(this->signer_out);
-       }
-       if (this->prf)
-       {
-               this->prf->destroy(this->prf);
-       }
-       if (this->child_prf)
-       {
-               this->child_prf->destroy(this->child_prf);
-       }
-       if (this->prf_auth_i)
-       {
-               this->prf_auth_i->destroy(this->prf_auth_i);
-       }
-       if (this->prf_auth_r)
-       {
-               this->prf_auth_r->destroy(this->prf_auth_r);
-       }
-       if (this->connection)
-       {
-               host_t *my_host, *other_host;
-               identification_t *my_id = NULL, *other_id = NULL;
-               my_host = this->connection->get_my_host(this->connection);
-               other_host = this->connection->get_other_host(this->connection);
-               if (this->policy)
-               {
-                       my_id = this->policy->get_my_id(this->policy);
-                       other_id = this->policy->get_other_id(this->policy);
-               }
-               
-               this->logger->log(this->logger, AUDIT, "IKE_SA deleted between %s[%s]...%s[%s]", 
-                                                 my_host->get_string(my_host),
-                                                 my_id ? my_id->get_string(my_id) : "(unknown)",
-                                                 other_host->get_string(other_host),
-                                                 other_id ? other_id->get_string(other_id) : "(unknown)");
-               this->connection->destroy(this->connection);
-       }
-       if (this->policy)
-       {
-               this->policy->destroy(this->policy);
-       }
+       
+       DESTROY_IF(this->transaction_in);
+       DESTROY_IF(this->transaction_in_next);
+       DESTROY_IF(this->transaction_out);
+       DESTROY_IF(this->crypter_in);
+       DESTROY_IF(this->crypter_out);
+       DESTROY_IF(this->signer_in);
+       DESTROY_IF(this->signer_out);
+       DESTROY_IF(this->prf);
+       DESTROY_IF(this->child_prf);
+       DESTROY_IF(this->prf_auth_i);
+       DESTROY_IF(this->prf_auth_r);
+       
+       my_host = this->my_host ?
+                       this->my_host->get_string(this->my_host) : "(unknown)";
+       other_host = this->other_host ?
+                       this->other_host->get_string(this->other_host) : "(unknown)";
+       my_id = this->my_id ?
+                       this->my_id->get_string(this->my_id) : "(unknown)";
+       other_id = this->other_id ?
+                       this->other_id->get_string(this->other_id) : "(unknown)";
+
+       this->logger->log(this->logger, AUDIT, 
+                                         "IKE_SA deleted between %s[%s]...%s[%s]", 
+                                         my_host, my_id, other_host, other_id);
+       
+       DESTROY_IF(this->my_host);
+       DESTROY_IF(this->other_host);
+       DESTROY_IF(this->my_id);
+       DESTROY_IF(this->other_id);
+       
+       free(this->name);
        this->ike_sa_id->destroy(this->ike_sa_id);
        free(this);
 }
@@ -1417,11 +1447,20 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        /* Public functions */
        this->public.get_state = (ike_sa_state_t(*)(ike_sa_t*)) get_state;
        this->public.set_state = (void(*)(ike_sa_t*,ike_sa_state_t)) set_state;
+       this->public.get_name = (char*(*)(ike_sa_t*))get_name;
+       this->public.set_name = (void(*)(ike_sa_t*,char*))set_name;
        this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
-       this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*)) initiate;
+       this->public.initiate = (status_t(*)(ike_sa_t*,connection_t*,policy_t*)) initiate;
+       this->public.route = (status_t(*)(ike_sa_t*,policy_t*)) route;
+       this->public.acquire = (status_t(*)(ike_sa_t*,u_int32_t)) acquire;
        this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
+       this->public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
+       this->public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host;
+       this->public.get_my_id = (identification_t*(*)(ike_sa_t*)) get_my_id;
+       this->public.set_my_id = (void(*)(ike_sa_t*,identification_t*)) set_my_id;
+       this->public.get_other_id = (identification_t*(*)(ike_sa_t*)) get_other_id;
+       this->public.set_other_id = (void(*)(ike_sa_t*,identification_t*)) set_other_id;
        this->public.get_next_message_id = (u_int32_t(*)(ike_sa_t*)) get_next_message_id;
-       this->public.get_connection = (connection_t*(*)(ike_sa_t*)) get_connection;
        this->public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request;
        this->public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status;
        this->public.delete = (status_t(*)(ike_sa_t*))delete_;
@@ -1432,10 +1471,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->public.get_child_prf = (prf_t *(*) (ike_sa_t *)) get_child_prf;
        this->public.get_prf_auth_i = (prf_t *(*) (ike_sa_t *)) get_prf_auth_i;
        this->public.get_prf_auth_r = (prf_t *(*) (ike_sa_t *)) get_prf_auth_r;
-       this->public.set_connection = (void (*) (ike_sa_t *,connection_t *)) set_connection;
-       this->public.get_connection = (connection_t *(*) (ike_sa_t *)) get_connection;
-       this->public.set_policy = (void (*) (ike_sa_t *,policy_t *)) set_policy;
-       this->public.get_policy = (policy_t *(*) (ike_sa_t *)) get_policy;
        this->public.build_transforms = (status_t (*) (ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t,bool)) build_transforms;
        this->public.add_child_sa = (void (*) (ike_sa_t*,child_sa_t*)) add_child_sa;
        this->public.get_child_sa = (child_sa_t* (*)(ike_sa_t*,protocol_id_t,u_int32_t,bool)) get_child_sa;
@@ -1448,7 +1483,12 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        /* initialize private fields */
        this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
        this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+       this->name = strdup("(uninitialized)");
        this->child_sas = linked_list_create();
+       this->my_host = NULL;
+       this->other_host = NULL;
+       this->my_id = NULL;
+       this->other_id = NULL;
        this->crypter_in = NULL;
        this->crypter_out = NULL;
        this->signer_in = NULL;
@@ -1457,8 +1497,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->prf_auth_i = NULL;
        this->prf_auth_r = NULL;
        this->child_prf = NULL;
-       this->connection = NULL;
-       this->policy = NULL;
        this->nat_here = FALSE;
        this->nat_there = FALSE;
        this->transaction_queue = linked_list_create();
index ab94505..f593e38 100644 (file)
@@ -152,20 +152,115 @@ struct ike_sa_t {
         * @param state                 state to set for the IKE_SA
         */
        void (*set_state) (ike_sa_t *this, ike_sa_state_t ike_sa);
+       
+       /**
+        * @brief Get the name of the connection this IKE_SA uses.
+        *
+        * @param this                  calling object
+        * @return                              name
+        */
+       char* (*get_name) (ike_sa_t *this);
+       
+       /**
+        * @brief Set the name of the connection this IKE_SA uses.
+        *
+        * @param this                  calling object
+        * @param name                  name, gets cloned
+        */
+       void (*set_name) (ike_sa_t *this, char* name);
+       
+       /**
+        * @brief Get the own host address.
+        * 
+        * @param this                  calling object
+        * @return                              host address
+        */
+       host_t* (*get_my_host) (ike_sa_t *this);
+       
+       /**
+        * @brief Get the other peers host address.
+        * 
+        * @param this                  calling object
+        * @return                              host address
+        */
+       host_t* (*get_other_host) (ike_sa_t *this);
+       
+       /**
+        * @brief Get the own identification.
+        * 
+        * @param this                  calling object
+        * @return                              identification
+        */
+       identification_t* (*get_my_id) (ike_sa_t *this);
+       
+       /**
+        * @brief Set the own identification.
+        * 
+        * @param this                  calling object
+        * @param me                    identification
+        */
+       void (*set_my_id) (ike_sa_t *this, identification_t *me);
+       
+       /**
+        * @brief Get the other peers identification.
+        * 
+        * @param this                  calling object
+        * @return                              identification
+        */
+       identification_t* (*get_other_id) (ike_sa_t *this);
+       
+       /**
+        * @brief Set the other peers identification.
+        * 
+        * @param this                  calling object
+        * @param other                 identification
+        */
+       void (*set_other_id) (ike_sa_t *this, identification_t *other);
 
        /**
         * @brief Initiate a new connection.
         *
-        * The connection_t object is owned by the IKE_SA after the call, so
+        * The policy/connection is owned by the IKE_SA after the call, so
         * do not modify or destroy it.
         * 
         * @param this                  calling object
         * @param connection    connection to initiate
+        * @param policy                policy to set up
+        * @return                              
+        *                                              - SUCCESS if initialization started
+        *                                              - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
+        */
+       status_t (*initiate) (ike_sa_t *this, connection_t *connection, policy_t *policy);
+
+       /**
+        * @brief Route a policy in the kernel.
+        *
+        * Installs the policies in the kernel. If traffic matches,
+        * the kernel requests connection setup from the IKE_SA via acquire().
+        * The policy is owned by the IKE_SA after the call, so
+        * do not modify or destroy it.
+        * 
+        * @param this                  calling object
+        * @param policy                policy to route
+        * @return                              
+        *                                              - SUCCESS if initialization started
+        *                                              - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
+        */
+       status_t (*route) (ike_sa_t *this, policy_t *policy);
+       
+       /**
+        * @brief Acquire connection setup for a policy.
+        *
+        * If an installed policy raises an acquire, the kernel calls
+        * this function to establsh the CHILD_SA (and maybe the IKE_SA).
+        *
+        * @param this                  calling object
+        * @param reqid                 reqid of the CHILD_SA the policy belongs to.
         * @return                              
         *                                              - SUCCESS if initialization started
         *                                              - DESTROY_ME if initialization failed and IKE_SA MUST be deleted
         */
-       status_t (*initiate) (ike_sa_t *this, connection_t *connection);
+       status_t (*acquire) (ike_sa_t *this, u_int32_t reqid);
        
        /**
         * @brief Initiates the deletion of an IKE_SA.
@@ -280,38 +375,6 @@ struct ike_sa_t {
         * @param name                  name of the connection
         */     
        void (*log_status) (ike_sa_t *this, logger_t *logger, char *name);
-               
-       /**
-        * @brief Get the internal stored connection_t object.
-        * 
-        * @param this                  calling object
-        * @return                              pointer to the internal stored connection_t object
-        */
-       connection_t *(*get_connection) (ike_sa_t *this);
-       
-       /**
-        * @brief Set the internal connection object.
-        * 
-        * @param this                  calling object
-        * @param connection    object of type connection_t
-        */
-       void (*set_connection) (ike_sa_t *this, connection_t *connection);
-       
-       /**
-        * @brief Get the internal stored policy object.
-        * 
-        * @param this                  calling object
-        * @return                              pointer to the internal stored policy_t object
-        */
-       policy_t *(*get_policy) (ike_sa_t *this);
-       
-       /**
-        * @brief Set the internal policy_t object.
-        * 
-        * @param this                  calling object
-        * @param policy                object of type policy_t
-        */
-       void (*set_policy) (ike_sa_t *this, policy_t *policy);
 
        /**
         * @brief Derive all keys and create the transforms for IKE communication.
index e6a738d..b0822ac 100644 (file)
@@ -600,19 +600,15 @@ linked_list_t *get_ike_sa_list_by_name(private_ike_sa_manager_t* this, const cha
 {
        linked_list_t *list;
        iterator_t *iterator;
+       ike_sa_entry_t *entry;
        
        pthread_mutex_lock(&(this->mutex));
        
        list = linked_list_create();
        iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
-       while (iterator->has_next(iterator))
+       while (iterator->iterate(iterator, (void**)&entry))
        {
-               ike_sa_entry_t *entry;
-               connection_t *connection;
-               
-               iterator->current(iterator, (void**)&entry);
-               connection = entry->ike_sa->get_connection(entry->ike_sa);
-               if (strcmp(name, connection->get_name(connection)) == 0)
+               if (strcmp(name, entry->ike_sa->get_name(entry->ike_sa)) == 0)
                {
                        list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id));
                }
index 14d1dab..4c29cab 100644 (file)
@@ -70,11 +70,6 @@ struct private_create_child_sa_t {
        u_int32_t rekey_spi;
        
        /**
-        * connection of IKE_SA
-        */
-       connection_t *connection;
-       
-       /**
         * policy definition used
         */
        policy_t *policy;
@@ -152,6 +147,14 @@ static u_int32_t requested(private_create_child_sa_t *this)
 }
 
 /**
+ * Implementation of create_child_sa_t.set_policy.
+ */
+static void set_policy(private_create_child_sa_t *this, policy_t *policy)
+{
+       this->policy = policy;
+}
+
+/**
  * Implementation of create_child_sa_t.rekeys_child.
  */
 static void rekeys_child(private_create_child_sa_t *this, child_sa_t *child_sa)
@@ -169,6 +172,22 @@ static void cancel(private_create_child_sa_t *this)
 }
 
 /**
+ * destroy a list of traffic selectors
+ */
+static void destroy_ts_list(linked_list_t *list)
+{
+       if (list)
+       {
+               traffic_selector_t *ts;
+               while (list->remove_last(list, (void**)&ts) == SUCCESS)
+               {
+                       ts->destroy(ts);
+               }
+               list->destroy(list);
+       }
+}
+
+/**
  * Implementation of transaction_t.get_request.
  */
 static status_t get_request(private_create_child_sa_t *this, message_t **result)
@@ -176,6 +195,13 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
        message_t *request;
        host_t *me, *other;
        
+       /* check if we already have built a message (retransmission) */
+       if (this->message)
+       {
+               *result = this->message;
+               return SUCCESS;
+       }
+       
        /* check if we are not already rekeying */
        if (this->rekeyed_sa)
        {
@@ -195,17 +221,8 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
                this->rekeyed_sa->set_state(this->rekeyed_sa, CHILD_REKEYING);
        }
        
-       /* check if we already have built a message (retransmission) */
-       if (this->message)
-       {
-               *result = this->message;
-               return SUCCESS;
-       }
-       
-       this->connection = this->ike_sa->get_connection(this->ike_sa);
-       me = this->connection->get_my_host(this->connection);
-       other = this->connection->get_other_host(this->connection);
-       this->policy = this->ike_sa->get_policy(this->ike_sa);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        
        /* build the request */
        request = message_create();
@@ -223,9 +240,31 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
                bool use_natt;
                u_int32_t reqid = 0;
                
+               /* get a policy, if we are rekeying */
                if (this->rekeyed_sa)
                {
+                       linked_list_t *my_ts, *other_ts;
+                       identification_t *my_id, *other_id;
+                       
+                       my_ts = this->rekeyed_sa->get_my_traffic_selectors(this->rekeyed_sa);
+                       other_ts = this->rekeyed_sa->get_other_traffic_selectors(this->rekeyed_sa);
+                       my_id = this->ike_sa->get_my_id(this->ike_sa);
+                       other_id = this->ike_sa->get_other_id(this->ike_sa);
+                       
+                       this->policy = charon->policies->get_policy(charon->policies,
+                                                                                                               my_id, other_id,
+                                                                                                               my_ts, other_ts,
+                                                                                                           me, other);
+                       
                        reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
+                       
+                       if (this->policy == NULL)
+                       {
+                               this->logger->log(this->logger, ERROR,
+                                                                 "no policy found to rekey CHILD_SA with reqid %d",
+                                                                 reqid);
+                               return FAILED;
+                       }
                }
                
                proposals = this->policy->get_proposals(this->policy);
@@ -261,8 +300,9 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
                linked_list_t *ts_list;
                ts_payload_t *ts_payload;
                
-               ts_list = this->policy->get_my_traffic_selectors(this->policy);
+               ts_list = this->policy->get_my_traffic_selectors(this->policy, me);
                ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list);
+               destroy_ts_list(ts_list);
                request->add_payload(request, (payload_t*)ts_payload);
        }
        
@@ -270,8 +310,9 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
                linked_list_t *ts_list;
                ts_payload_t *ts_payload;
                
-               ts_list = this->policy->get_other_traffic_selectors(this->policy);
+               ts_list = this->policy->get_other_traffic_selectors(this->policy, other);
                ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list);
+               destroy_ts_list(ts_list);
                request->add_payload(request, (payload_t*)ts_payload);
        }
        
@@ -439,22 +480,6 @@ static status_t install_child_sa(private_create_child_sa_t *this, bool initiator
 }
 
 /**
- * destroy a list of traffic selectors
- */
-static void destroy_ts_list(linked_list_t *list)
-{
-       if (list)
-       {
-               traffic_selector_t *ts;
-               while (list->remove_last(list, (void**)&ts) == SUCCESS)
-               {
-                       ts->destroy(ts);
-               }
-               list->destroy(list);
-       }
-}
-
-/**
  * Implementation of transaction_t.get_response.
  */
 static status_t get_response(private_create_child_sa_t *this, message_t *request, 
@@ -477,10 +502,8 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
                return SUCCESS;
        }
        
-       this->connection = this->ike_sa->get_connection(this->ike_sa);
-       me = this->connection->get_my_host(this->connection);
-       other = this->connection->get_other_host(this->connection);
-       this->policy = this->ike_sa->get_policy(this->ike_sa);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        this->message_id = request->get_message_id(request);
        
        /* set up response */
@@ -573,16 +596,35 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
                nonce_response->set_nonce(nonce_response, this->nonce_r);
        }
        
-       {       /* process traffic selectors for other */
-               linked_list_t *ts_received = tsi_request->get_traffic_selectors(tsi_request);
-               this->tsi = this->policy->select_other_traffic_selectors(this->policy, ts_received);
-               destroy_ts_list(ts_received);
-       }
-       
-       {       /* process traffic selectors for us */
-               linked_list_t *ts_received = ts_received = tsr_request->get_traffic_selectors(tsr_request);
-               this->tsr = this->policy->select_my_traffic_selectors(this->policy, ts_received);
-               destroy_ts_list(ts_received);
+       {       /* get a policy and process traffic selectors */
+               identification_t *my_id, *other_id;
+               linked_list_t *my_ts, *other_ts;
+               
+               my_id = this->ike_sa->get_my_id(this->ike_sa);
+               other_id = this->ike_sa->get_other_id(this->ike_sa);
+               
+               my_ts = tsr_request->get_traffic_selectors(tsr_request);
+               other_ts = tsi_request->get_traffic_selectors(tsi_request);
+               
+               this->policy = charon->policies->get_policy(charon->policies,
+                                                                                                       my_id, other_id,
+                                                                                                       my_ts, other_ts,
+                                                                                                   me, other);
+               if (this->policy)
+               {
+                       this->tsr = this->policy->select_my_traffic_selectors(this->policy, my_ts, me);
+                       this->tsi = this->policy->select_other_traffic_selectors(this->policy, other_ts, other);
+               }
+               destroy_ts_list(my_ts);
+               destroy_ts_list(other_ts);
+               
+               if (this->policy == NULL)
+               {
+                       this->logger->log(this->logger, AUDIT,
+                                                         "no acceptable policy found, adding TS_UNACCEPTABLE notify");
+                       build_notify(TS_UNACCEPTABLE, CHUNK_INITIALIZER, response, TRUE);
+                       return FAILED;
+               }
        }
        
        {       /* process SA payload */
@@ -705,8 +747,8 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
                return FAILED;
        }
        
-       me = this->connection->get_my_host(this->connection);
-       other = this->connection->get_other_host(this->connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        
        /* Iterate over all payloads to collect them */
        payloads = response->get_payload_iterator(response);
@@ -761,13 +803,13 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
        
        {       /* process traffic selectors for us */
                linked_list_t *ts_received = tsi_payload->get_traffic_selectors(tsi_payload);
-               this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received);
+               this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received, me);
                destroy_ts_list(ts_received);
        }
        
        {       /* process traffic selectors for other */
                linked_list_t *ts_received = tsr_payload->get_traffic_selectors(tsr_payload);
-               this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received);
+               this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received, other);
                destroy_ts_list(ts_received);
        }
        
@@ -790,8 +832,7 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
                        this->tsi->get_count(this->tsi) == 0 ||
                        this->tsr->get_count(this->tsr) == 0)
                {
-                       this->logger->log(this->logger, AUDIT,
-                                                         "CHILD_SA creation failed");
+                       this->logger->log(this->logger, AUDIT, "CHILD_SA creation failed");
                        return FAILED;
                }
                new_child = this->child_sa;
@@ -863,18 +904,10 @@ static status_t conclude(private_create_child_sa_t *this, message_t *response,
  */
 static void destroy(private_create_child_sa_t *this)
 {
-       if (this->message)
-       {
-               this->message->destroy(this->message);
-       }
-       if (this->proposal)
-       {
-               this->proposal->destroy(this->proposal);
-       }
-       if (this->child_sa)
-       {
-               this->child_sa->destroy(this->child_sa);
-       }
+       DESTROY_IF(this->message);
+       DESTROY_IF(this->proposal);
+       DESTROY_IF(this->child_sa);
+       DESTROY_IF(this->policy);
        destroy_ts_list(this->tsi);
        destroy_ts_list(this->tsr);
        chunk_free(&this->nonce_i);
@@ -900,6 +933,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
        this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
        
        /* public functions */
+       this->public.set_policy = (void(*)(create_child_sa_t*,policy_t*))set_policy;
        this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
        this->public.cancel = (void(*)(create_child_sa_t*))cancel;
        
@@ -916,6 +950,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
        this->rekeyed_sa = NULL;
        this->lost = FALSE;
        this->proposal = NULL;
+       this->policy = NULL;
        this->tsi = NULL;
        this->tsr = NULL;
        this->randomizer = randomizer_create();
index df7a64f..d45bfcc 100644 (file)
@@ -33,6 +33,10 @@ typedef struct create_child_sa_t create_child_sa_t;
 /**
  * @brief A transaction to create a new or rekey an existing CHILD_SA.
  *
+ * If the CHILD_SA is intended to create a new CHILD_SA, set the policy
+ * with set_policy(). If it is intended to rekey an existing CHILD_SA,
+ * set the appropriate CHILD_SA with rekeys_child().
+ *
  * Rekeying of an CHILD_SA works the same way as creating a new one,
  * but includes an additional REKEY_SA notify and deletes the old
  * one (in a separate transaction).
@@ -68,10 +72,15 @@ struct create_child_sa_t {
        transaction_t transaction;
        
        /**
-        * @brief Set the CHILD_SA which gets rekeyed by the new one.
+        * @brief Set the policy to use for creating a new CHILD_SA.
         *
-        * If this transaction is used for rekeying, set the inbound
-        * SPI of the CHILD_SA which the new CHILD_SA rekeys.
+        * @param this          calling object
+        * @param policy        policy for CHILD_SA
+        */
+       void (*set_policy) (create_child_sa_t* this, policy_t *policy);
+       
+       /**
+        * @brief Set the CHILD_SA which gets rekeyed by the new one.
         *
         * @param this          calling object
         * @param child_sa      CHILD_SA to rekey
@@ -79,9 +88,9 @@ struct create_child_sa_t {
        void (*rekeys_child) (create_child_sa_t* this, child_sa_t *child_sa);
        
        /**
-        * @brief Cancel a rekeying request.
+        * @brief Cancel the request.
         *
-        * Cancelling a rekeying request will set a flag in the transaction. When
+        * Cancelling the request will set a flag in the transaction. When
         * the response for the transaction is received, the created CHILD_SA
         * gets deleted afterwards.
         *
index c7f5db6..a0e687c 100644 (file)
@@ -85,7 +85,6 @@ static u_int32_t requested(private_dead_peer_detection_t *this)
 static status_t get_request(private_dead_peer_detection_t *this, message_t **result)
 {
        message_t *request;
-       connection_t *connection;
        host_t *me, *other;
        
        /* check if we already have built a message (retransmission) */
@@ -95,9 +94,8 @@ static status_t get_request(private_dead_peer_detection_t *this, message_t **res
                return SUCCESS;
        }
        
-       connection = this->ike_sa->get_connection(this->ike_sa);
-       me = connection->get_my_host(connection);
-       other = connection->get_other_host(connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        
        /* build the request */
        request = message_create();
@@ -124,7 +122,6 @@ static status_t get_response(private_dead_peer_detection_t *this, message_t *req
 {
        host_t *me, *other;
        message_t *response;
-       connection_t *connection;
        
        /* check if we already have built a response (retransmission) */
        if (this->message)
@@ -133,9 +130,8 @@ static status_t get_response(private_dead_peer_detection_t *this, message_t *req
                return SUCCESS;
        }
        
-       connection = this->ike_sa->get_connection(this->ike_sa);
-       me = connection->get_my_host(connection);
-       other = connection->get_other_host(connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        this->message_id = request->get_message_id(request);
        
        /* set up response */
@@ -167,10 +163,7 @@ static status_t conclude(private_dead_peer_detection_t *this, message_t *respons
  */
 static void destroy(private_dead_peer_detection_t *this)
 {
-       if (this->message)
-       {
-               this->message->destroy(this->message);
-       }
+       DESTROY_IF(this->message);
        free(this);
 }
 
index e8ca4bb..f839962 100644 (file)
@@ -100,7 +100,6 @@ static void set_child_sa(private_delete_child_sa_t *this, child_sa_t *child_sa)
 static status_t get_request(private_delete_child_sa_t *this, message_t **result)
 {
        message_t *request;
-       connection_t *connection;
        host_t *me, *other;
        
        /* check if we already have built a message (retransmission) */
@@ -110,9 +109,8 @@ static status_t get_request(private_delete_child_sa_t *this, message_t **result)
                return SUCCESS;
        }
        
-       connection = this->ike_sa->get_connection(this->ike_sa);
-       me = connection->get_my_host(connection);
-       other = connection->get_other_host(connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        
        /* build the request */
        request = message_create();
@@ -228,7 +226,6 @@ static status_t get_response(private_delete_child_sa_t *this, message_t *request
        host_t *me, *other;
        message_t *response;
        iterator_t *payloads;
-       connection_t *connection;
        
        /* check if we already have built a response (retransmission) */
        if (this->message)
@@ -237,9 +234,8 @@ static status_t get_response(private_delete_child_sa_t *this, message_t *request
                return SUCCESS;
        }
        
-       connection = this->ike_sa->get_connection(this->ike_sa);
-       me = connection->get_my_host(connection);
-       other = connection->get_other_host(connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        this->message_id = request->get_message_id(request);
        
        /* set up response */
@@ -335,10 +331,7 @@ static status_t conclude(private_delete_child_sa_t *this, message_t *response,
  */
 static void destroy(private_delete_child_sa_t *this)
 {
-       if (this->message)
-       {
-               this->message->destroy(this->message);
-       }
+       DESTROY_IF(this->message);
        free(this);
 }
 
index 95f9fc6..3ab89a4 100644 (file)
@@ -86,7 +86,6 @@ static u_int32_t requested(private_delete_ike_sa_t *this)
 static status_t get_request(private_delete_ike_sa_t *this, message_t **result)
 {
        message_t *request;
-       connection_t *connection;
        host_t *me, *other;
        delete_payload_t *delete_payload;
        
@@ -97,9 +96,8 @@ static status_t get_request(private_delete_ike_sa_t *this, message_t **result)
                return SUCCESS;
        }
        
-       connection = this->ike_sa->get_connection(this->ike_sa);
-       me = connection->get_my_host(connection);
-       other = connection->get_other_host(connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        
        /* build the request */
        request = message_create();
@@ -134,7 +132,6 @@ static status_t get_response(private_delete_ike_sa_t *this, message_t *request,
        message_t *response;
        iterator_t *payloads;
        delete_payload_t *delete_request = NULL;
-       connection_t *connection;
        
        /* check if we already have built a response (retransmission) 
         * this only happens in special simultanous transaction cases,
@@ -145,9 +142,8 @@ static status_t get_response(private_delete_ike_sa_t *this, message_t *request,
                return SUCCESS;
        }
        
-       connection = this->ike_sa->get_connection(this->ike_sa);
-       me = connection->get_my_host(connection);
-       other = connection->get_other_host(connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        this->message_id = request->get_message_id(request);
        
        /* set up response */
@@ -240,10 +236,7 @@ static status_t conclude(private_delete_ike_sa_t *this, message_t *response,
  */
 static void destroy(private_delete_ike_sa_t *this)
 {
-       if (this->message)
-       {
-               this->message->destroy(this->message);
-       }
+       DESTROY_IF(this->message);
        free(this);
 }
 
index 53ba620..2bf12f7 100644 (file)
@@ -90,12 +90,12 @@ struct private_ike_auth_t {
        chunk_t init_response;
        
        /**
-        * connection definition used
+        * connection definition used for IKE_SA setup
         */
        connection_t *connection;
        
        /**
-        * policy definition used
+        * policy definition used CHILD_SA creation
         */
        policy_t *policy;
        
@@ -147,6 +147,16 @@ static u_int32_t requested(private_ike_auth_t *this)
 }
 
 /**
+ * Implementation of transaction_t.set_config.
+ */
+static void set_config(private_ike_auth_t *this,
+                                          connection_t *connection, policy_t *policy)
+{
+       this->connection = connection;
+       this->policy = policy;
+}
+
+/**
  * Implementation of transaction_t.set_nonces.
  */
 static void set_nonces(private_ike_auth_t *this, chunk_t nonce_i, chunk_t nonce_r)
@@ -165,6 +175,23 @@ static void set_init_messages(private_ike_auth_t *this, chunk_t init_request, ch
 }
 
 /**
+ * destroy a list of traffic selectors
+ */
+static void destroy_ts_list(linked_list_t *list)
+{
+       if (list)
+       {
+               traffic_selector_t *ts;
+
+               while (list->remove_last(list, (void**)&ts) == SUCCESS)
+               {
+                       ts->destroy(ts);
+               }
+               list->destroy(list);
+       }
+}
+
+/**
  * Implementation of transaction_t.get_request.
  */
 static status_t get_request(private_ike_auth_t *this, message_t **result)
@@ -181,10 +208,8 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
                return SUCCESS;
        }
        
-       this->connection = this->ike_sa->get_connection(this->ike_sa);
-       me = this->connection->get_my_host(this->connection);
-       other = this->connection->get_other_host(this->connection);
-       this->policy = this->ike_sa->get_policy(this->ike_sa);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        my_id = this->policy->get_my_id(this->policy);
        other_id = this->policy->get_other_id(this->policy);
        
@@ -203,6 +228,7 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
        {       /* build ID payload */
                my_id_payload = id_payload_create_from_identification(TRUE, my_id);
                request->add_payload(request, (payload_t*)my_id_payload);
+               this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
        }
        
        {       /* TODO: build certreq payload */
@@ -239,9 +265,11 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
        {       /* build auth payload */
                authenticator_t *authenticator;
                auth_payload_t *auth_payload;
+               auth_method_t auth_method;
                status_t status;
-       
-               authenticator = authenticator_create(this->ike_sa);
+               
+               auth_method = this->connection->get_auth_method(this->connection);
+               authenticator = authenticator_create(this->ike_sa, auth_method);
                status = authenticator->compute_auth_data(authenticator, &auth_payload,
                                this->init_request, this->nonce_r, my_id_payload, TRUE);
                authenticator->destroy(authenticator);
@@ -278,8 +306,9 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
                linked_list_t *ts_list;
                ts_payload_t *ts_payload;
        
-               ts_list = this->policy->get_my_traffic_selectors(this->policy);
+               ts_list = this->policy->get_my_traffic_selectors(this->policy, me);
                ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list);
+               destroy_ts_list(ts_list);
                
                request->add_payload(request, (payload_t*)ts_payload);
        }
@@ -288,8 +317,9 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
                linked_list_t *ts_list;
                ts_payload_t *ts_payload;
        
-               ts_list = this->policy->get_other_traffic_selectors(this->policy);
+               ts_list = this->policy->get_other_traffic_selectors(this->policy, other);
                ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list);
+               destroy_ts_list(ts_list);
                
                request->add_payload(request, (payload_t*)ts_payload);
        }
@@ -465,23 +495,6 @@ static status_t install_child_sa(private_ike_auth_t *this, bool initiator)
 }
 
 /**
- * destroy a list of traffic selectors
- */
-static void destroy_ts_list(linked_list_t *list)
-{
-       if (list)
-       {
-               traffic_selector_t *ts;
-
-               while (list->remove_last(list, (void**)&ts) == SUCCESS)
-               {
-                       ts->destroy(ts);
-               }
-               list->destroy(list);
-       }
-}
-
-/**
  * Implementation of transaction_t.get_response.
  */
 static status_t get_response(private_ike_auth_t *this, message_t *request, 
@@ -508,9 +521,8 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                return SUCCESS;
        }
        
-       this->connection = this->ike_sa->get_connection(this->ike_sa);
-       me = this->connection->get_my_host(this->connection);
-       other = this->connection->get_other_host(this->connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        this->message_id = request->get_message_id(request);
        
        /* set up response */
@@ -607,13 +619,32 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                {
                        my_id = identification_create_from_encoding(ID_ANY, CHUNK_INITIALIZER);
                }
+       }
+       
+       {       /* get a policy and process traffic selectors */
+               linked_list_t *my_ts, *other_ts;
+               
+               my_ts = tsr_request->get_traffic_selectors(tsr_request);
+               other_ts = tsi_request->get_traffic_selectors(tsi_request);
+               
+               this->policy = charon->policies->get_policy(charon->policies,
+                                                                                                       my_id, other_id,
+                                                                                                       my_ts, other_ts,
+                                                                                                   me, other);
+               if (this->policy)
+               {
+                       this->tsr = this->policy->select_my_traffic_selectors(this->policy, my_ts, me);
+                       this->tsi = this->policy->select_other_traffic_selectors(this->policy, other_ts, other);
+               }
+               destroy_ts_list(my_ts);
+               destroy_ts_list(other_ts);
                
-               /* get policy from store */
-               this->policy = charon->policies->get_policy_by_ids(charon->policies, my_id, other_id);
+               /* TODO: We should check somehow if we have a policy, but with other
+                * traffic selectors. Then we would create a IKE_SA without a CHILD_SA. */
                if (this->policy == NULL)
                {
                        this->logger->log(this->logger, AUDIT,
-                                                         "we don't have a policy for IDs %s - %s, deleting IKE_SA", 
+                                                         "no acceptable policy for IDs %s - %s found, deleting IKE_SA", 
                                                          my_id->get_string(my_id), other_id->get_string(other_id));
                        my_id->destroy(my_id);
                        other_id->destroy(other_id);
@@ -621,16 +652,12 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                        return DESTROY_ME;
                }
                my_id->destroy(my_id);
-               other_id->destroy(other_id);
                
                /* get my id from policy, which must contain a fully qualified valid id */
                my_id = this->policy->get_my_id(this->policy);
+               this->ike_sa->set_my_id(this->ike_sa, my_id->clone(my_id));
+               this->ike_sa->set_other_id(this->ike_sa, other_id);
                
-               /* update others traffic selectors with actually used address */
-               this->policy->update_my_ts(this->policy, me);
-               this->policy->update_other_ts(this->policy, other);
-               
-               this->ike_sa->set_policy(this->ike_sa, this->policy);
                idr_response = id_payload_create_from_identification(FALSE, my_id);
                response->add_payload(response, (payload_t*)idr_response);
        }
@@ -658,9 +685,11 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
        {       /* process auth payload */
                authenticator_t *authenticator;
                auth_payload_t *auth_response;
+               auth_method_t auth_method;
                status_t status;
-       
-               authenticator = authenticator_create(this->ike_sa);
+               
+               auth_method = this->connection->get_auth_method(this->connection);
+               authenticator = authenticator_create(this->ike_sa, auth_method);
                status = authenticator->verify_auth_data(authenticator, auth_request,
                                                                                                this->init_request,
                                                                                                this->nonce_r, idi_request,
@@ -688,18 +717,6 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                response->add_payload(response, (payload_t*)auth_response);
        }
        
-       {       /* process traffic selectors for other */
-               linked_list_t *ts_received = tsi_request->get_traffic_selectors(tsi_request);
-               this->tsi = this->policy->select_other_traffic_selectors(this->policy, ts_received);
-               destroy_ts_list(ts_received);
-       }
-       
-       {       /* process traffic selectors for us */
-               linked_list_t *ts_received = ts_received = tsr_request->get_traffic_selectors(tsr_request);
-               this->tsr = this->policy->select_my_traffic_selectors(this->policy, ts_received);
-               destroy_ts_list(ts_received);
-       }
-       
        {       /* process SA payload */
                proposal_t *proposal;
                linked_list_t *proposal_list;
@@ -793,8 +810,8 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
                return DESTROY_ME;
        }
        
-       me = this->connection->get_my_host(this->connection);
-       other = this->connection->get_other_host(this->connection);
+       me = this->ike_sa->get_my_host(this->ike_sa);
+       other = this->ike_sa->get_other_host(this->ike_sa);
        
        /* Iterate over all payloads to collect them */
        payloads = response->get_payload_iterator(response);
@@ -872,8 +889,7 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
                                                          configured_other_id->get_string(configured_other_id));
                        return DESTROY_ME;
                }
-               
-               this->policy->update_other_id(this->policy, other_id);
+               this->ike_sa->set_other_id(this->ike_sa, other_id);
        }
        
        if (cert_payload)
@@ -883,9 +899,11 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
        
        {       /* authenticate peer */
                authenticator_t *authenticator;
+               auth_method_t auth_method;
                status_t status;
                
-               authenticator = authenticator_create(this->ike_sa);
+               auth_method = this->connection->get_auth_method(this->connection);
+               authenticator = authenticator_create(this->ike_sa, auth_method);
                status = authenticator->verify_auth_data(authenticator, auth_payload,
                                this->init_response,
                                this->nonce_i, idr_payload,
@@ -900,13 +918,13 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
        
        {       /* process traffic selectors for us */
                linked_list_t *ts_received = tsi_payload->get_traffic_selectors(tsi_payload);
-               this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received);
+               this->tsi = this->policy->select_my_traffic_selectors(this->policy, ts_received, me);
                destroy_ts_list(ts_received);
        }
        
        {       /* process traffic selectors for other */
                linked_list_t *ts_received = tsr_payload->get_traffic_selectors(tsr_payload);
-               this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received);
+               this->tsr = this->policy->select_other_traffic_selectors(this->policy, ts_received, other);
                destroy_ts_list(ts_received);
        }
        
@@ -952,18 +970,11 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
  */
 static void destroy(private_ike_auth_t *this)
 {
-       if (this->message)
-       {
-               this->message->destroy(this->message);
-       }
-       if (this->proposal)
-       {
-               this->proposal->destroy(this->proposal);
-       }
-       if (this->child_sa)
-       {
-               this->child_sa->destroy(this->child_sa);
-       }
+       DESTROY_IF(this->message);
+       DESTROY_IF(this->proposal);
+       DESTROY_IF(this->child_sa);
+       DESTROY_IF(this->policy);
+       DESTROY_IF(this->connection);
        destroy_ts_list(this->tsi);
        destroy_ts_list(this->tsr);
        chunk_free(&this->nonce_i);
@@ -989,6 +1000,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa)
        this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
        
        /* public functions */
+       this->public.set_config = (void(*)(ike_auth_t*,connection_t*,policy_t*))set_config;
        this->public.set_nonces = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_nonces;
        this->public.set_init_messages = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_init_messages;
        
index 5c2b14c..89263d4 100644 (file)
@@ -50,6 +50,20 @@ struct ike_auth_t {
        transaction_t transaction;
        
        /**
+        * @brief Set the config used for the ike_auth exchange.
+        *
+        * The connection definition is used to complete IKE_SA setup, the
+        * policy defines the CHILD_SA which is created along with the ike_auth
+        * exchange.
+        *
+        * @param this                  calling object
+        * @param connection    connection definition
+        * @param policy                policy definition
+        */
+       void (*set_config) (ike_auth_t* this, 
+                                               connection_t *connection, policy_t *policy);
+       
+       /**
         * @brief Set the nonces used in the previous ike_sa_init transaction.
         * 
         * The nonces are used to create the authentication data.
index d66ba84..29cdcaf 100644 (file)
@@ -90,11 +90,16 @@ struct private_ike_sa_init_t {
        chunk_t nonce_r;
        
        /**
-        * connection definition used
+        * connection definition used for initiation
         */
        connection_t *connection;
        
        /**
+        * policy definition forwarded to ike_auth transaction
+        */
+       policy_t *policy;
+       
+       /**
         * Negotiated proposal used for IKE_SA
         */
        proposal_t *proposal;
@@ -150,8 +155,6 @@ struct private_ike_sa_init_t {
  */
 static bool use_dh_group(private_ike_sa_init_t *this, diffie_hellman_group_t dh_group)
 {
-       this->connection = this->ike_sa->get_connection(this->ike_sa);
-       
        if (this->connection->check_dh_group(this->connection, dh_group))
        {
                this->diffie_hellman = diffie_hellman_create(dh_group);
@@ -164,6 +167,16 @@ static bool use_dh_group(private_ike_sa_init_t *this, diffie_hellman_group_t dh_
 }
 
 /**
+ * Implementation of ike_sa_init_t.set_config.
+ */
+static void set_config(private_ike_sa_init_t *this,
+                                          connection_t *connection, policy_t *policy)
+{
+       this->connection = connection;
+       this->policy = policy;
+}
+
+/**
  * Implementation of transaction_t.get_message_id.
  */
 static u_int32_t get_message_id(private_ike_sa_init_t *this)
@@ -264,7 +277,6 @@ static status_t get_request(private_ike_sa_init_t *this, message_t **result)
                return SUCCESS;
        }
        
-       this->connection = this->ike_sa->get_connection(this->ike_sa);
        me = this->connection->get_my_host(this->connection);
        other = this->connection->get_other_host(this->connection);
        
@@ -398,6 +410,9 @@ static status_t process_notifys(private_ike_sa_init_t *this, notify_payload_t *n
                                return DESTROY_ME;
                        }
                        retry = ike_sa_init_create(this->ike_sa);
+                       retry->set_config(retry, this->connection, this->policy);
+                       this->connection = NULL;
+                       this->policy = NULL;
                        retry->use_dh_group(retry, dh_group);
                        *this->next = (transaction_t*)retry;
                        return FAILED;
@@ -523,7 +538,8 @@ static status_t get_response(private_ike_sa_init_t *this,
                                                  me->get_string(me), other->get_string(other));
                return DESTROY_ME;
        }
-       this->ike_sa->set_connection(this->ike_sa, this->connection);
+       this->ike_sa->set_name(this->ike_sa, 
+                                                  this->connection->get_name(this->connection));
        
        /* Precompute NAT-D hashes for incoming NAT notify comparison */
        ike_sa_id = request->get_ike_sa_id(request);
@@ -769,6 +785,9 @@ static status_t get_response(private_ike_sa_init_t *this,
                
                /* create next transaction, for which we except a message */
                ike_auth = ike_auth_create(this->ike_sa);
+               ike_auth->set_config(ike_auth, this->connection, this->policy);
+               this->connection = NULL;
+               this->policy = NULL;
                ike_auth->set_nonces(ike_auth,
                                                         chunk_clone(this->nonce_i),
                                                         chunk_clone(this->nonce_r));
@@ -802,7 +821,6 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
        sa_payload_t *sa_payload = NULL;
        ke_payload_t *ke_payload = NULL;
        nonce_payload_t *nonce_payload = NULL;
-       policy_t *policy;
        status_t status;
        
        /* check message type */
@@ -816,7 +834,6 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
        /* allow setting of next transaction in other functions */
        this->next = next;
        
-       this->connection = this->ike_sa->get_connection(this->ike_sa);
        me = this->connection->get_my_host(this->connection);
        other = this->connection->get_other_host(this->connection);
        
@@ -971,9 +988,6 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
                        other->set_port(other, IKEV2_NATT_PORT);
                        this->logger->log(this->logger, CONTROL|LEVEL1, "switching to port %d", IKEV2_NATT_PORT);
                }
-               policy = this->ike_sa->get_policy(this->ike_sa);
-               policy->update_my_ts(policy, me);
-               policy->update_other_ts(policy, other);
        }
        
        /* because we are original initiator we have to update the responder SPI to the new one */
@@ -1000,6 +1014,9 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
                
                /* create next transaction, for which we except a message */
                ike_auth = ike_auth_create(this->ike_sa);
+               ike_auth->set_config(ike_auth, this->connection, this->policy);
+               this->connection = NULL;
+               this->policy = NULL;
                ike_auth->set_nonces(ike_auth,
                                                         chunk_clone(this->nonce_i),
                                                         chunk_clone(this->nonce_r));
@@ -1012,18 +1029,11 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
 
 static void destroy(private_ike_sa_init_t *this)
 {
-       if (this->message)
-       {
-               this->message->destroy(this->message);
-       }
-       if (this->diffie_hellman)
-       {
-               this->diffie_hellman->destroy(this->diffie_hellman);
-       }
-       if (this->proposal)
-       {
-               this->proposal->destroy(this->proposal);
-       }
+       DESTROY_IF(this->message);
+       DESTROY_IF(this->diffie_hellman);
+       DESTROY_IF(this->proposal);
+       DESTROY_IF(this->connection);
+       DESTROY_IF(this->policy);
        chunk_free(&this->nonce_i);
        chunk_free(&this->nonce_r);
        this->randomizer->destroy(this->randomizer);
@@ -1049,6 +1059,7 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
        this->public.transaction.destroy = (void(*)(transaction_t*))destroy;
        
        /* public functions */
+       this->public.set_config = (void(*)(ike_sa_init_t*,connection_t*,policy_t*))set_config;
        this->public.use_dh_group = (bool(*)(ike_sa_init_t*,diffie_hellman_group_t))use_dh_group;
        
        /* private data */
@@ -1060,6 +1071,7 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
        this->nonce_i = CHUNK_INITIALIZER;
        this->nonce_r = CHUNK_INITIALIZER;
        this->connection = NULL;
+       this->policy = NULL;
        this->proposal = NULL;
        this->randomizer = randomizer_create();
        this->nat_hasher = hasher_create(HASH_SHA1);
@@ -1070,6 +1082,6 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
        this->natd_src_matched = FALSE;
        this->natd_dst_matched = FALSE;
        this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
-
+       
        return &this->public;
 }
index b268fac..3bc049d 100644 (file)
@@ -47,6 +47,19 @@ struct ike_sa_init_t {
        transaction_t transaction;
        
        /**
+        * @brief Set connection & policy to use for initiation.
+        *
+        * The policy is not used directly, but forwarded to the 
+        * ike_auth transaction.
+        * 
+        * @param this                  calling object
+        * @param connection    connection to use for initiation
+        * @param policy                policy used in ike_auth transaction
+        */
+       void (*set_config) (ike_sa_init_t* this, 
+                                               connection_t *connection, policy_t *policy);
+       
+       /**
         * @brief Set the Diffie Hellman group to use for initiating.
         * 
         * If a first exchange fails with a INVALID_KE_PAYLOAD, the second
index f4d7acc..2242ea2 100755 (executable)
@@ -260,12 +260,12 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        }
                                
        my_ts = traffic_selector_create_from_subnet(my_subnet,
-                               msg->add_conn.me.subnet ?  msg->add_conn.me.subnet_mask : 32,
+                               msg->add_conn.me.subnet ?  msg->add_conn.me.subnet_mask : 0,
                                msg->add_conn.me.protocol, msg->add_conn.me.port);
        my_subnet->destroy(my_subnet);
 
        other_ts = traffic_selector_create_from_subnet(other_subnet, 
-                       msg->add_conn.other.subnet ?  msg->add_conn.other.subnet_mask : 32,
+                       msg->add_conn.other.subnet ?  msg->add_conn.other.subnet_mask : 0,
                        msg->add_conn.other.protocol, msg->add_conn.other.port);
        other_subnet->destroy(other_subnet);
 
@@ -383,11 +383,11 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        policy = policy_create(msg->add_conn.name, my_id, other_id,
                                                   msg->add_conn.rekey.ipsec_lifetime,
                                                   msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
-                                                  msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
+                                                  msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100, 
+                                                  msg->add_conn.me.updown);
        policy->add_my_traffic_selector(policy, my_ts);
        policy->add_other_traffic_selector(policy, other_ts);
        policy->add_authorities(policy, my_ca, other_ca);
-       policy->add_updown(policy, msg->add_conn.me.updown);
        
        if (msg->add_conn.algorithms.esp)
        {
@@ -479,40 +479,65 @@ static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
 {
        initiate_ike_sa_job_t *job;
        connection_t *connection;
+       policy_t *policy;
        linked_list_t *ike_sas;
        ike_sa_id_t *ike_sa_id;
        
        pop_string(msg, &(msg->initiate.name));
-       this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name);
-       connection = charon->connections->get_connection_by_name(charon->connections, msg->initiate.name);
+       this->logger->log(this->logger, CONTROL,
+                                         "received stroke: initiate \"%s\"",
+                                         msg->initiate.name);
+       
+       connection = charon->connections->get_connection_by_name(charon->connections,
+                                                                                                                        msg->initiate.name);
        if (connection == NULL)
        {
-               this->stroke_logger->log(this->stroke_logger, ERROR, "no connection named \"%s\"", msg->initiate.name);
+               this->stroke_logger->log(this->stroke_logger, ERROR, 
+                                                                "no connection named \"%s\"", 
+                                                                msg->initiate.name);
        }
        /* only initiate if it is an IKEv2 connection, ignore IKEv1 */
        else if (connection->is_ikev2(connection))
        {
-               /* check for already set up IKE_SAs befor initiating */
-               ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager, msg->initiate.name);
-               if (ike_sas->get_count(ike_sas) == 0)
+               
+               policy = charon->policies->get_policy_by_name(charon->policies, 
+                                                                                                         msg->initiate.name);
+               if (policy == NULL)
                {
-                       this->stroke_logger->log(this->stroke_logger, CONTROL,
-                                       "initiating connection \"%s\" (see log)...", msg->initiate.name);
-                       job = initiate_ike_sa_job_create(connection);
-                       charon->job_queue->add(charon->job_queue, (job_t*)job);
+                       this->stroke_logger->log(this->stroke_logger, ERROR,
+                                                                        "no policy named \"%s\"",
+                                                                        msg->initiate.name);
+                       connection->destroy(connection);
+                       return;
                }
-               else
+               /* check for already set up IKE_SAs befor initiating */
+               ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager,
+                                                                                                                                 msg->initiate.name);
+               if (ike_sas->get_count(ike_sas) > 0)
                {
                        this->stroke_logger->log(this->stroke_logger, CONTROL,
-                                       "connection \"%s\" already up", msg->initiate.name);
+                                                                        "connection \"%s\" already up", 
+                                                                        msg->initiate.name);
+                       /* TODO: setup CHILD_SA with policy */
                        connection->destroy(connection);
+                       ike_sas->destroy(ike_sas);
+                       return;
                }
+               this->stroke_logger->log(this->stroke_logger, CONTROL,
+                                                                "initiating connection \"%s\" (see log)...", 
+                                                                msg->initiate.name);
+               job = initiate_ike_sa_job_create(connection, policy);
+               charon->job_queue->add(charon->job_queue, (job_t*)job);
                while (ike_sas->remove_last(ike_sas, (void**)&ike_sa_id) == SUCCESS)
                {
                        ike_sa_id->destroy(ike_sa_id);
                }
                ike_sas->destroy(ike_sas);
        }
+       else
+       {
+               connection->destroy(connection);
+       }
 }
 
 /**
index c8839ef..db920e3 100644 (file)
 #define min(x,y) ((x) < (y) ? (x):(y))
 
 /**
+ * Call destructor of a object if object != NULL
+ */
+#define DESTROY_IF(obj) if (obj) obj->destroy(obj)
+
+/**
  * Debug macro to follow control flow
  */
 #define POS printf("%s, line %d\n", __FILE__, __LINE__)