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