2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2007-2010 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "task_manager_v1.h"
22 #include <sa/tasks/ike_init.h>
23 #include <sa/tasks/ike_natd.h>
24 #include <sa/tasks/ike_mobike.h>
25 #include <sa/tasks/ike_auth.h>
26 #include <sa/tasks/ike_auth_lifetime.h>
27 #include <sa/tasks/ike_cert_pre.h>
28 #include <sa/tasks/ike_cert_post.h>
29 #include <sa/tasks/ike_rekey.h>
30 #include <sa/tasks/ike_delete.h>
31 #include <sa/tasks/ike_config.h>
32 #include <sa/tasks/ike_dpd.h>
33 #include <sa/tasks/ike_vendor.h>
34 #include <sa/tasks/child_create.h>
35 #include <sa/tasks/child_rekey.h>
36 #include <sa/tasks/child_delete.h>
37 #include <encoding/payloads/delete_payload.h>
38 #include <processing/jobs/retransmit_job.h>
41 #include <sa/tasks/ike_me.h>
44 typedef struct exchange_t exchange_t
;
47 * An exchange in the air, used do detect and handle retransmission
52 * Message ID used for this transaction
57 * generated packet for retransmission
62 typedef struct private_task_manager_t private_task_manager_t
;
65 * private data of the task manager
67 struct private_task_manager_t
{
72 task_manager_v1_t
public;
75 * associated IKE_SA we are serving
80 * Exchange we are currently handling as responder
84 * Message ID of the exchange
89 * packet for retransmission
96 * Exchange we are currently handling as initiator
100 * Message ID of the exchange
105 * how many times we have retransmitted so far
110 * packet for retransmission
115 * type of the initated exchange
117 exchange_type_t type
;
122 * List of queued tasks not yet in action
124 linked_list_t
*queued_tasks
;
127 * List of active tasks, initiated by ourselve
129 linked_list_t
*active_tasks
;
132 * List of tasks initiated by peer
134 linked_list_t
*passive_tasks
;
137 * the task manager has been reset
142 * Number of times we retransmit messages before giving up
144 u_int retransmit_tries
;
147 * Retransmission timeout
149 double retransmit_timeout
;
152 * Base to calculate retransmission timeout
154 double retransmit_base
;
158 * flush all tasks in the task manager
160 static void flush(private_task_manager_t
*this)
162 this->queued_tasks
->destroy_offset(this->queued_tasks
,
163 offsetof(task_t
, destroy
));
164 this->queued_tasks
= linked_list_create();
165 this->passive_tasks
->destroy_offset(this->passive_tasks
,
166 offsetof(task_t
, destroy
));
167 this->passive_tasks
= linked_list_create();
168 this->active_tasks
->destroy_offset(this->active_tasks
,
169 offsetof(task_t
, destroy
));
170 this->active_tasks
= linked_list_create();
173 METHOD(task_manager_t
, retransmit
, status_t
,
174 private_task_manager_t
*this, u_int32_t message_id
)
179 METHOD(task_manager_t
, initiate
, status_t
,
180 private_task_manager_t
*this)
186 * handle exchange collisions
188 static bool handle_collisions(private_task_manager_t
*this, task_t
*task
)
194 * build a response depending on the "passive" task list
196 static status_t
build_response(private_task_manager_t
*this, message_t
*request
)
198 enumerator_t
*enumerator
;
205 me
= request
->get_destination(request
);
206 other
= request
->get_source(request
);
208 message
= message_create(IKEV1_MAJOR_VERSION
, IKEV1_MINOR_VERSION
);
209 message
->set_exchange_type(message
, request
->get_exchange_type(request
));
210 /* send response along the path the request came in */
211 message
->set_source(message
, me
->clone(me
));
212 message
->set_destination(message
, other
->clone(other
));
213 message
->set_message_id(message
, this->responding
.mid
);
214 message
->set_request(message
, FALSE
);
216 enumerator
= this->passive_tasks
->create_enumerator(this->passive_tasks
);
217 while (enumerator
->enumerate(enumerator
, (void*)&task
))
219 switch (task
->build(task
, message
))
222 /* task completed, remove it */
223 this->passive_tasks
->remove_at(this->passive_tasks
, enumerator
);
224 if (!handle_collisions(this, task
))
230 /* processed, but task needs another exchange */
231 if (handle_collisions(this, task
))
233 this->passive_tasks
->remove_at(this->passive_tasks
,
239 charon
->bus
->ike_updown(charon
->bus
, this->ike_sa
, FALSE
);
242 /* destroy IKE_SA, but SEND response first */
251 enumerator
->destroy(enumerator
);
253 /* message complete, send it */
254 DESTROY_IF(this->responding
.packet
);
255 this->responding
.packet
= NULL
;
256 status
= this->ike_sa
->generate_message(this->ike_sa
, message
,
257 &this->responding
.packet
);
258 message
->destroy(message
);
259 if (status
!= SUCCESS
)
261 charon
->bus
->ike_updown(charon
->bus
, this->ike_sa
, FALSE
);
265 charon
->sender
->send(charon
->sender
,
266 this->responding
.packet
->clone(this->responding
.packet
));
275 * handle an incoming request message
277 static status_t
process_request(private_task_manager_t
*this,
280 enumerator_t
*enumerator
;
283 if (this->passive_tasks
->get_count(this->passive_tasks
) == 0)
284 { /* create tasks depending on request type, if not already some queued */
285 switch (message
->get_exchange_type(message
))
288 /* TODO-IKEv1: handle mainmode */
291 /* TODO-IKEv1: agressive mode */
294 /* TODO-IKEv1: quick mode */
296 case INFORMATIONAL_V1
:
297 /* TODO-IKEv1: informational */
303 /* let the tasks process the message */
304 enumerator
= this->passive_tasks
->create_enumerator(this->passive_tasks
);
305 while (enumerator
->enumerate(enumerator
, (void*)&task
))
307 switch (task
->process(task
, message
))
310 /* task completed, remove it */
311 this->passive_tasks
->remove_at(this->passive_tasks
, enumerator
);
315 /* processed, but task needs at least another call to build() */
319 charon
->bus
->ike_updown(charon
->bus
, this->ike_sa
, FALSE
);
322 /* critical failure, destroy IKE_SA */
323 this->passive_tasks
->remove_at(this->passive_tasks
, enumerator
);
324 enumerator
->destroy(enumerator
);
329 enumerator
->destroy(enumerator
);
331 return build_response(this, message
);
334 METHOD(task_manager_t
, process_message
, status_t
,
335 private_task_manager_t
*this, message_t
*msg
)
337 /* TODO-IKEv1: detect request/response */
340 /* TODO-IKEv1: detect mainmode retransmission */
341 charon
->bus
->message(charon
->bus
, msg
, TRUE
);
342 if (process_request(this, msg
) != SUCCESS
)
350 /* TODO-IKEv1: handle response */
356 METHOD(task_manager_t
, queue_task
, void,
357 private_task_manager_t
*this, task_t
*task
)
359 DBG2(DBG_IKE
, "queueing %N task", task_type_names
, task
->get_type(task
));
360 this->queued_tasks
->insert_last(this->queued_tasks
, task
);
363 METHOD(task_manager_t
, adopt_tasks
, void,
364 private_task_manager_t
*this, task_manager_t
*other_public
)
366 private_task_manager_t
*other
= (private_task_manager_t
*)other_public
;
369 /* move queued tasks from other to this */
370 while (other
->queued_tasks
->remove_last(other
->queued_tasks
,
371 (void**)&task
) == SUCCESS
)
373 DBG2(DBG_IKE
, "migrating %N task", task_type_names
, task
->get_type(task
));
374 task
->migrate(task
, this->ike_sa
);
375 this->queued_tasks
->insert_first(this->queued_tasks
, task
);
379 METHOD(task_manager_t
, busy
, bool,
380 private_task_manager_t
*this)
382 return (this->active_tasks
->get_count(this->active_tasks
) > 0);
385 METHOD(task_manager_t
, incr_mid
, void,
386 private_task_manager_t
*this, bool initiate
)
390 this->initiating
.mid
++;
394 this->responding
.mid
++;
398 METHOD(task_manager_t
, reset
, void,
399 private_task_manager_t
*this, u_int32_t initiate
, u_int32_t respond
)
404 METHOD(task_manager_t
, create_task_enumerator
, enumerator_t
*,
405 private_task_manager_t
*this, task_queue_t queue
)
409 case TASK_QUEUE_ACTIVE
:
410 return this->active_tasks
->create_enumerator(this->active_tasks
);
411 case TASK_QUEUE_PASSIVE
:
412 return this->passive_tasks
->create_enumerator(this->passive_tasks
);
413 case TASK_QUEUE_QUEUED
:
414 return this->queued_tasks
->create_enumerator(this->queued_tasks
);
416 return enumerator_create_empty();
420 METHOD(task_manager_t
, destroy
, void,
421 private_task_manager_t
*this)
425 this->active_tasks
->destroy(this->active_tasks
);
426 this->queued_tasks
->destroy(this->queued_tasks
);
427 this->passive_tasks
->destroy(this->passive_tasks
);
429 DESTROY_IF(this->responding
.packet
);
430 DESTROY_IF(this->initiating
.packet
);
437 task_manager_v1_t
*task_manager_v1_create(ike_sa_t
*ike_sa
)
439 private_task_manager_t
*this;
444 .process_message
= _process_message
,
445 .queue_task
= _queue_task
,
446 .initiate
= _initiate
,
447 .retransmit
= _retransmit
,
448 .incr_mid
= _incr_mid
,
450 .adopt_tasks
= _adopt_tasks
,
452 .create_task_enumerator
= _create_task_enumerator
,
457 .initiating
.type
= EXCHANGE_TYPE_UNDEFINED
,
458 .queued_tasks
= linked_list_create(),
459 .active_tasks
= linked_list_create(),
460 .passive_tasks
= linked_list_create(),
461 .retransmit_tries
= lib
->settings
->get_int(lib
->settings
,
462 "charon.retransmit_tries", RETRANSMIT_TRIES
),
463 .retransmit_timeout
= lib
->settings
->get_double(lib
->settings
,
464 "charon.retransmit_timeout", RETRANSMIT_TIMEOUT
),
465 .retransmit_base
= lib
->settings
->get_double(lib
->settings
,
466 "charon.retransmit_base", RETRANSMIT_BASE
),
469 return &this->public;