fixing checkout of IKE SAs with only the initiator SPI
[strongswan.git] / src / charon / sa / ike_sa_manager.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 * $Id$
18 */
19
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/mutex.h>
28 #include <utils/linked_list.h>
29 #include <crypto/hashers/hasher.h>
30
31 /* the default size of the hash table (MUST be a power of 2) */
32 #define DEFAULT_HASHTABLE_SIZE 1
33
34 /* the maximum size of the hash table (MUST be a power of 2) */
35 #define MAX_HASHTABLE_SIZE (1 << 30)
36
37 /* the default number of segments (MUST be a power of 2) */
38 #define DEFAULT_SEGMENT_COUNT 1
39
40 typedef struct entry_t entry_t;
41
42 /**
43 * An entry in the linked list, contains IKE_SA, locking and lookup data.
44 */
45 struct entry_t {
46
47 /**
48 * Number of threads waiting for this ike_sa_t object.
49 */
50 int waiting_threads;
51
52 /**
53 * Condvar where threads can wait until ike_sa_t object is free for use again.
54 */
55 condvar_t *condvar;
56
57 /**
58 * Is this ike_sa currently checked out?
59 */
60 bool checked_out;
61
62 /**
63 * Does this SA drives out new threads?
64 */
65 bool driveout_new_threads;
66
67 /**
68 * Does this SA drives out waiting threads?
69 */
70 bool driveout_waiting_threads;
71
72 /**
73 * Identification of an IKE_SA (SPIs).
74 */
75 ike_sa_id_t *ike_sa_id;
76
77 /**
78 * The contained ike_sa_t object.
79 */
80 ike_sa_t *ike_sa;
81
82 /**
83 * hash of the IKE_SA_INIT message, used to detect retransmissions
84 */
85 chunk_t init_hash;
86
87 /**
88 * remote host address, required for DoS detection
89 */
90 host_t *other;
91
92 /**
93 * As responder: Is this SA half-open?
94 */
95 bool half_open;
96
97 /**
98 * own identity, required for duplicate checking
99 */
100 identification_t *my_id;
101
102 /**
103 * remote identity, required for duplicate checking
104 */
105 identification_t *other_id;
106
107 /**
108 * message ID currently processing, if any
109 */
110 u_int32_t message_id;
111 };
112
113 /**
114 * Implementation of entry_t.destroy.
115 */
116 static status_t entry_destroy(entry_t *this)
117 {
118 /* also destroy IKE SA */
119 this->ike_sa->destroy(this->ike_sa);
120 this->ike_sa_id->destroy(this->ike_sa_id);
121 chunk_free(&this->init_hash);
122 DESTROY_IF(this->other);
123 DESTROY_IF(this->my_id);
124 DESTROY_IF(this->other_id);
125 this->condvar->destroy(this->condvar);
126 free(this);
127 return SUCCESS;
128 }
129
130 /**
131 * Creates a new entry for the ike_sa_t list.
132 */
133 static entry_t *entry_create()
134 {
135 entry_t *this = malloc_thing(entry_t);
136
137 this->waiting_threads = 0;
138 this->condvar = condvar_create(CONDVAR_DEFAULT);
139
140 /* we set checkout flag when we really give it out */
141 this->checked_out = FALSE;
142 this->driveout_new_threads = FALSE;
143 this->driveout_waiting_threads = FALSE;
144 this->message_id = -1;
145 this->init_hash = chunk_empty;
146 this->other = NULL;
147 this->half_open = FALSE;
148 this->my_id = NULL;
149 this->other_id = NULL;
150 this->ike_sa_id = NULL;
151 this->ike_sa = NULL;
152
153 return this;
154 }
155
156 /**
157 * Function that matches entry_t objects by initiator SPI and the hash of the
158 * IKE_SA_INIT message.
159 */
160 static bool entry_match_by_hash(entry_t *entry, ike_sa_id_t *id, chunk_t *hash)
161 {
162 return id->get_responder_spi(id) == 0 &&
163 id->is_initiator(id) == entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
164 id->get_initiator_spi(id) == entry->ike_sa_id->get_initiator_spi(entry->ike_sa_id) &&
165 chunk_equals(*hash, entry->init_hash);
166 }
167
168 /**
169 * Function that matches entry_t objects by ike_sa_id_t.
170 */
171 static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
172 {
173 if (id->equals(id, entry->ike_sa_id))
174 {
175 return TRUE;
176 }
177 if ((id->get_responder_spi(id) == 0 ||
178 entry->ike_sa_id->get_responder_spi(entry->ike_sa_id) == 0) &&
179 id->is_initiator(id) == entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
180 id->get_initiator_spi(id) == entry->ike_sa_id->get_initiator_spi(entry->ike_sa_id))
181 {
182 /* this is TRUE for IKE_SAs that we initiated but have not yet received a response */
183 return TRUE;
184 }
185 return FALSE;
186 }
187
188 /**
189 * Function that matches entry_t objects by ike_sa_t pointers.
190 */
191 static bool entry_match_by_sa(entry_t *entry, ike_sa_t *ike_sa)
192 {
193 return entry->ike_sa == ike_sa;
194 }
195
196 /**
197 * Hash function for ike_sa_id_t objects.
198 */
199 static u_int ike_sa_id_hash(ike_sa_id_t *ike_sa_id)
200 {
201 /* we always use initiator spi as key */
202 return ike_sa_id->get_initiator_spi(ike_sa_id);
203 }
204
205 typedef struct half_open_t half_open_t;
206
207 /**
208 * Struct to manage half-open IKE_SAs per peer.
209 */
210 struct half_open_t {
211 /** chunk of remote host address */
212 chunk_t other;
213
214 /** the number of half-open IKE_SAs with that host */
215 u_int count;
216 };
217
218 /**
219 * Destroys a half_open_t object.
220 */
221 static void half_open_destroy(half_open_t *this)
222 {
223 chunk_free(&this->other);
224 free(this);
225 }
226
227 /**
228 * Function that matches half_open_t objects by the given IP address chunk.
229 */
230 static bool half_open_match(half_open_t *half_open, chunk_t *addr)
231 {
232 return chunk_equals(*addr, half_open->other);
233 }
234
235 typedef struct connected_peers_t connected_peers_t;
236
237 struct connected_peers_t {
238 /** own identity */
239 identification_t *my_id;
240
241 /** remote identity */
242 identification_t *other_id;
243
244 /** list of ike_sa_id_t objects of IKE_SAs between the two identities */
245 linked_list_t *sas;
246 };
247
248 static void connected_peers_destroy(connected_peers_t *this)
249 {
250 this->my_id->destroy(this->my_id);
251 this->other_id->destroy(this->other_id);
252 this->sas->destroy(this->sas);
253 free(this);
254 }
255
256 /**
257 * Function that matches connected_peers_t objects by the given ids.
258 */
259 static bool connected_peers_match(connected_peers_t *connected_peers,
260 identification_t *my_id, identification_t *other_id)
261 {
262 return my_id->equals(my_id, connected_peers->my_id) &&
263 other_id->equals(other_id, connected_peers->other_id);
264 }
265
266 typedef struct segment_t segment_t;
267
268 /**
269 * Struct to manage segments of the hash table.
270 */
271 struct segment_t {
272 /** mutex to access a segment exclusively */
273 mutex_t *mutex;
274
275 /** the number of entries in this segment */
276 u_int count;
277 };
278
279 typedef struct shareable_segment_t shareable_segment_t;
280
281 /**
282 * Struct to manage segments of the "half-open" and "connected peers" hash tables.
283 */
284 struct shareable_segment_t {
285 /** rwlock to access a segment non-/exclusively */
286 rwlock_t *lock;
287
288 /** the number of entries in this segment - in case of the "half-open table"
289 * it's the sum of all half_open_t.count in a segment. */
290 u_int count;
291 };
292
293 typedef struct private_ike_sa_manager_t private_ike_sa_manager_t;
294
295 /**
296 * Additional private members of ike_sa_manager_t.
297 */
298 struct private_ike_sa_manager_t {
299 /**
300 * Public interface of ike_sa_manager_t.
301 */
302 ike_sa_manager_t public;
303
304 /**
305 * Hash table with entries for the ike_sa_t objects.
306 */
307 linked_list_t **ike_sa_table;
308
309 /**
310 * The size of the hash table.
311 */
312 u_int table_size;
313
314 /**
315 * Mask to map the hashes to table rows.
316 */
317 u_int table_mask;
318
319 /**
320 * Segments of the hash table.
321 */
322 segment_t *segments;
323
324 /**
325 * The number of segments.
326 */
327 u_int segment_count;
328
329 /**
330 * Mask to map a table row to a segment.
331 */
332 u_int segment_mask;
333
334 /**
335 * Hash table with half_open_t objects.
336 */
337 linked_list_t **half_open_table;
338
339 /**
340 * Segments of the "half-open" hash table.
341 */
342 shareable_segment_t *half_open_segments;
343
344 /**
345 * Hash table with connected_peers_t objects.
346 */
347 linked_list_t **connected_peers_table;
348
349 /**
350 * Segments of the "connected peers" hash table.
351 */
352 shareable_segment_t *connected_peers_segments;
353
354 /**
355 * RNG to get random SPIs for our side
356 */
357 rng_t *rng;
358
359 /**
360 * SHA1 hasher for IKE_SA_INIT retransmit detection
361 */
362 hasher_t *hasher;
363
364 /**
365 * reuse existing IKE_SAs in checkout_by_config
366 */
367 bool reuse_ikesa;
368 };
369
370 /**
371 * Acquire a lock to access the segment of the table row with the given index.
372 * It also works with the segment index directly.
373 */
374 static void lock_single_segment(private_ike_sa_manager_t *this, u_int index)
375 {
376 mutex_t *lock = this->segments[index & this->segment_mask].mutex;
377
378 lock->lock(lock);
379 }
380
381 /**
382 * Release the lock required to access the segment of the table row with the given index.
383 * It also works with the segment index directly.
384 */
385 static void unlock_single_segment(private_ike_sa_manager_t *this, u_int index)
386 {
387 mutex_t *lock = this->segments[index & this->segment_mask].mutex;
388
389 lock->unlock(lock);
390 }
391
392 /**
393 * Lock all segments
394 */
395 static void lock_all_segments(private_ike_sa_manager_t *this)
396 {
397 u_int i;
398
399 for (i = 0; i < this->segment_count; ++i)
400 {
401 this->segments[i].mutex->lock(this->segments[i].mutex);
402 }
403 }
404
405 /**
406 * Unlock all segments
407 */
408 static void unlock_all_segments(private_ike_sa_manager_t *this)
409 {
410 u_int i;
411
412 for (i = 0; i < this->segment_count; ++i)
413 {
414 this->segments[i].mutex->unlock(this->segments[i].mutex);
415 }
416 }
417
418 typedef struct private_enumerator_t private_enumerator_t;
419
420 /**
421 * hash table enumerator implementation
422 */
423 struct private_enumerator_t {
424
425 /**
426 * implements enumerator interface
427 */
428 enumerator_t enumerator;
429
430 /**
431 * associated ike_sa_manager_t
432 */
433 private_ike_sa_manager_t *manager;
434
435 /**
436 * current segment index
437 */
438 u_int segment;
439
440 /**
441 * current table row index
442 */
443 u_int row;
444
445 /**
446 * enumerator for the current table row
447 */
448 enumerator_t *current;
449 };
450
451 /**
452 * Implementation of private_enumerator_t.enumerator.enumerate.
453 */
454 static bool enumerate(private_enumerator_t *this, entry_t **entry, u_int *segment)
455 {
456 while (this->segment < this->manager->segment_count)
457 {
458 while (this->row < this->manager->table_size)
459 {
460 if (this->current)
461 {
462 entry_t *item;
463
464 if (this->current->enumerate(this->current, (void**)&item))
465 {
466 *entry = item;
467 *segment = this->segment;
468 return TRUE;
469 }
470 this->current->destroy(this->current);
471 this->current = NULL;
472 unlock_single_segment(this->manager, this->segment);
473 }
474 else
475 {
476 linked_list_t *list;
477
478 lock_single_segment(this->manager, this->segment);
479 if ((list = this->manager->ike_sa_table[this->row]) != NULL &&
480 list->get_count(list))
481 {
482 this->current = list->create_enumerator(list);
483 continue;
484 }
485 unlock_single_segment(this->manager, this->segment);
486 }
487 this->row += this->manager->segment_count;
488 }
489 this->segment++;
490 this->row = this->segment;
491 }
492 return FALSE;
493 }
494
495 /**
496 * Implementation of private_enumerator_t.enumerator.destroy.
497 */
498 static void enumerator_destroy(private_enumerator_t *this)
499 {
500 if (this->current)
501 {
502 this->current->destroy(this->current);
503 unlock_single_segment(this->manager, this->segment);
504 }
505 free(this);
506 }
507
508 /**
509 * Creates an enumerator to enumerate the entries in the hash table.
510 */
511 static enumerator_t* create_table_enumerator(private_ike_sa_manager_t *this)
512 {
513 private_enumerator_t *enumerator = malloc_thing(private_enumerator_t);
514
515 enumerator->enumerator.enumerate = (void*)enumerate;
516 enumerator->enumerator.destroy = (void*)enumerator_destroy;
517 enumerator->manager = this;
518 enumerator->segment = 0;
519 enumerator->row = 0;
520 enumerator->current = NULL;
521
522 return &enumerator->enumerator;
523 }
524
525 /**
526 * Put an entry into the hash table.
527 * Note: The caller has to unlock the returned segment.
528 */
529 static u_int put_entry(private_ike_sa_manager_t *this, entry_t *entry)
530 {
531 linked_list_t *list;
532 u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
533 u_int segment = row & this->segment_mask;
534
535 lock_single_segment(this, segment);
536 if ((list = this->ike_sa_table[row]) == NULL)
537 {
538 list = this->ike_sa_table[row] = linked_list_create();
539 }
540 list->insert_last(list, entry);
541 this->segments[segment].count++;
542 return segment;
543 }
544
545 /**
546 * Remove an entry from the hash table.
547 * Note: The caller MUST have a lock on the segment of this entry.
548 */
549 static void remove_entry(private_ike_sa_manager_t *this, entry_t *entry)
550 {
551 linked_list_t *list;
552 u_int row = ike_sa_id_hash(entry->ike_sa_id) & this->table_mask;
553 u_int segment = row & this->segment_mask;
554
555 if ((list = this->ike_sa_table[row]) != NULL)
556 {
557 entry_t *current;
558
559 enumerator_t *enumerator = list->create_enumerator(list);
560 while (enumerator->enumerate(enumerator, &current))
561 {
562 if (current == entry)
563 {
564 list->remove_at(list, enumerator);
565 this->segments[segment].count--;
566 break;
567 }
568 }
569 enumerator->destroy(enumerator);
570 }
571 }
572
573 /**
574 * Remove the entry at the current enumerator position.
575 */
576 static void remove_entry_at(private_enumerator_t *this)
577 {
578 if (this->current)
579 {
580 linked_list_t *list = this->manager->ike_sa_table[this->row];
581 list->remove_at(list, this->current);
582 this->manager->segments[this->segment].count--;
583 }
584 }
585
586 /**
587 * Find an entry using the provided match function to compare the entries for
588 * equality.
589 */
590 static status_t get_entry_by_match_function(private_ike_sa_manager_t *this,
591 ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment,
592 linked_list_match_t match, void *p1, void *p2)
593 {
594 entry_t *current;
595 linked_list_t *list;
596 u_int row = ike_sa_id_hash(ike_sa_id) & this->table_mask;
597 u_int seg = row & this->segment_mask;
598
599 lock_single_segment(this, seg);
600 if ((list = this->ike_sa_table[row]) != NULL)
601 {
602 if (list->find_first(list, match, (void**)&current, p1, p2) == SUCCESS)
603 {
604 *entry = current;
605 *segment = seg;
606 /* the locked segment has to be unlocked by the caller */
607 return SUCCESS;
608 }
609 }
610 unlock_single_segment(this, seg);
611 return NOT_FOUND;
612 }
613
614 /**
615 * Find an entry by ike_sa_id_t.
616 * Note: On SUCCESS, the caller has to unlock the segment.
617 */
618 static status_t get_entry_by_id(private_ike_sa_manager_t *this,
619 ike_sa_id_t *ike_sa_id, entry_t **entry, u_int *segment)
620 {
621 return get_entry_by_match_function(this, ike_sa_id, entry, segment,
622 (linked_list_match_t)entry_match_by_id, ike_sa_id, NULL);
623 }
624
625 /**
626 * Find an entry by initiator SPI and IKE_SA_INIT hash.
627 * Note: On SUCCESS, the caller has to unlock the segment.
628 */
629 static status_t get_entry_by_hash(private_ike_sa_manager_t *this,
630 ike_sa_id_t *ike_sa_id, chunk_t hash, entry_t **entry, u_int *segment)
631 {
632 return get_entry_by_match_function(this, ike_sa_id, entry, segment,
633 (linked_list_match_t)entry_match_by_hash, ike_sa_id, &hash);
634 }
635
636 /**
637 * Find an entry by IKE_SA pointer.
638 * Note: On SUCCESS, the caller has to unlock the segment.
639 */
640 static status_t get_entry_by_sa(private_ike_sa_manager_t *this,
641 ike_sa_id_t *ike_sa_id, ike_sa_t *ike_sa, entry_t **entry, u_int *segment)
642 {
643 return get_entry_by_match_function(this, ike_sa_id, entry, segment,
644 (linked_list_match_t)entry_match_by_sa, ike_sa, NULL);
645 }
646
647 /**
648 * Wait until no other thread is using an IKE_SA, return FALSE if entry not
649 * acquirable.
650 */
651 static bool wait_for_entry(private_ike_sa_manager_t *this, entry_t *entry,
652 u_int segment)
653 {
654 if (entry->driveout_new_threads)
655 {
656 /* we are not allowed to get this */
657 return FALSE;
658 }
659 while (entry->checked_out && !entry->driveout_waiting_threads)
660 {
661 /* so wait until we can get it for us.
662 * we register us as waiting. */
663 entry->waiting_threads++;
664 entry->condvar->wait(entry->condvar, this->segments[segment].mutex);
665 entry->waiting_threads--;
666 }
667 /* hm, a deletion request forbids us to get this SA, get next one */
668 if (entry->driveout_waiting_threads)
669 {
670 /* we must signal here, others may be waiting on it, too */
671 entry->condvar->signal(entry->condvar);
672 return FALSE;
673 }
674 return TRUE;
675 }
676
677 /**
678 * Put a half-open SA into the hash table.
679 */
680 static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
681 {
682 half_open_t *half_open = NULL;
683 linked_list_t *list;
684 chunk_t addr = entry->other->get_address(entry->other);
685 u_int row = chunk_hash(addr) & this->table_mask;
686 u_int segment = row & this->segment_mask;
687
688 rwlock_t *lock = this->half_open_segments[segment].lock;
689 lock->write_lock(lock);
690 if ((list = this->half_open_table[row]) == NULL)
691 {
692 list = this->half_open_table[row] = linked_list_create();
693 }
694 else
695 {
696 half_open_t *current;
697 if (list->find_first(list, (linked_list_match_t)half_open_match,
698 (void**)&current, &addr) == SUCCESS)
699 {
700 half_open = current;
701 half_open->count++;
702 this->half_open_segments[segment].count++;
703 }
704 }
705
706 if (!half_open)
707 {
708 half_open = malloc_thing(half_open_t);
709 half_open->other = chunk_clone(addr);
710 half_open->count = 1;
711 list->insert_last(list, half_open);
712 this->half_open_segments[segment].count++;
713 }
714 lock->unlock(lock);
715 }
716
717 /**
718 * Remove a half-open SA from the hash table.
719 */
720 static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
721 {
722 linked_list_t *list;
723 chunk_t addr = entry->other->get_address(entry->other);
724 u_int row = chunk_hash(addr) & this->table_mask;
725 u_int segment = row & this->segment_mask;
726
727 rwlock_t *lock = this->half_open_segments[segment].lock;
728 lock->write_lock(lock);
729 if ((list = this->half_open_table[row]) != NULL)
730 {
731 half_open_t *current;
732 enumerator_t *enumerator = list->create_enumerator(list);
733 while (enumerator->enumerate(enumerator, &current))
734 {
735 if (half_open_match(current, &addr))
736 {
737 if (--current->count == 0)
738 {
739 list->remove_at(list, enumerator);
740 half_open_destroy(current);
741 }
742 this->half_open_segments[segment].count--;
743 break;
744 }
745 }
746 enumerator->destroy(enumerator);
747 }
748 lock->unlock(lock);
749 }
750
751 /**
752 * Put an SA between two peers into the hash table.
753 */
754 static void put_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
755 {
756 linked_list_t *list;
757 connected_peers_t *connected_peers = NULL;
758 chunk_t my_id = entry->my_id->get_encoding(entry->my_id),
759 other_id = entry->other_id->get_encoding(entry->other_id);
760 u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
761 u_int segment = row & this->segment_mask;
762
763 rwlock_t *lock = this->connected_peers_segments[segment].lock;
764 lock->write_lock(lock);
765 if ((list = this->connected_peers_table[row]) == NULL)
766 {
767 list = this->connected_peers_table[row] = linked_list_create();
768 }
769 else
770 {
771 connected_peers_t *current;
772 if (list->find_first(list, (linked_list_match_t)connected_peers_match,
773 (void**)&current, entry->my_id, entry->other_id) == SUCCESS)
774 {
775 connected_peers = current;
776 if (connected_peers->sas->find_first(connected_peers->sas,
777 (linked_list_match_t)entry->ike_sa_id->equals,
778 NULL, entry->ike_sa_id) == SUCCESS)
779 {
780 lock->unlock(lock);
781 return;
782 }
783 }
784 }
785
786 if (!connected_peers)
787 {
788 connected_peers = malloc_thing(connected_peers_t);
789 connected_peers->my_id = entry->my_id->clone(entry->my_id);
790 connected_peers->other_id = entry->other_id->clone(entry->other_id);
791 connected_peers->sas = linked_list_create();
792 list->insert_last(list, connected_peers);
793 }
794 connected_peers->sas->insert_last(connected_peers->sas,
795 entry->ike_sa_id->clone(entry->ike_sa_id));
796 this->connected_peers_segments[segment].count++;
797 lock->unlock(lock);
798 }
799
800 /**
801 * Remove an SA between two peers from the hash table.
802 */
803 static void remove_connected_peers(private_ike_sa_manager_t *this, entry_t *entry)
804 {
805 linked_list_t *list;
806 chunk_t my_id = entry->my_id->get_encoding(entry->my_id),
807 other_id = entry->other_id->get_encoding(entry->other_id);
808 u_int row = chunk_hash_inc(other_id, chunk_hash(my_id)) & this->table_mask;
809 u_int segment = row & this->segment_mask;
810
811 rwlock_t *lock = this->connected_peers_segments[segment].lock;
812 lock->write_lock(lock);
813 if ((list = this->connected_peers_table[row]) != NULL)
814 {
815 connected_peers_t *current;
816 enumerator_t *enumerator = list->create_enumerator(list);
817 while (enumerator->enumerate(enumerator, &current))
818 {
819 if (connected_peers_match(current, entry->my_id, entry->other_id))
820 {
821 ike_sa_id_t *ike_sa_id;
822 enumerator_t *inner = current->sas->create_enumerator(current->sas);
823 while (inner->enumerate(inner, &ike_sa_id))
824 {
825 if (ike_sa_id->equals(ike_sa_id, entry->ike_sa_id))
826 {
827 current->sas->remove_at(current->sas, inner);
828 ike_sa_id->destroy(ike_sa_id);
829 this->connected_peers_segments[segment].count--;
830 break;
831 }
832 }
833 inner->destroy(inner);
834 if (current->sas->get_count(current->sas) == 0)
835 {
836 list->remove_at(list, enumerator);
837 connected_peers_destroy(current);
838 }
839 break;
840 }
841 }
842 enumerator->destroy(enumerator);
843 }
844 lock->unlock(lock);
845 }
846
847 /**
848 * Implementation of private_ike_sa_manager_t.get_next_spi.
849 */
850 static u_int64_t get_next_spi(private_ike_sa_manager_t *this)
851 {
852 u_int64_t spi;
853
854 this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi);
855 return spi;
856 }
857
858 /**
859 * Implementation of of ike_sa_manager.checkout.
860 */
861 static ike_sa_t* checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id)
862 {
863 ike_sa_t *ike_sa = NULL;
864 entry_t *entry;
865 u_int segment;
866
867 DBG2(DBG_MGR, "checkout IKE_SA");
868
869 if (get_entry_by_id(this, ike_sa_id, &entry, &segment) == SUCCESS)
870 {
871 if (wait_for_entry(this, entry, segment))
872 {
873 DBG2(DBG_MGR, "IKE_SA successfully checked out");
874 entry->checked_out = TRUE;
875 ike_sa = entry->ike_sa;
876 }
877 unlock_single_segment(this, segment);
878 }
879 charon->bus->set_sa(charon->bus, ike_sa);
880 return ike_sa;
881 }
882
883 /**
884 * Implementation of of ike_sa_manager.checkout_new.
885 */
886 static ike_sa_t *checkout_new(private_ike_sa_manager_t* this, bool initiator)
887 {
888 entry_t *entry;
889 u_int segment;
890
891 entry = entry_create();
892 if (initiator)
893 {
894 entry->ike_sa_id = ike_sa_id_create(get_next_spi(this), 0, TRUE);
895 }
896 else
897 {
898 entry->ike_sa_id = ike_sa_id_create(0, get_next_spi(this), FALSE);
899 }
900 entry->ike_sa = ike_sa_create(entry->ike_sa_id);
901
902 segment = put_entry(this, entry);
903 entry->checked_out = TRUE;
904 unlock_single_segment(this, segment);
905
906 DBG2(DBG_MGR, "created IKE_SA");
907 return entry->ike_sa;
908 }
909
910 /**
911 * Implementation of of ike_sa_manager.checkout_by_message.
912 */
913 static ike_sa_t* checkout_by_message(private_ike_sa_manager_t* this,
914 message_t *message)
915 {
916 u_int segment;
917 entry_t *entry;
918 ike_sa_t *ike_sa = NULL;
919 ike_sa_id_t *id = message->get_ike_sa_id(message);
920
921 id = id->clone(id);
922 id->switch_initiator(id);
923
924 DBG2(DBG_MGR, "checkout IKE_SA by message");
925
926 if (message->get_request(message) &&
927 message->get_exchange_type(message) == IKE_SA_INIT)
928 {
929 /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
930 chunk_t data, hash;
931
932 data = message->get_packet_data(message);
933 this->hasher->allocate_hash(this->hasher, data, &hash);
934 chunk_free(&data);
935
936 if (get_entry_by_hash(this, id, hash, &entry, &segment) == SUCCESS)
937 {
938 if (entry->message_id == 0)
939 {
940 unlock_single_segment(this, segment);
941 chunk_free(&hash);
942 id->destroy(id);
943 DBG1(DBG_MGR, "ignoring IKE_SA_INIT, already processing");
944 return NULL;
945 }
946 else if (wait_for_entry(this, entry, segment))
947 {
948 DBG2(DBG_MGR, "IKE_SA checked out by hash");
949 entry->checked_out = TRUE;
950 entry->message_id = message->get_message_id(message);
951 ike_sa = entry->ike_sa;
952 }
953 unlock_single_segment(this, segment);
954 }
955
956 if (ike_sa == NULL)
957 {
958 if (id->get_responder_spi(id) == 0 &&
959 message->get_exchange_type(message) == IKE_SA_INIT)
960 {
961 /* no IKE_SA found, create a new one */
962 id->set_responder_spi(id, get_next_spi(this));
963 entry = entry_create();
964 entry->ike_sa = ike_sa_create(id);
965 entry->ike_sa_id = id->clone(id);
966
967 segment = put_entry(this, entry);
968 entry->checked_out = TRUE;
969 unlock_single_segment(this, segment);
970
971 entry->message_id = message->get_message_id(message);
972 entry->init_hash = hash;
973 ike_sa = entry->ike_sa;
974
975 DBG2(DBG_MGR, "created IKE_SA");
976 }
977 else
978 {
979 chunk_free(&hash);
980 DBG1(DBG_MGR, "ignoring message, no such IKE_SA");
981 }
982 }
983 else
984 {
985 chunk_free(&hash);
986 }
987 id->destroy(id);
988 charon->bus->set_sa(charon->bus, ike_sa);
989 return ike_sa;
990 }
991
992 if (get_entry_by_id(this, id, &entry, &segment) == SUCCESS)
993 {
994 /* only check out if we are not processing this request */
995 if (message->get_request(message) &&
996 message->get_message_id(message) == entry->message_id)
997 {
998 DBG1(DBG_MGR, "ignoring request with ID %d, already processing",
999 entry->message_id);
1000 }
1001 else if (wait_for_entry(this, entry, segment))
1002 {
1003 ike_sa_id_t *ike_id = entry->ike_sa->get_id(entry->ike_sa);
1004 DBG2(DBG_MGR, "IKE_SA successfully checked out");
1005 entry->checked_out = TRUE;
1006 entry->message_id = message->get_message_id(message);
1007 if (ike_id->get_responder_spi(ike_id) == 0)
1008 {
1009 ike_id->set_responder_spi(ike_id, id->get_responder_spi(id));
1010 }
1011 ike_sa = entry->ike_sa;
1012 }
1013 unlock_single_segment(this, segment);
1014 }
1015 id->destroy(id);
1016 charon->bus->set_sa(charon->bus, ike_sa);
1017 return ike_sa;
1018 }
1019
1020 /**
1021 * Implementation of of ike_sa_manager.checkout_by_config.
1022 */
1023 static ike_sa_t* checkout_by_config(private_ike_sa_manager_t *this,
1024 peer_cfg_t *peer_cfg)
1025 {
1026 enumerator_t *enumerator;
1027 entry_t *entry;
1028 ike_sa_t *ike_sa = NULL;
1029 identification_t *my_id, *other_id;
1030 host_t *my_host, *other_host;
1031 ike_cfg_t *ike_cfg;
1032 u_int segment;
1033
1034 ike_cfg = peer_cfg->get_ike_cfg(peer_cfg);
1035 my_id = peer_cfg->get_my_id(peer_cfg);
1036 other_id = peer_cfg->get_other_id(peer_cfg);
1037 my_host = host_create_from_dns(ike_cfg->get_my_addr(ike_cfg), 0, 0);
1038 other_host = host_create_from_dns(ike_cfg->get_other_addr(ike_cfg), 0, 0);
1039
1040 if (my_host && other_host && this->reuse_ikesa)
1041 {
1042 enumerator = create_table_enumerator(this);
1043 while (enumerator->enumerate(enumerator, &entry, &segment))
1044 {
1045 identification_t *found_my_id, *found_other_id;
1046 host_t *found_my_host, *found_other_host;
1047
1048 if (!wait_for_entry(this, entry, segment))
1049 {
1050 continue;
1051 }
1052
1053 if (entry->ike_sa->get_state(entry->ike_sa) == IKE_DELETING)
1054 {
1055 /* skip IKE_SAs which are not usable */
1056 continue;
1057 }
1058
1059 found_my_id = entry->ike_sa->get_my_id(entry->ike_sa);
1060 found_other_id = entry->ike_sa->get_other_id(entry->ike_sa);
1061 found_my_host = entry->ike_sa->get_my_host(entry->ike_sa);
1062 found_other_host = entry->ike_sa->get_other_host(entry->ike_sa);
1063
1064 if (found_my_id->get_type(found_my_id) == ID_ANY &&
1065 found_other_id->get_type(found_other_id) == ID_ANY)
1066 {
1067 /* IKE_SA has no IDs yet, so we can't use it */
1068 continue;
1069 }
1070 DBG2(DBG_MGR, "candidate IKE_SA for \n"
1071 " %H[%D]...%H[%D]\n"
1072 " %H[%D]...%H[%D]",
1073 my_host, my_id, other_host, other_id,
1074 found_my_host, found_my_id, found_other_host, found_other_id);
1075 /* compare ID and hosts. Supplied ID may contain wildcards, and IP
1076 * may be %any. */
1077 if ((my_host->is_anyaddr(my_host) ||
1078 my_host->ip_equals(my_host, found_my_host)) &&
1079 (other_host->is_anyaddr(other_host) ||
1080 other_host->ip_equals(other_host, found_other_host)) &&
1081 found_my_id->matches(found_my_id, my_id) &&
1082 found_other_id->matches(found_other_id, other_id) &&
1083 streq(peer_cfg->get_name(peer_cfg),
1084 entry->ike_sa->get_name(entry->ike_sa)))
1085 {
1086 /* looks good, we take this one */
1087 DBG2(DBG_MGR, "found an existing IKE_SA for %H[%D]...%H[%D]",
1088 my_host, my_id, other_host, other_id);
1089 entry->checked_out = TRUE;
1090 ike_sa = entry->ike_sa;
1091 break;
1092 }
1093 }
1094 enumerator->destroy(enumerator);
1095 }
1096 DESTROY_IF(my_host);
1097 DESTROY_IF(other_host);
1098
1099 if (!ike_sa)
1100 {
1101 entry = entry_create();
1102 entry->ike_sa_id = ike_sa_id_create(get_next_spi(this), 0, TRUE);
1103 entry->ike_sa = ike_sa_create(entry->ike_sa_id);
1104
1105 segment = put_entry(this, entry);
1106
1107 /* check ike_sa out */
1108 DBG2(DBG_MGR, "new IKE_SA created for IDs [%D]...[%D]", my_id, other_id);
1109 entry->checked_out = TRUE;
1110 ike_sa = entry->ike_sa;
1111 unlock_single_segment(this, segment);
1112 }
1113 charon->bus->set_sa(charon->bus, ike_sa);
1114 return ike_sa;
1115 }
1116
1117 /**
1118 * Implementation of of ike_sa_manager.checkout_by_id.
1119 */
1120 static ike_sa_t* checkout_by_id(private_ike_sa_manager_t *this, u_int32_t id,
1121 bool child)
1122 {
1123 enumerator_t *enumerator;
1124 iterator_t *children;
1125 entry_t *entry;
1126 ike_sa_t *ike_sa = NULL;
1127 child_sa_t *child_sa;
1128 u_int segment;
1129
1130 enumerator = create_table_enumerator(this);
1131 while (enumerator->enumerate(enumerator, &entry, &segment))
1132 {
1133 if (wait_for_entry(this, entry, segment))
1134 {
1135 /* look for a child with such a reqid ... */
1136 if (child)
1137 {
1138 children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
1139 while (children->iterate(children, (void**)&child_sa))
1140 {
1141 if (child_sa->get_reqid(child_sa) == id)
1142 {
1143 ike_sa = entry->ike_sa;
1144 break;
1145 }
1146 }
1147 children->destroy(children);
1148 }
1149 else /* ... or for a IKE_SA with such a unique id */
1150 {
1151 if (entry->ike_sa->get_unique_id(entry->ike_sa) == id)
1152 {
1153 ike_sa = entry->ike_sa;
1154 }
1155 }
1156 /* got one, return */
1157 if (ike_sa)
1158 {
1159 entry->checked_out = TRUE;
1160 break;
1161 }
1162 }
1163 }
1164 enumerator->destroy(enumerator);
1165
1166 charon->bus->set_sa(charon->bus, ike_sa);
1167 return ike_sa;
1168 }
1169
1170 /**
1171 * Implementation of of ike_sa_manager.checkout_by_name.
1172 */
1173 static ike_sa_t* checkout_by_name(private_ike_sa_manager_t *this, char *name,
1174 bool child)
1175 {
1176 enumerator_t *enumerator;
1177 iterator_t *children;
1178 entry_t *entry;
1179 ike_sa_t *ike_sa = NULL;
1180 child_sa_t *child_sa;
1181 u_int segment;
1182
1183 enumerator = create_table_enumerator(this);
1184 while (enumerator->enumerate(enumerator, &entry, &segment))
1185 {
1186 if (wait_for_entry(this, entry, segment))
1187 {
1188 /* look for a child with such a policy name ... */
1189 if (child)
1190 {
1191 children = entry->ike_sa->create_child_sa_iterator(entry->ike_sa);
1192 while (children->iterate(children, (void**)&child_sa))
1193 {
1194 if (streq(child_sa->get_name(child_sa), name))
1195 {
1196 ike_sa = entry->ike_sa;
1197 break;
1198 }
1199 }
1200 children->destroy(children);
1201 }
1202 else /* ... or for a IKE_SA with such a connection name */
1203 {
1204 if (streq(entry->ike_sa->get_name(entry->ike_sa), name))
1205 {
1206 ike_sa = entry->ike_sa;
1207 }
1208 }
1209 /* got one, return */
1210 if (ike_sa)
1211 {
1212 entry->checked_out = TRUE;
1213 break;
1214 }
1215 }
1216 }
1217 enumerator->destroy(enumerator);
1218
1219 charon->bus->set_sa(charon->bus, ike_sa);
1220 return ike_sa;
1221 }
1222
1223 /**
1224 * Implementation of ike_sa_manager_t.checkout_duplicate.
1225 */
1226 static ike_sa_t* checkout_duplicate(private_ike_sa_manager_t *this,
1227 ike_sa_t *ike_sa)
1228 {
1229 linked_list_t *list;
1230 entry_t *entry;
1231 ike_sa_id_t *duplicate_id = NULL;
1232 ike_sa_t *duplicate = NULL;
1233 identification_t *me, *other;
1234 u_int row, segment;
1235 rwlock_t *lock;
1236
1237 me = ike_sa->get_my_id(ike_sa);
1238 other = ike_sa->get_other_id(ike_sa);
1239
1240 row = chunk_hash_inc(other->get_encoding(other),
1241 chunk_hash(me->get_encoding(me))) & this->table_mask;
1242 segment = row & this->segment_mask;
1243
1244 lock = this->connected_peers_segments[segment & this->segment_mask].lock;
1245 lock->read_lock(lock);
1246 if ((list = this->connected_peers_table[row]) != NULL)
1247 {
1248 connected_peers_t *current;
1249 if (list->find_first(list, (linked_list_match_t)connected_peers_match,
1250 (void**)&current, me, other) == SUCCESS)
1251 {
1252 /* we just return the first ike_sa_id we have cached for these ids */
1253 current->sas->get_first(current->sas, (void**)&duplicate_id);
1254 }
1255 }
1256 lock->unlock(lock);
1257
1258 if (duplicate_id)
1259 {
1260 if (get_entry_by_id(this, duplicate_id, &entry, &segment) == SUCCESS)
1261 {
1262 if (wait_for_entry(this, entry, segment))
1263 {
1264 duplicate = entry->ike_sa;
1265 entry->checked_out = TRUE;
1266 }
1267 unlock_single_segment(this, segment);
1268 }
1269 }
1270 return duplicate;
1271 }
1272
1273 /**
1274 * enumerator filter function
1275 */
1276 static bool enumerator_filter(private_ike_sa_manager_t *this,
1277 entry_t **in, ike_sa_t **out, u_int *segment)
1278 {
1279 if (wait_for_entry(this, *in, *segment))
1280 {
1281 *out = (*in)->ike_sa;
1282 return TRUE;
1283 }
1284 return FALSE;
1285 }
1286
1287 /**
1288 * Implementation of ike_sa_manager_t.create_enumerator.
1289 */
1290 static enumerator_t *create_enumerator(private_ike_sa_manager_t* this)
1291 {
1292 return enumerator_create_filter(
1293 create_table_enumerator(this),
1294 (void*)enumerator_filter, this, NULL);
1295 }
1296
1297 /**
1298 * Implementation of ike_sa_manager_t.checkin.
1299 */
1300 static void checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
1301 {
1302 /* to check the SA back in, we look for the pointer of the ike_sa
1303 * in all entries.
1304 * The lookup is done by initiator SPI, so even if the SPI has changed (e.g.
1305 * on reception of a IKE_SA_INIT response) the lookup will work but
1306 * updating of the SPI MAY be necessary...
1307 */
1308 entry_t *entry;
1309 ike_sa_id_t *ike_sa_id;
1310 host_t *other;
1311 identification_t *my_id, *other_id;
1312 u_int segment;
1313
1314 ike_sa_id = ike_sa->get_id(ike_sa);
1315 my_id = ike_sa->get_my_id(ike_sa);
1316 other_id = ike_sa->get_other_id(ike_sa);
1317 other = ike_sa->get_other_host(ike_sa);
1318
1319 DBG2(DBG_MGR, "checkin IKE_SA");
1320
1321 /* look for the entry */
1322 if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
1323 {
1324 /* ike_sa_id must be updated */
1325 entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa));
1326 /* signal waiting threads */
1327 entry->checked_out = FALSE;
1328 entry->message_id = -1;
1329 /* check if this SA is half-open */
1330 if (entry->half_open && ike_sa->get_state(ike_sa) != IKE_CONNECTING)
1331 {
1332 /* not half open anymore */
1333 entry->half_open = FALSE;
1334 remove_half_open(this, entry);
1335 }
1336 else if (entry->half_open && !other->ip_equals(other, entry->other))
1337 {
1338 /* the other host's IP has changed, we must update the hash table */
1339 remove_half_open(this, entry);
1340 DESTROY_IF(entry->other);
1341 entry->other = other->clone(other);
1342 put_half_open(this, entry);
1343 }
1344 else if (!entry->half_open &&
1345 !entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
1346 ike_sa->get_state(ike_sa) == IKE_CONNECTING)
1347 {
1348 /* this is a new half-open SA */
1349 entry->half_open = TRUE;
1350 entry->other = other->clone(other);
1351 put_half_open(this, entry);
1352 }
1353 DBG2(DBG_MGR, "check-in of IKE_SA successful.");
1354 entry->condvar->signal(entry->condvar);
1355 }
1356 else
1357 {
1358 entry = entry_create();
1359 entry->ike_sa_id = ike_sa_id->clone(ike_sa_id);
1360 entry->ike_sa = ike_sa;
1361 segment = put_entry(this, entry);
1362 }
1363
1364 /* apply identities for duplicate test (only as responder) */
1365 if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
1366 (!entry->my_id || !entry->other_id))
1367 {
1368 if (!entry->my_id && my_id->get_type(my_id) != ID_ANY)
1369 {
1370 entry->my_id = my_id->clone(my_id);
1371 }
1372 if (!entry->other_id && other_id->get_type(other_id) != ID_ANY)
1373 {
1374 entry->other_id = other_id->clone(other_id);
1375 }
1376 if (entry->my_id && entry->other_id)
1377 {
1378 put_connected_peers(this, entry);
1379 }
1380 }
1381
1382 unlock_single_segment(this, segment);
1383
1384 charon->bus->set_sa(charon->bus, NULL);
1385 }
1386
1387 /**
1388 * Implementation of ike_sa_manager_t.checkin_and_destroy.
1389 */
1390 static void checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
1391 {
1392 /* deletion is a bit complex, we must ensure that no thread is waiting for
1393 * this SA.
1394 * We take this SA from the table, and start signaling while threads
1395 * are in the condvar.
1396 */
1397 entry_t *entry;
1398 ike_sa_id_t *ike_sa_id;
1399 u_int segment;
1400
1401 ike_sa_id = ike_sa->get_id(ike_sa);
1402
1403 DBG2(DBG_MGR, "checkin and destroy IKE_SA");
1404
1405 if (get_entry_by_sa(this, ike_sa_id, ike_sa, &entry, &segment) == SUCCESS)
1406 {
1407 /* drive out waiting threads, as we are in hurry */
1408 entry->driveout_waiting_threads = TRUE;
1409 /* mark it, so no new threads can get this entry */
1410 entry->driveout_new_threads = TRUE;
1411 /* wait until all workers have done their work */
1412 while (entry->waiting_threads)
1413 {
1414 /* wake up all */
1415 entry->condvar->broadcast(entry->condvar);
1416 /* they will wake us again when their work is done */
1417 entry->condvar->wait(entry->condvar, this->segments[segment].mutex);
1418 }
1419
1420 if (entry->half_open)
1421 {
1422 remove_half_open(this, entry);
1423 }
1424 if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
1425 entry->my_id && entry->other_id)
1426 {
1427 remove_connected_peers(this, entry);
1428 }
1429
1430 remove_entry(this, entry);
1431 entry_destroy(entry);
1432 unlock_single_segment(this, segment);
1433
1434 DBG2(DBG_MGR, "check-in and destroy of IKE_SA successful");
1435 }
1436 else
1437 {
1438 DBG1(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
1439 ike_sa->destroy(ike_sa);
1440 }
1441 charon->bus->set_sa(charon->bus, NULL);
1442 }
1443
1444 /**
1445 * Implementation of ike_sa_manager_t.get_half_open_count.
1446 */
1447 static int get_half_open_count(private_ike_sa_manager_t *this, host_t *ip)
1448 {
1449 int count = 0;
1450
1451 if (ip)
1452 {
1453 linked_list_t *list;
1454 chunk_t addr = ip->get_address(ip);
1455 u_int row = chunk_hash(addr) & this->table_mask;
1456 u_int segment = row & this->segment_mask;
1457
1458 rwlock_t *lock = this->half_open_segments[segment & this->segment_mask].lock;
1459 lock->read_lock(lock);
1460 if ((list = this->half_open_table[row]) != NULL)
1461 {
1462 half_open_t *current;
1463
1464 if (list->find_first(list, (linked_list_match_t)half_open_match,
1465 (void**)&current, &addr) == SUCCESS)
1466 {
1467 count = current->count;
1468 }
1469 }
1470 lock->unlock(lock);
1471 }
1472 else
1473 {
1474 u_int segment;
1475
1476 for (segment = 0; segment < this->segment_count; ++segment)
1477 {
1478 rwlock_t *lock;
1479 lock = this->half_open_segments[segment & this->segment_mask].lock;
1480 lock->read_lock(lock);
1481 count += this->half_open_segments[segment].count;
1482 lock->unlock(lock);
1483 }
1484 }
1485
1486 return count;
1487 }
1488
1489 /**
1490 * Implementation of ike_sa_manager_t.flush.
1491 */
1492 static void flush(private_ike_sa_manager_t *this)
1493 {
1494 /* destroy all list entries */
1495 enumerator_t *enumerator;
1496 entry_t *entry;
1497 u_int segment;
1498
1499 lock_all_segments(this);
1500 DBG2(DBG_MGR, "going to destroy IKE_SA manager and all managed IKE_SA's");
1501 /* Step 1: drive out all waiting threads */
1502 DBG2(DBG_MGR, "set driveout flags for all stored IKE_SA's");
1503 enumerator = create_table_enumerator(this);
1504 while (enumerator->enumerate(enumerator, &entry, &segment))
1505 {
1506 /* do not accept new threads, drive out waiting threads */
1507 entry->driveout_new_threads = TRUE;
1508 entry->driveout_waiting_threads = TRUE;
1509 }
1510 enumerator->destroy(enumerator);
1511 DBG2(DBG_MGR, "wait for all threads to leave IKE_SA's");
1512 /* Step 2: wait until all are gone */
1513 enumerator = create_table_enumerator(this);
1514 while (enumerator->enumerate(enumerator, &entry, &segment))
1515 {
1516 while (entry->waiting_threads)
1517 {
1518 /* wake up all */
1519 entry->condvar->broadcast(entry->condvar);
1520 /* go sleeping until they are gone */
1521 entry->condvar->wait(entry->condvar, this->segments[segment].mutex);
1522 }
1523 }
1524 enumerator->destroy(enumerator);
1525 DBG2(DBG_MGR, "delete all IKE_SA's");
1526 /* Step 3: initiate deletion of all IKE_SAs */
1527 enumerator = create_table_enumerator(this);
1528 while (enumerator->enumerate(enumerator, &entry, &segment))
1529 {
1530 charon->bus->set_sa(charon->bus, entry->ike_sa);
1531 entry->ike_sa->delete(entry->ike_sa);
1532 }
1533 enumerator->destroy(enumerator);
1534
1535 DBG2(DBG_MGR, "destroy all entries");
1536 /* Step 4: destroy all entries */
1537 enumerator = create_table_enumerator(this);
1538 while (enumerator->enumerate(enumerator, &entry, &segment))
1539 {
1540 charon->bus->set_sa(charon->bus, entry->ike_sa);
1541 if (entry->half_open)
1542 {
1543 remove_half_open(this, entry);
1544 }
1545 if (!entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
1546 entry->my_id && entry->other_id)
1547 {
1548 remove_connected_peers(this, entry);
1549 }
1550 remove_entry_at((private_enumerator_t*)enumerator);
1551 entry_destroy(entry);
1552 }
1553 enumerator->destroy(enumerator);
1554 charon->bus->set_sa(charon->bus, NULL);
1555 unlock_all_segments(this);
1556 }
1557
1558 /**
1559 * Implementation of ike_sa_manager_t.destroy.
1560 */
1561 static void destroy(private_ike_sa_manager_t *this)
1562 {
1563 u_int i;
1564
1565 for (i = 0; i < this->table_size; ++i)
1566 {
1567 linked_list_t *list;
1568
1569 if ((list = this->ike_sa_table[i]) != NULL)
1570 {
1571 list->destroy(list);
1572 }
1573 if ((list = this->half_open_table[i]) != NULL)
1574 {
1575 list->destroy(list);
1576 }
1577 if ((list = this->connected_peers_table[i]) != NULL)
1578 {
1579 list->destroy(list);
1580 }
1581 }
1582 free(this->ike_sa_table);
1583 free(this->half_open_table);
1584 free(this->connected_peers_table);
1585 for (i = 0; i < this->segment_count; ++i)
1586 {
1587 this->segments[i].mutex->destroy(this->segments[i].mutex);
1588 this->half_open_segments[i].lock->destroy(this->half_open_segments[i].lock);
1589 this->connected_peers_segments[i].lock->destroy(this->connected_peers_segments[i].lock);
1590 }
1591 free(this->segments);
1592 free(this->half_open_segments);
1593 free(this->connected_peers_segments);
1594
1595 this->rng->destroy(this->rng);
1596 this->hasher->destroy(this->hasher);
1597 free(this);
1598 }
1599
1600 /**
1601 * This function returns the next-highest power of two for the given number.
1602 * The algorithm works by setting all bits on the right-hand side of the most
1603 * significant 1 to 1 and then increments the whole number so it rolls over
1604 * to the nearest power of two. Note: returns 0 for n == 0
1605 */
1606 static u_int get_nearest_powerof2(u_int n)
1607 {
1608 u_int i;
1609
1610 --n;
1611 for (i = 1; i < sizeof(u_int) * 8; i <<= 1)
1612 {
1613 n |= n >> i;
1614 }
1615 return ++n;
1616 }
1617
1618 /*
1619 * Described in header.
1620 */
1621 ike_sa_manager_t *ike_sa_manager_create()
1622 {
1623 u_int i;
1624 private_ike_sa_manager_t *this = malloc_thing(private_ike_sa_manager_t);
1625
1626 /* assign public functions */
1627 this->public.flush = (void(*)(ike_sa_manager_t*))flush;
1628 this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
1629 this->public.checkout = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_id_t*))checkout;
1630 this->public.checkout_new = (ike_sa_t*(*)(ike_sa_manager_t*,bool))checkout_new;
1631 this->public.checkout_by_message = (ike_sa_t*(*)(ike_sa_manager_t*,message_t*))checkout_by_message;
1632 this->public.checkout_by_config = (ike_sa_t*(*)(ike_sa_manager_t*,peer_cfg_t*))checkout_by_config;
1633 this->public.checkout_by_id = (ike_sa_t*(*)(ike_sa_manager_t*,u_int32_t,bool))checkout_by_id;
1634 this->public.checkout_by_name = (ike_sa_t*(*)(ike_sa_manager_t*,char*,bool))checkout_by_name;
1635 this->public.checkout_duplicate = (ike_sa_t*(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))checkout_duplicate;
1636 this->public.create_enumerator = (enumerator_t*(*)(ike_sa_manager_t*))create_enumerator;
1637 this->public.checkin = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
1638 this->public.checkin_and_destroy = (void(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_destroy;
1639 this->public.get_half_open_count = (int(*)(ike_sa_manager_t*,host_t*))get_half_open_count;
1640
1641 /* initialize private variables */
1642 this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
1643 if (this->hasher == NULL)
1644 {
1645 DBG1(DBG_MGR, "manager initialization failed, no hasher supported");
1646 free(this);
1647 return NULL;
1648 }
1649 this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
1650 if (this->rng == NULL)
1651 {
1652 DBG1(DBG_MGR, "manager initialization failed, no RNG supported");
1653 this->hasher->destroy(this->hasher);
1654 free(this);
1655 return NULL;
1656 }
1657 this->table_size = get_nearest_powerof2(lib->settings->get_int(lib->settings,
1658 "charon.ikesa_table_size",
1659 DEFAULT_HASHTABLE_SIZE));
1660 this->table_size = max(1, min(this->table_size, MAX_HASHTABLE_SIZE));
1661 this->table_mask = this->table_size - 1;
1662
1663 this->segment_count = get_nearest_powerof2(lib->settings->get_int(lib->settings,
1664 "charon.ikesa_table_segments",
1665 DEFAULT_SEGMENT_COUNT));
1666 this->segment_count = max(1, min(this->segment_count, this->table_size));
1667 this->segment_mask = this->segment_count - 1;
1668
1669 this->ike_sa_table = (linked_list_t**)calloc(this->table_size, sizeof(linked_list_t*));
1670 memset(this->ike_sa_table, 0, this->table_size * sizeof(linked_list_t*));
1671
1672 this->segments = (segment_t*)calloc(this->segment_count, sizeof(segment_t));
1673 for (i = 0; i < this->segment_count; ++i)
1674 {
1675 this->segments[i].mutex = mutex_create(MUTEX_RECURSIVE);
1676 this->segments[i].count = 0;
1677 }
1678
1679 /* we use the same parameters as above for the hash table to track half-open SAs */
1680 this->half_open_table = (linked_list_t**)calloc(this->table_size, sizeof(linked_list_t*));
1681 memset(this->half_open_table, 0, this->table_size * sizeof(linked_list_t*));
1682
1683 this->half_open_segments = (shareable_segment_t*)calloc(this->segment_count, sizeof(shareable_segment_t));
1684 for (i = 0; i < this->segment_count; ++i)
1685 {
1686 this->half_open_segments[i].lock = rwlock_create(RWLOCK_DEFAULT);
1687 this->half_open_segments[i].count = 0;
1688 }
1689
1690 /* also for the hash table used for duplicate tests */
1691 this->connected_peers_table = (linked_list_t**)calloc(this->table_size, sizeof(linked_list_t*));
1692 memset(this->connected_peers_table, 0, this->table_size * sizeof(linked_list_t*));
1693
1694 this->connected_peers_segments = (shareable_segment_t*)calloc(this->segment_count, sizeof(shareable_segment_t));
1695 for (i = 0; i < this->segment_count; ++i)
1696 {
1697 this->connected_peers_segments[i].lock = rwlock_create(RWLOCK_DEFAULT);
1698 this->connected_peers_segments[i].count = 0;
1699 }
1700
1701 this->reuse_ikesa = lib->settings->get_bool(lib->settings,
1702 "charon.reuse_ikesa", TRUE);
1703 return &this->public;
1704 }