Added a stub for a IKEv1 task manager
[strongswan.git] / src / libcharon / sa / task_manager_v1.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
3 * Copyright (C) 2007-2010 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 */
16
17 #include "task_manager_v1.h"
18
19 #include <math.h>
20
21 #include <daemon.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>
39
40 #ifdef ME
41 #include <sa/tasks/ike_me.h>
42 #endif
43
44 typedef struct exchange_t exchange_t;
45
46 /**
47 * An exchange in the air, used do detect and handle retransmission
48 */
49 struct exchange_t {
50
51 /**
52 * Message ID used for this transaction
53 */
54 u_int32_t mid;
55
56 /**
57 * generated packet for retransmission
58 */
59 packet_t *packet;
60 };
61
62 typedef struct private_task_manager_t private_task_manager_t;
63
64 /**
65 * private data of the task manager
66 */
67 struct private_task_manager_t {
68
69 /**
70 * public functions
71 */
72 task_manager_v1_t public;
73
74 /**
75 * associated IKE_SA we are serving
76 */
77 ike_sa_t *ike_sa;
78
79 /**
80 * Exchange we are currently handling as responder
81 */
82 struct {
83 /**
84 * Message ID of the exchange
85 */
86 u_int32_t mid;
87
88 /**
89 * packet for retransmission
90 */
91 packet_t *packet;
92
93 } responding;
94
95 /**
96 * Exchange we are currently handling as initiator
97 */
98 struct {
99 /**
100 * Message ID of the exchange
101 */
102 u_int32_t mid;
103
104 /**
105 * how many times we have retransmitted so far
106 */
107 u_int retransmitted;
108
109 /**
110 * packet for retransmission
111 */
112 packet_t *packet;
113
114 /**
115 * type of the initated exchange
116 */
117 exchange_type_t type;
118
119 } initiating;
120
121 /**
122 * List of queued tasks not yet in action
123 */
124 linked_list_t *queued_tasks;
125
126 /**
127 * List of active tasks, initiated by ourselve
128 */
129 linked_list_t *active_tasks;
130
131 /**
132 * List of tasks initiated by peer
133 */
134 linked_list_t *passive_tasks;
135
136 /**
137 * the task manager has been reset
138 */
139 bool reset;
140
141 /**
142 * Number of times we retransmit messages before giving up
143 */
144 u_int retransmit_tries;
145
146 /**
147 * Retransmission timeout
148 */
149 double retransmit_timeout;
150
151 /**
152 * Base to calculate retransmission timeout
153 */
154 double retransmit_base;
155 };
156
157 /**
158 * flush all tasks in the task manager
159 */
160 static void flush(private_task_manager_t *this)
161 {
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();
171 }
172
173 METHOD(task_manager_t, retransmit, status_t,
174 private_task_manager_t *this, u_int32_t message_id)
175 {
176 return FAILED;
177 }
178
179 METHOD(task_manager_t, initiate, status_t,
180 private_task_manager_t *this)
181 {
182 return FAILED;
183 }
184
185 /**
186 * handle exchange collisions
187 */
188 static bool handle_collisions(private_task_manager_t *this, task_t *task)
189 {
190 return FALSE;
191 }
192
193 /**
194 * build a response depending on the "passive" task list
195 */
196 static status_t build_response(private_task_manager_t *this, message_t *request)
197 {
198 enumerator_t *enumerator;
199 task_t *task;
200 message_t *message;
201 host_t *me, *other;
202 bool delete = FALSE;
203 status_t status;
204
205 me = request->get_destination(request);
206 other = request->get_source(request);
207
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);
215
216 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
217 while (enumerator->enumerate(enumerator, (void*)&task))
218 {
219 switch (task->build(task, message))
220 {
221 case SUCCESS:
222 /* task completed, remove it */
223 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
224 if (!handle_collisions(this, task))
225 {
226 task->destroy(task);
227 }
228 break;
229 case NEED_MORE:
230 /* processed, but task needs another exchange */
231 if (handle_collisions(this, task))
232 {
233 this->passive_tasks->remove_at(this->passive_tasks,
234 enumerator);
235 }
236 break;
237 case FAILED:
238 default:
239 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
240 /* FALL */
241 case DESTROY_ME:
242 /* destroy IKE_SA, but SEND response first */
243 delete = TRUE;
244 break;
245 }
246 if (delete)
247 {
248 break;
249 }
250 }
251 enumerator->destroy(enumerator);
252
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)
260 {
261 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
262 return DESTROY_ME;
263 }
264
265 charon->sender->send(charon->sender,
266 this->responding.packet->clone(this->responding.packet));
267 if (delete)
268 {
269 return DESTROY_ME;
270 }
271 return SUCCESS;
272 }
273
274 /**
275 * handle an incoming request message
276 */
277 static status_t process_request(private_task_manager_t *this,
278 message_t *message)
279 {
280 enumerator_t *enumerator;
281 task_t *task = NULL;
282
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))
286 {
287 case ID_PROT:
288 /* TODO-IKEv1: handle mainmode */
289 break;
290 case AGGRESSIVE:
291 /* TODO-IKEv1: agressive mode */
292 return FAILED;
293 case QUICK_MODE:
294 /* TODO-IKEv1: quick mode */
295 return FAILED;
296 case INFORMATIONAL_V1:
297 /* TODO-IKEv1: informational */
298 return FAILED;
299 default:
300 return FAILED;
301 }
302 }
303 /* let the tasks process the message */
304 enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
305 while (enumerator->enumerate(enumerator, (void*)&task))
306 {
307 switch (task->process(task, message))
308 {
309 case SUCCESS:
310 /* task completed, remove it */
311 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
312 task->destroy(task);
313 break;
314 case NEED_MORE:
315 /* processed, but task needs at least another call to build() */
316 break;
317 case FAILED:
318 default:
319 charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE);
320 /* FALL */
321 case DESTROY_ME:
322 /* critical failure, destroy IKE_SA */
323 this->passive_tasks->remove_at(this->passive_tasks, enumerator);
324 enumerator->destroy(enumerator);
325 task->destroy(task);
326 return DESTROY_ME;
327 }
328 }
329 enumerator->destroy(enumerator);
330
331 return build_response(this, message);
332 }
333
334 METHOD(task_manager_t, process_message, status_t,
335 private_task_manager_t *this, message_t *msg)
336 {
337 /* TODO-IKEv1: detect request/response */
338 if (TRUE)
339 {
340 /* TODO-IKEv1: detect mainmode retransmission */
341 charon->bus->message(charon->bus, msg, TRUE);
342 if (process_request(this, msg) != SUCCESS)
343 {
344 flush(this);
345 return DESTROY_ME;
346 }
347 }
348 else
349 {
350 /* TODO-IKEv1: handle response */
351 return DESTROY_ME;
352 }
353 return SUCCESS;
354 }
355
356 METHOD(task_manager_t, queue_task, void,
357 private_task_manager_t *this, task_t *task)
358 {
359 DBG2(DBG_IKE, "queueing %N task", task_type_names, task->get_type(task));
360 this->queued_tasks->insert_last(this->queued_tasks, task);
361 }
362
363 METHOD(task_manager_t, adopt_tasks, void,
364 private_task_manager_t *this, task_manager_t *other_public)
365 {
366 private_task_manager_t *other = (private_task_manager_t*)other_public;
367 task_t *task;
368
369 /* move queued tasks from other to this */
370 while (other->queued_tasks->remove_last(other->queued_tasks,
371 (void**)&task) == SUCCESS)
372 {
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);
376 }
377 }
378
379 METHOD(task_manager_t, busy, bool,
380 private_task_manager_t *this)
381 {
382 return (this->active_tasks->get_count(this->active_tasks) > 0);
383 }
384
385 METHOD(task_manager_t, incr_mid, void,
386 private_task_manager_t *this, bool initiate)
387 {
388 if (initiate)
389 {
390 this->initiating.mid++;
391 }
392 else
393 {
394 this->responding.mid++;
395 }
396 }
397
398 METHOD(task_manager_t, reset, void,
399 private_task_manager_t *this, u_int32_t initiate, u_int32_t respond)
400 {
401
402 }
403
404 METHOD(task_manager_t, create_task_enumerator, enumerator_t*,
405 private_task_manager_t *this, task_queue_t queue)
406 {
407 switch (queue)
408 {
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);
415 default:
416 return enumerator_create_empty();
417 }
418 }
419
420 METHOD(task_manager_t, destroy, void,
421 private_task_manager_t *this)
422 {
423 flush(this);
424
425 this->active_tasks->destroy(this->active_tasks);
426 this->queued_tasks->destroy(this->queued_tasks);
427 this->passive_tasks->destroy(this->passive_tasks);
428
429 DESTROY_IF(this->responding.packet);
430 DESTROY_IF(this->initiating.packet);
431 free(this);
432 }
433
434 /*
435 * see header file
436 */
437 task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa)
438 {
439 private_task_manager_t *this;
440
441 INIT(this,
442 .public = {
443 .task_manager = {
444 .process_message = _process_message,
445 .queue_task = _queue_task,
446 .initiate = _initiate,
447 .retransmit = _retransmit,
448 .incr_mid = _incr_mid,
449 .reset = _reset,
450 .adopt_tasks = _adopt_tasks,
451 .busy = _busy,
452 .create_task_enumerator = _create_task_enumerator,
453 .destroy = _destroy,
454 },
455 },
456 .ike_sa = ike_sa,
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),
467 );
468
469 return &this->public;
470 }