aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2006-09-05 14:07:25 +0000
committerMartin Willi <martin@strongswan.org>2006-09-05 14:07:25 +0000
commita655f5c09c2ba180b7d393dbdfc8b8057293d9ab (patch)
treee645a61c178ebcb932a56f09e4bdcca80b230431
parentda8ab11e918353293953636abea73f12bf8f956e (diff)
downloadstrongswan-a655f5c09c2ba180b7d393dbdfc8b8057293d9ab.tar.bz2
strongswan-a655f5c09c2ba180b7d393dbdfc8b8057293d9ab.tar.xz
reuse reqid when a ROUTED child_sa gets INSTALLED
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
-rw-r--r--src/charon/Makefile.am8
-rwxr-xr-xsrc/charon/config/configuration.c89
-rwxr-xr-xsrc/charon/config/configuration.h40
-rw-r--r--src/charon/config/connections/connection.c32
-rw-r--r--src/charon/config/connections/connection.h36
-rw-r--r--src/charon/config/policies/policy.c8
-rw-r--r--src/charon/config/policies/policy.h3
-rw-r--r--src/charon/config/traffic_selector.c26
-rw-r--r--src/charon/doc/Todo-list.txt3
-rw-r--r--src/charon/queues/jobs/delete_established_ike_sa_job.c99
-rw-r--r--src/charon/queues/jobs/delete_established_ike_sa_job.h62
-rw-r--r--src/charon/queues/jobs/delete_half_open_ike_sa_job.c117
-rw-r--r--src/charon/queues/jobs/delete_ike_sa_job.c136
-rw-r--r--src/charon/queues/jobs/delete_ike_sa_job.h (renamed from src/charon/queues/jobs/delete_half_open_ike_sa_job.h)32
-rw-r--r--src/charon/queues/jobs/incoming_packet_job.c1
-rw-r--r--src/charon/queues/jobs/initiate_job.c9
-rw-r--r--src/charon/queues/jobs/job.c3
-rw-r--r--src/charon/queues/jobs/job.h19
-rw-r--r--src/charon/queues/jobs/retransmit_request_job.c2
-rw-r--r--src/charon/queues/jobs/route_job.c8
-rw-r--r--src/charon/sa/ike_sa.c59
-rw-r--r--src/charon/sa/ike_sa_manager.c26
-rw-r--r--src/charon/sa/ike_sa_manager.h16
-rw-r--r--src/charon/sa/transactions/create_child_sa.c28
-rw-r--r--src/charon/sa/transactions/create_child_sa.h41
-rw-r--r--src/charon/sa/transactions/ike_auth.c19
-rw-r--r--src/charon/sa/transactions/ike_auth.h12
-rw-r--r--src/charon/sa/transactions/ike_sa_init.c23
-rw-r--r--src/charon/sa/transactions/ike_sa_init.h13
-rw-r--r--src/charon/threads/kernel_interface.c3
-rwxr-xr-xsrc/charon/threads/stroke_interface.c4
-rw-r--r--src/starter/ipsec.conf.543
-rw-r--r--src/starter/starterstroke.c2
-rw-r--r--src/stroke/stroke.c3
-rw-r--r--src/stroke/stroke.h4
35 files changed, 552 insertions, 477 deletions
diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am
index 024205ac0..330aefcca 100644
--- a/src/charon/Makefile.am
+++ b/src/charon/Makefile.am
@@ -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 \
diff --git a/src/charon/config/configuration.c b/src/charon/config/configuration.c
index 2dcf0bb72..e983e5968 100755
--- a/src/charon/config/configuration.c
+++ b/src/charon/config/configuration.c
@@ -29,38 +29,77 @@
/**
* 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);
}
diff --git a/src/charon/config/configuration.h b/src/charon/config/configuration.h
index 553a01edd..ee25872fc 100755
--- a/src/charon/config/configuration.h
+++ b/src/charon/config/configuration.h
@@ -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
diff --git a/src/charon/config/connections/connection.c b/src/charon/config/connections/connection.c
index 281d43d9c..6b8192beb 100644
--- a/src/charon/config/connections/connection.c
+++ b/src/charon/config/connections/connection.c
@@ -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;
diff --git a/src/charon/config/connections/connection.h b/src/charon/config/connections/connection.h
index 61ca9cfc0..c425590ae 100644
--- a/src/charon/config/connections/connection.h
+++ b/src/charon/config/connections/connection.h
@@ -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_ */
diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c
index 49983ade7..71fadbdfa 100644
--- a/src/charon/config/policies/policy.c
+++ b/src/charon/config/policies/policy.c
@@ -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;
diff --git a/src/charon/config/policies/policy.h b/src/charon/config/policies/policy.h
index 454f69c12..9505e53fd 100644
--- a/src/charon/config/policies/policy.h
+++ b/src/charon/config/policies/policy.h
@@ -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_ */
diff --git a/src/charon/config/traffic_selector.c b/src/charon/config/traffic_selector.c
index 24cf7eaad..d8293b808 100644
--- a/src/charon/config/traffic_selector.c
+++ b/src/charon/config/traffic_selector.c
@@ -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);
}
diff --git a/src/charon/doc/Todo-list.txt b/src/charon/doc/Todo-list.txt
index 10cd2f930..1d21d927e 100644
--- a/src/charon/doc/Todo-list.txt
+++ b/src/charon/doc/Todo-list.txt
@@ -63,9 +63,12 @@
- 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
index e5230e532..000000000
--- a/src/charon/queues/jobs/delete_established_ike_sa_job.c
+++ /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
index 9f04c7846..000000000
--- a/src/charon/queues/jobs/delete_established_ike_sa_job.h
+++ /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
index 7b79480bf..000000000
--- a/src/charon/queues/jobs/delete_half_open_ike_sa_job.c
+++ /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_ike_sa_job.c b/src/charon/queues/jobs/delete_ike_sa_job.c
new file mode 100644
index 000000000..e2a861757
--- /dev/null
+++ b/src/charon/queues/jobs/delete_ike_sa_job.c
@@ -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_half_open_ike_sa_job.h b/src/charon/queues/jobs/delete_ike_sa_job.h
index 3f11d1aac..8ef68b1c6 100644
--- a/src/charon/queues/jobs/delete_half_open_ike_sa_job.h
+++ b/src/charon/queues/jobs/delete_ike_sa_job.h
@@ -1,7 +1,7 @@
/**
- * @file delete_half_open_ike_sa_job.h
+ * @file delete_ike_sa_job.h
*
- * @brief Interface of delete_half_open_ike_sa_job_t.
+ * @brief Interface of delete_ike_sa_job_t.
*
*/
@@ -21,29 +21,29 @@
* for more details.
*/
-#ifndef DELETE_HALF_OPEN_IKE_SA_JOB_H_
-#define DELETE_HALF_OPEN_IKE_SA_JOB_H_
+#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_half_open_ike_sa_job_t delete_half_open_ike_sa_job_t;
+typedef struct delete_ike_sa_job_t delete_ike_sa_job_t;
/**
- * @brief Class representing an DELETE_HALF_OPEN_IKE_SA Job.
+ * @brief Class representing an DELETE_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
+ * 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_half_open_ike_sa_job_create()
+ * - delete_ike_sa_job_create()
*
* @ingroup jobs
*/
-struct delete_half_open_ike_sa_job_t {
+struct delete_ike_sa_job_t {
/**
* The job_t interface.
@@ -52,13 +52,15 @@ struct delete_half_open_ike_sa_job_t {
};
/**
- * @brief Creates a job of type DELETE_HALF_OPEN_IKE_SA.
+ * @brief Creates a job of type DELETE_IKE_SA.
*
- * @param ike_sa_id id of the IKE_SA to delete
- * @return created delete_half_open_ike_sa_job_t object
+ * @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_half_open_ike_sa_job_t *delete_half_open_ike_sa_job_create(ike_sa_id_t *ike_sa_id);
+delete_ike_sa_job_t *delete_ike_sa_job_create(ike_sa_id_t *ike_sa_id,
+ bool delete_if_established);
-#endif /* DELETE_HALF_OPEN_IKE_SA_JOB_H_ */
+#endif /* DELETE_IKE_SA_JOB_H_ */
diff --git a/src/charon/queues/jobs/incoming_packet_job.c b/src/charon/queues/jobs/incoming_packet_job.c
index 81e0366c8..f773a57f4 100644
--- a/src/charon/queues/jobs/incoming_packet_job.c
+++ b/src/charon/queues/jobs/incoming_packet_job.c
@@ -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;
diff --git a/src/charon/queues/jobs/initiate_job.c b/src/charon/queues/jobs/initiate_job.c
index 4b5b704ae..00c4ef32e 100644
--- a/src/charon/queues/jobs/initiate_job.c
+++ b/src/charon/queues/jobs/initiate_job.c
@@ -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);
diff --git a/src/charon/queues/jobs/job.c b/src/charon/queues/jobs/job.c
index f99ea14c1..fe9127a75 100644
--- a/src/charon/queues/jobs/job.c
+++ b/src/charon/queues/jobs/job.c
@@ -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"},
diff --git a/src/charon/queues/jobs/job.h b/src/charon/queues/jobs/job.h
index d1b0a5c82..879b9ab12 100644
--- a/src/charon/queues/jobs/job.h
+++ b/src/charon/queues/jobs/job.h
@@ -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
*/
diff --git a/src/charon/queues/jobs/retransmit_request_job.c b/src/charon/queues/jobs/retransmit_request_job.c
index 6a533ec7a..494897e41 100644
--- a/src/charon/queues/jobs/retransmit_request_job.c
+++ b/src/charon/queues/jobs/retransmit_request_job.c
@@ -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)
{
diff --git a/src/charon/queues/jobs/route_job.c b/src/charon/queues/jobs/route_job.c
index ae773afdf..b60f117d7 100644
--- a/src/charon/queues/jobs/route_job.c
+++ b/src/charon/queues/jobs/route_job.c
@@ -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)
diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c
index fe8e05207..6488cc20c 100644
--- a/src/charon/sa/ike_sa.c
+++ b/src/charon/sa/ike_sa.c
@@ -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;
}
diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c
index 7e9ce1f57..46bf3a1bb 100644
--- a/src/charon/sa/ike_sa_manager.c
+++ b/src/charon/sa/ike_sa_manager.c
@@ -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;
diff --git a/src/charon/sa/ike_sa_manager.h b/src/charon/sa/ike_sa_manager.h
index f327be09c..f0c90f38f 100644
--- a/src/charon/sa/ike_sa_manager.h
+++ b/src/charon/sa/ike_sa_manager.h
@@ -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);
diff --git a/src/charon/sa/transactions/create_child_sa.c b/src/charon/sa/transactions/create_child_sa.c
index bd6efd3b0..d88c2341b 100644
--- a/src/charon/sa/transactions/create_child_sa.c
+++ b/src/charon/sa/transactions/create_child_sa.c
@@ -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;
diff --git a/src/charon/sa/transactions/create_child_sa.h b/src/charon/sa/transactions/create_child_sa.h
index d45bfcc6b..f35b25246 100644
--- a/src/charon/sa/transactions/create_child_sa.h
+++ b/src/charon/sa/transactions/create_child_sa.h
@@ -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.
diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c
index 68abba814..1d15daebb 100644
--- a/src/charon/sa/transactions/ike_auth.c
+++ b/src/charon/sa/transactions/ike_auth.c
@@ -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;
diff --git a/src/charon/sa/transactions/ike_auth.h b/src/charon/sa/transactions/ike_auth.h
index 89263d47c..4c6fd822c 100644
--- a/src/charon/sa/transactions/ike_auth.h
+++ b/src/charon/sa/transactions/ike_auth.h
@@ -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.
diff --git a/src/charon/sa/transactions/ike_sa_init.c b/src/charon/sa/transactions/ike_sa_init.c
index fed03fa49..7a7866970 100644
--- a/src/charon/sa/transactions/ike_sa_init.c
+++ b/src/charon/sa/transactions/ike_sa_init.c
@@ -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;
diff --git a/src/charon/sa/transactions/ike_sa_init.h b/src/charon/sa/transactions/ike_sa_init.h
index 3bc049db3..c7a493ccf 100644
--- a/src/charon/sa/transactions/ike_sa_init.h
+++ b/src/charon/sa/transactions/ike_sa_init.h
@@ -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.
diff --git a/src/charon/threads/kernel_interface.c b/src/charon/threads/kernel_interface.c
index b09070390..796cd04a8 100644
--- a/src/charon/threads/kernel_interface.c
+++ b/src/charon/threads/kernel_interface.c
@@ -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;
diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c
index b095b605c..55a3b79c3 100755
--- a/src/charon/threads/stroke_interface.c
+++ b/src/charon/threads/stroke_interface.c
@@ -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);
diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5
index bb8942f82..a0e926078 100644
--- a/src/starter/ipsec.conf.5
+++ b/src/starter/ipsec.conf.5
@@ -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.
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 0c05ebaf3..32866be05 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -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);
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index e29a58813..03a5ca245 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -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);
diff --git a/src/stroke/stroke.h b/src/stroke/stroke.h
index b71e19921..320284229 100644
--- a/src/stroke/stroke.h
+++ b/src/stroke/stroke.h
@@ -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;