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