fixed acquire-delay bug by:
authorMartin Willi <martin@strongswan.org>
Wed, 16 Jul 2008 11:51:37 +0000 (11:51 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 16 Jul 2008 11:51:37 +0000 (11:51 -0000)
  installing policies before states
  updating policies if protocol has changed

src/charon/kernel/kernel_interface.c
src/charon/sa/child_sa.c
src/charon/sa/child_sa.h
src/charon/sa/ike_sa.c
src/charon/sa/tasks/child_create.c

index 81d1e8b..8e16ba1 100644 (file)
@@ -5,9 +5,6 @@
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
- * Copyright (C) 2003 Herbert Xu.
- * 
- * Based on xfrm code from pluto.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -227,6 +224,9 @@ struct policy_entry_t {
        /** direction of this policy: in, out, forward */
        u_int8_t direction;
        
+       /** protocol ID: ESP/AH */
+       protocol_id_t proto;
+       
        /** reqid of the policy */
        u_int32_t reqid;
        
@@ -2612,14 +2612,16 @@ static status_t add_policy(private_kernel_interface_t *this,
        memset(policy, 0, sizeof(policy_entry_t));
        policy->sel = ts2selector(src_ts, dst_ts);
        policy->direction = direction;
+       policy->proto = protocol;
        
        /* find the policy, which matches EXACTLY */
        pthread_mutex_lock(&this->mutex);
        iterator = this->policies->create_iterator(this->policies, TRUE);
        while (iterator->iterate(iterator, (void**)&current))
        {
-               if (memcmp(&current->sel, &policy->sel, sizeof(struct xfrm_selector)) == 0 &&
-                       policy->direction == current->direction)
+               if (memeq(&current->sel, &policy->sel, sizeof(struct xfrm_selector)) &&
+                       policy->direction == current->direction &&
+                       policy->proto == current->proto)
                {
                        /* use existing policy */
                        current->refcount++;
index 21f29a3..443f9d9 100644 (file)
@@ -662,14 +662,19 @@ static status_t update(private_child_sa_t *this, proposal_t *proposal,
 }
 
 static status_t add_policies(private_child_sa_t *this,
-                                                        linked_list_t *my_ts_list,
-                                                        linked_list_t *other_ts_list, mode_t mode)
+                                       linked_list_t *my_ts_list, linked_list_t *other_ts_list,
+                                       mode_t mode, protocol_id_t proto)
 {
        iterator_t *my_iter, *other_iter;
        traffic_selector_t *my_ts, *other_ts;
        /* use low prio for ROUTED policies */
        bool high_prio = (this->state != CHILD_CREATED);
        
+       if (this->protocol == PROTO_NONE)
+       {       /* update if not set yet */
+               this->protocol = proto;
+       }
+       
        /* iterate over both lists */
        my_iter = my_ts_list->create_iterator(my_ts_list, TRUE);
        other_iter = other_ts_list->create_iterator(other_ts_list, TRUE);
@@ -1029,7 +1034,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        this->public.add = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))add;
        this->public.update = (status_t(*)(child_sa_t*,proposal_t*,mode_t,prf_plus_t*))update;
        this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,bool))update_hosts;
-       this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,mode_t))add_policies;
+       this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,mode_t,protocol_id_t))add_policies;
        this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
        this->public.get_use_time = (status_t (*)(child_sa_t*,bool,time_t*))get_use_time;
        this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
index 018f922..c566e56 100644 (file)
@@ -203,10 +203,12 @@ struct child_sa_t {
         * @param my_ts         traffic selectors for local site
         * @param other_ts      traffic selectors for remote site
         * @param mode          mode for the SA: tunnel/transport
+        * @param proto         protocol for policy, ESP/AH
         * @return                      SUCCESS or FAILED
         */     
        status_t (*add_policies)(child_sa_t *this, linked_list_t *my_ts_list,
-                                                        linked_list_t *other_ts_list, mode_t mode);
+                                                        linked_list_t *other_ts_list, mode_t mode,
+                                                        protocol_id_t proto);
        
        /**
         * Get the traffic selectors of added policies of local host.
index feb8d8d..41e4316 100644 (file)
@@ -1263,7 +1263,7 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
        my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, me);
        other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, other);
        status = child_sa->add_policies(child_sa, my_ts, other_ts,
-                                                                       child_cfg->get_mode(child_cfg));
+                                                                       child_cfg->get_mode(child_cfg), PROTO_NONE);
        my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
        other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
        if (status == SUCCESS)
index c011a2b..9d32433 100644 (file)
@@ -341,7 +341,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
        {
                seed = chunk_cata("cc", nonce_i, nonce_r);
        }
-       prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
        
        if (this->ipcomp != IPCOMP_NONE)
        {
@@ -349,6 +348,15 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
                                                                                this->other_cpi);
        }
        
+       status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
+                                       this->mode, this->proposal->get_protocol(this->proposal));
+       if (status != SUCCESS)
+       {       
+               SIG(CHILD_UP_FAILED, "unable to install IPsec policies (SPD) in kernel");
+               return NOT_FOUND;
+       }
+       
+       prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed);
        if (this->initiator)
        {
                status = this->child_sa->update(this->child_sa, this->proposal,
@@ -366,15 +374,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
                SIG(CHILD_UP_FAILED, "unable to install IPsec SA (SAD) in kernel");
                return FAILED;
        }
-       
-       status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
-                                                                                 this->mode);
-                                                                                 
-       if (status != SUCCESS)
-       {       
-               SIG(CHILD_UP_FAILED, "unable to install IPsec policies (SPD) in kernel");
-               return NOT_FOUND;
-       }
        /* add to IKE_SA, and remove from task */
        this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
        this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);