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