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