---
 src/libcharon/sa/child_sa.c |   95
++++++++++++++++++++++++++-----------------
 src/libcharon/sa/child_sa.h |   11 +++++
 2 files changed, 68 insertions(+), 38 deletions(-)

diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 8fd2a8c..8b125d9 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -156,6 +156,11 @@ struct private_child_sa_t {
         * last number of outbound bytes
         */
        u_int64_t other_usebytes;
+
+       /**
+        * Number of references hold by others to this child_sa
+        */
+       refcount_t refcount;
 };

 /**
@@ -833,62 +838,74 @@ static status_t update(private_child_sa_t *this,
host_t *me, host_t *other,
 }

 /**
+ * Implementation of child_sa_t.get_ref.
+ */
+static child_sa_t* get_ref(private_child_sa_t *this)
+{
+       ref_get(&this->refcount);
+       return &this->public;
+}
+
+/**
  * Implementation of child_sa_t.destroy.
  */
 static void destroy(private_child_sa_t *this)
 {
-       enumerator_t *enumerator;
-       traffic_selector_t *my_ts, *other_ts;
-       bool unrouted = (this->state == CHILD_ROUTED);
+       if (ref_put(&this->refcount))
+       {
+               enumerator_t *enumerator;
+               traffic_selector_t *my_ts, *other_ts;
+               bool unrouted = (this->state == CHILD_ROUTED);

-       set_state(this, CHILD_DESTROYING);
+               set_state(this, CHILD_DESTROYING);

-       /* delete SAs in the kernel, if they are set up */
-       if (this->my_spi)
-       {
-               /* if CHILD was not established, use PROTO_ESP used during 
alloc_spi().
-                * TODO: For AH support, we have to store protocol specific 
SPI.s */
-               if (this->protocol == PROTO_NONE)
+               /* delete SAs in the kernel, if they are set up */
+               if (this->my_spi)
                {
-                       this->protocol = PROTO_ESP;
-               }
-               charon->kernel_interface->del_sa(charon->kernel_interface,
+                       /* if CHILD was not established, use PROTO_ESP used 
during alloc_spi().
+                        * TODO: For AH support, we have to store protocol 
specific SPI.s */
+                       if (this->protocol == PROTO_NONE)
+                       {
+                               this->protocol = PROTO_ESP;
+                       }
+                       
charon->kernel_interface->del_sa(charon->kernel_interface,
                                        this->other_addr, this->my_addr, 
this->my_spi,
                                        this->protocol, this->my_cpi);
-       }
-       if (this->other_spi)
-       {
-               charon->kernel_interface->del_sa(charon->kernel_interface,
+               }
+               if (this->other_spi)
+               {
+                       
charon->kernel_interface->del_sa(charon->kernel_interface,
                                        this->my_addr, this->other_addr, 
this->other_spi,
                                        this->protocol, this->other_cpi);
-       }
+               }

-       if (this->config->install_policy(this->config))
-       {
-               /* delete all policies in the kernel */
-               enumerator = create_policy_enumerator(this);
-               while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+               if (this->config->install_policy(this->config))
                {
-                       
charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                               
my_ts, other_ts, POLICY_OUT, unrouted);
-                       
charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                               
other_ts, my_ts, POLICY_IN, unrouted);
-                       if (this->mode != MODE_TRANSPORT)
+                       /* delete all policies in the kernel */
+                       enumerator = create_policy_enumerator(this);
+                       while (enumerator->enumerate(enumerator, &my_ts, 
&other_ts))
                        {
                                
charon->kernel_interface->del_policy(charon->kernel_interface,
-                                                                               
other_ts, my_ts, POLICY_FWD, unrouted);
+                                               my_ts, other_ts, POLICY_OUT, 
unrouted);
+                               
charon->kernel_interface->del_policy(charon->kernel_interface,
+                                               other_ts, my_ts, POLICY_IN, 
unrouted);
+                               if (this->mode != MODE_TRANSPORT)
+                               {
+                                       
charon->kernel_interface->del_policy(charon->kernel_interface,
+                                                       other_ts, my_ts, 
POLICY_FWD, unrouted);
+                               }
                        }
+                       enumerator->destroy(enumerator);
                }
-               enumerator->destroy(enumerator);
-       }

-       this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t,
destroy));
-       this->other_ts->destroy_offset(this->other_ts,
offsetof(traffic_selector_t, destroy));
-       this->my_addr->destroy(this->my_addr);
-       this->other_addr->destroy(this->other_addr);
-       DESTROY_IF(this->proposal);
-       this->config->destroy(this->config);
-       free(this);
+               this->my_ts->destroy_offset(this->my_ts, 
offsetof(traffic_selector_t,
destroy));
+               this->other_ts->destroy_offset(this->other_ts,
offsetof(traffic_selector_t, destroy));
+               this->my_addr->destroy(this->my_addr);
+               this->other_addr->destroy(this->other_addr);
+               DESTROY_IF(this->proposal);
+               this->config->destroy(this->config);
+               free(this);
+       }
 }

 /*
@@ -926,6 +943,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        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.get_ref = (child_sa_t *(*)(child_sa_t *))get_ref;
        this->public.destroy = (void(*)(child_sa_t*))destroy;

        /* private data */
@@ -950,6 +968,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        this->rekey_time = 0;
        this->expire_time = 0;
        this->config = config;
+       this->refcount = 1;
        config->get_ref(config);
        this->reqid = config->get_reqid(config);
        if (!this->reqid)
diff --git a/src/libcharon/sa/child_sa.h b/src/libcharon/sa/child_sa.h
index e6c6035..31702c8 100644
--- a/src/libcharon/sa/child_sa.h
+++ b/src/libcharon/sa/child_sa.h
@@ -315,8 +315,19 @@ struct child_sa_t {
         */
        status_t (*update)(child_sa_t *this, host_t *me, host_t *other,
                                           host_t *vip, bool encap);
+
+       /**
+        * Increase the reference count.
+        *
+        * @return                              reference to this
+        */
+       child_sa_t* (*get_ref) (child_sa_t *this);
+
        /**
         * Destroys a child_sa.
+        *
+        * Decrements the internal reference counter and
+        * destroys the child_sa when it reaches zero.
         */
        void (*destroy) (child_sa_t *this);
 };
-- 
1.7.0.2



_______________________________________________
Dev mailing list
[email protected]
https://lists.strongswan.org/mailman/listinfo/dev

Reply via email to