[strongSwan-dev] [PATCH 1/2] Add reference counting to child_sa

Thomas Egerer thomas.egerer at secunet.com
Fri May 14 17:28:42 CEST 2010


---
 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






More information about the Dev mailing list