properly handle orphaned renewSession jobs
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 3 Apr 2013 14:44:44 +0000 (16:44 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 3 Apr 2013 19:38:04 +0000 (21:38 +0200)
src/libcharon/plugins/tnc_ifmap/tnc_ifmap_http.c
src/libcharon/plugins/tnc_ifmap/tnc_ifmap_listener.c
src/libcharon/plugins/tnc_ifmap/tnc_ifmap_renew_session_job.c
src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.c
src/libcharon/plugins/tnc_ifmap/tnc_ifmap_soap.h

index e2a1582..9105b7b 100644 (file)
@@ -98,7 +98,7 @@ METHOD(tnc_ifmap_http_t, build, status_t,
                return FAILED;
        }
        *out = chunk_create(request, len);
-       DBG3(DBG_TLS, "sending HTML POST request %B", out);
+       DBG3(DBG_TLS, "sending HTTP POST request %B", out);
 
        return SUCCESS;
 }
index d204405..4b2538e 100644 (file)
@@ -120,7 +120,14 @@ METHOD(listener_t, alert, bool,
 METHOD(tnc_ifmap_listener_t, destroy, void,
        private_tnc_ifmap_listener_t *this)
 {
-       DESTROY_IF(this->ifmap);
+       if (this->ifmap)
+       {
+               if (this->ifmap->get_session_id(this->ifmap))
+               {
+                       this->ifmap->endSession(this->ifmap);
+               }
+               this->ifmap->destroy(this->ifmap);
+       }
        free(this);
 }
 
@@ -178,7 +185,8 @@ tnc_ifmap_listener_t *tnc_ifmap_listener_create(bool reload)
                                                "%s.plugins.tnc-ifmap.renew_session_interval",
                                                 IFMAP_RENEW_SESSION_INTERVAL, charon->name);
 
-       job = (job_t*)tnc_ifmap_renew_session_job_create(this->ifmap, reschedule);
+       job = (job_t*)tnc_ifmap_renew_session_job_create(
+                                               this->ifmap->get_ref(this->ifmap), reschedule);
        lib->scheduler->schedule_job(lib->scheduler, job, reschedule);
 
        return &this->public;
index eb20bb6..370cb62 100644 (file)
@@ -52,9 +52,25 @@ METHOD(job_t, destroy, void,
 METHOD(job_t, execute, job_requeue_t,
        private_tnc_ifmap_renew_session_job_t *this)
 {
-       this->ifmap->renewSession(this->ifmap);
-
-       return JOB_RESCHEDULE(this->reschedule);
+       char *session_id;
+
+       if (this->ifmap->orphaned(this->ifmap))
+       {
+               session_id = this->ifmap->get_session_id(this->ifmap);
+               DBG2(DBG_TNC, "removing orphaned ifmap renewSession job for '%s'",
+                                          session_id);
+               this->ifmap->destroy(this->ifmap);
+               return JOB_REQUEUE_NONE;
+       }
+       else
+       {
+               if (!this->ifmap->renewSession(this->ifmap))
+               {
+                       DBG1(DBG_TNC, "sending ifmap renewSession failed");
+                       /* TODO take some action */
+               }
+               return JOB_RESCHEDULE(this->reschedule);
+       }
 }
 
 METHOD(job_t, get_priority, job_priority_t,
index d189f6f..8d5da58 100644 (file)
@@ -99,6 +99,11 @@ struct private_tnc_ifmap_soap_t {
         */
        mem_cred_t *creds;
 
+       /**
+        * reference count
+        */
+       refcount_t ref;
+
 };
 
 METHOD(tnc_ifmap_soap_t, newSession, bool,
@@ -124,7 +129,7 @@ METHOD(tnc_ifmap_soap_t, newSession, bool,
        this->ifmap_publisher_id = xmlGetProp(result, "ifmap-publisher-id");
        soap_msg->destroy(soap_msg);
 
-       DBG1(DBG_TNC, "session-id: %s, ifmap-publisher-id: %s",
+       DBG1(DBG_TNC, "created ifmap session '%s' as publisher '%s'",
                                   this->session_id, this->ifmap_publisher_id);
 
        /* set PEP and PDP device name (defaults to IF-MAP Publisher ID) */
@@ -415,9 +420,9 @@ METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
 
        /* extract relevant data from IKE_SA*/
        ike_sa_id = ike_sa->get_unique_id(ike_sa);
+       host = ike_sa->get_other_host(ike_sa);
        id = ike_sa->get_other_id(ike_sa);
        eap_id = ike_sa->get_other_eap_id(ike_sa);
-       host = ike_sa->get_other_host(ike_sa);
 
        /* in the presence of an EAP Identity, treat it as a username */
        if (!id->equals(id, eap_id))
@@ -460,7 +465,7 @@ METHOD(tnc_ifmap_soap_t, publish_ike_sa, bool,
        }
 
        /**
-        * update or delete access-request-ip metadata
+        * update or delete access-request-ip metadata for physical IP address
         */
        if (up)
        {
@@ -615,30 +620,54 @@ METHOD(tnc_ifmap_soap_t, endSession, bool,
        success = soap_msg->post(soap_msg, request, "endSessionResult", NULL);
        soap_msg->destroy(soap_msg);
 
+       DBG1(DBG_TNC, "ended ifmap session '%s' as publisher '%s'",
+                                  this->session_id, this->ifmap_publisher_id);
+
        return success;
 }
 
+METHOD(tnc_ifmap_soap_t, get_session_id, char*,
+       private_tnc_ifmap_soap_t *this)
+{
+       return this->session_id;
+}
+
+METHOD(tnc_ifmap_soap_t, orphaned, bool,
+       private_tnc_ifmap_soap_t *this)
+{
+       return this->ref == 1;
+}
+
+METHOD(tnc_ifmap_soap_t, get_ref, tnc_ifmap_soap_t*,
+       private_tnc_ifmap_soap_t *this)
+{
+       ref_get(&this->ref);
+       return &this->public;
+}
+
 METHOD(tnc_ifmap_soap_t, destroy, void,
        private_tnc_ifmap_soap_t *this)
 {
-       if (this->session_id)
+       if (ref_put(&this->ref))
        {
-               endSession(this);
-               xmlFree(this->session_id);
-               xmlFree(this->ifmap_publisher_id);
-               free(this->device_name);
-       }
-       DESTROY_IF(this->tls);
-       DESTROY_IF(this->host);
+               if (this->session_id)
+               {
+                       xmlFree(this->session_id);
+                       xmlFree(this->ifmap_publisher_id);
+                       free(this->device_name);
+               }
+               DESTROY_IF(this->tls);
+               DESTROY_IF(this->host);
 
-       if (this->fd != IFMAP_NO_FD)
-       {
-               close(this->fd);
+               if (this->fd != IFMAP_NO_FD)
+               {
+                       close(this->fd);
+               }
+               lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
+               this->creds->destroy(this->creds);
+               free(this->user_pass.ptr);
+               free(this);
        }
-       lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
-       this->creds->destroy(this->creds);
-       free(this->user_pass.ptr);
-       free(this);
 }
 
 static bool soap_init(private_tnc_ifmap_soap_t *this)
@@ -824,10 +853,14 @@ tnc_ifmap_soap_t *tnc_ifmap_soap_create()
                        .publish_device_ip = _publish_device_ip,
                        .publish_enforcement_report = _publish_enforcement_report,
                        .endSession = _endSession,
+                       .get_session_id = _get_session_id,
+                       .orphaned = _orphaned,
+                       .get_ref = _get_ref,
                        .destroy = _destroy,
                },
                .fd = IFMAP_NO_FD,
                .creds = mem_cred_create(),
+               .ref = 1,
        );
 
        lib->credmgr->add_set(lib->credmgr, &this->creds->set);
index 9c5a53b..4a0434a 100644 (file)
@@ -89,6 +89,27 @@ struct tnc_ifmap_soap_t {
        bool (*endSession)(tnc_ifmap_soap_t *this);
 
        /**
+        * Get ID of IF-MAP session
+        *
+        * @return                              IF-MAP session ID
+        */
+       char* (*get_session_id)(tnc_ifmap_soap_t *this);
+
+       /**
+        * Check for an orphaned IF-MAP session
+        *
+        * @return                              TRUE if IF-MAP session is orphaned
+        */
+       bool (*orphaned)(tnc_ifmap_soap_t *this);
+
+       /**
+        * Get a reference to an IF-MAP session
+        *
+        * @return                              referenced IF-MAP session
+        */
+       tnc_ifmap_soap_t* (*get_ref)(tnc_ifmap_soap_t *this);
+
+       /**
         * Destroy a tnc_ifmap_soap_t.
         */
        void (*destroy)(tnc_ifmap_soap_t *this);