Handle DELETE as responder as INFORMATIONAL subtask
[strongswan.git] / src / libcharon / sa / tasks / informational.c
index 8cbe10e..c1a30e4 100644 (file)
@@ -16,6 +16,9 @@
 #include "informational.h"
 
 #include <daemon.h>
+#include <sa/tasks/ike_delete.h>
+#include <sa/tasks/child_delete.h>
+#include <encoding/payloads/delete_payload.h>
 
 typedef struct private_informational_t private_informational_t;
 
@@ -38,6 +41,11 @@ struct private_informational_t {
         * Notify payload to send
         */
        notify_payload_t *notify;
+
+       /**
+        * Delete subtask
+        */
+       task_t *del;
 };
 
 METHOD(task_t, build_i, status_t,
@@ -51,12 +59,73 @@ METHOD(task_t, build_i, status_t,
 METHOD(task_t, process_r, status_t,
        private_informational_t *this, message_t *message)
 {
-       return FAILED;
+       enumerator_t *enumerator;
+       delete_payload_t *delete;
+       notify_payload_t *notify;
+       notify_type_t type;
+       payload_t *payload;
+       status_t status = SUCCESS;
+
+       enumerator = message->create_payload_enumerator(message);
+       while (enumerator->enumerate(enumerator, &payload))
+       {
+               switch (payload->get_type(payload))
+               {
+                       case NOTIFY_V1:
+                               notify = (notify_payload_t*)payload;
+                               type = notify->get_notify_type(notify);
+
+                               if (type == INITIAL_CONTACT_IKEV1)
+                               {
+                                       this->ike_sa->set_condition(this->ike_sa,
+                                                                                               COND_INIT_CONTACT_SEEN, TRUE);
+                               }
+                               else if (type < 16384)
+                               {
+                                       DBG1(DBG_IKE, "received %N error notify",
+                                                notify_type_names, notify->get_notify_type(notify));
+                                       status = FAILED;
+                                       break;
+                               }
+                               else
+                               {
+                                       DBG1(DBG_IKE, "received %N notify",
+                                                notify_type_names, notify->get_notify_type(notify));
+                               }
+                               continue;
+                       case DELETE_V1:
+                               delete = (delete_payload_t*)payload;
+                               if (delete->get_protocol_id(delete) == PROTO_IKE)
+                               {
+                                       this->del = (task_t*)ike_delete_create(this->ike_sa, FALSE);
+                               }
+                               else
+                               {
+                                       this->del = (task_t*)child_delete_create(this->ike_sa,
+                                                                                                                        PROTO_NONE, 0);
+                               }
+                               break;
+                       default:
+                               continue;
+               }
+               break;
+       }
+       enumerator->destroy(enumerator);
+
+       if (status == SUCCESS)
+       {
+               return this->del->process(this->del, message);
+       }
+       return status;
 }
 
 METHOD(task_t, build_r, status_t,
        private_informational_t *this, message_t *message)
 {
+       if (this->del)
+       {
+               return this->del->build(this->del, message);
+       }
        return FAILED;
 }
 
@@ -82,6 +151,7 @@ METHOD(task_t, destroy, void,
        private_informational_t *this)
 {
        DESTROY_IF(this->notify);
+       DESTROY_IF(this->del);
        free(this);
 }