refactored and cleaned up child_sa interface
authorMartin Willi <martin@strongswan.org>
Wed, 19 Nov 2008 15:31:27 +0000 (15:31 -0000)
committerMartin Willi <martin@strongswan.org>
Wed, 19 Nov 2008 15:31:27 +0000 (15:31 -0000)
replaced add/update calls by a install() call
allocating SPIs always externally
support installation of non-allocated CHILD_SAs
some other cleanups

src/charon/processing/jobs/migrate_job.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
src/charon/sa/tasks/ike_mobike.c

index 92bdac0..e52b91c 100644 (file)
@@ -110,7 +110,7 @@ static void execute(private_migrate_job_t *this)
                host->set_port(host, IKEV2_UDP_PORT);
                ike_sa->set_other_host(ike_sa, host);
 
-               if (child_sa->update_hosts(child_sa, this->local, this->remote,
+               if (child_sa->update(child_sa, this->local, this->remote,
                                ike_sa->get_virtual_ip(ike_sa, TRUE),
                                ike_sa->has_condition(ike_sa, COND_NAT_ANY)) == NOT_SUPPORTED)
                {
index e7ab356..092210b 100644 (file)
@@ -90,16 +90,6 @@ struct private_child_sa_t {
        linked_list_t *other_ts;
        
        /**
-        * Allocated SPI for a ESP proposal candidates
-        */
-       u_int32_t alloc_esp_spi;
-       
-       /**
-        * Allocated SPI for a AH proposal candidates
-        */
-       u_int32_t alloc_ah_spi;
-       
-       /**
         * Protocol used to protect this SA, ESP|AH
         */
        protocol_id_t protocol;
@@ -135,11 +125,6 @@ struct private_child_sa_t {
        ipcomp_transform_t ipcomp;
        
        /**
-        * TRUE if we allocated (or tried to allocate) a CPI
-        */
-       bool cpi_allocated;
-       
-       /**
         * mode this SA uses, tunnel/transport
         */
        ipsec_mode_t mode;
@@ -170,7 +155,32 @@ static u_int32_t get_reqid(private_child_sa_t *this)
 {
        return this->reqid;
 }
-       
+
+/**
+ * Implements child_sa_t.get_config
+ */
+static child_cfg_t* get_config(private_child_sa_t *this)
+{
+       return this->config;
+}
+
+/**
+ * Implements child_sa_t.set_state
+ */
+static void set_state(private_child_sa_t *this, child_sa_state_t state)
+{
+       charon->bus->child_state_change(charon->bus, &this->public, state);
+       this->state = state;
+}
+
+/**
+ * Implements child_sa_t.get_state
+ */
+static child_sa_state_t get_state(private_child_sa_t *this)
+{
+       return this->state;
+}
+
 /**
  * Implements child_sa_t.get_spi
  */
@@ -196,6 +206,14 @@ protocol_id_t get_protocol(private_child_sa_t *this)
 }
 
 /**
+ * Implementation of child_sa_t.set_protocol
+ */
+static void set_protocol(private_child_sa_t *this, protocol_id_t protocol)
+{
+       this->protocol = protocol;
+}
+
+/**
  * Implementation of child_sa_t.get_mode
  */
 static ipsec_mode_t get_mode(private_child_sa_t *this)
@@ -204,6 +222,14 @@ static ipsec_mode_t get_mode(private_child_sa_t *this)
 }
 
 /**
+ * Implementation of child_sa_t.set_mode
+ */
+static void set_mode(private_child_sa_t *this, ipsec_mode_t mode)
+{
+       this->mode = mode;
+}
+
+/**
  * Implementation of child_sa_t.has_encap
  */
 static bool has_encap(private_child_sa_t *this)
@@ -220,19 +246,35 @@ static ipcomp_transform_t get_ipcomp(private_child_sa_t *this)
 }
 
 /**
- * Implements child_sa_t.get_state
+ * Implementation of child_sa_t.set_ipcomp.
  */
-static child_sa_state_t get_state(private_child_sa_t *this)
+static void set_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp)
 {
-       return this->state;
+       this->ipcomp = ipcomp;
 }
 
 /**
- * Implements child_sa_t.get_config
+ * Implementation of child_sa_t.get_proposal
  */
-static child_cfg_t* get_config(private_child_sa_t *this)
+static proposal_t* get_proposal(private_child_sa_t *this)
 {
-       return this->config;
+       return this->proposal;
+}
+
+/**
+ * Implementation of child_sa_t.set_proposal
+ */
+static void set_proposal(private_child_sa_t *this, proposal_t *proposal)
+{
+       this->proposal = proposal->clone(proposal);
+}
+
+/**
+ * Implementation of child_sa_t.get_traffic_selectors.
+ */
+static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
+{
+       return local ? this->my_ts : this->other_ts;
 }
 
 typedef struct policy_enumerator_t policy_enumerator_t;
@@ -366,143 +408,100 @@ static u_int32_t get_lifetime(private_child_sa_t *this, bool hard)
 }
 
 /**
- * Implements child_sa_t.set_state
- */
-static void set_state(private_child_sa_t *this, child_sa_state_t state)
-{
-       charon->bus->child_state_change(charon->bus, &this->public, state);
-       this->state = state;
-}
-
-/**
- * Allocate SPI for a single proposal
+ * Implementation of child_sa_t.alloc_spi
  */
-static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal)
+static u_int32_t alloc_spi(private_child_sa_t *this, protocol_id_t protocol)
 {
-       protocol_id_t protocol = proposal->get_protocol(proposal);
-               
-       if (protocol == PROTO_AH)
+       switch (protocol)
        {
-               /* get a new spi for AH, if not already done */
-               if (this->alloc_ah_spi == 0)
-               {
-                       if (charon->kernel_interface->get_spi(
-                                                charon->kernel_interface, 
-                                                this->other_addr, this->my_addr,
-                                                PROTO_AH, this->reqid,
-                                                &this->alloc_ah_spi) != SUCCESS)
+               case PROTO_AH:
+                       if (charon->kernel_interface->get_spi(charon->kernel_interface, 
+                                                       this->other_addr, this->my_addr, PROTO_AH,
+                                                       this->reqid, &this->my_spi) == SUCCESS)
                        {
-                               return FAILED;
+                               return this->my_spi;
                        }
-               }
-               proposal->set_spi(proposal, this->alloc_ah_spi);
-       }
-       if (protocol == PROTO_ESP)
-       {
-               /* get a new spi for ESP, if not already done */
-               if (this->alloc_esp_spi == 0)
-               {
-                       if (charon->kernel_interface->get_spi(
-                                                charon->kernel_interface,
-                                                this->other_addr, this->my_addr,
-                                                PROTO_ESP, this->reqid,
-                                                &this->alloc_esp_spi) != SUCCESS)
+                       break;
+               case PROTO_ESP:
+                       if (charon->kernel_interface->get_spi(charon->kernel_interface,
+                                                       this->other_addr, this->my_addr, PROTO_ESP,
+                                                       this->reqid, &this->my_spi) == SUCCESS)
                        {
-                               return FAILED;
+                               return this->my_spi;
                        }
-               }
-               proposal->set_spi(proposal, this->alloc_esp_spi);
+                       break;
+               default:
+                       break;
        }
-       return SUCCESS;
+       return 0;
 }
 
 /**
- * Implements child_sa_t.alloc
+ * Implementation of child_sa_t.alloc_cpi
  */
-static status_t alloc(private_child_sa_t *this, linked_list_t *proposals)
+static u_int16_t alloc_cpi(private_child_sa_t *this)
 {
-       iterator_t *iterator;
-       proposal_t *proposal;
-       
-       /* iterator through proposals to update spis */
-       iterator = proposals->create_iterator(proposals, TRUE);
-       while(iterator->iterate(iterator, (void**)&proposal))
+       if (charon->kernel_interface->get_cpi(charon->kernel_interface,
+                                       this->other_addr, this->my_addr, this->reqid,
+                                       &this->my_cpi) == SUCCESS)
        {
-               if (alloc_proposal(this, proposal) != SUCCESS)
-               {
-                       iterator->destroy(iterator);
-                       return FAILED;
-               }
+               return this->my_cpi;
        }
-       iterator->destroy(iterator);
-       return SUCCESS;
+       return 0;
 }
 
 /**
- * Install an SA for one direction
+ * Implementation of child_sa_t.install
  */
-static status_t install(private_child_sa_t *this, proposal_t *proposal,
-                                               ipsec_mode_t mode, chunk_t integ, chunk_t encr, bool in)
+static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
+                                               u_int32_t spi, u_int16_t cpi, bool inbound)
 {
        u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
-       u_int32_t spi, soft, hard, now;
+       u_int32_t soft, hard, now;
        host_t *src, *dst;
        status_t status;
+       bool update = FALSE;
        
        /* now we have to decide which spi to use. Use self allocated, if "in",
         * or the one in the proposal, if not "in" (others). Additionally,
         * source and dest host switch depending on the role */
-       if (in)
+       if (inbound)
        {
-               /* if we have allocated SPIs for AH and ESP, we must delete the unused
-                * one. */
-               if (this->protocol == PROTO_ESP)
-               {
-                       this->my_spi = this->alloc_esp_spi;
-                       if (this->alloc_ah_spi)
-                       {
-                               charon->kernel_interface->del_sa(charon->kernel_interface,
-                                                               this->my_addr, this->alloc_ah_spi, 0, PROTO_AH);
-                       }
-               }
-               else
-               {
-                       this->my_spi = this->alloc_ah_spi;
-                       if (this->alloc_esp_spi)
-                       {
-                               charon->kernel_interface->del_sa(charon->kernel_interface,
-                                                               this->my_addr, this->alloc_esp_spi, 0, PROTO_ESP);
-                       }
-               }
-               spi = this->my_spi;
                dst = this->my_addr;
                src = this->other_addr;
+               if (this->my_spi == spi)
+               {       /* alloc_spi has been called, do an SA update */
+                       update = TRUE;
+               }
+               this->my_spi = spi;
+               this->my_cpi = cpi;
        }
        else
        {
-               this->other_spi = proposal->get_spi(proposal);
-               spi = this->other_spi;
                src = this->my_addr;
                dst = this->other_addr;
+               this->other_spi = spi;
+               this->other_cpi = cpi;
        }
        
-       DBG2(DBG_CHD, "adding %s %N SA", in ? "inbound" : "outbound",
+       DBG2(DBG_CHD, "adding %s %N SA", inbound ? "inbound" : "outbound",
                 protocol_id_names, this->protocol);
        
        /* send SA down to the kernel */
        DBG2(DBG_CHD, "  SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst);
        
-       proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &size);
-       proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &size);
+       this->proposal->get_algorithm(this->proposal, ENCRYPTION_ALGORITHM,
+                                                                 &enc_alg, &size);
+       this->proposal->get_algorithm(this->proposal, INTEGRITY_ALGORITHM,
+                                                                 &int_alg, &size);
        
        soft = this->config->get_lifetime(this->config, TRUE);
        hard = this->config->get_lifetime(this->config, FALSE);
-
+       
        status = charon->kernel_interface->add_sa(charon->kernel_interface,
                                src, dst, spi, this->protocol, this->reqid,
-                               in ? soft : 0, hard, enc_alg, encr, int_alg, integ,
-                               mode, this->ipcomp, in ? this->my_cpi : this->other_cpi,
-                               this->encap, in);
+                               inbound ? soft : 0, hard, enc_alg, encr, int_alg, integ,
+                               this->mode, this->ipcomp, cpi, this->encap, update);
        
        now = time(NULL);
        this->rekey_time = now + soft;
@@ -511,83 +510,16 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal,
 }
 
 /**
- * Implementation of child_sa_t.add
- */
-static status_t add(private_child_sa_t *this, 
-                                       proposal_t *proposal, ipsec_mode_t mode,
-                                       chunk_t integ_in, chunk_t integ_out,
-                                       chunk_t encr_in, chunk_t encr_out)
-{
-       this->proposal = proposal->clone(proposal);
-       this->protocol = proposal->get_protocol(proposal);
-       
-       /* get SPIs for inbound SAs, write to proposal */
-       if (alloc_proposal(this, proposal) != SUCCESS)
-       {
-               return FAILED;
-       }
-       /* install inbound SAs using allocated SPI */
-       if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS)
-       {
-               return FAILED;
-       }
-       /* install outbound SAs using received SPI*/
-       if (install(this, this->proposal, mode, integ_out, encr_out, FALSE) != SUCCESS)
-       {
-               return FAILED;
-       }
-       return SUCCESS;
-}
-
-/**
- * Implementation of child_sa_t.update
- */
-static status_t update(private_child_sa_t *this,
-                                          proposal_t *proposal, ipsec_mode_t mode,
-                                          chunk_t integ_in, chunk_t integ_out,
-                                          chunk_t encr_in, chunk_t encr_out)
-{
-       this->proposal = proposal->clone(proposal);
-       this->protocol = proposal->get_protocol(proposal);
-       
-       /* install outbound SAs */
-       if (install(this, proposal, mode, integ_out, encr_out, FALSE) != SUCCESS)
-       {
-               return FAILED;
-       }
-       /* install inbound SAs */
-       if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS)
-       {
-               return FAILED;
-       }
-       return SUCCESS;
-}
-
-/**
- * Implementation of child_sa_t.get_proposal
- */
-static proposal_t* get_proposal(private_child_sa_t *this)
-{
-       return this->proposal;
-}
-
-/**
  * Implementation of child_sa_t.add_policies
  */
 static status_t add_policies(private_child_sa_t *this,
-                                       linked_list_t *my_ts_list, linked_list_t *other_ts_list,
-                                       ipsec_mode_t mode, protocol_id_t proto)
+                                       linked_list_t *my_ts_list, linked_list_t *other_ts_list)
 {
        enumerator_t *enumerator;
        traffic_selector_t *my_ts, *other_ts;
        status_t status = SUCCESS;
        bool routed = (this->state == CHILD_CREATED);
        
-       if (this->protocol == PROTO_NONE)
-       {       /* update if not set yet */
-               this->protocol = proto;
-       }
-
        /* apply traffic selectors */
        enumerator = my_ts_list->create_enumerator(my_ts_list);
        while (enumerator->enumerate(enumerator, &my_ts))
@@ -611,19 +543,19 @@ static status_t add_policies(private_child_sa_t *this,
                        /* install 3 policies: out, in and forward */
                        status |= charon->kernel_interface->add_policy(charon->kernel_interface,
                                        this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
-                                       this->other_spi, this->protocol, this->reqid, mode, this->ipcomp,
-                                       this->other_cpi, routed);
+                                       this->other_spi, this->protocol, this->reqid, this->mode,
+                                       this->ipcomp, this->other_cpi, routed);
                        
                        status |= charon->kernel_interface->add_policy(charon->kernel_interface,
                                        this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
-                                       this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
-                                       this->my_cpi, routed);
-                       if (mode != MODE_TRANSPORT)
+                                       this->my_spi, this->protocol, this->reqid, this->mode,
+                                       this->ipcomp, this->my_cpi, routed);
+                       if (this->mode != MODE_TRANSPORT)
                        {
                                status |= charon->kernel_interface->add_policy(charon->kernel_interface,
                                        this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
-                                       this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
-                                       this->my_cpi, routed);
+                                       this->my_spi, this->protocol, this->reqid, this->mode,
+                                       this->ipcomp, this->my_cpi, routed);
                        }
                        
                        if (status != SUCCESS)
@@ -634,32 +566,18 @@ static status_t add_policies(private_child_sa_t *this,
                enumerator->destroy(enumerator);
        }
        
-       if (status == SUCCESS)
-       {
-               /* switch to routed state if no SAD entry set up */
-               if (this->state == CHILD_CREATED)
-               {
-                       set_state(this, CHILD_ROUTED);
-               }
-               /* needed to update hosts */
-               this->mode = mode;
+       if (status == SUCCESS && this->state == CHILD_CREATED)
+       {       /* switch to routed state if no SAD entry set up */
+               set_state(this, CHILD_ROUTED);
        }
        return status;
 }
 
 /**
- * Implementation of child_sa_t.get_traffic_selectors.
+ * Implementation of child_sa_t.update.
  */
-static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local)
-{
-       return local ? this->my_ts : this->other_ts;
-}
-
-/**
- * Implementation of child_sa_t.update_hosts.
- */
-static status_t update_hosts(private_child_sa_t *this, 
-                                                        host_t *me, host_t *other, host_t *vip, bool encap) 
+static status_t update(private_child_sa_t *this,  host_t *me, host_t *other,
+                                          host_t *vip, bool encap) 
 {
        child_sa_state_t old;
        bool transport_proxy_mode;
@@ -792,30 +710,6 @@ static status_t update_hosts(private_child_sa_t *this,
 }
 
 /**
- * Implementation of child_sa_t.activate_ipcomp.
- */
-static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
-               u_int16_t other_cpi)
-{
-       this->ipcomp = ipcomp;
-       this->other_cpi = other_cpi;
-}
-
-/**
- * Implementation of child_sa_t.allocate_cpi.
- */
-static u_int16_t allocate_cpi(private_child_sa_t *this)
-{
-       if (!this->cpi_allocated)
-       {
-               charon->kernel_interface->get_cpi(charon->kernel_interface,
-                       this->other_addr, this->my_addr, this->reqid, &this->my_cpi);
-               this->cpi_allocated = TRUE;
-       }
-       return this->my_cpi;
-}
-
-/**
  * Implementation of child_sa_t.destroy.
  */
 static void destroy(private_child_sa_t *this)
@@ -833,16 +727,6 @@ static void destroy(private_child_sa_t *this)
                                        this->my_addr, this->my_spi, this->protocol,
                                        this->my_cpi);
        }
-       if (this->alloc_esp_spi && this->alloc_esp_spi != this->my_spi)
-       {
-               charon->kernel_interface->del_sa(charon->kernel_interface,
-                                       this->my_addr, this->alloc_esp_spi, PROTO_ESP, 0);
-       }
-       if (this->alloc_ah_spi && this->alloc_ah_spi != this->my_spi)
-       {
-               charon->kernel_interface->del_sa(charon->kernel_interface,
-                                       this->my_addr, this->alloc_ah_spi, PROTO_AH, 0);
-       }
        if (this->other_spi)
        {
                charon->kernel_interface->del_sa(charon->kernel_interface,
@@ -890,40 +774,39 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        /* public functions */
        this->public.get_name = (char*(*)(child_sa_t*))get_name;
        this->public.get_reqid = (u_int32_t(*)(child_sa_t*))get_reqid;
+       this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
+       this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
+       this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
        this->public.get_spi = (u_int32_t(*)(child_sa_t*, bool))get_spi;
        this->public.get_cpi = (u_int16_t(*)(child_sa_t*, bool))get_cpi;
        this->public.get_protocol = (protocol_id_t(*)(child_sa_t*))get_protocol;
+       this->public.set_protocol = (void(*)(child_sa_t*, protocol_id_t protocol))set_protocol;
        this->public.get_mode = (ipsec_mode_t(*)(child_sa_t*))get_mode;
-       this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
-       this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
+       this->public.set_mode = (void(*)(child_sa_t*, ipsec_mode_t mode))set_mode;
+       this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
+       this->public.set_proposal = (void(*)(child_sa_t*, proposal_t *proposal))set_proposal;
        this->public.get_lifetime = (u_int32_t(*)(child_sa_t*, bool))get_lifetime;
        this->public.get_usetime = (u_int32_t(*)(child_sa_t*, bool))get_usetime;
-       this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
-       this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))add;
-       this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))update;
-       this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal;
-       this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update_hosts;
-       this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,ipsec_mode_t,protocol_id_t))add_policies;
+       this->public.has_encap = (bool(*)(child_sa_t*))has_encap;
+       this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp;
+       this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
+       this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi;
+       this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi;
+       this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound))install;
+       this->public.update = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update;
+       this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
        this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
        this->public.create_policy_enumerator = (enumerator_t*(*)(child_sa_t*))create_policy_enumerator;
-       this->public.set_state = (void(*)(child_sa_t*,child_sa_state_t))set_state;
-       this->public.get_state = (child_sa_state_t(*)(child_sa_t*))get_state;
-       this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
-       this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
-       this->public.allocate_cpi = (u_int16_t(*)(child_sa_t*))allocate_cpi;
        this->public.destroy = (void(*)(child_sa_t*))destroy;
-
+       
        /* private data */
        this->my_addr = me->clone(me);
        this->other_addr = other->clone(other);
        this->my_spi = 0;
-       this->my_cpi = 0;
        this->other_spi = 0;
+       this->my_cpi = 0;
        this->other_cpi = 0;
-       this->alloc_ah_spi = 0;
-       this->alloc_esp_spi = 0;
        this->encap = encap;
-       this->cpi_allocated = FALSE;
        this->ipcomp = IPCOMP_NONE;
        this->state = CHILD_CREATED;
        /* reuse old reqid if we are rekeying an existing CHILD_SA */
@@ -935,7 +818,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        this->proposal = NULL;
        this->config = config;
        config->get_ref(config);
-
+       
        /* MIPv6 proxy transport mode sets SA endpoints to TS hosts */  
        if (config->get_mode(config) == MODE_TRANSPORT &&
            config->use_proxy_mode(config))
@@ -947,9 +830,9 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
                enumerator_t *enumerator;
                linked_list_t *my_ts_list, *other_ts_list;
                traffic_selector_t *my_ts, *other_ts;
-
+               
                this->mode = MODE_TRANSPORT;
-
+               
                my_ts_list = config->get_traffic_selectors(config, TRUE, NULL, me);
                enumerator = my_ts_list->create_enumerator(my_ts_list);
                if (enumerator->enumerate(enumerator, &my_ts))
@@ -970,7 +853,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
                }
                enumerator->destroy(enumerator);
                my_ts_list->destroy_offset(my_ts_list, offsetof(traffic_selector_t, destroy));
-
+               
                other_ts_list = config->get_traffic_selectors(config, FALSE, NULL, other);
                enumerator = other_ts_list->create_enumerator(other_ts_list);
                if (enumerator->enumerate(enumerator, &other_ts))
index 202573a..7e180b7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2006-2008 Tobias Brunner
- * Copyright (C) 2006-2007 Martin Willi
+ * Copyright (C) 2006-2008 Martin Willi
  * Copyright (C) 2006 Daniel Roethlisberger
  * Hochschule fuer Technik Rapperswil
  *
@@ -93,12 +93,13 @@ extern enum_name_t *child_sa_state_names;
  * SAs and the policies have the same reqid.
  * 
  * The procedure for child sa setup is as follows:
- * - A gets SPIs for a proposal via child_sa_t.alloc
- * - A send the updated proposal to B
+ * - A gets SPIs for a all protocols in its proposals via child_sa_t.alloc
+ * - A send the proposals with the allocated SPIs to B
  * - B selects a suitable proposal
- * - B calls child_sa_t.add to add and update the selected proposal
- * - B sends the updated proposal to A
- * - A calls child_sa_t.update to update the already allocated SPIs with the chosen proposal
+ * - B allocates an SPI for the selected protocol
+ * - B calls child_sa_t.install for both, the allocated and received SPI
+ * - B sends the proposal with the allocated SPI to A
+ * - A calls child_sa_t.install for both, the allocated and recevied SPI
  * 
  * Once SAs are set up, policies can be added using add_policies.
  */
@@ -122,6 +123,27 @@ struct child_sa_t {
        u_int32_t (*get_reqid)(child_sa_t *this);
        
        /**
+        * Get the config used to set up this child sa.
+        *
+        * @return                      child_cfg
+        */
+       child_cfg_t* (*get_config) (child_sa_t *this);
+       
+       /**
+        * Get the state of the CHILD_SA.
+        *
+        * @return                      CHILD_SA state
+        */     
+       child_sa_state_t (*get_state) (child_sa_t *this);
+       
+       /**
+        * Set the state of the CHILD_SA.
+        *
+        * @param state         state to set on CHILD_SA
+        */     
+       void (*set_state) (child_sa_t *this, child_sa_state_t state);
+       
+       /**
         * Get the SPI of this CHILD_SA.
         * 
         * Set the boolean parameter inbound to TRUE to
@@ -153,6 +175,13 @@ struct child_sa_t {
        protocol_id_t (*get_protocol) (child_sa_t *this);
        
        /**
+        * Set the negotiated protocol to use for this CHILD_SA.
+        *
+        * @param protocol      AH | ESP
+        */
+       void (*set_protocol)(child_sa_t *this, protocol_id_t protocol);
+       
+       /**
         * Get the IPsec mode of this CHILD_SA.
         *
         * @return                      TUNNEL | TRANSPORT | BEET
@@ -160,6 +189,13 @@ struct child_sa_t {
        ipsec_mode_t (*get_mode)(child_sa_t *this);
        
        /**
+        * Set the negotiated IPsec mode to use.
+        *
+        * @param mode          TUNNEL | TRANPORT | BEET
+        */
+       void (*set_mode)(child_sa_t *this, ipsec_mode_t mode);
+       
+       /**
         * Get the used IPComp algorithm.
         *
         * @return                      IPComp compression algorithm.
@@ -167,6 +203,27 @@ struct child_sa_t {
        ipcomp_transform_t (*get_ipcomp)(child_sa_t *this);
        
        /**
+        * Set the IPComp algorithm to use.
+        * 
+        * @param ipcomp        the IPComp transform to use
+        */
+       void (*set_ipcomp)(child_sa_t *this, ipcomp_transform_t ipcomp);
+       
+       /**
+        * Get the selected proposal.
+        *
+        * @return                      selected proposal
+        */
+       proposal_t* (*get_proposal)(child_sa_t *this);
+       
+       /**
+        * Set the negotiated proposal.
+        *
+        * @param proposal      selected proposal
+        */
+       void (*set_proposal)(child_sa_t *this, proposal_t *proposal);   
+       
+       /**
         * Check if this CHILD_SA uses UDP encapsulation.
         *
         * @return                      TRUE if SA encapsulates ESP packets
@@ -190,69 +247,48 @@ struct child_sa_t {
        u_int32_t (*get_usetime)(child_sa_t *this, bool inbound);
        
        /**
-        * Allocate SPIs for given proposals.
-        * 
-        * Since the kernel manages SPIs for us, we need
-        * to allocate them. If a proposal contains more
-        * than one protocol, for each protocol an SPI is
-        * allocated. SPIs are stored internally and written
-        * back to the proposal.
+        * Get the traffic selectors list added for one side.
         *
-        * @param proposals     list of proposals for which SPIs are allocated
-        */
-       status_t (*alloc)(child_sa_t *this, linked_list_t* proposals);
+        * @param local         TRUE for own traffic selectors, FALSE for remote
+        * @return                      list of traffic selectors
+        */     
+       linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local);
        
        /**
-        * Install the kernel SAs for a proposal, without previous SPI allocation.
+        * Create an enumerator over installed policies.
         *
-        * @param proposal      proposal for which SPIs are allocated
-        * @param mode          mode for the CHILD_SA
-        * @param integ_in      integrity key for inbound traffic
-        * @param integ_out     integrity key for outbound traffic
-        * @param encr_in       encryption key for inbound traffic
-        * @param enc_out       encryption key for outbound traffic
-        * @return                      SUCCESS or FAILED
+        * @return                      enumerator over pairs of traffic selectors.
         */
-       status_t (*add)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
-                                       chunk_t integ_in, chunk_t integ_out,
-                                       chunk_t encr_in, chunk_t encr_out);
+       enumerator_t* (*create_policy_enumerator)(child_sa_t *this);
+       
        /**
-        * Install the kernel SAs for a proposal, after SPIs have been allocated.
-        *
-        * Updates an SA, for which SPIs are already allocated via alloc().
+        * Allocate an SPI to include in a proposal.
         *
-        * @param proposal      proposal for which SPIs are allocated
-        * @param mode          mode for the CHILD_SA
-        * @param integ_in      integrity key for inbound traffic
-        * @param integ_out     integrity key for outbound traffic
-        * @param encr_in       encryption key for inbound traffic
-        * @param enc_out       encryption key for outbound traffic
-        * @return                      SUCCESS or FAILED
+        * @param protocol      protocol to allocate SPI for (ESP|AH)
+        * @param spi           SPI output pointer
+        * @return                      SPI, 0 on failure
         */
-       status_t (*update)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode,
-                                          chunk_t integ_in, chunk_t integ_out,
-                                          chunk_t encr_in, chunk_t encr_out);
+       u_int32_t (*alloc_spi)(child_sa_t *this, protocol_id_t protocol);
+       
        /**
-        * Get the selected proposal passed to add()/update().
+        * Allocate a CPI to use for IPComp.
         *
-        * @return                      selected proposal
+        * @return                      CPI, 0 on failure
         */
-       proposal_t* (*get_proposal)(child_sa_t *this);
+       u_int16_t (*alloc_cpi)(child_sa_t *this);
        
        /**
-        * Update the hosts in the kernel SAs and policies.
+        * Install an IPsec SA for one direction.
         *
-        * The CHILD must be INSTALLED to do this update.
-        *
-        * @param me            the new local host
-        * @param other         the new remote host
-        * @param vip           virtual IP, if any
-        * @param                       TRUE to use UDP encapsulation for NAT traversal
+        * @param encr          encryption key, if any
+        * @param integ         integrity key
+        * @param spi           SPI to use, allocated for inbound
+        * @param cpi           CPI to use, allocated for outbound
+        * @param inbound       TRUE to install an inbound SA, FALSE for outbound
         * @return                      SUCCESS or FAILED
         */
-       status_t (*update_hosts)(child_sa_t *this, host_t *me, host_t *other,
-                                                        host_t *vip, bool encap);
-       
+       status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
+                                               u_int32_t spi, u_int16_t cpi, bool inbound);
        /**
         * Install the policies using some traffic selectors.
         *
@@ -261,64 +297,21 @@ 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, ipsec_mode_t mode,
-                                                        protocol_id_t proto);
-       
-       /**
-        * Get the traffic selectors of added policies of local host.
-        *
-        * @param local         TRUE for own traffic selectors, FALSE for remote
-        * @return                      list of traffic selectors
-        */     
-       linked_list_t* (*get_traffic_selectors) (child_sa_t *this, bool local);
-       
+                                                        linked_list_t *other_ts_list);
        /**
-        * Create an enumerator over installed policies.
+        * Update hosts and ecapulation mode in the kernel SAs and policies.
         *
-        * @return                      enumerator over pairs of traffic selectors.
-        */
-       enumerator_t* (*create_policy_enumerator)(child_sa_t *this);
-       
-       /**
-        * Get the state of the CHILD_SA.
-        */     
-       child_sa_state_t (*get_state) (child_sa_t *this);
-       
-       /**
-        * Set the state of the CHILD_SA.
-        *
-        * @param state         state to set on CHILD_SA
-        */     
-       void (*set_state) (child_sa_t *this, child_sa_state_t state);
-       
-       /**
-        * Get the config used to set up this child sa.
-        *
-        * @return                      child_cfg
-        */
-       child_cfg_t* (*get_config) (child_sa_t *this);
-       
-       /**
-        * Activate IPComp by setting the transform ID and CPI values.
-        * 
-        * @param ipcomp        the IPComp transform to use
-        * @param other_cpi     other Compression Parameter Index
-        */
-       void (*activate_ipcomp) (child_sa_t *this, ipcomp_transform_t ipcomp,
-                                                        u_int16_t other_cpi);
-       
-       /**
-        * Returns the Compression Parameter Index (CPI) allocated from the kernel.
-        * 
-        * @return                      allocated CPI
+        * @param me            the new local host
+        * @param other         the new remote host
+        * @param vip           virtual IP, if any
+        * @param                       TRUE to use UDP encapsulation for NAT traversal
+        * @return                      SUCCESS or FAILED
         */
-       u_int16_t (*allocate_cpi) (child_sa_t *this);
-       
+       status_t (*update)(child_sa_t *this, host_t *me, host_t *other,
+                                          host_t *vip, bool encap);
        /**
         * Destroys a child_sa.
         */
index f6fa351..d8932dd 100644 (file)
@@ -874,7 +874,7 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
                iterator = this->child_sas->create_iterator(this->child_sas, TRUE);
                while (iterator->iterate(iterator, (void**)&child_sa))
                {
-                       if (child_sa->update_hosts(child_sa, this->my_host,
+                       if (child_sa->update(child_sa, this->my_host,
                                                this->other_host, this->my_virtual_ip,
                                                has_condition(this, COND_NAT_ANY)) == NOT_SUPPORTED)
                        {
@@ -1288,8 +1288,8 @@ 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), PROTO_NONE);
+       child_sa->set_mode(child_sa, child_cfg->get_mode(child_cfg));
+       status = child_sa->add_policies(child_sa, my_ts, other_ts);
 
        my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
        other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
index 0266433..f1453f0 100644 (file)
@@ -117,7 +117,22 @@ struct private_child_create_t {
        ipcomp_transform_t ipcomp_received;
        
        /**
-        * Other Compression Parameter Index (CPI)
+        * Own allocated SPI
+        */
+       u_int32_t my_spi;
+       
+       /**
+        * SPI received in proposal
+        */
+       u_int32_t other_spi;
+       
+       /**
+        * Own allocated Compression Parameter Index (CPI)
+        */
+       u_int16_t my_cpi;
+       
+       /**
+        * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
         */
        u_int16_t other_cpi;
        
@@ -189,6 +204,36 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host)
 }
 
 /**
+ * Allocate SPIs and update proposals
+ */
+static bool allocate_spi(private_child_create_t *this)
+{
+       enumerator_t *enumerator;
+       proposal_t *proposal;
+       
+       /* TODO: allocate additional SPI for AH if we have such proposals */ 
+       this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
+       if (this->my_spi)
+       {
+               if (this->initiator)
+               {
+                       enumerator = this->proposals->create_enumerator(this->proposals);
+                       while (enumerator->enumerate(enumerator, &proposal))
+                       {
+                               proposal->set_spi(proposal, this->my_spi);
+                       }
+                       enumerator->destroy(enumerator);
+               }
+               else
+               {
+                       this->proposal->set_spi(this->proposal, this->my_spi);
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/**
  * Install a CHILD_SA for usage, return value:
  * - FAILED: no acceptable proposal
  * - INVALID_ARG: diffie hellman group inacceptable
@@ -216,7 +261,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
        other = this->ike_sa->get_other_host(this->ike_sa);
        my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
        other_vip = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
-
+       
        this->proposal = this->config->select_proposal(this->config, this->proposals,
                                                                                                   no_dh);
        if (this->proposal == NULL)
@@ -224,6 +269,14 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
                DBG1(DBG_IKE, "no acceptable proposal found");
                return FAILED;
        }
+       this->other_spi = this->proposal->get_spi(this->proposal);
+       
+       if (!this->initiator && !allocate_spi(this))
+       {       /* responder has no SPI allocated yet */
+               DBG1(DBG_IKE, "allocating SPI failed");
+               return FAILED;
+       }
+       this->child_sa->set_proposal(this->child_sa, this->proposal);
        
        if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
        {
@@ -328,26 +381,33 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
        }
        
        this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
+       this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
+       this->child_sa->set_mode(this->child_sa, this->mode);
+       this->child_sa->set_protocol(this->child_sa,
+                                                                this->proposal->get_protocol(this->proposal));
        
-       if (this->ipcomp != IPCOMP_NONE)
+       if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
        {
-               this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp,
-                                                                               this->other_cpi);
+               this->my_cpi = this->other_cpi = 0;
+               this->ipcomp = IPCOMP_NONE;
        }
-       
        status = FAILED;
        if (this->keymat->derive_child_keys(this->keymat, this->proposal,
                        this->dh, nonce_i, nonce_r,     &encr_i, &integ_i, &encr_r, &integ_r))
        {
                if (this->initiator)
                {
-                       status = this->child_sa->update(this->child_sa, this->proposal,
-                                                       this->mode, integ_r, integ_i, encr_r, encr_i);
+                       status = this->child_sa->install(this->child_sa, encr_r, integ_r,
+                                                                               this->my_spi, this->my_cpi, TRUE);
+                       status = this->child_sa->install(this->child_sa, encr_i, integ_i,
+                                                                               this->other_spi, this->other_cpi, FALSE);
                }
                else
                {
-                       status = this->child_sa->add(this->child_sa, this->proposal,
-                                                       this->mode, integ_i, integ_r, encr_i, encr_r);
+                       status = this->child_sa->install(this->child_sa, encr_i, integ_i,
+                                                                               this->my_spi, this->my_cpi, TRUE);
+                       status = this->child_sa->install(this->child_sa, encr_r, integ_r,
+                                                                               this->other_spi, this->other_cpi, FALSE);
                }
        }
        chunk_clear(&integ_i);
@@ -361,8 +421,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
                return FAILED;
        }
        
-       status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts,
-                                       this->mode, this->proposal->get_protocol(this->proposal));
+       status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
        if (status != SUCCESS)
        {       
                DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
@@ -436,33 +495,71 @@ static void build_payloads(private_child_create_t *this, message_t *message)
 }
 
 /**
- * Adds an IPCOMP_SUPPORTED notify to the message, if possible
+ * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
  */
-static void build_ipcomp_supported_notify(private_child_create_t *this,
-                                                                                 message_t *message)
+static void add_ipcomp_notify(private_child_create_t *this,
+                                                                 message_t *message, u_int8_t ipcomp)
 {
-       u_int16_t cpi;
-       u_int8_t tid;
-
        if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
        {
                DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
                         "IPComp disabled");
-               this->ipcomp = IPCOMP_NONE;
                return;
        }
        
-       cpi = this->child_sa->allocate_cpi(this->child_sa);
-       tid = this->ipcomp;
-       if (cpi)
+       this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
+       if (this->my_cpi)
        {
-               message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
-                               chunk_cata("cc", chunk_from_thing(cpi), chunk_from_thing(tid)));
+               this->ipcomp = ipcomp;
+               message->add_notify(message, FALSE, IPCOMP_SUPPORTED, 
+                                                       chunk_cata("cc", chunk_from_thing(this->my_cpi),
+                                                                          chunk_from_thing(ipcomp)));
        }
        else
        {
                DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
-               this->ipcomp = IPCOMP_NONE;
+       }
+}
+
+/**
+ * handle a received notify payload
+ */
+static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
+{
+       switch (notify->get_notify_type(notify))
+       {
+               case USE_TRANSPORT_MODE:
+                       this->mode = MODE_TRANSPORT;
+                       break;
+               case USE_BEET_MODE:
+                       this->mode = MODE_BEET;
+                       break;
+               case IPCOMP_SUPPORTED:
+               {
+                       ipcomp_transform_t ipcomp;
+                       u_int16_t cpi;
+                       chunk_t data;
+                       
+                       data = notify->get_notification_data(notify);
+                       cpi = *(u_int16_t*)data.ptr;
+                       ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
+                       switch (ipcomp)
+                       {
+                               case IPCOMP_DEFLATE:
+                                       this->other_cpi = cpi;
+                                       this->ipcomp_received = ipcomp;
+                                       break;
+                               case IPCOMP_LZS:
+                               case IPCOMP_LZJH:
+                               default:
+                                       DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a "
+                                                "transform ID we don't support %N",
+                                                ipcomp_transform_names, ipcomp);
+                                       break;
+                       }
+               }
+               default:
+                       break;
        }
 }
 
@@ -476,7 +573,6 @@ static void process_payloads(private_child_create_t *this, message_t *message)
        sa_payload_t *sa_payload;
        ke_payload_t *ke_payload;
        ts_payload_t *ts_payload;
-       notify_payload_t *notify_payload;
        
        /* defaults to TUNNEL mode */
        this->mode = MODE_TUNNEL;
@@ -512,37 +608,7 @@ static void process_payloads(private_child_create_t *this, message_t *message)
                                this->tsr = ts_payload->get_traffic_selectors(ts_payload);
                                break;
                        case NOTIFY:
-                               notify_payload = (notify_payload_t*)payload;
-                               switch (notify_payload ->get_notify_type(notify_payload ))
-                               {
-                                       case USE_TRANSPORT_MODE:
-                                               this->mode = MODE_TRANSPORT;
-                                               break;
-                                       case USE_BEET_MODE:
-                                               this->mode = MODE_BEET;
-                                               break;
-                                       case IPCOMP_SUPPORTED:
-                                       {
-                                               chunk_t data = notify_payload->get_notification_data(notify_payload);
-                                               u_int16_t cpi = *(u_int16_t*)data.ptr;
-                                               ipcomp_transform_t ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
-                                               switch(ipcomp)
-                                               {
-                                                       case IPCOMP_DEFLATE:
-                                                               this->other_cpi = cpi;
-                                                               this->ipcomp_received = ipcomp;
-                                                               break;
-                                                       case IPCOMP_LZS:
-                                                       case IPCOMP_LZJH:
-                                                       default:
-                                                               DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a transform"
-                                                                               " ID we don't support %N", ipcomp_transform_names, ipcomp);
-                                                               break;
-                                               }
-                                       }
-                                       default:
-                                               break;
-                               }
+                               handle_notify(this, (notify_payload_t*)payload);
                                break;
                        default:
                                break;
@@ -559,7 +625,7 @@ static status_t build_i(private_child_create_t *this, message_t *message)
        host_t *me, *other, *vip;
        bool propose_all = FALSE;
        peer_cfg_t *peer_cfg;
-
+       
        switch (message->get_exchange_type(message))
        {
                case IKE_SA_INIT:
@@ -641,7 +707,7 @@ static status_t build_i(private_child_create_t *this, message_t *message)
                        this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
                        this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
        
-       if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
+       if (!allocate_spi(this))
        {
                DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
                return FAILED;
@@ -652,10 +718,10 @@ static status_t build_i(private_child_create_t *this, message_t *message)
                this->dh = this->keymat->create_dh(this->keymat, this->dh_group);
        }
        
-       if (this->config->use_ipcomp(this->config)) {
+       if (this->config->use_ipcomp(this->config))
+       {
                /* IPCOMP_DEFLATE is the only transform we support at the moment */
-               this->ipcomp = IPCOMP_DEFLATE;
-               build_ipcomp_supported_notify(this, message);
+               add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
        }
        
        build_payloads(this, message);
@@ -821,16 +887,17 @@ static status_t build_r(private_child_create_t *this, message_t *message)
                        this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
                        this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
        
-       if (this->config->use_ipcomp(this->config) &&
-               this->ipcomp_received != IPCOMP_NONE)
-       {
-               this->ipcomp = this->ipcomp_received;
-               build_ipcomp_supported_notify(this, message);
-       }
-       else if (this->ipcomp_received != IPCOMP_NONE)
+       if (this->ipcomp_received != IPCOMP_NONE)
        {
-               DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
-                        notify_type_names, IPCOMP_SUPPORTED);
+               if (this->config->use_ipcomp(this->config))
+               {
+                       add_ipcomp_notify(this, message, this->ipcomp_received);
+               }
+               else
+               {
+                       DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
+                                notify_type_names, IPCOMP_SUPPORTED);
+               }
        }
        
        switch (select_and_install(this, no_dh))
@@ -1137,6 +1204,9 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config)
        this->mode = MODE_TUNNEL;
        this->ipcomp = IPCOMP_NONE;
        this->ipcomp_received = IPCOMP_NONE;
+       this->my_spi = 0;
+       this->other_spi = 0;
+       this->my_cpi = 0;
        this->other_cpi = 0;
        this->reqid = 0;
        this->established = FALSE;
index 026190b..38650cb 100644 (file)
@@ -251,7 +251,7 @@ static void update_children(private_ike_mobike_t *this)
        iterator = this->ike_sa->create_child_sa_iterator(this->ike_sa);
        while (iterator->iterate(iterator, (void**)&child_sa))
        {
-               if (child_sa->update_hosts(child_sa,
+               if (child_sa->update(child_sa,
                                this->ike_sa->get_my_host(this->ike_sa), 
                                this->ike_sa->get_other_host(this->ike_sa),
                                this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),