add priority management for kernel policy
[strongswan.git] / src / charon / sa / ike_sa_manager.c
1 /**
2 * @file ike_sa_manager.c
3 *
4 * @brief Implementation of ike_sa_mananger_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <pthread.h>
25 #include <string.h>
26
27 #include "ike_sa_manager.h"
28
29 #include <daemon.h>
30 #include <sa/ike_sa_id.h>
31 #include <utils/logger.h>
32 #include <utils/logger_manager.h>
33 #include <utils/linked_list.h>
34
35 typedef struct ike_sa_entry_t ike_sa_entry_t;
36
37 /**
38 * An entry in the linked list, contains IKE_SA, locking and lookup data.
39 */
40 struct ike_sa_entry_t {
41 /**
42 * Destructor, also destroys associated ike_sa_t object.
43 */
44 status_t (*destroy) (ike_sa_entry_t *this);
45
46 /**
47 * Number of threads waiting for this ike_sa_t object.
48 */
49 int waiting_threads;
50
51 /**
52 * Condvar where threads can wait until ike_sa_t object is free for use again.
53 */
54 pthread_cond_t condvar;
55
56 /**
57 * Is this ike_sa currently checked out?
58 */
59 bool checked_out;
60
61 /**
62 * Does this SA drives out new threads?
63 */
64 bool driveout_new_threads;
65
66 /**
67 * Does this SA drives out waiting threads?
68 */
69 bool driveout_waiting_threads;
70
71 /**
72 * Identifiaction of an IKE_SA (SPIs).
73 */
74 ike_sa_id_t *ike_sa_id;
75
76 /**
77 * The contained ike_sa_t object.
78 */
79 ike_sa_t *ike_sa;
80 };
81
82 /**
83 * Implementation of ike_sa_entry_t.destroy.
84 */
85 static status_t ike_sa_entry_destroy(ike_sa_entry_t *this)
86 {
87 /* also destroy IKE SA */
88 this->ike_sa->destroy(this->ike_sa);
89 this->ike_sa_id->destroy(this->ike_sa_id);
90 free(this);
91 return SUCCESS;
92 }
93
94 /**
95 * @brief Creates a new entry for the ike_sa_t list.
96 *
97 * This constructor additionaly creates a new and empty SA.
98 *
99 * @param ike_sa_id The associated ike_sa_id_t, will be cloned
100 * @return ike_sa_entry_t object
101 */
102 static ike_sa_entry_t *ike_sa_entry_create(ike_sa_id_t *ike_sa_id)
103 {
104 ike_sa_entry_t *this = malloc_thing(ike_sa_entry_t);
105
106 /* destroy function */
107 this->destroy = ike_sa_entry_destroy;
108
109 this->waiting_threads = 0;
110 pthread_cond_init(&(this->condvar), NULL);
111
112 /* we set checkout flag when we really give it out */
113 this->checked_out = FALSE;
114 this->driveout_new_threads = FALSE;
115 this->driveout_waiting_threads = FALSE;
116
117 /* ike_sa_id is always cloned */
118 this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
119
120 /* create new ike_sa */
121 this->ike_sa = ike_sa_create(ike_sa_id);
122
123 return this;
124 }
125
126
127 typedef struct private_ike_sa_manager_t private_ike_sa_manager_t;
128
129 /**
130 * Additional private members of ike_sa_manager_t.
131 */
132 struct private_ike_sa_manager_t {
133 /**
134 * Public interface of ike_sa_manager_t.
135 */
136 ike_sa_manager_t public;
137
138 /**
139 * Lock for exclusivly accessing the manager.
140 */
141 pthread_mutex_t mutex;
142
143 /**
144 * Logger used for this IKE SA Manager.
145 */
146 logger_t *logger;
147
148 /**
149 * Linked list with entries for the ike_sa_t objects.
150 */
151 linked_list_t *ike_sa_list;
152
153 /**
154 * A randomizer, to get random SPIs for our side
155 */
156 randomizer_t *randomizer;
157 };
158
159 /**
160 * Implementation of private_ike_sa_manager_t.get_entry_by_id.
161 */
162 static status_t get_entry_by_id(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id, ike_sa_entry_t **entry)
163 {
164 linked_list_t *list = this->ike_sa_list;
165 iterator_t *iterator;
166 status_t status;
167
168 /* create iterator over list of ike_sa's */
169 iterator = list->create_iterator(list, TRUE);
170
171 /* default status */
172 status = NOT_FOUND;
173
174 while (iterator->has_next(iterator))
175 {
176 ike_sa_entry_t *current;
177
178 iterator->current(iterator, (void**)&current);
179 if (current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0)
180 {
181 /* seems to be a half ready ike_sa */
182 if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) ==
183 ike_sa_id->get_initiator_spi(ike_sa_id)) &&
184 (ike_sa_id->is_initiator(ike_sa_id) ==
185 current->ike_sa_id->is_initiator(current->ike_sa_id)))
186 {
187 this->logger->log(this->logger, CONTROL|LEVEL2,
188 "found entry by initiator spi %d",
189 ike_sa_id->get_initiator_spi(ike_sa_id));
190 *entry = current;
191 status = SUCCESS;
192 break;
193 }
194 }
195 else if (ike_sa_id->get_responder_spi(ike_sa_id) == 0)
196 {
197 if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) ==
198 ike_sa_id->get_initiator_spi(ike_sa_id)) &&
199 (ike_sa_id->is_initiator(ike_sa_id) ==
200 current->ike_sa_id->is_initiator(current->ike_sa_id)))
201 {
202 this->logger->log(this->logger, CONTROL|LEVEL2, "found entry by initiator spi %d",
203 ike_sa_id->get_initiator_spi(ike_sa_id));
204 *entry = current;
205 status = SUCCESS;
206 break;
207 }
208 }
209 if (current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id))
210 {
211 this->logger->log(this->logger, CONTROL|LEVEL2, "found entry by full ID");
212 *entry = current;
213 status = SUCCESS;
214 break;
215 }
216 }
217
218 iterator->destroy(iterator);
219 return status;
220 }
221
222 /**
223 * Implementation of private_ike_sa_manager_t.get_entry_by_sa.
224 */
225 static status_t get_entry_by_sa(private_ike_sa_manager_t *this, ike_sa_t *ike_sa, ike_sa_entry_t **entry)
226 {
227 linked_list_t *list = this->ike_sa_list;
228 iterator_t *iterator;
229 status_t status;
230
231 iterator = list->create_iterator(list, TRUE);
232
233 /* default status */
234 status = NOT_FOUND;
235
236 while (iterator->has_next(iterator))
237 {
238 ike_sa_entry_t *current;
239 iterator->current(iterator, (void**)&current);
240 /* only pointers are compared */
241 if (current->ike_sa == ike_sa)
242 {
243 this->logger->log(this->logger, CONTROL|LEVEL2, "found entry by pointer");
244 *entry = current;
245 status = SUCCESS;
246 break;
247 }
248 }
249 iterator->destroy(iterator);
250
251 return status;
252 }
253
254 /**
255 * Implementation of private_ike_sa_manager_s.delete_entry.
256 */
257 static status_t delete_entry(private_ike_sa_manager_t *this, ike_sa_entry_t *entry)
258 {
259 linked_list_t *list = this->ike_sa_list;
260 iterator_t *iterator;
261 status_t status;
262
263 iterator = list->create_iterator(list, TRUE);
264
265 status = NOT_FOUND;
266
267 while (iterator->has_next(iterator))
268 {
269 ike_sa_entry_t *current;
270 iterator->current(iterator, (void**)&current);
271 if (current == entry)
272 {
273 /* mark it, so now new threads can get this entry */
274 entry->driveout_new_threads = TRUE;
275 /* wait until all workers have done their work */
276 while (entry->waiting_threads)
277 {
278 /* wake up all */
279 pthread_cond_broadcast(&(entry->condvar));
280 /* they will wake us again when their work is done */
281 pthread_cond_wait(&(entry->condvar), &(this->mutex));
282 }
283
284 this->logger->log(this->logger, CONTROL|LEVEL2,
285 "found entry by pointer. Going to delete it");
286 iterator->remove(iterator);
287 entry->destroy(entry);
288 status = SUCCESS;
289 break;
290 }
291 }
292 iterator->destroy(iterator);
293 return status;
294 }
295
296 /**
297 * Wait until no other thread is using an IKE_SA, return FALSE if entry not
298 * acquireable
299 */
300 static bool wait_for_entry(private_ike_sa_manager_t *this, ike_sa_entry_t *entry)
301 {
302 if (entry->driveout_new_threads)
303 {
304 /* we are not allowed to get this */
305 return FALSE;
306 }
307 while (entry->checked_out && !entry->driveout_waiting_threads)
308 {
309 /* so wait until we can get it for us.
310 * we register us as waiting. */
311 entry->waiting_threads++;
312 pthread_cond_wait(&(entry->condvar), &(this->mutex));
313 entry->waiting_threads--;
314 }
315 /* hm, a deletion request forbids us to get this SA, get next one */
316 if (entry->driveout_waiting_threads)
317 {
318 /* we must signal here, others may be waiting on it, too */
319 pthread_cond_signal(&(entry->condvar));
320 return FALSE;
321 }
322 return TRUE;
323 }
324
325 /**
326 * Implementation of private_ike_sa_manager_t.get_next_spi.
327 */
328 static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
329 {
330 u_int64_t spi;
331
332 this->randomizer->get_pseudo_random_bytes(this->randomizer, 8, (u_int8_t*)&spi);
333
334 return spi;
335 }
336
337 /**
338 * Implementation of of ike_sa_manager.checkout_by_id.
339 */
340 static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this,
341 host_t *my_host,
342 host_t *other_host,
343 identification_t *my_id,
344 identification_t *other_id)
345 {
346 iterator_t *iterator;
347 ike_sa_t *ike_sa = NULL;
348
349 pthread_mutex_lock(&(this->mutex));
350
351 iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
352 while (iterator->has_next(iterator))
353 {
354 ike_sa_entry_t *entry;
355 identification_t *found_my_id, *found_other_id;
356 host_t *found_my_host, *found_other_host;
357 int wc;
358
359 iterator->current(iterator, (void**)&entry);
360 if (!wait_for_entry(this, entry))
361 {
362 continue;
363 }
364
365 found_my_id = entry->ike_sa->get_my_id(entry->ike_sa);
366 found_other_id = entry->ike_sa->get_other_id(entry->ike_sa);
367 found_my_host = entry->ike_sa->get_my_host(entry->ike_sa);
368 found_other_host = entry->ike_sa->get_other_host(entry->ike_sa);
369
370 if (found_my_id->get_type(found_my_id) == ID_ANY &&
371 found_other_id->get_type(found_other_id) == ID_ANY)
372 {
373 /* IKE_SA has no IDs yet, so we can't use it */
374 continue;
375 }
376
377 /* compare ID and hosts. Supplied ID may contain wildcards, and IP
378 * may be %any. */
379 if ((found_my_host->is_anyaddr(found_my_host) ||
380 my_host->ip_equals(my_host, found_my_host)) &&
381 (found_other_host->is_anyaddr(found_other_host) ||
382 other_host->ip_equals(other_host, found_other_host)) &&
383 found_my_id->matches(found_my_id, my_id, &wc) &&
384 found_other_id->matches(found_other_id, other_id, &wc))
385 {
386 /* looks good, we take this one */
387 this->logger->log(this->logger, CONTROL|LEVEL1,
388 "found an existing IKE_SA for %s[%s]...%s[%s]",
389 my_host->get_string(my_host), other_host->get_string(other_host),
390 my_id->get_string(my_id), other_id->get_string(other_id));
391 entry->checked_out = TRUE;
392 ike_sa = entry->ike_sa;
393 }
394 }
395 iterator->destroy(iterator);
396
397 if (!ike_sa)
398 {
399 u_int64_t initiator_spi;
400 ike_sa_entry_t *new_ike_sa_entry;
401 ike_sa_id_t *new_ike_sa_id;
402
403 initiator_spi = get_next_spi(this);
404 new_ike_sa_id = ike_sa_id_create(0, 0, TRUE);
405 new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi);
406
407 /* create entry */
408 new_ike_sa_entry = ike_sa_entry_create(new_ike_sa_id);
409 this->logger->log(this->logger, CONTROL|LEVEL2,
410 "created IKE_SA %llx:%llx, role %s",
411 new_ike_sa_id->get_initiator_spi(new_ike_sa_id),
412 new_ike_sa_id->get_responder_spi(new_ike_sa_id),
413 new_ike_sa_id->is_initiator(new_ike_sa_id) ? "initiator" : "responder");
414 new_ike_sa_id->destroy(new_ike_sa_id);
415
416 this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry);
417
418 /* check ike_sa out */
419 this->logger->log(this->logger, CONTROL|LEVEL1,
420 "new IKE_SA created for IDs %s - %s",
421 my_id->get_string(my_id), other_id->get_string(other_id));
422 new_ike_sa_entry->checked_out = TRUE;
423 ike_sa = new_ike_sa_entry->ike_sa;
424 }
425 pthread_mutex_unlock(&(this->mutex));
426
427 return ike_sa;
428 }
429
430 /**
431 * Implementation of of ike_sa_manager.checkout.
432 */
433 static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
434 {
435 bool responder_spi_set;
436 bool initiator_spi_set;
437 bool original_initiator;
438 ike_sa_t *ike_sa = NULL;
439
440 this->logger->log(this->logger, CONTROL|LEVEL2,
441 "checkout IKE_SA %llx:%llx, role %s",
442 ike_sa_id->get_initiator_spi(ike_sa_id),
443 ike_sa_id->get_responder_spi(ike_sa_id),
444 ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
445
446 this->logger->log(this->logger, CONTROL|LEVEL2, "%d IKE_SAs in manager",
447 this->ike_sa_list->get_count(this->ike_sa_list));
448
449 /* each access is locked */
450 pthread_mutex_lock(&(this->mutex));
451
452 responder_spi_set = ike_sa_id->get_responder_spi(ike_sa_id);
453 initiator_spi_set = ike_sa_id->get_initiator_spi(ike_sa_id);
454 original_initiator = ike_sa_id->is_initiator(ike_sa_id);
455
456 if ((initiator_spi_set && responder_spi_set) ||
457 ((initiator_spi_set && !responder_spi_set) && (original_initiator)))
458 {
459 /* we SHOULD have an IKE_SA for these SPIs in the list,
460 * if not, we can't handle the request...
461 */
462 ike_sa_entry_t *entry;
463 /* look for the entry */
464 if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
465 {
466 if (wait_for_entry(this, entry))
467 {
468 this->logger->log(this->logger, CONTROL|LEVEL2,
469 "IKE_SA successfully checked out");
470 /* ok, this IKE_SA is finally ours */
471 entry->checked_out = TRUE;
472 ike_sa = entry->ike_sa;
473 }
474 else
475 {
476 this->logger->log(this->logger, CONTROL|LEVEL2,
477 "IKE_SA found, but not allowed to check it out");
478 }
479 }
480 else
481 {
482 this->logger->log(this->logger, ERROR|LEVEL1,
483 "IKE_SA not stored in list");
484 /* looks like there is no such IKE_SA, better luck next time... */
485 }
486 }
487 else if ((initiator_spi_set && !responder_spi_set) && (!original_initiator))
488 {
489 /* an IKE_SA_INIT from an another endpoint,
490 * he is the initiator.
491 * For simplicity, we do NOT check for retransmitted
492 * IKE_SA_INIT-Requests here, so EVERY single IKE_SA_INIT-
493 * Request (even a retransmitted one) will result in a
494 * IKE_SA. This could be improved...
495 */
496 u_int64_t responder_spi;
497 ike_sa_entry_t *new_ike_sa_entry;
498
499 /* set SPIs, we are the responder */
500 responder_spi = get_next_spi(this);
501
502 /* we also set arguments spi, so its still valid */
503 ike_sa_id->set_responder_spi(ike_sa_id, responder_spi);
504
505 /* create entry */
506 new_ike_sa_entry = ike_sa_entry_create(ike_sa_id);
507
508 this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry);
509
510 /* check ike_sa out */
511 this->logger->log(this->logger, CONTROL|LEVEL1,
512 "IKE_SA added to list of known IKE_SAs");
513 new_ike_sa_entry->checked_out = TRUE;
514 ike_sa = new_ike_sa_entry->ike_sa;
515 }
516 else if (!initiator_spi_set && !responder_spi_set && original_initiator)
517 {
518 /* checkout of a new and unused IKE_SA, used for rekeying */
519 ike_sa_entry_t *new_ike_sa_entry;
520
521 ike_sa_id->set_initiator_spi(ike_sa_id, get_next_spi(this));
522 /* create entry */
523 new_ike_sa_entry = ike_sa_entry_create(ike_sa_id);
524 this->logger->log(this->logger, CONTROL|LEVEL2,
525 "created IKE_SA %llx:%llx, role %s",
526 ike_sa_id->get_initiator_spi(ike_sa_id),
527 ike_sa_id->get_responder_spi(ike_sa_id),
528 ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
529
530 this->ike_sa_list->insert_last(this->ike_sa_list, new_ike_sa_entry);
531
532 /* check ike_sa out */
533 new_ike_sa_entry->checked_out = TRUE;
534 ike_sa = new_ike_sa_entry->ike_sa;
535 }
536 else
537 {
538 /* responder set, initiator not: here is something seriously wrong! */
539 this->logger->log(this->logger, ERROR|LEVEL1, "invalid IKE_SA SPIs");
540 }
541
542 pthread_mutex_unlock(&(this->mutex));
543 return ike_sa;
544 }
545
546 /**
547 * Implementation of of ike_sa_manager.checkout_by_child.
548 */
549 static ike_sa_t* checkout_by_child(private_ike_sa_manager_t *this,
550 u_int32_t reqid)
551 {
552 iterator_t *iterator;
553 ike_sa_t *ike_sa = NULL;
554
555 pthread_mutex_lock(&(this->mutex));
556
557 iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
558 while (iterator->has_next(iterator))
559 {
560 ike_sa_entry_t *entry;
561
562 iterator->current(iterator, (void**)&entry);
563 if (wait_for_entry(this, entry))
564 {
565 /* ok, access is exclusive for us, check for child */
566 if (entry->ike_sa->has_child_sa(entry->ike_sa, reqid))
567 {
568 /* match */
569 entry->checked_out = TRUE;
570 ike_sa = entry->ike_sa;
571 break;
572 }
573 }
574 }
575 iterator->destroy(iterator);
576 pthread_mutex_unlock(&(this->mutex));
577
578 return ike_sa;
579 }
580
581 /**
582 * Implementation of ike_sa_manager_t.get_ike_sa_list.
583 */
584 static linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this)
585 {
586 linked_list_t *list;
587 iterator_t *iterator;
588
589 pthread_mutex_lock(&(this->mutex));
590
591 list = linked_list_create();
592 iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
593 while (iterator->has_next(iterator))
594 {
595 ike_sa_entry_t *entry;
596 iterator->current(iterator, (void**)&entry);
597 list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id));
598 }
599 iterator->destroy(iterator);
600
601 pthread_mutex_unlock(&(this->mutex));
602 return list;
603 }
604
605 /**
606 * Implementation of ike_sa_manager_t.log_status.
607 */
608 static void log_status(private_ike_sa_manager_t* this, logger_t* logger, char* name)
609 {
610 iterator_t *iterator;
611 u_int instances;
612
613 pthread_mutex_lock(&(this->mutex));
614
615 instances = this->ike_sa_list->get_count(this->ike_sa_list);
616 if (instances)
617 {
618 logger->log(logger, CONTROL, "Instances (%d):", instances);
619 }
620 iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
621 while (iterator->has_next(iterator))
622 {
623 ike_sa_entry_t *entry;
624
625 iterator->current(iterator, (void**)&entry);
626 if (wait_for_entry(this, entry))
627 {
628 entry->ike_sa->log_status(entry->ike_sa, logger, name);
629 }
630 }
631 iterator->destroy(iterator);
632
633 pthread_mutex_unlock(&(this->mutex));
634 }
635
636 /**
637 * Implementation of ike_sa_manager_t.checkin.
638 */
639 static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
640 {
641 /* to check the SA back in, we look for the pointer of the ike_sa
642 * in all entries.
643 * We can't search by SPI's since the MAY have changed (e.g. on reception
644 * of a IKE_SA_INIT response). Updating of the SPI MAY be necessary...
645 */
646 status_t retval;
647 ike_sa_entry_t *entry;
648 ike_sa_id_t *ike_sa_id;
649
650 ike_sa_id = ike_sa->get_id(ike_sa);
651
652 this->logger->log(this->logger, CONTROL|LEVEL2,
653 "checkin IKE_SA %llx:%llx, role %s",
654 ike_sa_id->get_initiator_spi(ike_sa_id),
655 ike_sa_id->get_responder_spi(ike_sa_id),
656 ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
657
658 pthread_mutex_lock(&(this->mutex));
659
660 /* look for the entry */
661 if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
662 {
663 /* ike_sa_id must be updated */
664 entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
665 /* signal waiting threads */
666 entry->checked_out = FALSE;
667 this->logger->log(this->logger, CONTROL|LEVEL1, "check-in of IKE_SA successful.");
668 pthread_cond_signal(&(entry->condvar));
669 retval = SUCCESS;
670 }
671 else
672 {
673 this->logger->log(this->logger, ERROR,
674 "tried to check in nonexisting IKE_SA");
675 /* this SA is no more, this REALLY should not happen */
676 retval = NOT_FOUND;
677 }
678
679 this->logger->log(this->logger, CONTROL|LEVEL2, "%d IKE_SAs in manager now",
680 this->ike_sa_list->get_count(this->ike_sa_list));
681 pthread_mutex_unlock(&(this->mutex));
682 return retval;
683 }
684
685
686 /**
687 * Implementation of ike_sa_manager_t.checkin_and_destroy.
688 */
689 static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
690 {
691 /* deletion is a bit complex, we must garant that no thread is waiting for
692 * this SA.
693 * We take this SA from the list, and start signaling while threads
694 * are in the condvar.
695 */
696 ike_sa_entry_t *entry;
697 status_t retval;
698 ike_sa_id_t *ike_sa_id;
699
700 ike_sa_id = ike_sa->get_id(ike_sa);
701 this->logger->log(this->logger, CONTROL|LEVEL2,
702 "checkin and destroy IKE_SA %llx:%llx, role %s",
703 ike_sa_id->get_initiator_spi(ike_sa_id),
704 ike_sa_id->get_responder_spi(ike_sa_id),
705 ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
706
707 pthread_mutex_lock(&(this->mutex));
708
709 if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
710 {
711 /* drive out waiting threads, as we are in hurry */
712 entry->driveout_waiting_threads = TRUE;
713
714 delete_entry(this, entry);
715
716 this->logger->log(this->logger, CONTROL|LEVEL1,
717 "check-in and destroy of IKE_SA successful");
718 retval = SUCCESS;
719 }
720 else
721 {
722 this->logger->log(this->logger,ERROR,
723 "tried to check-in and delete nonexisting IKE_SA");
724 retval = NOT_FOUND;
725 }
726
727 pthread_mutex_unlock(&(this->mutex));
728 return retval;
729 }
730
731 /**
732 * Implementation of ike_sa_manager_t.delete.
733 */
734 static status_t delete_(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
735 {
736 /* deletion is a bit complex, we must garant that no thread is waiting for
737 * this SA.
738 * We take this SA from the list, and start signaling while threads
739 * are in the condvar.
740 */
741 ike_sa_entry_t *entry;
742 status_t retval;
743
744 this->logger->log(this->logger, CONTROL|LEVEL2,
745 "delete IKE_SA %llx:%llx, role %s",
746 ike_sa_id->get_initiator_spi(ike_sa_id),
747 ike_sa_id->get_responder_spi(ike_sa_id),
748 ike_sa_id->is_initiator(ike_sa_id) ? "initiator" : "responder");
749
750 pthread_mutex_lock(&(this->mutex));
751
752 if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
753 {
754 /* we try a delete. If it succeeds, our job is done here. The
755 * other peer will reply, and the IKE SA gets the finally deleted...
756 */
757 if (entry->ike_sa->delete(entry->ike_sa) == SUCCESS)
758 {
759 this->logger->log(this->logger, CONTROL|LEVEL1,
760 "initiated delete for IKE_SA");
761 }
762 /* but if the IKE SA is not in a state where the deletion is
763 * negotiated with the other peer, we can destroy the IKE SA on our own.
764 */
765 else
766 {
767
768 }
769 retval = SUCCESS;
770 }
771 else
772 {
773 this->logger->log(this->logger,ERROR|LEVEL1,
774 "tried to delete nonexisting IKE_SA");
775 retval = NOT_FOUND;
776 }
777
778 pthread_mutex_unlock(&(this->mutex));
779 return retval;
780 }
781
782 /**
783 * Implementation of ike_sa_manager_t.delete_by_name.
784 */
785 static status_t delete_by_name(private_ike_sa_manager_t *this, char *name)
786 {
787 iterator_t *iterator;
788 iterator_t *child_iter;
789 ike_sa_entry_t *entry;
790 size_t name_len = strlen(name);
791
792 pthread_mutex_lock(&(this->mutex));
793
794 iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
795 while (iterator->iterate(iterator, (void**)&entry))
796 {
797 if (wait_for_entry(this, entry))
798 {
799 /* delete ike_sa if:
800 * name{x} matches completely
801 * name{} matches by name
802 * name matches by name
803 */
804 bool del = FALSE;
805 char *ike_name;
806 char *child_name;
807 child_sa_t *child_sa;
808
809 ike_name = entry->ike_sa->get_name(entry->ike_sa);
810 /* check if "name{x}" matches completely */
811 if (strcmp(name, ike_name) == 0)
812 {
813 del = TRUE;
814 }
815 /* check if name is in form of "name{}" and matches to ike_name */
816 else if (name_len > 1 &&
817 name[name_len - 2] == '{' && name[name_len - 1] == '}' &&
818 strlen(ike_name) > name_len &&
819 ike_name[name_len - 2] == '{' &&
820 strncmp(name, ike_name, name_len - 2) == 0)
821 {
822 del = TRUE;
823 }
824 /* finally, check if name is "name" and matches ike_name */
825 else if (name_len == strchr(ike_name, '{') - ike_name &&
826 strncmp(name, ike_name, name_len) == 0)
827 {
828 del = TRUE;
829 }
830
831 if (del)
832 {
833 if (entry->ike_sa->delete(entry->ike_sa) == DESTROY_ME)
834 {
835 delete_entry(this, entry);
836 iterator->reset(iterator);
837 }
838 /* no need to check children, as we delete all */
839 continue;
840 }
841
842 /* and now the same game for all children. delete child_sa if:
843 * name[x] matches completely
844 * name[] matches by name
845 * name matches by name
846 */
847 child_iter = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
848 while (child_iter->iterate(child_iter, (void**)&child_sa))
849 {
850 /* skip ROUTED children, they have their "unroute" command */
851 if (child_sa->get_state(child_sa) == CHILD_ROUTED)
852 {
853 continue;
854 }
855
856 child_name = child_sa->get_name(child_sa);
857 del = FALSE;
858 /* check if "name[x]" matches completely */
859 if (strcmp(name, child_name) == 0)
860 {
861 del = TRUE;
862 }
863 /* check if name is in form of "name[]" and matches to child_name */
864 else if (name_len > 1 &&
865 name[name_len - 2] == '[' && name[name_len - 1] == ']' &&
866 strlen(child_name) > name_len &&
867 child_name[name_len - 2] == '[' &&
868 strncmp(name, child_name, name_len - 2) == 0)
869 {
870 del = TRUE;
871 }
872 /* finally, check if name is "name" and matches child_name */
873 else if (name_len == strchr(child_name, '[') - child_name &&
874 strncmp(name, child_name, name_len) == 0)
875 {
876 del = TRUE;
877 }
878 if (del)
879 {
880 if (entry->ike_sa->delete_child_sa(entry->ike_sa,
881 child_sa->get_protocol(child_sa),
882 child_sa->get_spi(child_sa, TRUE)) == DESTROY_ME)
883 {
884 /* when a fatal error occurs, we are responsible to
885 * remove the IKE_SA */
886 delete_entry(this, entry);
887 iterator->reset(iterator);
888 break;
889 }
890 }
891 }
892 child_iter->destroy(child_iter);
893 }
894 }
895 iterator->destroy(iterator);
896 pthread_mutex_unlock(&(this->mutex));
897
898 return SUCCESS;
899 }
900
901 /**
902 * Implementation of ike_sa_manager_t.destroy.
903 */
904 static void destroy(private_ike_sa_manager_t *this)
905 {
906 /* destroy all list entries */
907 linked_list_t *list = this->ike_sa_list;
908 iterator_t *iterator;
909 ike_sa_entry_t *entry;
910
911 pthread_mutex_lock(&(this->mutex));
912 this->logger->log(this->logger, CONTROL|LEVEL1,
913 "going to destroy IKE_SA manager and all managed IKE_SA's");
914 /* Step 1: drive out all waiting threads */
915 this->logger->log(this->logger, CONTROL|LEVEL2,
916 "set driveout flags for all stored IKE_SA's");
917 iterator = list->create_iterator(list, TRUE);
918 while (iterator->has_next(iterator))
919 {
920 iterator->current(iterator, (void**)&entry);
921 /* do not accept new threads, drive out waiting threads */
922 entry->driveout_new_threads = TRUE;
923 entry->driveout_waiting_threads = TRUE;
924 }
925 this->logger->log(this->logger, CONTROL|LEVEL2,
926 "wait for all threads to leave IKE_SA's");
927 /* Step 2: wait until all are gone */
928 iterator->reset(iterator);
929 while (iterator->has_next(iterator))
930 {
931 iterator->current(iterator, (void**)&entry);
932 while (entry->waiting_threads)
933 {
934 /* wake up all */
935 pthread_cond_broadcast(&(entry->condvar));
936 /* go sleeping until they are gone */
937 pthread_cond_wait(&(entry->condvar), &(this->mutex));
938 }
939 }
940 this->logger->log(this->logger, CONTROL|LEVEL2, "delete all IKE_SA's");
941 /* Step 3: initiate deletion of all IKE_SAs */
942 iterator->reset(iterator);
943 while (iterator->has_next(iterator))
944 {
945 iterator->current(iterator, (void**)&entry);
946 entry->ike_sa->delete(entry->ike_sa);
947 }
948 iterator->destroy(iterator);
949
950 this->logger->log(this->logger, CONTROL|LEVEL2, "destroy all entries");
951 /* Step 4: destroy all entries */
952 while (list->remove_last(list, (void**)&entry) == SUCCESS)
953 {
954 entry->destroy(entry);
955 }
956 list->destroy(list);
957 pthread_mutex_unlock(&(this->mutex));
958
959 this->randomizer->destroy(this->randomizer);
960
961 free(this);
962 }
963
964 /*
965 * Described in header.
966 */
967 ike_sa_manager_t *ike_sa_manager_create()
968 {
969 private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t);
970
971 /* assign public functions */
972 this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
973 this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,host_t*,host_t*,identification_t*,identification_t*))checkout_by_id;
974 this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
975 this->public.checkout_by_child = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t))checkout_by_child;
976 this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list;
977 this->public.log_status = (void(*)(ike_sa_manager_t*,logger_t*,char*))log_status;
978 this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
979 this->public.delete = (status_t(*)(ike_sa_manager_t*,ike_sa_id_t*))delete_;
980 this->public.delete_by_name = (status_t(*)(ike_sa_manager_t*,char*))delete_by_name;
981 this->public.checkin_and_destroy = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
982
983 /* initialize private variables */
984 this->logger = logger_manager->get_logger(logger_manager, IKE_SA_MANAGER);
985
986 this->ike_sa_list = linked_list_create();
987
988 pthread_mutex_init(&(this->mutex), NULL);
989
990 this->randomizer = randomizer_create();
991
992 return (ike_sa_manager_t*)this;
993 }