reuse reqid when a ROUTED child_sa gets INSTALLED
authorMartin Willi <martin@strongswan.org>
Tue, 5 Sep 2006 14:07:25 +0000 (14:07 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 5 Sep 2006 14:07:25 +0000 (14:07 -0000)
fixed a bug in retransmission code
added support for the "keyingtries" ipsec.conf parameter
added support for the "dpddelay" ipsec.conf parameter
done some work for "dpdaction" behavior
some other cleanups and fixes

36 files changed:
src/charon/Makefile.am
src/charon/config/configuration.c
src/charon/config/configuration.h
src/charon/config/connections/connection.c
src/charon/config/connections/connection.h
src/charon/config/policies/policy.c
src/charon/config/policies/policy.h
src/charon/config/traffic_selector.c
src/charon/doc/Todo-list.txt
src/charon/queues/jobs/delete_established_ike_sa_job.c [deleted file]
src/charon/queues/jobs/delete_established_ike_sa_job.h [deleted file]
src/charon/queues/jobs/delete_half_open_ike_sa_job.c [deleted file]
src/charon/queues/jobs/delete_half_open_ike_sa_job.h [deleted file]
src/charon/queues/jobs/delete_ike_sa_job.c [new file with mode: 0644]
src/charon/queues/jobs/delete_ike_sa_job.h [new file with mode: 0644]
src/charon/queues/jobs/incoming_packet_job.c
src/charon/queues/jobs/initiate_job.c
src/charon/queues/jobs/job.c
src/charon/queues/jobs/job.h
src/charon/queues/jobs/retransmit_request_job.c
src/charon/queues/jobs/route_job.c
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa_manager.c
src/charon/sa/ike_sa_manager.h
src/charon/sa/transactions/create_child_sa.c
src/charon/sa/transactions/create_child_sa.h
src/charon/sa/transactions/ike_auth.c
src/charon/sa/transactions/ike_auth.h
src/charon/sa/transactions/ike_sa_init.c
src/charon/sa/transactions/ike_sa_init.h
src/charon/threads/kernel_interface.c
src/charon/threads/stroke_interface.c
src/starter/ipsec.conf.5
src/starter/starterstroke.c
src/stroke/stroke.c
src/stroke/stroke.h

index 024205a..330aefc 100644 (file)
@@ -39,10 +39,10 @@ encoding/payloads/vendor_id_payload.h encoding/payloads/proposal_substructure.c
 encoding/parser.h encoding/message.c encoding/generator.c encoding/message.h encoding/generator.h \
 encoding/parser.c daemon.c daemon.h network/packet.c \
 network/socket.c network/packet.h network/socket.h queues/jobs/job.h queues/jobs/job.c \
-queues/jobs/delete_established_ike_sa_job.c queues/jobs/retransmit_request_job.h queues/jobs/initiate_job.h \
-queues/jobs/incoming_packet_job.c queues/jobs/delete_half_open_ike_sa_job.c \
-queues/jobs/delete_established_ike_sa_job.h queues/jobs/delete_half_open_ike_sa_job.h \
-queues/jobs/incoming_packet_job.h queues/jobs/retransmit_request_job.c queues/jobs/initiate_job.c \
+queues/jobs/retransmit_request_job.h queues/jobs/initiate_job.h \
+queues/jobs/incoming_packet_job.h queues/jobs/incoming_packet_job.c \
+queues/jobs/delete_ike_sa_job.c queues/jobs/delete_ike_sa_job.h \
+queues/jobs/retransmit_request_job.c queues/jobs/initiate_job.c \
 queues/jobs/send_keepalive_job.c queues/jobs/send_keepalive_job.h \
 queues/jobs/rekey_child_sa_job.c queues/jobs/rekey_child_sa_job.h queues/jobs/delete_child_sa_job.c queues/jobs/delete_child_sa_job.h \
 queues/jobs/send_dpd_job.c queues/jobs/send_dpd_job.h queues/jobs/route_job.c queues/jobs/route_job.h \
index 2dcf0bb..e983e59 100755 (executable)
 
 /**
  * Timeout in milliseconds after that a half open IKE_SA gets deleted.
- * Set to zero to disable
  */
 #define HALF_OPEN_IKE_SA_TIMEOUT 30000
 
 /**
+ * The retransmission algorithm uses a multiple sequences.
+ * Each sequence contains multiple retransmits. Those retransmits
+ * are sent using a exponential backoff algorithm. The sequences
+ * are retried with linear timings:
+ *
+ * <------sequence---------><------sequence---------><------sequence--------->
+ *
+ * T-R---R-----R---------R--R-R---R-----R---------R--R-R---R-----R---------R--X
+ *
+ * T = first transmit
+ * R = retransmit
+ * X = giving up, peer is dead
+ *
+ * if (retransmit >= TRIES * sequences)
+ *     => abort
+ * TIMEOUT * (BASE ** (try % TRIES))
+ *
+ * Using an initial TIMEOUT of 4s, a BASE of 1.8, 5 TRIES
+ * per sequnce and 3 sequences, this gives us:
+ *
+ *                        | relative | absolute
+ * ---------------------------------------------------------
+ * 4s * (1.8 ** (0  % 5)) =    4s         4s
+ * 4s * (1.8 ** (1  % 5)) =    7s        11s
+ * 4s * (1.8 ** (2  % 5)) =   13s        24s
+ * 4s * (1.8 ** (3  % 5)) =   23s        47s
+ * 4s * (1.8 ** (4  % 5)) =   42s        89s
+ * 4s * (1.8 ** (5  % 5)) =   76s       165s
+ * 4s * (1.8 ** (6  % 5)) =    4s       169s
+ * 4s * (1.8 ** (7  % 5)) =    7s       176s
+ * 4s * (1.8 ** (8  % 5)) =   13s       189s
+ * 4s * (1.8 ** (9  % 5)) =   23s       212s
+ * 4s * (1.8 ** (10 % 5)) =   42s       254s
+ * 4s * (1.8 ** (11 % 5)) =   76s       330s
+ * 4s * (1.8 ** (12 % 5)) =    4s       334
+ * 4s * (1.8 ** (13 % 5)) =    7s       341s
+ * 4s * (1.8 ** (14 % 5)) =   13s       354s
+ * 4s * (1.8 ** (15 % 5)) =   23s       377s
+ * 4s * (1.8 ** (16 % 5)) =   42s       419s
+ * 4s * (1.8 ** (17 % 5)) =   76s       495s
+ *
+ * If the configuration uses 1 sequence, the peer is considered dead
+ * after 2min 45s when no reply comes in. If it uses 3 sequences, after
+ * 8min 15s the DPD action is executed...
+ */
+
+/**
  * First retransmit timeout in milliseconds.
  * Timeout value is increasing in each retransmit round.
  */
-#define RETRANSMIT_TIMEOUT 6000
+#define RETRANSMIT_TIMEOUT 4000
 
 /**
  * Base which is raised to the power of the retransmission count.
  */
-#define RETRANSMIT_BASE 1.5
+#define RETRANSMIT_BASE 1.8
 
 /**
- * Max retransmit count.
- * 0 for infinite. The max time a half open IKE_SA is alive is set by 
- * RETRANSMIT_TIMEOUT.
+ * Number of retransmits done in a retransmit sequence
  */
-#define MAX_RETRANSMIT_COUNT 6
+#define RETRANSMIT_TRIES 5
 
 /**
  * Keepalive interval in seconds.
  */
 #define KEEPALIVE_INTERVAL 20
 
-/**
- * DPD interval in seconds.
- */
-#define DPD_INTERVAL 60
-
 
 typedef struct private_configuration_t private_configuration_t;
 
@@ -79,13 +118,18 @@ struct private_configuration_t {
 /**
  * Implementation of configuration_t.get_retransmit_timeout.
  */
-static u_int32_t get_retransmit_timeout (private_configuration_t *this, u_int32_t retransmit_count)
+static u_int32_t get_retransmit_timeout (private_configuration_t *this,
+                                                                                u_int32_t retransmit_count,
+                                                                                u_int32_t max_sequences)
 {
-       if (retransmit_count > MAX_RETRANSMIT_COUNT && MAX_RETRANSMIT_COUNT != 0)
+       if (max_sequences != 0 && 
+               retransmit_count >= RETRANSMIT_TRIES * max_sequences)
        {
+               /* give up */
                return 0;
        }
-       return (u_int32_t)(RETRANSMIT_TIMEOUT * pow(RETRANSMIT_BASE, retransmit_count));
+       return (u_int32_t)(RETRANSMIT_TIMEOUT *
+                                          pow(RETRANSMIT_BASE, retransmit_count % RETRANSMIT_TRIES));
 }
 
 /**
@@ -105,14 +149,6 @@ static u_int32_t get_keepalive_interval (private_configuration_t *this)
 }
 
 /**
- * Implementation of configuration_t.get_dpd_interval.
- */
-static u_int32_t get_dpd_interval (private_configuration_t *this)
-{
-       return DPD_INTERVAL;
-}
-
-/**
  * Implementation of configuration_t.destroy.
  */
 static void destroy(private_configuration_t *this)
@@ -129,10 +165,9 @@ configuration_t *configuration_create()
        
        /* public functions */
        this->public.destroy = (void(*)(configuration_t*))destroy;
-       this->public.get_retransmit_timeout = (u_int32_t (*) (configuration_t *, u_int32_t retransmit_count))get_retransmit_timeout;
-       this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t *)) get_half_open_ike_sa_timeout;
-       this->public.get_keepalive_interval = (u_int32_t (*) (configuration_t *)) get_keepalive_interval;
-       this->public.get_dpd_interval = (u_int32_t (*) (configuration_t *)) get_dpd_interval;
+       this->public.get_retransmit_timeout = (u_int32_t (*) (configuration_t*,u_int32_t,u_int32_t))get_retransmit_timeout;
+       this->public.get_half_open_ike_sa_timeout = (u_int32_t (*) (configuration_t*)) get_half_open_ike_sa_timeout;
+       this->public.get_keepalive_interval = (u_int32_t (*) (configuration_t*)) get_keepalive_interval;
        
        return (&this->public);
 }
index 553a01e..ee25872 100755 (executable)
@@ -36,34 +36,33 @@ typedef struct configuration_t configuration_t;
  * 
  * @ingroup config
  */
-struct configuration_t { 
+struct configuration_t {
 
        /**
         * @brief Returns the retransmit timeout.
         *
-        * A return value of zero means the request should not retransmitted again.
-        * The timeout values are managed by the configuration, so 
-        * another backoff algorithm may be implemented here.
+        * A return value of zero means the request should not be retransmitted again.
+        * The retransmission algorithm uses sequences of retransmits, in which
+        * every sequence contains exponential delayed retransmits. These
+        * sequences are compareable to the keyingtries mechanism used in pluto.
         *
         * @param this                          calling object
-        * @param retransmit_count      number of times a message was retransmitted so far
+        * @param retransmitted         number of times a message was retransmitted so far
+        * @param max_sequences         maximum number of retransmission sequences to allow
         * @return                                      time in milliseconds, when to schedule next retransmit
         */
-       u_int32_t (*get_retransmit_timeout) (configuration_t *this, u_int32_t retransmit_count);
+       u_int32_t (*get_retransmit_timeout) (configuration_t *this, 
+                                                                                u_int32_t retransmitted, 
+                                                                                u_int32_t max_sequences);
        
        /**
         * @brief Returns the timeout for an half open IKE_SA in ms.
-        * 
-        * Half open means that the IKE_SA is still in one of the following states:
-        *  - INITIATOR_INIT
-        *  - RESPONDER_INIT
-        *  - IKE_SA_INIT_REQUESTED
-        *  - IKE_SA_INIT_RESPONDED
-        *  - IKE_AUTH_REQUESTED
-        * 
+        *
+        * Half open means that the IKE_SA is still on a not established state
+        *
         * @param this                          calling object
         * @return                                      timeout in milliseconds (ms)
-        */     
+        */
        u_int32_t (*get_half_open_ike_sa_timeout) (configuration_t *this);
 
        /**
@@ -78,17 +77,6 @@ struct configuration_t {
        u_int32_t (*get_keepalive_interval) (configuration_t *this);
 
        /**
-        * @brief Returns the DPD interval in ms.
-        * 
-        * The DPD interval defines the time after which a
-        * DPD request packet should be sent.
-        * 
-        * @param this                          calling object
-        * @return                                      interval in seconds
-        */     
-       u_int32_t (*get_dpd_interval) (configuration_t *this);
-
-       /**
         * @brief Destroys a configuration_t object.
         * 
         * @param this                                  calling object
index 281d43d..6b8192b 100644 (file)
@@ -106,6 +106,16 @@ struct private_connection_t {
        auth_method_t auth_method;
        
        /**
+        * Interval to send DPD liveness checks on inactivity
+        */
+       u_int32_t dpd_delay;
+       
+       /**
+        * Number of retransmission sequences to send bevore giving up
+        */
+       u_int32_t retrans_sequences;
+       
+       /**
         * Supported proposals
         */
        linked_list_t *proposals;
@@ -249,6 +259,22 @@ static auth_method_t get_auth_method(private_connection_t *this)
 }
 
 /**
+ * Implementation of connection_t.get_dpd_delay.
+ */
+static u_int32_t get_dpd_delay(private_connection_t *this)
+{
+       return this->dpd_delay;
+}
+
+/**
+ * Implementation of connection_t.get_retrans_seq.
+ */
+static u_int32_t get_retrans_seq(private_connection_t *this)
+{
+       return this->retrans_sequences;
+}
+
+/**
  * Implementation of connection_t.get_dh_group.
  */
 static diffie_hellman_group_t get_dh_group(private_connection_t *this)
@@ -359,6 +385,8 @@ connection_t * connection_create(char *name, bool ikev2,
                                                                 cert_policy_t certreq_policy,
                                                                 host_t *my_host, host_t *other_host,
                                                                 auth_method_t auth_method,
+                                                                u_int32_t dpd_delay,
+                                                                u_int32_t retrans_sequences,
                                                                 u_int32_t hard_lifetime,
                                                                 u_int32_t soft_lifetime, u_int32_t jitter)
 {
@@ -375,6 +403,8 @@ connection_t * connection_create(char *name, bool ikev2,
        this->public.select_proposal = (proposal_t*(*)(connection_t*,linked_list_t*))select_proposal;
        this->public.add_proposal = (void(*)(connection_t*, proposal_t*)) add_proposal;
        this->public.get_auth_method = (auth_method_t(*)(connection_t*)) get_auth_method;
+       this->public.get_dpd_delay = (u_int32_t(*)(connection_t*)) get_dpd_delay;
+       this->public.get_retrans_seq = (u_int32_t(*)(connection_t*)) get_retrans_seq;
        this->public.get_dh_group = (diffie_hellman_group_t(*)(connection_t*)) get_dh_group;
        this->public.check_dh_group = (bool(*)(connection_t*,diffie_hellman_group_t)) check_dh_group;
        this->public.get_soft_lifetime = (u_int32_t (*) (connection_t *))get_soft_lifetime;
@@ -391,6 +421,8 @@ connection_t * connection_create(char *name, bool ikev2,
        this->my_host = my_host;
        this->other_host = other_host;
        this->auth_method = auth_method;
+       this->dpd_delay = dpd_delay;
+       this->retrans_sequences = retrans_sequences;
        this->hard_lifetime = hard_lifetime;
        this->soft_lifetime = soft_lifetime;
        this->jitter = jitter;
index 61ca9cf..c425590 100644 (file)
@@ -164,7 +164,7 @@ struct connection_t {
        proposal_t *(*select_proposal) (connection_t *this, linked_list_t *proposals);
        
        /**
-        * @brief Get the authentication method to use
+        * @brief Get the authentication method to use.
         * 
         * @param this          calling object
         * @return                      authentication method
@@ -172,6 +172,25 @@ struct connection_t {
        auth_method_t (*get_auth_method) (connection_t *this);
        
        /**
+        * @brief Get the DPD check interval.
+        * 
+        * @param this          calling object
+        * @return                      dpd_delay in seconds
+        */
+       u_int32_t (*get_dpd_delay) (connection_t *this);
+       
+       /**
+        * @brief Get the max number of retransmission sequences.
+        *
+        * After this number of sequences, a not responding peer is considered
+        * dead.
+        *
+        * @param this          calling object
+        * @return                      max number of retransmission sequences
+        */
+       u_int32_t (*get_retrans_seq) (connection_t *this);
+       
+       /**
         * @brief Get the connection name.
         * 
         * Name must not be freed, since it points to 
@@ -281,9 +300,12 @@ struct connection_t {
 /**
  * @brief Creates a connection_t object.
  *
- * Supplied hosts become owned by connection, so 
- * do not modify or destroy them after a call to 
+ * Supplied hosts become owned by connection, so
+ * do not modify or destroy them after a call to
  * connection_create(). Name gets cloned internally.
+ * The retrasmit sequence number says how fast we give up when the peer
+ * does not respond. A high value may bridge-over temporary connection 
+ * problems, a small value can detect dead peers faster.
  *
  * @param name                         connection identifier
  * @param ikev2                                TRUE if this is an IKEv2 connection
@@ -292,6 +314,8 @@ struct connection_t {
  * @param my_host                      host_t representing local address
  * @param other_host           host_t representing remote address
  * @param auth_method          Authentication method to use for our(!) auth data
+ * @param dpd_delay                    interval of DPD liveness checks
+ * @param retrans_sequences    number of retransmit sequences to use
  * @param hard_lifetime                lifetime before deleting an IKE_SA
  * @param soft_lifetime                lifetime before rekeying an IKE_SA
  * @param jitter                       range of randomization time
@@ -302,7 +326,9 @@ struct connection_t {
 connection_t * connection_create(char *name, bool ikev2,
                                                                 cert_policy_t cert_pol, cert_policy_t req_pol,
                                                                 host_t *my_host, host_t *other_host,
-                                                                auth_method_t auth_method, u_int32_t hard_lifetime, 
-                                                                u_int32_t soft_lifetime, u_int32_t jitter);
+                                                                auth_method_t auth_method,
+                                                                u_int32_t dpd_delay, u_int32_t retrans_sequences,
+                                                                u_int32_t hard_lifetime, u_int32_t soft_lifetime, 
+                                                                u_int32_t jitter);
 
 #endif /* CONNECTION_H_ */
index 49983ad..71fadbd 100644 (file)
@@ -110,6 +110,11 @@ struct private_policy_t {
        u_int32_t jitter;
        
        /**
+        * Should the SA get ROUTED when peer detected as dead?
+        */
+       bool dpd_route;
+       
+       /**
         * logger
         */
        logger_t *logger;
@@ -441,7 +446,7 @@ static void destroy(private_policy_t *this)
  */
 policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id,
                                                u_int32_t hard_lifetime, u_int32_t soft_lifetime, 
-                                               u_int32_t jitter, char *updown)
+                                               u_int32_t jitter, char *updown, bool dpd_route)
 {
        private_policy_t *this = malloc_thing(private_policy_t);
 
@@ -473,6 +478,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o
        this->soft_lifetime = soft_lifetime;
        this->jitter = jitter;
        this->updown = (updown == NULL) ? NULL : strdup(updown);
+       this->dpd_route = dpd_route;
        
        /* initialize private members*/
        this->refcount = 1;
index 454f69c..9505e53 100644 (file)
@@ -264,6 +264,7 @@ struct policy_t {
  * @param soft_lifetime                lifetime before rekeying an SA
  * @param jitter                       range of randomization time
  * @param updown                       updown script to execute on up/down event
+ * @param dpd_route                    should the connection go to routed state if DPD detected?
  * @return                                     policy_t object
  * 
  * @ingroup config
@@ -271,6 +272,6 @@ struct policy_t {
 policy_t *policy_create(char *name, 
                                                identification_t *my_id, identification_t *other_id,
                                                u_int32_t hard_lifetime, u_int32_t soft_lifetime,
-                                               u_int32_t jitter, char *updown);
+                                               u_int32_t jitter, char *updown, bool dpd_route);
 
 #endif /* POLICY_H_ */
index 24cf7ea..d8293b8 100644 (file)
@@ -464,24 +464,16 @@ static u_int8_t get_protocol(private_traffic_selector_t *this)
  */
 static void update_address_range(private_traffic_selector_t *this, host_t *host)
 {
-       if (host->get_family(host) == AF_INET && this->type == TS_IPV4_ADDR_RANGE)
+       if ((this->type == TS_IPV4_ADDR_RANGE && this->from4[0] == 0) ||
+               (this->type == TS_IPV6_ADDR_RANGE && this->from6[0] == 0 &&
+                this->from6[1] == 0 && this->from6[2] == 0 && this->from6[3] == 0))
        {
-               if (this->from4[0] == 0)
-               {
-                       chunk_t from = host->get_address(host);
-                       memcpy(this->from4, from.ptr, from.len);
-                       memcpy(this->to4, from.ptr, from.len);
-               }
-       }
-       if (host->get_family(host) == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE)
-       {
-               if (this->from6[0] == 0 && this->from6[1] == 0 &&
-                       this->from6[2] == 0 && this->from6[3] == 0)
-               {
-                       chunk_t from = host->get_address(host);
-                       memcpy(this->from6, from.ptr, from.len);
-                       memcpy(this->to6, from.ptr, from.len);
-               }
+               this->type = host->get_family(host) == AF_INET ?
+                                               TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
+               
+               chunk_t from = host->get_address(host);
+               memcpy(this->from, from.ptr, from.len);
+               memcpy(this->to, from.ptr, from.len);
        }
        update_string(this);
 }
index 10cd2f9..1d21d92 100644 (file)
 - configure flag which allows to ommit vendor id in pluto
 - use dpdaction/dpddelay parameters from ipsec.conf
 - ikelifetime should optionally enforce reauthentication
+- cookies/DDoS prevention
 - implement a mechanism against thread exhaustion
   when a blocked IKE_SA receives a lot of messages
 - add a crl fetch mechanism which synchronizes equal fetches
 - add support for CERTREQs
 - use same reqid for routed connections when they are set up
+- if a CHILD_SA gets created, check if it is already ROUTED somewhere:
+  - remove that route and reuse reqid
 - add firewall script support
diff --git a/src/charon/queues/jobs/delete_established_ike_sa_job.c b/src/charon/queues/jobs/delete_established_ike_sa_job.c
deleted file mode 100644 (file)
index e5230e5..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * @file delete_established_ike_sa_job.c
- * 
- * @brief Implementation of delete_established_ike_sa_job_t.
- * 
- */
-
-/*
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include "delete_established_ike_sa_job.h"
-
-#include <daemon.h>
-
-
-typedef struct private_delete_established_ike_sa_job_t private_delete_established_ike_sa_job_t;
-
-/**
- * Private data of an delete_established_ike_sa_job_t object.
- */
-struct private_delete_established_ike_sa_job_t {
-       /**
-        * Public delete_established_ike_sa_job_t interface.
-        */
-       delete_established_ike_sa_job_t public;
-       
-       /**
-        * ID of the ike_sa to delete.
-        */
-       ike_sa_id_t *ike_sa_id;
-       
-       /**
-        * Logger ref
-        */
-       logger_t *logger;
-};
-
-/**
- * Implementation of job_t.get_type.
- */
-static job_type_t get_type(private_delete_established_ike_sa_job_t *this)
-{
-       return DELETE_ESTABLISHED_IKE_SA;
-}
-
-
-/**
- * Implementation of job_t.execute.
- */
-static status_t execute(private_delete_established_ike_sa_job_t *this)
-{
-       if (charon->ike_sa_manager->delete(charon->ike_sa_manager, 
-                                                                          this->ike_sa_id) != SUCCESS)
-       {
-               this->logger->log(this->logger, ERROR|LEVEL1, "IKE SA didn't exist anymore");
-       }
-       return DESTROY_ME;
-}
-
-/**
- * Implementation of job_t.destroy.
- */
-static void destroy(private_delete_established_ike_sa_job_t *this)
-{
-       this->ike_sa_id->destroy(this->ike_sa_id);
-       free(this);
-}
-
-/*
- * Described in header
- */
-delete_established_ike_sa_job_t *delete_established_ike_sa_job_create(ike_sa_id_t *ike_sa_id)
-{
-       private_delete_established_ike_sa_job_t *this = malloc_thing(private_delete_established_ike_sa_job_t);
-       
-       /* interface functions */
-       this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
-       this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
-       this->public.job_interface.destroy = (void (*)(job_t*)) destroy;
-               
-       /* private variables */
-       this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
-       this->logger = logger_manager->get_logger(logger_manager, WORKER);
-       
-       return &(this->public);
-}
diff --git a/src/charon/queues/jobs/delete_established_ike_sa_job.h b/src/charon/queues/jobs/delete_established_ike_sa_job.h
deleted file mode 100644 (file)
index 9f04c78..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * @file delete_established_ike_sa_job.h
- * 
- * @brief Interface of delete_established_ike_sa_job_t.
- * 
- */
-
-/*
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-#ifndef DELETE_ESTABLISHED_IKE_SA_JOB_H_
-#define DELETE_ESTABLISHED_IKE_SA_JOB_H_
-
-#include <types.h>
-#include <sa/ike_sa_id.h>
-#include <queues/jobs/job.h>
-
-
-typedef struct delete_established_ike_sa_job_t delete_established_ike_sa_job_t;
-
-/**
- * @brief Class representing an DELETE_ESTABLISHED_IKE_SA Job.
- * 
- * This job initiates the deletion of an IKE_SA. The SA
- * to delete is specified via an ike_sa_id_t.
- * 
- * @b Constructors:
- *  - delete_established_ike_sa_job_create()
- * 
- * @ingroup jobs
- */
-struct delete_established_ike_sa_job_t {
-       /**
-        * The job_t interface.
-        */
-       job_t job_interface;
-};
-
-/**
- * @brief Creates a job of type DELETE_ESTABLISHED_IKE_SA.
- * 
- * @param ike_sa_id            id of the IKE_SA to delete
- * @return                             delete_established_ike_sa_job_t object
- * 
- * @ingroup jobs
- */
-delete_established_ike_sa_job_t *delete_established_ike_sa_job_create(ike_sa_id_t *ike_sa_id);
-
-#endif /*DELETE_ESTABLISHED_IKE_SA_JOB_H_*/
diff --git a/src/charon/queues/jobs/delete_half_open_ike_sa_job.c b/src/charon/queues/jobs/delete_half_open_ike_sa_job.c
deleted file mode 100644 (file)
index 7b79480..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * @file delete_half_open_ike_sa_job.c
- * 
- * @brief Implementation of delete_half_open_ike_sa_job_t.
- * 
- */
-
-/*
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include "delete_half_open_ike_sa_job.h"
-
-#include <daemon.h>
-
-typedef struct private_delete_half_open_ike_sa_job_t private_delete_half_open_ike_sa_job_t;
-
-/**
- * Private data of an delete_half_open_ike_sa_job_t Object
- */
-struct private_delete_half_open_ike_sa_job_t {
-       /**
-        * public delete_half_open_ike_sa_job_t interface
-        */
-       delete_half_open_ike_sa_job_t public;
-       
-       /**
-        * ID of the ike_sa to delete
-        */
-       ike_sa_id_t *ike_sa_id;
-       
-       /**
-        * logger ref
-        */
-       logger_t *logger;
-};
-
-/**
- * Implements job_t.get_type.
- */
-static job_type_t get_type(private_delete_half_open_ike_sa_job_t *this)
-{
-       return DELETE_HALF_OPEN_IKE_SA;
-}
-
-/**
- * Implementation of job_t.execute.
- */
-static status_t execute(private_delete_half_open_ike_sa_job_t *this)
-{
-       ike_sa_t *ike_sa;
-       
-       ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id);
-       if (ike_sa == NULL)
-       {
-               /* hm, somebody was faster ;-) */
-               return DESTROY_ME;
-       }
-       
-       switch (ike_sa->get_state(ike_sa))
-       {
-               case IKE_ESTABLISHED:
-               {
-                       /* IKE_SA is established and so is not getting destroyed */
-                       charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
-                       return DESTROY_ME;
-               }
-               default:
-               {
-                       /* IKE_SA is half open and gets destroyed */
-                       this->logger->log(this->logger, AUDIT,
-                                                         "deleting half open IKE_SA after timeout");
-                       charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
-                       return DESTROY_ME;
-               }
-       }
-}
-
-/**
- * Implements job_t.destroy.
- */
-static void destroy(private_delete_half_open_ike_sa_job_t *this)
-{
-       this->ike_sa_id->destroy(this->ike_sa_id);
-       free(this);
-}
-
-/*
- * Described in header
- */
-delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id)
-{
-       private_delete_half_open_ike_sa_job_t *this = malloc_thing(private_delete_half_open_ike_sa_job_t);
-       
-       /* interface functions */
-       this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
-       this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
-       this->public.job_interface.destroy = (void (*)(job_t *)) destroy;;
-       
-       /* private variables */
-       this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
-       this->logger = logger_manager->get_logger(logger_manager, WORKER);
-       
-       return &(this->public);
-}
diff --git a/src/charon/queues/jobs/delete_half_open_ike_sa_job.h b/src/charon/queues/jobs/delete_half_open_ike_sa_job.h
deleted file mode 100644 (file)
index 3f11d1a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * @file delete_half_open_ike_sa_job.h
- * 
- * @brief Interface of delete_half_open_ike_sa_job_t.
- * 
- */
-
-/*
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-#ifndef DELETE_HALF_OPEN_IKE_SA_JOB_H_
-#define DELETE_HALF_OPEN_IKE_SA_JOB_H_
-
-#include <types.h>
-#include <sa/ike_sa_id.h>
-#include <queues/jobs/job.h>
-
-
-typedef struct delete_half_open_ike_sa_job_t delete_half_open_ike_sa_job_t;
-
-/**
- * @brief Class representing an DELETE_HALF_OPEN_IKE_SA Job.
- * 
- * This job is responsible for deleting of half open IKE_SAs. A half 
- * open IKE_SA is every IKE_SA which hasn't reache the SA_ESTABLISHED
- * state.
- * 
- * @b Constructors:
- *  - delete_half_open_ike_sa_job_create()
- * 
- * @ingroup jobs
- */
-struct delete_half_open_ike_sa_job_t {
-       
-       /**
-        * The job_t interface.
-        */
-       job_t job_interface;
-};
-
-/**
- * @brief Creates a job of type DELETE_HALF_OPEN_IKE_SA.
- * 
- * @param ike_sa_id            id of the IKE_SA to delete
- * @return                             created delete_half_open_ike_sa_job_t object
- * 
- * @ingroup jobs
- */
-delete_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id);
-
-#endif /* DELETE_HALF_OPEN_IKE_SA_JOB_H_ */
diff --git a/src/charon/queues/jobs/delete_ike_sa_job.c b/src/charon/queues/jobs/delete_ike_sa_job.c
new file mode 100644 (file)
index 0000000..e2a8617
--- /dev/null
@@ -0,0 +1,136 @@
+/**
+ * @file delete_ike_sa_job.c
+ * 
+ * @brief Implementation of delete_ike_sa_job_t.
+ * 
+ */
+
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "delete_ike_sa_job.h"
+
+#include <daemon.h>
+
+typedef struct private_delete_ike_sa_job_t private_delete_ike_sa_job_t;
+
+/**
+ * Private data of an delete_ike_sa_job_t Object
+ */
+struct private_delete_ike_sa_job_t {
+       /**
+        * public delete_ike_sa_job_t interface
+        */
+       delete_ike_sa_job_t public;
+       
+       /**
+        * ID of the ike_sa to delete
+        */
+       ike_sa_id_t *ike_sa_id;
+       
+       /**
+        * Should the IKE_SA be deleted if it is in ESTABLISHED state?
+        */
+       bool delete_if_established;
+       
+       /**
+        * logger ref
+        */
+       logger_t *logger;
+};
+
+/**
+ * Implements job_t.get_type.
+ */
+static job_type_t get_type(private_delete_ike_sa_job_t *this)
+{
+       return DELETE_IKE_SA;
+}
+
+/**
+ * Implementation of job_t.execute.
+ */
+static status_t execute(private_delete_ike_sa_job_t *this)
+{
+       ike_sa_t *ike_sa;
+       
+       if (this->delete_if_established)
+       {
+               if (charon->ike_sa_manager->delete(charon->ike_sa_manager, 
+                       this->ike_sa_id) != SUCCESS)
+               {
+                       this->logger->log(this->logger, ERROR|LEVEL1, "IKE SA didn't exist anymore");
+               }
+               return DESTROY_ME;
+       }
+       else
+       {
+               ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id);
+               if (ike_sa == NULL)
+               {
+                       /* hm, somebody was faster ;-) */
+                       return DESTROY_ME;
+               }
+               
+               switch (ike_sa->get_state(ike_sa))
+               {
+                       case IKE_ESTABLISHED:
+                       {
+                               /* IKE_SA is established and so is not getting destroyed */
+                               charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+                               return DESTROY_ME;
+                       }
+                       default:
+                       {
+                               /* IKE_SA is half open and gets destroyed */
+                               this->logger->log(this->logger, AUDIT,
+                                                               "deleting half open IKE_SA after timeout");
+                               charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
+                               return DESTROY_ME;
+                       }
+               }
+       }
+}
+
+/**
+ * Implements job_t.destroy.
+ */
+static void destroy(private_delete_ike_sa_job_t *this)
+{
+       this->ike_sa_id->destroy(this->ike_sa_id);
+       free(this);
+}
+
+/*
+ * Described in header
+ */
+delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id, 
+                                                                                         bool delete_if_established)
+{
+       private_delete_ike_sa_job_t *this = malloc_thing(private_delete_ike_sa_job_t);
+       
+       /* interface functions */
+       this->public.job_interface.get_type = (job_type_t (*) (job_t *)) get_type;
+       this->public.job_interface.execute = (status_t (*) (job_t *)) execute;
+       this->public.job_interface.destroy = (void (*)(job_t *)) destroy;;
+       
+       /* private variables */
+       this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
+       this->delete_if_established = delete_if_established;
+       this->logger = logger_manager->get_logger(logger_manager, WORKER);
+       
+       return &(this->public);
+}
diff --git a/src/charon/queues/jobs/delete_ike_sa_job.h b/src/charon/queues/jobs/delete_ike_sa_job.h
new file mode 100644 (file)
index 0000000..8ef68b1
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * @file delete_ike_sa_job.h
+ * 
+ * @brief Interface of delete_ike_sa_job_t.
+ * 
+ */
+
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+#ifndef DELETE_IKE_SA_JOB_H_
+#define DELETE_IKE_SA_JOB_H_
+
+#include <types.h>
+#include <sa/ike_sa_id.h>
+#include <queues/jobs/job.h>
+
+
+typedef struct delete_ike_sa_job_t delete_ike_sa_job_t;
+
+/**
+ * @brief Class representing an DELETE_IKE_SA Job.
+ * 
+ * This job is responsible for deleting established or half open IKE_SAs. 
+ * A half open IKE_SA is every IKE_SA which hasn't reache the SA_ESTABLISHED
+ * state.
+ * 
+ * @b Constructors:
+ *  - delete_ike_sa_job_create()
+ * 
+ * @ingroup jobs
+ */
+struct delete_ike_sa_job_t {
+       
+       /**
+        * The job_t interface.
+        */
+       job_t job_interface;
+};
+
+/**
+ * @brief Creates a job of type DELETE_IKE_SA.
+ * 
+ * @param ike_sa_id                            id of the IKE_SA to delete
+ * @param delete_if_established        should the IKE_SA be deleted if it is established?
+ * @return                                             created delete_ike_sa_job_t object
+ * 
+ * @ingroup jobs
+ */
+delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id,
+                                                                                         bool delete_if_established);
+
+#endif /* DELETE_IKE_SA_JOB_H_ */
index 81e0366..f773a57 100644 (file)
@@ -25,7 +25,6 @@
 #include "incoming_packet_job.h"
 
 #include <daemon.h>
-#include <queues/jobs/delete_half_open_ike_sa_job.h>
 
 typedef struct private_incoming_packet_job_t private_incoming_packet_job_t;
 
index 4b5b704..00c4ef3 100644 (file)
@@ -27,7 +27,6 @@
 #include "initiate_job.h"
 
 #include <daemon.h>
-#include <queues/jobs/delete_half_open_ike_sa_job.h>
 
 typedef struct private_initiate_job_t private_initiate_job_t;
 
@@ -71,9 +70,11 @@ static status_t execute(private_initiate_job_t *this)
 {
        ike_sa_t *ike_sa;
        
-       ike_sa = charon->ike_sa_manager->checkout_by_ids(charon->ike_sa_manager,
-                                                                               this->policy->get_my_id(this->policy),
-                                                                               this->policy->get_other_id(this->policy));
+       ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+                                                       this->connection->get_my_host(this->connection),
+                                                       this->connection->get_other_host(this->connection),
+                                                       this->policy->get_my_id(this->policy),
+                                                       this->policy->get_other_id(this->policy));
        
        this->connection->get_ref(this->connection);
        this->policy->get_ref(this->policy);
index f99ea14..fe9127a 100644 (file)
@@ -31,8 +31,7 @@ mapping_t job_type_m[] = {
        {INITIATE, "INITIATE"},
        {ROUTE, "ROUTE"},
        {ACQUIRE, "ACQUIRE"},
-       {DELETE_ESTABLISHED_IKE_SA, "DELETE_ESTABLISHED_IKE_SA"},
-       {DELETE_HALF_OPEN_IKE_SA, "DELETE_HALF_OPEN_IKE_SA"},
+       {DELETE_IKE_SA, "DELETE_IKE_SA"},
        {DELETE_CHILD_SA, "DELETE_CHILD_SA"},
        {REKEY_CHILD_SA, "REKEY_CHILD_SA"},
        {REKEY_IKE_SA, "REKEY_IKE_SA"},
index d1b0a5c..879b9ab 100644 (file)
@@ -72,35 +72,28 @@ enum job_type_t {
        ACQUIRE,
        
        /** 
-        * Delete an ike sa which is still not established.
+        * Delete an IKE_SA.
         * 
-        * Job is implemented in class delete_half_open_ike_sa_job_t
+        * Job is implemented in class delete_ike_sa_job_t
         */
-       DELETE_HALF_OPEN_IKE_SA,
-       
-       /** 
-        * Delete an ike sa which is established.
-        * 
-        * Job is implemented in class delete_established_ike_sa_job_t
-        */     
-       DELETE_ESTABLISHED_IKE_SA,
+       DELETE_IKE_SA,
        
        /**
-        * Delete a child sa.
+        * Delete a CHILD_SA.
         * 
         * Job is implemented in class delete_child_sa_job_t
         */
        DELETE_CHILD_SA,
        
        /**
-        * Rekey a child sa.
+        * Rekey a CHILD_SA.
         * 
         * Job is implemented in class rekey_child_sa_job_t
         */
        REKEY_CHILD_SA,
        
        /**
-        * Rekey an IKE_SA
+        * Rekey an IKE_SA.
         * 
         * Job is implemented in class rekey_ike_sa_job_t
         */
index 6a533ec..494897e 100644 (file)
@@ -66,7 +66,7 @@ static job_type_t get_type(private_retransmit_request_job_t *this)
 static status_t execute(private_retransmit_request_job_t *this)
 {
        ike_sa_t *ike_sa;
-                               
+       
        ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->ike_sa_id);
        if (ike_sa == NULL)
        {
index ae773af..b60f117 100644 (file)
@@ -74,9 +74,11 @@ static status_t execute(private_route_job_t *this)
 {
        ike_sa_t *ike_sa;
        
-       ike_sa = charon->ike_sa_manager->checkout_by_ids(charon->ike_sa_manager,
-                                                                               this->policy->get_my_id(this->policy),
-                                                                               this->policy->get_other_id(this->policy));
+       ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+                                                       this->connection->get_my_host(this->connection),
+                                                       this->connection->get_other_host(this->connection),
+                                                       this->policy->get_my_id(this->policy),
+                                                       this->policy->get_other_id(this->policy));
        if (this->route)
        {
                if (ike_sa->route(ike_sa, this->connection, this->policy) != SUCCESS)
index fe8e052..6488cc2 100644 (file)
@@ -51,8 +51,7 @@
 #include <sa/transactions/dead_peer_detection.h>
 #include <sa/transactions/rekey_ike_sa.h>
 #include <queues/jobs/retransmit_request_job.h>
-#include <queues/jobs/delete_established_ike_sa_job.h>
-#include <queues/jobs/delete_half_open_ike_sa_job.h>
+#include <queues/jobs/delete_ike_sa_job.h>
 #include <queues/jobs/send_dpd_job.h>
 #include <queues/jobs/send_keepalive_job.h>
 #include <queues/jobs/rekey_ike_sa_job.h>
@@ -204,6 +203,16 @@ struct private_ike_sa_t {
        } time;
        
        /**
+        * interval to send DPD liveness check
+        */
+       time_t dpd_delay;
+       
+       /**
+        * number of retransmit sequences to go through before giving up (keyingtries)
+        */
+       u_int32_t retrans_sequences;
+       
+       /**
         * List of queued transactions to process
         */
        linked_list_t *transaction_queue;
@@ -428,13 +437,19 @@ static status_t transmit_request(private_ike_sa_t *this)
        u_int32_t transmitted;
        u_int32_t timeout;
        transaction_t *transaction = this->transaction_out;
-       u_int32_t message_id = transaction->get_message_id(transaction);
+       u_int32_t message_id;
+       
+       
+       this->logger->log(this->logger, CONTROL,
+                                         "transmitting request");
        
        transmitted = transaction->requested(transaction);
        timeout = charon->configuration->get_retransmit_timeout(charon->configuration,
-                                                                                                                       transmitted);
+                                                                                                                       transmitted,
+                                                                                                                       this->retrans_sequences);
        if (timeout == 0)
        {
+               /* giving up. TODO: check for childrens with dpdaction=hold */
                this->logger->log(this->logger, ERROR,
                                                  "giving up after %d retransmits, deleting IKE_SA",
                                                  transmitted - 1);
@@ -444,8 +459,11 @@ static status_t transmit_request(private_ike_sa_t *this)
        status = transaction->get_request(transaction, &request);
        if (status != SUCCESS)
        {
+               this->logger->log(this->logger, ERROR,
+                                                 "generating request failed");
                return status;
        }
+       message_id = transaction->get_message_id(transaction);
        /* if we retransmit, the request is already generated */
        if (transmitted == 0)
        {
@@ -484,6 +502,8 @@ static status_t retransmit_request(private_ike_sa_t *this, u_int32_t message_id)
        if (this->transaction_out == NULL ||
                this->transaction_out->get_message_id(this->transaction_out) != message_id)
        {
+               if (this->transaction_out)
+               printf("trans_out->mid = %d, mid = %d\n", this->transaction_out->get_message_id(this->transaction_out), message_id);
                /* no retransmit necessary, transaction did already complete */
                return SUCCESS;
        }
@@ -668,8 +688,7 @@ static status_t process_response(private_ike_sa_t *this, message_t *response)
        current = this->transaction_out;
        /* check if message ID is that of our currently active transaction */
        if (current == NULL ||
-               current->get_message_id(current) !=
-                  response->get_message_id(response))
+               current->get_message_id(current) != response->get_message_id(response))
        {
                this->logger->log(this->logger, ERROR, 
                                                  "received response with message ID %d not requested, ignored");
@@ -839,6 +858,8 @@ static status_t initiate(private_ike_sa_t *this,
                        DESTROY_IF(this->other_host);
                        this->other_host = connection->get_other_host(connection);
                        this->other_host = this->other_host->clone(this->other_host);
+                       this->retrans_sequences = connection->get_retrans_seq(connection);
+                       this->dpd_delay = connection->get_dpd_delay(connection);
                        
                        this->message_id_out = 1;
                        ike_sa_init = ike_sa_init_create(&this->public);
@@ -958,6 +979,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
                        this->message_id_out = 1;
                        ike_sa_init = ike_sa_init_create(&this->public);
                        ike_sa_init->set_config(ike_sa_init, connection, policy);
+                       /* reuse existing reqid */
+                       ike_sa_init->set_reqid(ike_sa_init, reqid);
                        return queue_transaction(this, (transaction_t*)ike_sa_init, TRUE);
                }
                case IKE_CONNECTING:
@@ -971,6 +994,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
                        
                        create_child = create_child_sa_create(&this->public);
                        create_child->set_policy(create_child, policy);
+                       /* reuse existing reqid */
+                       create_child->set_reqid(create_child, reqid);
                        return queue_transaction(this, (transaction_t*)create_child, FALSE);
                }
                default:
@@ -1090,6 +1115,8 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
                                this->other_host = this->other_host->clone(this->other_host);
                        }
                        set_name(this, connection->get_name(connection));
+                       this->retrans_sequences = connection->get_retrans_seq(connection);
+                       this->dpd_delay = connection->get_dpd_delay(connection);
                        break;
                case IKE_ESTABLISHED:
                case IKE_REKEYING:
@@ -1102,6 +1129,7 @@ static status_t route(private_ike_sa_t *this, connection_t *connection, policy_t
        }
        
        child_sa = child_sa_create(0, this->my_host, this->other_host, 0, 0, FALSE);
+       child_sa->set_name(child_sa, policy->get_name(policy));
        my_ts = policy->get_my_traffic_selectors(policy, this->my_host);
        other_ts = policy->get_other_traffic_selectors(policy, this->other_host);
        status = child_sa->add_policies(child_sa, my_ts, other_ts);
@@ -1162,10 +1190,13 @@ static status_t unroute(private_ike_sa_t *this, policy_t *policy)
 static status_t send_dpd(private_ike_sa_t *this)
 {
        send_dpd_job_t *job;
-       time_t diff, interval;
-       status_t status = SUCCESS;
+       time_t diff;
        
-       interval = charon->configuration->get_dpd_interval(charon->configuration);
+       if (this->dpd_delay == 0)
+       {
+               /* DPD disabled */
+               return SUCCESS;
+       }
        
        if (this->transaction_out)
        {
@@ -1179,20 +1210,20 @@ static status_t send_dpd(private_ike_sa_t *this)
                last_in = get_time_inbound(this);
                now = time(NULL);
                diff = now - last_in;
-               if (diff >= interval)
+               if (diff >= this->dpd_delay)
                {
                        /* to long ago, initiate dead peer detection */
                        dead_peer_detection_t *dpd;
                        this->logger->log(this->logger, CONTROL, "sending DPD request");
                        dpd = dead_peer_detection_create(&this->public);
-                       status = queue_transaction(this, (transaction_t*)dpd, FALSE);
+                       queue_transaction(this, (transaction_t*)dpd, FALSE);
                        diff = 0;
                }
        }
        /* recheck in "interval" seconds */
        job = send_dpd_job_create(this->ike_sa_id);
        charon->event_queue->add_relative(charon->event_queue, (job_t*)job,
-                                                                         (interval - diff) * 1000);
+                                                                         (this->dpd_delay - diff) * 1000);
        return SUCCESS;
 }
 
@@ -1657,7 +1688,7 @@ static void set_lifetimes(private_ike_sa_t *this,
        if (hard_lifetime)
        {
                this->time.delete = this->time.established + hard_lifetime;
-               job = (job_t*)delete_established_ike_sa_job_create(this->ike_sa_id);
+               job = (job_t*)delete_ike_sa_job_create(this->ike_sa_id, TRUE);
                charon->event_queue->add_relative(charon->event_queue, job,
                                                                                  hard_lifetime * 1000);
        }
@@ -1982,6 +2013,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->time.established = 0;
        this->time.rekey = 0;
        this->time.delete = 0;
+       this->dpd_delay = 0;
+       this->retrans_sequences = 0;
        
        return &this->public;
 }
index 7e9ce1f..46bf3a1 100644 (file)
@@ -375,11 +375,13 @@ static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
 }
 
 /**
- * Implementation of of ike_sa_manager.create_and_checkout.
+ * Implementation of of ike_sa_manager.checkout_by_id.
  */
-static ike_sa_t* checkout_by_ids(private_ike_sa_manager_t *this,
-                                                                identification_t *my_id,
-                                                                identification_t *other_id)
+static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this,
+                                                                  host_t *my_host,
+                                                                  host_t *other_host,
+                                                                  identification_t *my_id,
+                                                                  identification_t *other_id)
 {
        iterator_t *iterator;
        ike_sa_t *ike_sa = NULL;
@@ -391,6 +393,7 @@ static ike_sa_t* checkout_by_ids(private_ike_sa_manager_t *this,
        {
                ike_sa_entry_t *entry;
                identification_t *found_my_id, *found_other_id;
+               host_t *found_my_host, *found_other_host;
                int wc;
                
                iterator->current(iterator, (void**)&entry);
@@ -401,6 +404,8 @@ static ike_sa_t* checkout_by_ids(private_ike_sa_manager_t *this,
                
                found_my_id = entry->ike_sa->get_my_id(entry->ike_sa);
                found_other_id = entry->ike_sa->get_other_id(entry->ike_sa);
+               found_my_host = entry->ike_sa->get_my_host(entry->ike_sa);
+               found_other_host = entry->ike_sa->get_other_host(entry->ike_sa);
                
                if (found_my_id->get_type(found_my_id) == ID_ANY &&
                        found_other_id->get_type(found_other_id) == ID_ANY)
@@ -409,12 +414,19 @@ static ike_sa_t* checkout_by_ids(private_ike_sa_manager_t *this,
                        continue;
                }
                
-               if (found_my_id->matches(found_my_id, my_id, &wc) &&
+               /* compare ID and hosts. Supplied ID may contain wildcards, and IP
+                * may be %any. */
+               if ((found_my_host->is_anyaddr(found_my_host) ||
+                        my_host->ip_equals(my_host, found_my_host)) &&
+                       (found_other_host->is_anyaddr(found_other_host) ||
+                        other_host->ip_equals(other_host, found_other_host)) &&
+                       found_my_id->matches(found_my_id, my_id, &wc) &&
                        found_other_id->matches(found_other_id, other_id, &wc))
                {
                        /* looks good, we take this one */
                        this->logger->log(this->logger, CONTROL|LEVEL1, 
-                                                         "found an existing IKE_SA for IDs %s - %s",
+                                                         "found an existing IKE_SA for %s[%s]...%s[%s]",
+                                                         my_host->get_string(my_host), other_host->get_string(other_host),
                                                          my_id->get_string(my_id), other_id->get_string(other_id));
                        entry->checked_out = TRUE;
                        ike_sa = entry->ike_sa;
@@ -931,7 +943,7 @@ ike_sa_manager_t *ike_sa_manager_create()
 
        /* assign public functions */
        this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
-       this->public.checkout_by_ids = (ike_sa_t*(*)(ike_sa_manager_t*,identification_t*,identification_t*))checkout_by_ids;
+       this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,host_t*,host_t*,identification_t*,identification_t*))checkout_by_id;
        this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
        this->public.checkout_by_child = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t))checkout_by_child;
        this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list;
index f327be0..f0c90f3 100644 (file)
@@ -69,18 +69,22 @@ struct ike_sa_manager_t {
        ike_sa_t* (*checkout) (ike_sa_manager_t* this, ike_sa_id_t *sa_id);
        
        /**
-        * @brief Checkout an IKE_SA by two identifications.
+        * @brief Checkout an existing IKE_SA by hosts and identifications.
         *
-        * Allows the lookup of an IKE_SA by two user IDs. It returns the
-        * first found occurence, if there are multiple canddates. Supplied IDs
-        * may contain wildcards. If no IKE_SA is found, a new one is created.
+        * Allows the lookup of an IKE_SA by user IDs and hosts. It returns the
+        * first found occurence, if there are multiple candidates. Supplied IDs
+        * may contain wildcards, hosts may be %any. 
+        * If no IKE_SA is found, a new one is created.
         *
         * @param this                          the manager object
+        * @param my_host                       address of our host
+        * @param other_id                      address of remote host
         * @param my_id                         ID used by us
-        * @param other_id                      ID used by other
+        * @param other_id                      ID used by remote
         * @return                                      checked out/created IKE_SA
         */
-       ike_sa_t* (*checkout_by_ids) (ike_sa_manager_t* this,
+       ike_sa_t* (*checkout_by_id) (ike_sa_manager_t* this,
+                                                                 host_t *my_host, host_t* other_host,
                                                                  identification_t *my_id, 
                                                                  identification_t *other_id);
        
index bd6efd3..d88c234 100644 (file)
@@ -70,6 +70,11 @@ struct private_create_child_sa_t {
        u_int32_t rekey_spi;
        
        /**
+        * reqid to use for new CHILD_SA
+        */
+       u_int32_t reqid;
+       
+       /**
         * policy definition used
         */
        policy_t *policy;
@@ -155,6 +160,14 @@ static void set_policy(private_create_child_sa_t *this, policy_t *policy)
 }
 
 /**
+ * Implementation of create_child_sa_t.set_reqid.
+ */
+static void set_reqid(private_create_child_sa_t *this, u_int32_t reqid)
+{
+       this->reqid = reqid;
+}
+
+/**
  * Implementation of create_child_sa_t.rekeys_child.
  */
 static void rekeys_child(private_create_child_sa_t *this, child_sa_t *child_sa)
@@ -252,7 +265,6 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
                sa_payload_t *sa_payload;
                linked_list_t *proposals;
                bool use_natt;
-               u_int32_t reqid = 0;
                
                /* get a policy, if we are rekeying */
                if (this->rekeyed_sa)
@@ -270,20 +282,20 @@ static status_t get_request(private_create_child_sa_t *this, message_t **result)
                                                                                                                my_ts, other_ts,
                                                                                                            me, other);
                        
-                       reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
+                       this->reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
                        
                        if (this->policy == NULL)
                        {
                                this->logger->log(this->logger, ERROR,
                                                                  "no policy found to rekey CHILD_SA with reqid %d",
-                                                                 reqid);
+                                                                 this->reqid);
                                return FAILED;
                        }
                }
                
                proposals = this->policy->get_proposals(this->policy);
                use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
-               this->child_sa = child_sa_create(reqid, me, other,
+               this->child_sa = child_sa_create(this->reqid, me, other,
                                                        this->policy->get_soft_lifetime(this->policy),
                                                        this->policy->get_hard_lifetime(this->policy),
                                                        use_natt);
@@ -686,16 +698,14 @@ static status_t get_response(private_create_child_sa_t *this, message_t *request
                }
                else
                {       /* create child sa */
-                       u_int32_t reqid = 0;
-               
                        if (this->rekeyed_sa)
                        {
-                               reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
+                               this->reqid = this->rekeyed_sa->get_reqid(this->rekeyed_sa);
                        }
                        soft_lifetime = this->policy->get_soft_lifetime(this->policy);
                        hard_lifetime = this->policy->get_hard_lifetime(this->policy);
                        use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
-                       this->child_sa = child_sa_create(reqid, me, other,
+                       this->child_sa = child_sa_create(this->reqid, me, other,
                                                                                         soft_lifetime, hard_lifetime,
                                                                                         use_natt);
                        this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
@@ -950,6 +960,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
        
        /* public functions */
        this->public.set_policy = (void(*)(create_child_sa_t*,policy_t*))set_policy;
+       this->public.set_reqid = (void(*)(create_child_sa_t*,u_int32_t))set_reqid;
        this->public.rekeys_child = (void(*)(create_child_sa_t*,child_sa_t*))rekeys_child;
        this->public.cancel = (void(*)(create_child_sa_t*))cancel;
        
@@ -959,6 +970,7 @@ create_child_sa_t *create_child_sa_create(ike_sa_t *ike_sa)
        this->message = NULL;
        this->requested = 0;
        this->rekey_spi = 0;
+       this->reqid = 0;
        this->nonce_i = CHUNK_INITIALIZER;
        this->nonce_r = CHUNK_INITIALIZER;
        this->nonce_s = CHUNK_INITIALIZER;
index d45bfcc..f35b252 100644 (file)
@@ -41,21 +41,21 @@ typedef struct create_child_sa_t create_child_sa_t;
  * but includes an additional REKEY_SA notify and deletes the old
  * one (in a separate transaction).
  * 
- *                     ¦__________  _________¦
- *                     ¦  Cyq     \/    Czq  ¦
- *                     ¦__________/\_________¦
- *              detect ¦__________  _________¦ detect
- *                     ¦  Czp     \/    Czp  ¦
- * compare nonces, won ¦__________/\_________¦ compare nonces, lost
- *                     ¦                     ¦
- *        delete old   ¦__________           ¦
- *                     ¦  Dxq     \__________¦
- *                     ¦           __________¦
- *                     ¦__________/    Dxp   ¦
- *                     ¦           __________¦ delete created
- *                     ¦__________/    Dzq   ¦
- *                     ¦__________           ¦
- *                     ¦  Dzp     \__________¦
+ *                     __________  _________
+ *                       Cyq     \/    Czq  
+ *                     __________/\_________
+ *              detect __________  _________ detect
+ *                       Czp     \/    Czp  
+ * compare nonces, won __________/\_________ compare nonces, lost
+ *                                          
+ *        delete old   __________           
+ *                       Dxq     \__________
+ *                                __________
+ *                     __________/    Dxp   
+ *                                __________ delete created
+ *                     __________/    Dzq   
+ *                     __________           
+ *                       Dzp     \__________
  * 
  *
  * @b Constructors:
@@ -78,6 +78,17 @@ struct create_child_sa_t {
         * @param policy        policy for CHILD_SA
         */
        void (*set_policy) (create_child_sa_t* this, policy_t *policy);
+
+       /**
+        * @brief Set the reqid used for CHILD_SA setup.
+        *
+        * If we acquire, we must use the same reqid as the
+        * installed policy.
+        * 
+        * @param this                  calling object
+        * @param reqid                 reqid to use for the CHILD_SA
+        */
+       void (*set_reqid) (create_child_sa_t* this, u_int32_t reqid);
        
        /**
         * @brief Set the CHILD_SA which gets rekeyed by the new one.
index 68abba8..1d15dae 100644 (file)
@@ -125,6 +125,11 @@ struct private_ike_auth_t {
        bool build_child;
        
        /**
+        * reqid to use for CHILD_SA setup
+        */
+       u_int32_t reqid;
+       
+       /**
         * Assigned logger.
         */
        logger_t *logger;
@@ -157,6 +162,14 @@ static void set_config(private_ike_auth_t *this,
 }
 
 /**
+ * Implementation of transaction_t.set_reqid.
+ */
+static void set_reqid(private_ike_auth_t *this, u_int32_t reqid)
+{
+       this->reqid = reqid;
+}
+
+/**
  * Implementation of transaction_t.set_nonces.
  */
 static void set_nonces(private_ike_auth_t *this, chunk_t nonce_i, chunk_t nonce_r)
@@ -303,7 +316,7 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
                proposal_list = this->policy->get_proposals(this->policy);
                soft_lifetime = this->policy->get_soft_lifetime(this->policy);
                hard_lifetime = this->policy->get_hard_lifetime(this->policy);
-               this->child_sa = child_sa_create(0, me, other, soft_lifetime, hard_lifetime,
+               this->child_sa = child_sa_create(this->reqid, me, other, soft_lifetime, hard_lifetime,
                                                                                 this->ike_sa->is_natt_enabled(this->ike_sa));
                this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
                if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS)
@@ -768,7 +781,7 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                        soft_lifetime = this->policy->get_soft_lifetime(this->policy);
                        hard_lifetime = this->policy->get_hard_lifetime(this->policy);
                        use_natt = this->ike_sa->is_natt_enabled(this->ike_sa);
-                       this->child_sa = child_sa_create(0, me, other, 
+                       this->child_sa = child_sa_create(this->reqid, me, other, 
                                                                                         soft_lifetime, hard_lifetime, 
                                                                                         use_natt);
                        this->child_sa->set_name(this->child_sa, this->policy->get_name(this->policy));
@@ -1006,6 +1019,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa)
        
        /* public functions */
        this->public.set_config = (void(*)(ike_auth_t*,connection_t*,policy_t*))set_config;
+       this->public.set_reqid = (void(*)(ike_auth_t*,u_int32_t))set_reqid;
        this->public.set_nonces = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_nonces;
        this->public.set_init_messages = (void(*)(ike_auth_t*,chunk_t,chunk_t))set_init_messages;
        
@@ -1023,6 +1037,7 @@ ike_auth_t *ike_auth_create(ike_sa_t *ike_sa)
        this->tsi = NULL;
        this->tsr = NULL;
        this->build_child = TRUE;
+       this->reqid = 0;
        this->logger = logger_manager->get_logger(logger_manager, IKE_SA);
 
        return &this->public;
index 89263d4..4c6fd82 100644 (file)
@@ -62,6 +62,18 @@ struct ike_auth_t {
         */
        void (*set_config) (ike_auth_t* this, 
                                                connection_t *connection, policy_t *policy);
+
+       /**
+        * @brief Set the reqid used for CHILD_SA setup.
+        *
+        * The first two message exchanges may set up an associated
+        * CHILD_SA. If we acquire, we must use the same reqid as the
+        * installed policy.
+        * 
+        * @param this                  calling object
+        * @param reqid                 reqid to use for the CHILD_SA
+        */
+       void (*set_reqid) (ike_auth_t* this, u_int32_t reqid);
        
        /**
         * @brief Set the nonces used in the previous ike_sa_init transaction.
index fed03fa..7a78669 100644 (file)
@@ -33,8 +33,7 @@
 #include <encoding/payloads/ke_payload.h>
 #include <encoding/payloads/nonce_payload.h>
 #include <sa/transactions/ike_auth.h>
-#include <queues/jobs/delete_half_open_ike_sa_job.h>
-#include <queues/jobs/delete_established_ike_sa_job.h>
+#include <queues/jobs/delete_ike_sa_job.h>
 #include <queues/jobs/rekey_ike_sa_job.h>
 
 
@@ -107,6 +106,11 @@ struct private_ike_sa_init_t {
        proposal_t *proposal;
        
        /**
+        * Reqid to pass to IKE_AUTH, used for created CHILD_SA
+        */
+       u_int32_t reqid;
+       
+       /**
         * Randomizer to generate nonces
         */
        randomizer_t *randomizer;
@@ -179,6 +183,14 @@ static void set_config(private_ike_sa_init_t *this,
 }
 
 /**
+ * Implementation of ike_sa_init_t.set_reqid.
+ */
+static void set_reqid(private_ike_sa_init_t *this, u_int32_t reqid)
+{
+       this->reqid = reqid;
+}
+
+/**
  * Implementation of transaction_t.get_message_id.
  */
 static u_int32_t get_message_id(private_ike_sa_init_t *this)
@@ -796,6 +808,7 @@ static status_t get_response(private_ike_sa_init_t *this,
                /* create next transaction, for which we except a message */
                ike_auth = ike_auth_create(this->ike_sa);
                ike_auth->set_config(ike_auth, this->connection, this->policy);
+               ike_auth->set_reqid(ike_auth, this->reqid);
                this->connection = NULL;
                this->policy = NULL;
                ike_auth->set_nonces(ike_auth,
@@ -809,7 +822,8 @@ static status_t get_response(private_ike_sa_init_t *this,
        timeout = charon->configuration->get_half_open_ike_sa_timeout(charon->configuration);
        if (timeout)
        {
-               job_t *job = (job_t*)delete_half_open_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa));
+               job_t *job = (job_t*)delete_ike_sa_job_create(
+                                               this->ike_sa->get_id(this->ike_sa), FALSE);
                charon->event_queue->add_relative(charon->event_queue, job, timeout);
        }
        /* set new state */
@@ -1029,6 +1043,7 @@ static status_t conclude(private_ike_sa_init_t *this, message_t *response,
                /* create next transaction, for which we except a message */
                ike_auth = ike_auth_create(this->ike_sa);
                ike_auth->set_config(ike_auth, this->connection, this->policy);
+               ike_auth->set_reqid(ike_auth, this->reqid);
                this->connection = NULL;
                this->policy = NULL;
                ike_auth->set_nonces(ike_auth,
@@ -1074,6 +1089,7 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
        
        /* public functions */
        this->public.set_config = (void(*)(ike_sa_init_t*,connection_t*,policy_t*))set_config;
+       this->public.set_reqid = (void(*)(ike_sa_init_t*,u_int32_t))set_reqid;
        this->public.use_dh_group = (bool(*)(ike_sa_init_t*,diffie_hellman_group_t))use_dh_group;
        
        /* private data */
@@ -1087,6 +1103,7 @@ ike_sa_init_t *ike_sa_init_create(ike_sa_t *ike_sa)
        this->connection = NULL;
        this->policy = NULL;
        this->proposal = NULL;
+       this->reqid = 0;
        this->randomizer = randomizer_create();
        this->nat_hasher = hasher_create(HASH_SHA1);
        this->natd_src_hash = CHUNK_INITIALIZER;
index 3bc049d..c7a493c 100644 (file)
@@ -58,6 +58,19 @@ struct ike_sa_init_t {
         */
        void (*set_config) (ike_sa_init_t* this, 
                                                connection_t *connection, policy_t *policy);
+
+       /**
+        * @brief Set the reqid used for CHILD_SA setup.
+        *
+        * The first two message exchanges may set up an associated
+        * CHILD_SA. If we acquire, we must use the same reqid as the
+        * installed policy. This requid is passed to the ike_auth
+        * transaction which creates the CHILD_AS.
+        * 
+        * @param this                  calling object
+        * @param reqid                 reqid to use for the CHILD_SA
+        */
+       void (*set_reqid) (ike_sa_init_t* this, u_int32_t reqid);
        
        /**
         * @brief Set the Diffie Hellman group to use for initiating.
index b090703..796cd04 100644 (file)
@@ -1009,11 +1009,8 @@ static status_t add_policy(private_kernel_interface_t *this,
                        if (!update)
                        {
                                current->refcount++;
-                               iterator->destroy(iterator);
-                               pthread_mutex_unlock(&this->pol_mutex);
                                this->logger->log(this->logger, CONTROL|LEVEL1, 
                                                                  "policy already exists, increasing refcount");
-                               return SUCCESS;
                        }
                        policy = current;
                        found = TRUE;
index b095b60..55a3b79 100755 (executable)
@@ -363,6 +363,8 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
                                                                   msg->add_conn.other.sendcert,
                                                                   my_host, other_host,
                                                                   RSA_DIGITAL_SIGNATURE,
+                                                                  msg->add_conn.dpd.delay,
+                                                                  msg->add_conn.rekey.tries,
                                                                   msg->add_conn.rekey.ike_lifetime,
                                                                   msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
                                                                   msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100);
@@ -410,7 +412,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
                                                   msg->add_conn.rekey.ipsec_lifetime,
                                                   msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin,
                                                   msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100, 
-                                                  msg->add_conn.me.updown);
+                                                  msg->add_conn.me.updown, msg->add_conn.dpd.route);
        policy->add_my_traffic_selector(policy, my_ts);
        policy->add_other_traffic_selector(policy, other_ts);
        policy->add_authorities(policy, my_ca, other_ca);
index bb8942f..a0e9260 100644 (file)
@@ -498,27 +498,11 @@ A value of
 prevents IPsec from proposing compression;
 a proposal to compress will still be accepted.
 .TP
-.B disablearrivalcheck
-whether KLIPS's normal tunnel-exit check
-(that a packet emerging from a tunnel has plausible addresses in its header)
-should be disabled;
-acceptable values are
-.B yes
-and
-.B no
-(the default).
-Tunnel-exit checks improve security and do not break any normal configuration.
-Relevant only locally, other end need not agree on it.
-.TP
 .B dpdaction
 controls the use of the Dead Peer Detection protocol (DPD, RFC 3706) where
-R_U_THERE IKE notification messages are periodically sent in order to check the
-liveliness of the IPsec peer. The default is..
-.B none
-which disables the active sending of R_U_THERE notifications.
-Nevertheless pluto will always send the DPD Vendor ID during connection set up
-in order to signal the readiness to act passively as a responder if the peer
-wants to use DPD. The values
+R_U_THERE notification messages (IKEv1) or empty INFORMATIONAL messages (IKEv2)
+are periodically sent in order to check the
+liveliness of the IPsec peer. The values
 .B clear
 and
 .B hold
@@ -527,14 +511,31 @@ are stopped and unrouted (
 .B clear
 ) or put in the hold state (
 .B hold
+). For
+.B IKEv1
+, the default is
+.B none
+which disables the active sending of R_U_THERE notifications.
+Nevertheless pluto will always send the DPD Vendor ID during connection set up
+in order to signal the readiness to act passively as a responder if the peer
+wants to use DPD. For
+.B IKEv2, none
+does't make sense, as all messages are used to detect dead peers. If specified,
+it has the same meaning as the default (
+.B clear
 ).
 .TP
 .B dpddelay
-defines the period time interval with which R_U_THERE messages are sent to the peer.
+defines the period time interval with which R_U_THERE messages/INFORMATIONAL
+exchanges are sent to the peer. These are only sent if no other traffic is
+received. In IKEv2, a value of 0 sends no additional INFORMATIONAL
+messages and uses only standard messages (such as those to rekey) to detect
+dead peers.
 .TP
 .B dpdtimeout
 defines the timeout interval, after which all connections to a peer are deleted
-in case of inactivity.
+in case of inactivity. This only applies to IKEv1, in IKEv2 the default
+retransmission timeout applies, as every exchange is used to detect dead peers.
 .TP
 .B failureshunt
 what to do with packets when negotiation fails.
index 0c05eba..32866be 100644 (file)
@@ -180,6 +180,8 @@ int starter_stroke_add_conn(starter_conn_t *conn)
        }
        msg.add_conn.algorithms.ike = push_string(&msg, conn->ike);
        msg.add_conn.algorithms.esp = push_string(&msg, conn->esp);
+       msg.add_conn.dpd.delay = conn->dpd_delay;
+       msg.add_conn.dpd.route = conn->dpd_action == DPD_ACTION_HOLD ? 1 : 0;
 
        starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->right);
        starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->left);
index e29a588..03a5ca2 100644 (file)
@@ -116,6 +116,9 @@ static int add_connection(char *name,
        msg.add_conn.algorithms.ike = NULL;
        msg.add_conn.algorithms.esp = NULL;
        
+       msg.add_conn.dpd.delay = 0;
+       msg.add_conn.dpd.route = 0;
+       
        msg.add_conn.me.id = push_string(&msg, my_id);
        msg.add_conn.me.address = push_string(&msg, my_addr);
        msg.add_conn.me.subnet = push_string(&msg, my_net);
index b71e199..3202842 100644 (file)
@@ -145,6 +145,10 @@ struct stroke_msg_t {
                                unsigned long tries;
                                unsigned long fuzz;
                        } rekey;
+                       struct {
+                               time_t delay;
+                               bool route;
+                       } dpd;
                        stroke_end_t me, other;
                } add_conn;