stopping connectivity checks on the responders side after receiving an IKE_SA_INIT...
authorTobias Brunner <tobias@strongswan.org>
Tue, 1 Apr 2008 11:38:18 +0000 (11:38 -0000)
committerTobias Brunner <tobias@strongswan.org>
Tue, 1 Apr 2008 11:38:18 +0000 (11:38 -0000)
src/charon/sa/connect_manager.c
src/charon/sa/connect_manager.h
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa.h
src/charon/sa/tasks/ike_init.c

index c231baa..56a7823 100644 (file)
@@ -1147,7 +1147,8 @@ static job_requeue_t initiate_mediated(initiate_data_t *data)
                while (iterator->iterate(iterator, (void**)&waiting_sa))
                {
                        ike_sa_t *sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, waiting_sa->ike_sa_id);
-                       if (sa->initiate_mediated(sa, pair->local, pair->remote, waiting_sa->childs) != SUCCESS)
+                       if (sa->initiate_mediated(sa, pair->local, pair->remote, waiting_sa->childs,
+                                       checklist->connect_id) != SUCCESS)
                        {
                                SIG(IKE_UP_FAILED, "establishing the mediated connection failed");
                                charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, sa);
@@ -1493,6 +1494,33 @@ static status_t set_responder_data(private_connect_manager_t *this,
 }
 
 /**
+ * Implementation of connect_manager_t.stop_checks.
+ */
+static status_t stop_checks(private_connect_manager_t *this, chunk_t connect_id)
+{
+       check_list_t *checklist;
+
+       pthread_mutex_lock(&(this->mutex));
+       
+       if (get_checklist_by_id(this, connect_id, &checklist) != SUCCESS)
+       {
+               DBG1(DBG_IKE, "checklist with id '%B' not found",
+                               &connect_id);
+               pthread_mutex_unlock(&(this->mutex));
+               return NOT_FOUND;
+       }
+       
+       DBG1(DBG_IKE, "removing checklist with id '%B'", &connect_id);
+       
+       remove_checklist(this, checklist);
+       check_list_destroy(checklist);
+       
+       pthread_mutex_unlock(&(this->mutex));
+       
+       return SUCCESS;
+}
+
+/**
  * Implementation of connect_manager_t.destroy.
  */
 static void destroy(private_connect_manager_t *this)
@@ -1521,6 +1549,7 @@ connect_manager_t *connect_manager_create()
        this->public.set_initiator_data = (status_t(*)(connect_manager_t*,identification_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))set_initiator_data;
        this->public.set_responder_data = (status_t(*)(connect_manager_t*,chunk_t,chunk_t,linked_list_t*))set_responder_data;
        this->public.process_check = (void(*)(connect_manager_t*,message_t*))process_check;
+       this->public.stop_checks = (status_t(*)(connect_manager_t*,chunk_t))stop_checks;
        
        this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
        if (this->hasher == NULL)
index 2f121c1..ad6ac94 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007-2008 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -92,6 +92,16 @@ struct connect_manager_t {
        status_t (*set_responder_data) (connect_manager_t *this,
                chunk_t connect_id, chunk_t key, linked_list_t *endpoints);
        
+       /**
+        * Stops checks for a checklist. Used after the responder received an IKE_SA_INIT
+        * request which contains a ME_CONNECTID payload.
+        * 
+        * @param connect_id            the connect ID
+        * @returns
+        *                                                      - NOT_FOUND, if the checklist has not been found
+        *                                                      - SUCCESS, otherwise
+        */
+       status_t (*stop_checks) (connect_manager_t *this, chunk_t connect_id);
        
        /**
         * Processes a connectivity check
index da5f0e0..213aa0e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2006-2008 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -147,6 +147,11 @@ struct private_ike_sa_t {
         * Server reflexive host
         */
        host_t *server_reflexive_host;
+       
+       /**
+        * Connect ID
+        */
+       chunk_t connect_id;
 #endif /* ME */
                
        /**
@@ -943,6 +948,14 @@ static void set_server_reflexive_host(private_ike_sa_t *this, host_t *host)
 }
 
 /**
+ * Implementation of ike_sa_t.get_connect_id.
+ */
+static chunk_t get_connect_id(private_ike_sa_t *this)
+{
+       return this->connect_id;
+}
+
+/**
  * Implementation of ike_sa_t.respond
  */
 static status_t respond(private_ike_sa_t *this, identification_t *peer_id,
@@ -992,10 +1005,11 @@ static status_t initiate_mediation(private_ike_sa_t *this, peer_cfg_t *mediated_
  * Implementation of ike_sa_t.initiate_mediated
  */
 static status_t initiate_mediated(private_ike_sa_t *this, host_t *me, host_t *other,
-               linked_list_t *childs)
+               linked_list_t *childs, chunk_t connect_id)
 {
        this->my_host = me->clone(me);
        this->other_host = other->clone(other);
+       this->connect_id = chunk_clone(connect_id);
        
        task_t *task;
        child_cfg_t *child_cfg; 
@@ -2314,6 +2328,7 @@ static void destroy(private_ike_sa_t *this)
                charon->mediation_manager->remove(charon->mediation_manager, this->ike_sa_id);
        }
        DESTROY_IF(this->server_reflexive_host);
+       chunk_free(&this->connect_id);
 #endif /* ME */
        
        DESTROY_IF(this->my_host);
@@ -2403,8 +2418,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
 #ifdef ME
        this->public.get_server_reflexive_host = (host_t* (*)(ike_sa_t*)) get_server_reflexive_host;
        this->public.set_server_reflexive_host = (void (*)(ike_sa_t*,host_t*)) set_server_reflexive_host;
+       this->public.get_connect_id = (chunk_t (*)(ike_sa_t*)) get_connect_id;
        this->public.initiate_mediation = (status_t (*)(ike_sa_t*,peer_cfg_t*)) initiate_mediation;
-       this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,linked_list_t*)) initiate_mediated;
+       this->public.initiate_mediated = (status_t (*)(ike_sa_t*,host_t*,host_t*,linked_list_t*,chunk_t)) initiate_mediated;
        this->public.relay = (status_t (*)(ike_sa_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool)) relay;
        this->public.callback = (status_t (*)(ike_sa_t*,identification_t*)) callback;
        this->public.respond = (status_t (*)(ike_sa_t*,identification_t*,chunk_t)) respond;
@@ -2448,6 +2464,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->ike_initiator = FALSE;
 #ifdef ME
        this->server_reflexive_host = NULL;
+       this->connect_id = chunk_empty;
 #endif /* ME */
        
        return &this->public;
index 33b9907..00dbcd3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2007 Tobias Brunner
+ * Copyright (C) 2006-2008 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -450,6 +450,13 @@ struct ike_sa_t {
        void (*set_server_reflexive_host) (ike_sa_t *this, host_t *host);
        
        /**
+        * Get the connect ID.
+        * 
+        * @return                              connect ID
+        */
+       chunk_t (*get_connect_id) (ike_sa_t *this);
+       
+       /**
         * Initiate the mediation of a mediated connection (i.e. initiate a
         * ME_CONNECT exchange).
         * 
@@ -466,12 +473,13 @@ struct ike_sa_t {
         * @param me                            local endpoint (gets cloned)
         * @param other                         remote endpoint (gets cloned)
         * @param childs                        linked list of child_cfg_t of CHILD_SAs (gets cloned)
+        * @param connect_id            connect ID (gets cloned)
         * @return                              
         *                                                      - SUCCESS if initialization started
         *                                                      - DESTROY_ME if initialization failed
         */
        status_t (*initiate_mediated) (ike_sa_t *this, host_t *me, host_t *other,
-                       linked_list_t *childs);
+                       linked_list_t *childs, chunk_t connect_id);
        
        /**
         * Relay data from one peer to another (i.e. initiate a
index f659697..384bced 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2008 Tobias Brunner
  * Copyright (C) 2005-2007 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -265,7 +266,16 @@ static status_t build_i(private_ike_init_t *this, message_t *message)
        }
        
        build_payloads(this, message);
-       
+
+#ifdef ME
+       {
+               chunk_t connect_id = this->ike_sa->get_connect_id(this->ike_sa);
+               if (connect_id.ptr)
+               {
+                       message->add_notify(message, FALSE, ME_CONNECTID, connect_id);
+               }
+       }
+#endif /* ME */
        
        return NEED_MORE;
 }
@@ -290,6 +300,56 @@ static status_t process_r(private_ike_init_t *this, message_t *message)
        }
        randomizer->destroy(randomizer);
        
+#ifdef ME
+       {
+               chunk_t connect_id = chunk_empty;
+               iterator_t *iterator;
+               payload_t *payload;
+       
+               /* check for a ME_CONNECTID notify */
+               iterator = message->get_payload_iterator(message);
+               while (iterator->iterate(iterator, (void**)&payload))
+               {
+                       if (payload->get_type(payload) == NOTIFY)
+                       {
+                               notify_payload_t *notify = (notify_payload_t*)payload;
+                               notify_type_t type = notify->get_notify_type(notify);
+                       
+                               switch (type)
+                               {
+                                       case ME_CONNECTID:
+                                       {
+                                               chunk_free(&connect_id);
+                                               connect_id = chunk_clone(notify->get_notification_data(notify));
+                                               DBG2(DBG_IKE, "received ME_CONNECTID %#B", &connect_id);
+                                               break;
+                                       }
+                                       default:
+                                       {
+                                               if (type < 16383)
+                                               {
+                                                       DBG1(DBG_IKE, "received %N notify error",
+                                                               notify_type_names, type);
+                                                       break;  
+                                               }
+                                               DBG1(DBG_IKE, "received %N notify",
+                                                       notify_type_names, type);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               iterator->destroy(iterator);
+               
+               if (connect_id.ptr)
+               {
+                       charon->connect_manager->stop_checks(charon->connect_manager,
+                               connect_id);
+                       chunk_free(&connect_id);
+               }
+       }
+#endif /* ME */
+       
        process_payloads(this, message);
        
        return NEED_MORE;