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