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