using a entry cache for duplicate checks, avoids deadlocks
[strongswan.git] / src / charon / sa / ike_sa_manager.c
1 /*
2 * Copyright (C) 2005-2006 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
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 * $Id$
17 */
18
19 #include <pthread.h>
20 #include <string.h>
21
22 #include "ike_sa_manager.h"
23
24 #include <daemon.h>
25 #include <sa/ike_sa_id.h>
26 #include <bus/bus.h>
27 #include <utils/linked_list.h>
28 #include <crypto/hashers/hasher.h>
29
30 typedef struct entry_t entry_t;
31
32 /**
33 * An entry in the linked list, contains IKE_SA, locking and lookup data.
34 */
35 struct entry_t {
36
37 /**
38 * Number of threads waiting for this ike_sa_t object.
39 */
40 int waiting_threads;
41
42 /**
43 * Condvar where threads can wait until ike_sa_t object is free for use again.
44 */
45 pthread_cond_t condvar;
46
47 /**
48 * Is this ike_sa currently checked out?
49 */
50 bool checked_out;
51
52 /**
53 * Does this SA drives out new threads?
54 */
55 bool driveout_new_threads;
56
57 /**
58 * Does this SA drives out waiting threads?
59 */
60 bool driveout_waiting_threads;
61
62 /**
63 * Identifiaction of an IKE_SA (SPIs).
64 */
65 ike_sa_id_t *ike_sa_id;
66
67 /**
68 * The contained ike_sa_t object.
69 */
70 ike_sa_t *ike_sa;
71
72 /**
73 * hash of the IKE_SA_INIT message, used to detect retransmissions
74 */
75 chunk_t init_hash;
76
77 /**
78 * remote host address, required for DoS detection
79 */
80 host_t *other;
81
82 /**
83 * own identity, required for duplicate checking
84 */
85 identification_t *my_id;
86
87 /**
88 * remote identity, required for duplicate checking
89 */
90 identification_t *other_id;
91
92 /**
93 * message ID currently processing, if any
94 */
95 u_int32_t message_id;
96 };
97
98 /**
99 * Implementation of entry_t.destroy.
100 */
101 static status_t entry_destroy(entry_t *this)
102 {
103 /* also destroy IKE SA */
104 this->ike_sa->destroy(this->ike_sa);
105 this->ike_sa_id->destroy(this->ike_sa_id);
106 chunk_free(&this->init_hash);
107 DESTROY_IF(this->other);
108 DESTROY_IF(this->my_id);
109 DESTROY_IF(this->other_id);
110 free(this);
111 return SUCCESS;
112 }
113
114 /**
115 * Creates a new entry for the ike_sa_t list.
116 */
117 static entry_t *entry_create(ike_sa_id_t *ike_sa_id)
118 {
119 entry_t *this = malloc_thing(entry_t);
120
121 this->waiting_threads = 0;
122 pthread_cond_init(&this->condvar, NULL);
123
124 /* we set checkout flag when we really give it out */
125 this->checked_out = FALSE;
126 this->driveout_new_threads = FALSE;
127 this->driveout_waiting_threads = FALSE;
128 this->message_id = -1;
129 this->init_hash = chunk_empty;
130 this->other = NULL;
131 this->my_id = NULL;
132 this->other_id = NULL;
133
134 /* ike_sa_id is always cloned */
135 this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
136
137 /* create new ike_sa */
138 this->ike_sa = ike_sa_create(ike_sa_id);
139
140 return this;
141 }
142
143
144 typedef struct private_ike_sa_manager_t private_ike_sa_manager_t;
145
146 /**
147 * Additional private members of ike_sa_manager_t.
148 */
149 struct private_ike_sa_manager_t {
150 /**
151 * Public interface of ike_sa_manager_t.
152 */
153 ike_sa_manager_t public;
154
155 /**
156 * Lock for exclusivly accessing the manager.
157 */
158 pthread_mutex_t mutex;
159
160 /**
161 * Linked list with entries for the ike_sa_t objects.
162 */
163 linked_list_t *ike_sa_list;
164
165 /**
166 * RNG to get random SPIs for our side
167 */
168 rng_t *rng;
169
170 /**
171 * SHA1 hasher for IKE_SA_INIT retransmit detection
172 */
173 hasher_t *hasher;
174
175 /**
176 * reuse existing IKE_SAs in checkout_by_config
177 */
178 bool reuse_ikesa;
179 };
180
181 /**
182 * Implementation of private_ike_sa_manager_t.get_entry_by_id.
183 */
184 static status_t get_entry_by_id(private_ike_sa_manager_t *this,
185 ike_sa_id_t *ike_sa_id, entry_t **entry)
186 {
187 enumerator_t *enumerator;
188 entry_t *current;
189 status_t status;
190
191 /* create enumerator over list of ike_sa's */
192 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
193
194 /* default status */
195 status = NOT_FOUND;
196
197 while (enumerator->enumerate(enumerator, &current))
198 {
199 if (current->ike_sa_id->equals(current->ike_sa_id, ike_sa_id))
200 {
201 DBG2(DBG_MGR, "found entry by both SPIs");
202 *entry = current;
203 status = SUCCESS;
204 break;
205 }
206 if (ike_sa_id->get_responder_spi(ike_sa_id) == 0 ||
207 current->ike_sa_id->get_responder_spi(current->ike_sa_id) == 0)
208 {
209 /* seems to be a half ready ike_sa */
210 if ((current->ike_sa_id->get_initiator_spi(current->ike_sa_id) ==
211 ike_sa_id->get_initiator_spi(ike_sa_id)) &&
212 (current->ike_sa_id->is_initiator(ike_sa_id) ==
213 ike_sa_id->is_initiator(current->ike_sa_id)))
214 {
215 DBG2(DBG_MGR, "found entry by initiator SPI");
216 *entry = current;
217 status = SUCCESS;
218 break;
219 }
220 }
221 }
222
223 enumerator->destroy(enumerator);
224 return status;
225 }
226
227 /**
228 * Implementation of private_ike_sa_manager_t.get_entry_by_sa.
229 */
230 static status_t get_entry_by_sa(private_ike_sa_manager_t *this,
231 ike_sa_t *ike_sa, entry_t **entry)
232 {
233 enumerator_t *enumerator;
234 entry_t *current;
235 status_t status;
236
237 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
238
239 /* default status */
240 status = NOT_FOUND;
241
242 while (enumerator->enumerate(enumerator, &current))
243 {
244 /* only pointers are compared */
245 if (current->ike_sa == ike_sa)
246 {
247 DBG2(DBG_MGR, "found entry by pointer");
248 *entry = current;
249 status = SUCCESS;
250 break;
251 }
252 }
253 enumerator->destroy(enumerator);
254
255 return status;
256 }
257
258 /**
259 * Implementation of private_ike_sa_manager_s.delete_entry.
260 */
261 static status_t delete_entry(private_ike_sa_manager_t *this, entry_t *entry)
262 {
263 enumerator_t *enumerator;
264 entry_t *current;
265 status_t status;
266
267 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
268
269 status = NOT_FOUND;
270
271 while (enumerator->enumerate(enumerator, &current))
272 {
273 if (current == entry)
274 {
275 /* mark it, so now new threads can get this entry */
276 entry->driveout_new_threads = TRUE;
277 /* wait until all workers have done their work */
278 while (entry->waiting_threads)
279 {
280 /* wake up all */
281 pthread_cond_broadcast(&(entry->condvar));
282 /* they will wake us again when their work is done */
283 pthread_cond_wait(&(entry->condvar), &(this->mutex));
284 }
285
286 DBG2(DBG_MGR, "found entry by pointer, deleting it");
287 this->ike_sa_list->remove_at(this->ike_sa_list, enumerator);
288 entry_destroy(entry);
289 status = SUCCESS;
290 break;
291 }
292 }
293 enumerator->destroy(enumerator);
294 return status;
295 }
296
297 /**
298 * Wait until no other thread is using an IKE_SA, return FALSE if entry not
299 * acquireable
300 */
301 static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry)
302 {
303 if (entry->driveout_new_threads)
304 {
305 /* we are not allowed to get this */
306 return FALSE;
307 }
308 while (entry->checked_out && !entry->driveout_waiting_threads)
309 {
310 /* so wait until we can get it for us.
311 * we register us as waiting. */
312 entry->waiting_threads++;
313 pthread_cond_wait(&(entry->condvar), &(this->mutex));
314 entry->waiting_threads--;
315 }
316 /* hm, a deletion request forbids us to get this SA, get next one */
317 if (entry->driveout_waiting_threads)
318 {
319 /* we must signal here, others may be waiting on it, too */
320 pthread_cond_signal(&(entry->condvar));
321 return FALSE;
322 }
323 return TRUE;
324 }
325
326 /**
327 * Implementation of private_ike_sa_manager_t.get_next_spi.
328 */
329 static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
330 {
331 u_int64_t spi;
332
333 this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi);
334 return spi;
335 }
336
337 /**
338 * Implementation of of ike_sa_manager.checkout.
339 */
340 static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
341 {
342 ike_sa_t *ike_sa = NULL;
343 entry_t *entry;
344
345 DBG2(DBG_MGR, "checkout IKE_SA, %d IKE_SAs in manager",
346 this->ike_sa_list->get_count(this->ike_sa_list));
347
348 pthread_mutex_lock(&(this->mutex));
349 if (get_entry_by_id(this, ike_sa_id, &entry) == SUCCESS)
350 {
351 if (wait_for_entry(this, entry))
352 {
353 DBG2(DBG_MGR, "IKE_SA successfully checked out");
354 entry->checked_out = TRUE;
355 ike_sa = entry->ike_sa;
356 }
357 }
358 pthread_mutex_unlock(&this->mutex);
359 charon->bus->set_sa(charon->bus, ike_sa);
360 return ike_sa;
361 }
362
363 /**
364 * Implementation of of ike_sa_manager.checkout_new.
365 */
366 static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
367 {
368 entry_t *entry;
369 ike_sa_id_t *id;
370
371 if (initiator)
372 {
373 id = ike_sa_id_create(get_next_spi(this), 0, TRUE);
374 }
375 else
376 {
377 id = ike_sa_id_create(0, get_next_spi(this), FALSE);
378 }
379 entry = entry_create(id);
380 id->destroy(id);
381 pthread_mutex_lock(&this->mutex);
382 this->ike_sa_list->insert_last(this->ike_sa_list, entry);
383 entry->checked_out = TRUE;
384 pthread_mutex_unlock(&this->mutex);
385 DBG2(DBG_MGR, "created IKE_SA, %d IKE_SAs in manager",
386 this->ike_sa_list->get_count(this->ike_sa_list));
387 return entry->ike_sa;
388 }
389
390 /**
391 * Implementation of of ike_sa_manager.checkout_by_message.
392 */
393 static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
394 message_t *message)
395 {
396 entry_t *entry;
397 ike_sa_t *ike_sa = NULL;
398 ike_sa_id_t *id = message->get_ike_sa_id(message);
399 id = id->clone(id);
400 id->switch_initiator(id);
401
402 DBG2(DBG_MGR, "checkout IKE_SA by message, %d IKE_SAs in manager",
403 this->ike_sa_list->get_count(this->ike_sa_list));
404
405 if (message->get_request(message) &&
406 message->get_exchange_type(message) == IKE_SA_INIT)
407 {
408 /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
409 enumerator_t *enumerator;
410 chunk_t data, hash;
411
412 data = message->get_packet_data(message);
413 this->hasher->allocate_hash(this->hasher, data, &hash);
414 chunk_free(&data);
415
416 pthread_mutex_lock(&this->mutex);
417 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
418 while (enumerator->enumerate(enumerator, &entry))
419 {
420 if (chunk_equals(hash, entry->init_hash))
421 {
422 if (entry->message_id == 0)
423 {
424 enumerator->destroy(enumerator);
425 pthread_mutex_unlock(&this->mutex);
426 chunk_free(&hash);
427 id->destroy(id);
428 DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing");
429 return NULL;
430 }
431 else if (wait_for_entry(this, entry))
432 {
433 DBG2(DBG_MGR, "IKE_SA checked out by hash");
434 entry->checked_out = TRUE;
435 entry->message_id = message->get_message_id(message);
436 ike_sa = entry->ike_sa;
437 }
438 break;
439 }
440 }
441 enumerator->destroy(enumerator);
442 pthread_mutex_unlock(&this->mutex);
443
444 if (ike_sa == NULL)
445 {
446 if (id->get_responder_spi(id) == 0 &&
447 message->get_exchange_type(message) == IKE_SA_INIT)
448 {
449 /* no IKE_SA found, create a new one */
450 id->set_responder_spi(id, get_next_spi(this));
451 entry = entry_create(id);
452
453 pthread_mutex_lock(&this->mutex);
454 this->ike_sa_list->insert_last(this->ike_sa_list, entry);
455 entry->checked_out = TRUE;
456 entry->message_id = message->get_message_id(message);
457 pthread_mutex_unlock(&this->mutex);
458 entry->init_hash = hash;
459 ike_sa = entry->ike_sa;
460 }
461 else
462 {
463 chunk_free(&hash);
464 DBG1(DBG_MGR, "ignoring message, no such IKE_SA");
465 }
466 }
467 else
468 {
469 chunk_free(&hash);
470 }
471 id->destroy(id);
472 charon->bus->set_sa(charon->bus, ike_sa);
473 return ike_sa;
474 }
475
476 pthread_mutex_lock(&(this->mutex));
477 if (get_entry_by_id(this, id, &entry) == SUCCESS)
478 {
479 /* only check out if we are not processing this request */
480 if (message->get_request(message) &&
481 message->get_message_id(message) == entry->message_id)
482 {
483 DBG1(DBG_MGR, "ignoring request with ID %d, already processing",
484 entry->message_id);
485 }
486 else if (wait_for_entry(this, entry))
487 {
488 ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
489 DBG2(DBG_MGR, "IKE_SA successfully checked out");
490 entry->checked_out = TRUE;
491 entry->message_id = message->get_message_id(message);
492 if (ike_id->get_responder_spi(ike_id) == 0)
493 {
494 ike_id->set_responder_spi(ike_id, id->get_responder_spi(id));
495 }
496 ike_sa = entry->ike_sa;
497 }
498 }
499 pthread_mutex_unlock(&this->mutex);
500 id->destroy(id);
501 charon->bus->set_sa(charon->bus, ike_sa);
502 return ike_sa;
503 }
504
505 /**
506 * Implementation of of ike_sa_manager.checkout_by_config.
507 */
508 static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
509 peer_cfg_t *peer_cfg)
510 {
511 enumerator_t *enumerator;
512 entry_t *entry;
513 ike_sa_t *ike_sa = NULL;
514 identification_t *my_id, *other_id;
515 host_t *my_host, *other_host;
516 ike_cfg_t *ike_cfg;
517
518 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
519 my_id = peer_cfg->get_my_id(peer_cfg);
520 other_id = peer_cfg->get_other_id(peer_cfg);
521 my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0);
522 other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0);
523
524 pthread_mutex_lock(&(this->mutex));
525
526 if (my_host && other_host && this->reuse_ikesa)
527 {
528 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
529 while (enumerator->enumerate(enumerator, &entry))
530 {
531 identification_t *found_my_id, *found_other_id;
532 host_t *found_my_host, *found_other_host;
533
534 if (!wait_for_entry(this, entry))
535 {
536 continue;
537 }
538
539 if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
540 {
541 /* skip IKE_SA which are not useable */
542 continue;
543 }
544
545 found_my_id = entry->ike_sa->get_my_id(entry->ike_sa);
546 found_other_id = entry->ike_sa->get_other_id(entry->ike_sa);
547 found_my_host = entry->ike_sa->get_my_host(entry->ike_sa);
548 found_other_host = entry->ike_sa->get_other_host(entry->ike_sa);
549
550 if (found_my_id->get_type(found_my_id) == ID_ANY &&
551 found_other_id->get_type(found_other_id) == ID_ANY)
552 {
553 /* IKE_SA has no IDs yet, so we can't use it */
554 continue;
555 }
556 DBG2(DBG_MGR, "candidate IKE_SA for \n\t"
557 "%H[%D]...%H[%D]\n\t%H[%D]...%H[%D]",
558 my_host, my_id, other_host, other_id,
559 found_my_host, found_my_id, found_other_host, found_other_id);
560 /* compare ID and hosts. Supplied ID may contain wildcards, and IP
561 * may be %any. */
562 if ((my_host->is_anyaddr(my_host) ||
563 my_host->ip_equals(my_host, found_my_host)) &&
564 (other_host->is_anyaddr(other_host) ||
565 other_host->ip_equals(other_host, found_other_host)) &&
566 found_my_id->matches(found_my_id, my_id) &&
567 found_other_id->matches(found_other_id, other_id) &&
568 streq(peer_cfg->get_name(peer_cfg),
569 entry->ike_sa->get_name(entry->ike_sa)))
570 {
571 /* looks good, we take this one */
572 DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]",
573 my_host, my_id, other_host, other_id);
574 entry->checked_out = TRUE;
575 ike_sa = entry->ike_sa;
576 break;
577 }
578 }
579 enumerator->destroy(enumerator);
580 }
581 DESTROY_IF(my_host);
582 DESTROY_IF(other_host);
583
584 if (!ike_sa)
585 {
586 u_int64_t initiator_spi;
587 entry_t *new_entry;
588 ike_sa_id_t *new_ike_sa_id;
589
590 initiator_spi = get_next_spi(this);
591 new_ike_sa_id = ike_sa_id_create(0, 0, TRUE);
592 new_ike_sa_id->set_initiator_spi(new_ike_sa_id, initiator_spi);
593
594 /* create entry */
595 new_entry = entry_create(new_ike_sa_id);
596 DBG2(DBG_MGR, "created IKE_SA");
597 new_ike_sa_id->destroy(new_ike_sa_id);
598
599 this->ike_sa_list->insert_last(this->ike_sa_list, new_entry);
600
601 /* check ike_sa out */
602 DBG2(DBG_MGR, "new IKE_SA created for IDs [%D]...[%D]", my_id, other_id);
603 new_entry->checked_out = TRUE;
604 ike_sa = new_entry->ike_sa;
605 }
606 pthread_mutex_unlock(&(this->mutex));
607 charon->bus->set_sa(charon->bus, ike_sa);
608 return ike_sa;
609 }
610
611 /**
612 * Implementation of of ike_sa_manager.checkout_by_id.
613 */
614 static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
615 bool child)
616 {
617 enumerator_t *enumerator;
618 iterator_t *children;
619 entry_t *entry;
620 ike_sa_t *ike_sa = NULL;
621 child_sa_t *child_sa;
622
623 pthread_mutex_lock(&(this->mutex));
624
625 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
626 while (enumerator->enumerate(enumerator, &entry))
627 {
628 if (wait_for_entry(this, entry))
629 {
630 /* look for a child with such a reqid ... */
631 if (child)
632 {
633 children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
634 while (children->iterate(children, (void**)&child_sa))
635 {
636 if (child_sa->get_reqid(child_sa) == id)
637 {
638 ike_sa = entry->ike_sa;
639 break;
640 }
641 }
642 children->destroy(children);
643 }
644 else /* ... or for a IKE_SA with such a unique id */
645 {
646 if (entry->ike_sa->get_unique_id(entry->ike_sa) == id)
647 {
648 ike_sa = entry->ike_sa;
649 }
650 }
651 /* got one, return */
652 if (ike_sa)
653 {
654 entry->checked_out = TRUE;
655 break;
656 }
657 }
658 }
659 enumerator->destroy(enumerator);
660 pthread_mutex_unlock(&(this->mutex));
661
662 charon->bus->set_sa(charon->bus, ike_sa);
663 return ike_sa;
664 }
665
666 /**
667 * Implementation of of ike_sa_manager.checkout_by_name.
668 */
669 static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
670 bool child)
671 {
672 enumerator_t *enumerator;
673 iterator_t *children;
674 entry_t *entry;
675 ike_sa_t *ike_sa = NULL;
676 child_sa_t *child_sa;
677
678 pthread_mutex_lock(&(this->mutex));
679
680 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
681 while (enumerator->enumerate(enumerator, &entry))
682 {
683 if (wait_for_entry(this, entry))
684 {
685 /* look for a child with such a policy name ... */
686 if (child)
687 {
688 children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
689 while (children->iterate(children, (void**)&child_sa))
690 {
691 if (streq(child_sa->get_name(child_sa), name))
692 {
693 ike_sa = entry->ike_sa;
694 break;
695 }
696 }
697 children->destroy(children);
698 }
699 else /* ... or for a IKE_SA with such a connection name */
700 {
701 if (streq(entry->ike_sa->get_name(entry->ike_sa), name))
702 {
703 ike_sa = entry->ike_sa;
704 }
705 }
706 /* got one, return */
707 if (ike_sa)
708 {
709 entry->checked_out = TRUE;
710 break;
711 }
712 }
713 }
714 enumerator->destroy(enumerator);
715 pthread_mutex_unlock(&(this->mutex));
716
717 charon->bus->set_sa(charon->bus, ike_sa);
718 return ike_sa;
719 }
720
721 /**
722 * Implementation of ike_sa_manager_t.checkout_duplicate.
723 */
724 static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
725 ike_sa_t *ike_sa)
726 {
727 enumerator_t *enumerator;
728 entry_t *entry;
729 ike_sa_t *duplicate = NULL;
730 identification_t *me, *other;
731
732 me = ike_sa->get_my_id(ike_sa);
733 other = ike_sa->get_other_id(ike_sa);
734
735 pthread_mutex_lock(&this->mutex);
736 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
737 while (enumerator->enumerate(enumerator, &entry))
738 {
739 if (entry->ike_sa == ike_sa)
740 { /* self is not a duplicate */
741 continue;
742 }
743 if (entry->my_id && me->equals(me, entry->my_id) &&
744 entry->other_id && other->equals(other, entry->other_id))
745 {
746 /* we are sure that the other entry is not calling
747 * checkout_duplicate here, as the identities in entry would not
748 * have been set yet. Otherwise we would risk a deadlock. */
749 if (wait_for_entry(this, entry))
750 {
751 duplicate = entry->ike_sa;
752 entry->checked_out = TRUE;
753 break;
754 }
755 }
756 }
757 enumerator->destroy(enumerator);
758 pthread_mutex_unlock(&this->mutex);
759 return duplicate;
760 }
761
762 /**
763 * enumerator cleanup function
764 */
765 static void enumerator_unlock(private_ike_sa_manager_t *this)
766 {
767 pthread_mutex_unlock(&this->mutex);
768 }
769
770 /**
771 * enumerator filter function
772 */
773 static bool enumerator_filter(private_ike_sa_manager_t *this,
774 entry_t **in, ike_sa_t **out)
775 {
776 if (wait_for_entry(this, *in))
777 {
778 *out = (*in)->ike_sa;
779 return TRUE;
780 }
781 return FALSE;
782 }
783
784 /**
785 * Implementation of ike_sa_manager_t.create_iterator.
786 */
787 static enumerator_t *create_enumerator(private_ike_sa_manager_t* this)
788 {
789 pthread_mutex_lock(&this->mutex);
790 return enumerator_create_filter(
791 this->ike_sa_list->create_enumerator(this->ike_sa_list),
792 (void*)enumerator_filter, this, (void*)enumerator_unlock);
793 }
794
795 /**
796 * Implementation of ike_sa_manager_t.checkin.
797 */
798 static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
799 {
800 /* to check the SA back in, we look for the pointer of the ike_sa
801 * in all entries.
802 * We can't search by SPI's since the MAY have changed (e.g. on reception
803 * of a IKE_SA_INIT response). Updating of the SPI MAY be necessary...
804 */
805 status_t retval;
806 entry_t *entry;
807 ike_sa_id_t *ike_sa_id;
808 host_t *other;
809 identification_t *my_id, *other_id;
810
811 ike_sa_id = ike_sa->get_id(ike_sa);
812
813 DBG2(DBG_MGR, "checkin IKE_SA");
814
815 pthread_mutex_lock(&(this->mutex));
816
817 /* look for the entry */
818 if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
819 {
820 /* ike_sa_id must be updated */
821 entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
822 /* signal waiting threads */
823 entry->checked_out = FALSE;
824 entry->message_id = -1;
825 /* apply remote address for DoS detection */
826 other = ike_sa->get_other_host(ike_sa);
827 if (!entry->other || !other->equals(other, entry->other))
828 {
829 DESTROY_IF(entry->other);
830 entry->other = other->clone(other);
831 }
832 /* apply identities for diplicate test */
833 my_id = ike_sa->get_my_id(ike_sa);
834 other_id = ike_sa->get_other_id(ike_sa);
835 if (!entry->my_id ||
836 entry->my_id->get_type(entry->my_id) == ID_ANY)
837 {
838 DESTROY_IF(entry->my_id);
839 entry->my_id = my_id->clone(my_id);
840 }
841 if (!entry->other_id ||
842 entry->other_id->get_type(entry->other_id) == ID_ANY)
843 {
844 DESTROY_IF(entry->other_id);
845 entry->other_id = other_id->clone(other_id);
846 }
847 DBG2(DBG_MGR, "check-in of IKE_SA successful.");
848 pthread_cond_signal(&(entry->condvar));
849 retval = SUCCESS;
850 }
851 else
852 {
853 DBG2(DBG_MGR, "tried to check in nonexisting IKE_SA");
854 /* this SA is no more, this REALLY should not happen */
855 retval = NOT_FOUND;
856 }
857
858 DBG2(DBG_MGR, "%d IKE_SAs in manager now",
859 this->ike_sa_list->get_count(this->ike_sa_list));
860 pthread_mutex_unlock(&(this->mutex));
861
862 charon->bus->set_sa(charon->bus, NULL);
863 return retval;
864 }
865
866
867 /**
868 * Implementation of ike_sa_manager_t.checkin_and_destroy.
869 */
870 static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
871 {
872 /* deletion is a bit complex, we must garant that no thread is waiting for
873 * this SA.
874 * We take this SA from the list, and start signaling while threads
875 * are in the condvar.
876 */
877 entry_t *entry;
878 status_t retval;
879 ike_sa_id_t *ike_sa_id;
880
881 ike_sa_id = ike_sa->get_id(ike_sa);
882 DBG2(DBG_MGR, "checkin and destroy IKE_SA");
883 charon->bus->set_sa(charon->bus, NULL);
884
885 pthread_mutex_lock(&(this->mutex));
886
887 if (get_entry_by_sa(this, ike_sa, &entry) == SUCCESS)
888 {
889 /* drive out waiting threads, as we are in hurry */
890 entry->driveout_waiting_threads = TRUE;
891
892 delete_entry(this, entry);
893
894 DBG2(DBG_MGR, "check-in and destroy of IKE_SA successful");
895 retval = SUCCESS;
896 }
897 else
898 {
899 DBG2(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
900 retval = NOT_FOUND;
901 }
902
903 pthread_mutex_unlock(&(this->mutex));
904 return retval;
905 }
906
907 /**
908 * Implementation of ike_sa_manager_t.get_half_open_count.
909 */
910 static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
911 {
912 enumerator_t *enumerator;
913 entry_t *entry;
914 int count = 0;
915
916 pthread_mutex_lock(&(this->mutex));
917 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
918 while (enumerator->enumerate(enumerator, &entry))
919 {
920 /* we check if we have a responder CONNECTING IKE_SA without checkout */
921 if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
922 entry->ike_sa->get_state(entry->ike_sa) == IKE_CONNECTING)
923 {
924 /* if we have a host, count only matching IKE_SAs */
925 if (ip)
926 {
927 if (entry->other && ip->ip_equals(ip, entry->other))
928 {
929 count++;
930 }
931 }
932 else
933 {
934 count++;
935 }
936 }
937 }
938 enumerator->destroy(enumerator);
939
940 pthread_mutex_unlock(&(this->mutex));
941 return count;
942 }
943
944 /**
945 * Implementation of ike_sa_manager_t.flush.
946 */
947 static void flush(private_ike_sa_manager_t *this)
948 {
949 /* destroy all list entries */
950 enumerator_t *enumerator;
951 entry_t *entry;
952
953 pthread_mutex_lock(&(this->mutex));
954 DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's");
955 /* Step 1: drive out all waiting threads */
956 DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's");
957 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
958 while (enumerator->enumerate(enumerator, &entry))
959 {
960 /* do not accept new threads, drive out waiting threads */
961 entry->driveout_new_threads = TRUE;
962 entry->driveout_waiting_threads = TRUE;
963 }
964 enumerator->destroy(enumerator);
965 DBG2(DBG_MGR, "wait for all threads to leave IKE_SA's");
966 /* Step 2: wait until all are gone */
967 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
968 while (enumerator->enumerate(enumerator, &entry))
969 {
970 while (entry->waiting_threads)
971 {
972 /* wake up all */
973 pthread_cond_broadcast(&(entry->condvar));
974 /* go sleeping until they are gone */
975 pthread_cond_wait(&(entry->condvar), &(this->mutex));
976 }
977 }
978 enumerator->destroy(enumerator);
979 DBG2(DBG_MGR, "delete all IKE_SA's");
980 /* Step 3: initiate deletion of all IKE_SAs */
981 enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
982 while (enumerator->enumerate(enumerator, &entry))
983 {
984 entry->ike_sa->delete(entry->ike_sa);
985 }
986 enumerator->destroy(enumerator);
987
988 DBG2(DBG_MGR, "destroy all entries");
989 /* Step 4: destroy all entries */
990 while (this->ike_sa_list->remove_last(this->ike_sa_list,
991 (void**)&entry) == SUCCESS)
992 {
993 entry_destroy(entry);
994 }
995 pthread_mutex_unlock(&(this->mutex));
996 }
997
998 /**
999 * Implementation of ike_sa_manager_t.destroy.
1000 */
1001 static void destroy(private_ike_sa_manager_t *this)
1002 {
1003 this->ike_sa_list->destroy(this->ike_sa_list);
1004 this->rng->destroy(this->rng);
1005 this->hasher->destroy(this->hasher);
1006
1007 free(this);
1008 }
1009
1010 /*
1011 * Described in header.
1012 */
1013 ike_sa_manager_t *ike_sa_manager_create()
1014 {
1015 private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t);
1016
1017 /* assign public functions */
1018 this->public.flush = (void(*)(ike_sa_manager_t*))flush;
1019 this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
1020 this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
1021 this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new;
1022 this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message;
1023 this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config;
1024 this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
1025 this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
1026 this->public.checkout_duplicate = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))checkout_duplicate;
1027 this->public.create_enumerator = (enumerator_t*(*)(ike_sa_manager_t*))create_enumerator;
1028 this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
1029 this->public.checkin_and_destroy = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
1030 this->public.get_half_open_count = (int(*)(ike_sa_manager_t*,host_t*))get_half_open_count;
1031
1032 /* initialize private variables */
1033 this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
1034 if (this->hasher == NULL)
1035 {
1036 DBG1(DBG_MGR, "manager initialization failed, no hasher supported");
1037 free(this);
1038 return NULL;
1039 }
1040 this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
1041 if (this->rng == NULL)
1042 {
1043 DBG1(DBG_MGR, "manager initialization failed, no RNG supported");
1044 this->hasher->destroy(this->hasher);
1045 free(this);
1046 return NULL;
1047 }
1048 this->ike_sa_list = linked_list_create();
1049 pthread_mutex_init(&this->mutex, NULL);
1050 this->reuse_ikesa = lib->settings->get_bool(lib->settings,
1051 "charon.reuse_ikesa", TRUE);
1052 return &this->public;
1053 }
1054