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
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>.
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
21 #include "ike_sa_manager.h"
24 #include <sa/ike_sa_id.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>
32 /* the default size of the hash table (MUST be a power of 2) */
33 #define DEFAULT_HASHTABLE_SIZE 1
35 /* the maximum size of the hash table (MUST be a power of 2) */
36 #define MAX_HASHTABLE_SIZE (1 << 30)
38 /* the default number of segments (MUST be a power of 2) */
39 #define DEFAULT_SEGMENT_COUNT 1
41 typedef struct entry_t entry_t
;
44 * An entry in the linked list, contains IKE_SA, locking and lookup data.
49 * Number of threads waiting for this ike_sa_t object.
54 * Condvar where threads can wait until ike_sa_t object is free for use again.
59 * Is this ike_sa currently checked out?
64 * Does this SA drives out new threads?
66 bool driveout_new_threads
;
69 * Does this SA drives out waiting threads?
71 bool driveout_waiting_threads
;
74 * Identification of an IKE_SA (SPIs).
76 ike_sa_id_t
*ike_sa_id
;
79 * The contained ike_sa_t object.
84 * hash of the IKE_SA_INIT message, used to detect retransmissions
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)
96 * As responder: Is this SA half-open?
101 * own identity, required for duplicate checking
103 identification_t
*my_id
;
106 * remote identity, required for duplicate checking
108 identification_t
*other_id
;
111 * message ID currently processing, if any
113 u_int32_t message_id
;
117 * Implementation of entry_t.destroy.
119 static status_t
entry_destroy(entry_t
*this)
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
);
134 * Creates a new entry for the ike_sa_t list.
136 static entry_t
*entry_create()
138 entry_t
*this = malloc_thing(entry_t
);
140 this->waiting_threads
= 0;
141 this->condvar
= condvar_create(CONDVAR_TYPE_DEFAULT
);
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
;
150 this->half_open
= FALSE
;
152 this->other_id
= NULL
;
153 this->ike_sa_id
= NULL
;
160 * Function that matches entry_t objects by initiator SPI and the hash of the
161 * IKE_SA_INIT message.
163 static bool entry_match_by_hash(entry_t
*entry
, ike_sa_id_t
*id
, chunk_t
*hash
)
165 return id
->get_responder_spi(id
) == 0 &&
166 id
->get_initiator_spi(id
) == entry
->ike_sa_id
->get_initiator_spi(entry
->ike_sa_id
) &&
167 chunk_equals(*hash
, entry
->init_hash
);
171 * Function that matches entry_t objects by ike_sa_id_t.
173 static bool entry_match_by_id(entry_t
*entry
, ike_sa_id_t
*id
)
175 if (id
->equals(id
, entry
->ike_sa_id
))
179 if ((id
->get_responder_spi(id
) == 0 ||
180 entry
->ike_sa_id
->get_responder_spi(entry
->ike_sa_id
) == 0) &&
181 id
->get_initiator_spi(id
) == entry
->ike_sa_id
->get_initiator_spi(entry
->ike_sa_id
))
183 /* this is TRUE for IKE_SAs that we initiated but have not yet received a response */
190 * Function that matches entry_t objects by ike_sa_t pointers.
192 static bool entry_match_by_sa(entry_t
*entry
, ike_sa_t
*ike_sa
)
194 return entry
->ike_sa
== ike_sa
;
198 * Hash function for ike_sa_id_t objects.
200 static u_int
ike_sa_id_hash(ike_sa_id_t
*ike_sa_id
)
202 /* we always use initiator spi as key */
203 return ike_sa_id
->get_initiator_spi(ike_sa_id
);
206 typedef struct half_open_t half_open_t
;
209 * Struct to manage half-open IKE_SAs per peer.
212 /** chunk of remote host address */
215 /** the number of half-open IKE_SAs with that host */
220 * Destroys a half_open_t object.
222 static void half_open_destroy(half_open_t
*this)
224 chunk_free(&this->other
);
229 * Function that matches half_open_t objects by the given IP address chunk.
231 static bool half_open_match(half_open_t
*half_open
, chunk_t
*addr
)
233 return chunk_equals(*addr
, half_open
->other
);
236 typedef struct connected_peers_t connected_peers_t
;
238 struct connected_peers_t
{
240 identification_t
*my_id
;
242 /** remote identity */
243 identification_t
*other_id
;
245 /** ip address family of peer */
248 /** list of ike_sa_id_t objects of IKE_SAs between the two identities */
252 static void connected_peers_destroy(connected_peers_t
*this)
254 this->my_id
->destroy(this->my_id
);
255 this->other_id
->destroy(this->other_id
);
256 this->sas
->destroy(this->sas
);
261 * Function that matches connected_peers_t objects by the given ids.
263 static bool connected_peers_match(connected_peers_t
*connected_peers
,
264 identification_t
*my_id
, identification_t
*other_id
,
267 return my_id
->equals(my_id
, connected_peers
->my_id
) &&
268 other_id
->equals(other_id
, connected_peers
->other_id
) &&
269 (!family
|| family
== connected_peers
->family
);
272 typedef struct segment_t segment_t
;
275 * Struct to manage segments of the hash table.
278 /** mutex to access a segment exclusively */
281 /** the number of entries in this segment */
285 typedef struct shareable_segment_t shareable_segment_t
;
288 * Struct to manage segments of the "half-open" and "connected peers" hash tables.
290 struct shareable_segment_t
{
291 /** rwlock to access a segment non-/exclusively */
294 /** the number of entries in this segment - in case of the "half-open table"
295 * it's the sum of all half_open_t.count in a segment. */
299 typedef struct private_ike_sa_manager_t private_ike_sa_manager_t
;
302 * Additional private members of ike_sa_manager_t.
304 struct private_ike_sa_manager_t
{
306 * Public interface of ike_sa_manager_t.
308 ike_sa_manager_t
public;
311 * Hash table with entries for the ike_sa_t objects.
313 linked_list_t
**ike_sa_table
;
316 * The size of the hash table.
321 * Mask to map the hashes to table rows.
326 * Segments of the hash table.
331 * The number of segments.
336 * Mask to map a table row to a segment.
341 * Hash table with half_open_t objects.
343 linked_list_t
**half_open_table
;
346 * Segments of the "half-open" hash table.
348 shareable_segment_t
*half_open_segments
;
351 * Hash table with connected_peers_t objects.
353 linked_list_t
**connected_peers_table
;
356 * Segments of the "connected peers" hash table.
358 shareable_segment_t
*connected_peers_segments
;
361 * RNG to get random SPIs for our side
366 * SHA1 hasher for IKE_SA_INIT retransmit detection
371 * reuse existing IKE_SAs in checkout_by_config
377 * Acquire a lock to access the segment of the table row with the given index.
378 * It also works with the segment index directly.
380 static void lock_single_segment(private_ike_sa_manager_t
*this, u_int index
)
382 mutex_t
*lock
= this->segments
[index
& this->segment_mask
].mutex
;
388 * Release the lock required to access the segment of the table row with the given index.
389 * It also works with the segment index directly.
391 static void unlock_single_segment(private_ike_sa_manager_t
*this, u_int index
)
393 mutex_t
*lock
= this->segments
[index
& this->segment_mask
].mutex
;
401 static void lock_all_segments(private_ike_sa_manager_t
*this)
405 for (i
= 0; i
< this->segment_count
; i
++)
407 this->segments
[i
].mutex
->lock(this->segments
[i
].mutex
);
412 * Unlock all segments
414 static void unlock_all_segments(private_ike_sa_manager_t
*this)
418 for (i
= 0; i
< this->segment_count
; i
++)
420 this->segments
[i
].mutex
->unlock(this->segments
[i
].mutex
);
424 typedef struct private_enumerator_t private_enumerator_t
;
427 * hash table enumerator implementation
429 struct private_enumerator_t
{
432 * implements enumerator interface
434 enumerator_t enumerator
;
437 * associated ike_sa_manager_t
439 private_ike_sa_manager_t
*manager
;
442 * current segment index
447 * currently enumerating entry
452 * current table row index
457 * enumerator for the current table row
459 enumerator_t
*current
;
462 METHOD(enumerator_t
, enumerate
, bool,
463 private_enumerator_t
*this, entry_t
**entry
, u_int
*segment
)
467 this->entry
->condvar
->signal(this->entry
->condvar
);
470 while (this->segment
< this->manager
->segment_count
)
472 while (this->row
< this->manager
->table_size
)
478 if (this->current
->enumerate(this->current
, &item
))
480 *entry
= this->entry
= item
;
481 *segment
= this->segment
;
484 this->current
->destroy(this->current
);
485 this->current
= NULL
;
486 unlock_single_segment(this->manager
, this->segment
);
492 lock_single_segment(this->manager
, this->segment
);
493 if ((list
= this->manager
->ike_sa_table
[this->row
]) != NULL
&&
494 list
->get_count(list
))
496 this->current
= list
->create_enumerator(list
);
499 unlock_single_segment(this->manager
, this->segment
);
501 this->row
+= this->manager
->segment_count
;
504 this->row
= this->segment
;
509 METHOD(enumerator_t
, enumerator_destroy
, void,
510 private_enumerator_t
*this)
514 this->entry
->condvar
->signal(this->entry
->condvar
);
518 this->current
->destroy(this->current
);
519 unlock_single_segment(this->manager
, this->segment
);
525 * Creates an enumerator to enumerate the entries in the hash table.
527 static enumerator_t
* create_table_enumerator(private_ike_sa_manager_t
*this)
529 private_enumerator_t
*enumerator
;
533 .enumerate
= (void*)_enumerate
,
534 .destroy
= _enumerator_destroy
,
538 return &enumerator
->enumerator
;
542 * Put an entry into the hash table.
543 * Note: The caller has to unlock the returned segment.
545 static u_int
put_entry(private_ike_sa_manager_t
*this, entry_t
*entry
)
550 row
= ike_sa_id_hash(entry
->ike_sa_id
) & this->table_mask
;
551 segment
= row
& this->segment_mask
;
553 lock_single_segment(this, segment
);
554 list
= this->ike_sa_table
[row
];
557 list
= this->ike_sa_table
[row
] = linked_list_create();
559 list
->insert_last(list
, entry
);
560 this->segments
[segment
].count
++;
565 * Remove an entry from the hash table.
566 * Note: The caller MUST have a lock on the segment of this entry.
568 static void remove_entry(private_ike_sa_manager_t
*this, entry_t
*entry
)
573 row
= ike_sa_id_hash(entry
->ike_sa_id
) & this->table_mask
;
574 segment
= row
& this->segment_mask
;
575 list
= this->ike_sa_table
[row
];
579 enumerator_t
*enumerator
;
581 enumerator
= list
->create_enumerator(list
);
582 while (enumerator
->enumerate(enumerator
, ¤t
))
584 if (current
== entry
)
586 list
->remove_at(list
, enumerator
);
587 this->segments
[segment
].count
--;
591 enumerator
->destroy(enumerator
);
596 * Remove the entry at the current enumerator position.
598 static void remove_entry_at(private_enumerator_t
*this)
603 linked_list_t
*list
= this->manager
->ike_sa_table
[this->row
];
604 list
->remove_at(list
, this->current
);
605 this->manager
->segments
[this->segment
].count
--;
610 * Find an entry using the provided match function to compare the entries for
613 static status_t
get_entry_by_match_function(private_ike_sa_manager_t
*this,
614 ike_sa_id_t
*ike_sa_id
, entry_t
**entry
, u_int
*segment
,
615 linked_list_match_t match
, void *p1
, void *p2
)
621 row
= ike_sa_id_hash(ike_sa_id
) & this->table_mask
;
622 seg
= row
& this->segment_mask
;
624 lock_single_segment(this, seg
);
625 list
= this->ike_sa_table
[row
];
628 if (list
->find_first(list
, match
, (void**)¤t
, p1
, p2
) == SUCCESS
)
632 /* the locked segment has to be unlocked by the caller */
636 unlock_single_segment(this, seg
);
641 * Find an entry by ike_sa_id_t.
642 * Note: On SUCCESS, the caller has to unlock the segment.
644 static status_t
get_entry_by_id(private_ike_sa_manager_t
*this,
645 ike_sa_id_t
*ike_sa_id
, entry_t
**entry
, u_int
*segment
)
647 return get_entry_by_match_function(this, ike_sa_id
, entry
, segment
,
648 (linked_list_match_t
)entry_match_by_id
, ike_sa_id
, NULL
);
652 * Find an entry by initiator SPI and IKE_SA_INIT hash.
653 * Note: On SUCCESS, the caller has to unlock the segment.
655 static status_t
get_entry_by_hash(private_ike_sa_manager_t
*this,
656 ike_sa_id_t
*ike_sa_id
, chunk_t hash
, entry_t
**entry
, u_int
*segment
)
658 return get_entry_by_match_function(this, ike_sa_id
, entry
, segment
,
659 (linked_list_match_t
)entry_match_by_hash
, ike_sa_id
, &hash
);
663 * Find an entry by IKE_SA pointer.
664 * Note: On SUCCESS, the caller has to unlock the segment.
666 static status_t
get_entry_by_sa(private_ike_sa_manager_t
*this,
667 ike_sa_id_t
*ike_sa_id
, ike_sa_t
*ike_sa
, entry_t
**entry
, u_int
*segment
)
669 return get_entry_by_match_function(this, ike_sa_id
, entry
, segment
,
670 (linked_list_match_t
)entry_match_by_sa
, ike_sa
, NULL
);
674 * Wait until no other thread is using an IKE_SA, return FALSE if entry not
677 static bool wait_for_entry(private_ike_sa_manager_t
*this, entry_t
*entry
,
680 if (entry
->driveout_new_threads
)
682 /* we are not allowed to get this */
685 while (entry
->checked_out
&& !entry
->driveout_waiting_threads
)
687 /* so wait until we can get it for us.
688 * we register us as waiting. */
689 entry
->waiting_threads
++;
690 entry
->condvar
->wait(entry
->condvar
, this->segments
[segment
].mutex
);
691 entry
->waiting_threads
--;
693 /* hm, a deletion request forbids us to get this SA, get next one */
694 if (entry
->driveout_waiting_threads
)
696 /* we must signal here, others may be waiting on it, too */
697 entry
->condvar
->signal(entry
->condvar
);
704 * Put a half-open SA into the hash table.
706 static void put_half_open(private_ike_sa_manager_t
*this, entry_t
*entry
)
708 half_open_t
*half_open
= NULL
;
714 addr
= entry
->other
->get_address(entry
->other
);
715 row
= chunk_hash(addr
) & this->table_mask
;
716 segment
= row
& this->segment_mask
;
717 lock
= this->half_open_segments
[segment
].lock
;
718 lock
->write_lock(lock
);
719 list
= this->half_open_table
[row
];
722 half_open_t
*current
;
724 if (list
->find_first(list
, (linked_list_match_t
)half_open_match
,
725 (void**)¤t
, &addr
) == SUCCESS
)
729 this->half_open_segments
[segment
].count
++;
734 list
= this->half_open_table
[row
] = linked_list_create();
740 .other
= chunk_clone(addr
),
743 list
->insert_last(list
, half_open
);
744 this->half_open_segments
[segment
].count
++;
750 * Remove a half-open SA from the hash table.
752 static void remove_half_open(private_ike_sa_manager_t
*this, entry_t
*entry
)
759 addr
= entry
->other
->get_address(entry
->other
);
760 row
= chunk_hash(addr
) & this->table_mask
;
761 segment
= row
& this->segment_mask
;
762 lock
= this->half_open_segments
[segment
].lock
;
763 lock
->write_lock(lock
);
764 list
= this->half_open_table
[row
];
767 half_open_t
*current
;
768 enumerator_t
*enumerator
;
770 enumerator
= list
->create_enumerator(list
);
771 while (enumerator
->enumerate(enumerator
, ¤t
))
773 if (half_open_match(current
, &addr
))
775 if (--current
->count
== 0)
777 list
->remove_at(list
, enumerator
);
778 half_open_destroy(current
);
780 this->half_open_segments
[segment
].count
--;
784 enumerator
->destroy(enumerator
);
790 * Put an SA between two peers into the hash table.
792 static void put_connected_peers(private_ike_sa_manager_t
*this, entry_t
*entry
)
794 connected_peers_t
*connected_peers
= NULL
;
795 chunk_t my_id
, other_id
;
800 my_id
= entry
->my_id
->get_encoding(entry
->my_id
);
801 other_id
= entry
->other_id
->get_encoding(entry
->other_id
);
802 row
= chunk_hash_inc(other_id
, chunk_hash(my_id
)) & this->table_mask
;
803 segment
= row
& this->segment_mask
;
804 lock
= this->connected_peers_segments
[segment
].lock
;
805 lock
->write_lock(lock
);
806 list
= this->connected_peers_table
[row
];
809 connected_peers_t
*current
;
811 if (list
->find_first(list
, (linked_list_match_t
)connected_peers_match
,
812 (void**)¤t
, entry
->my_id
, entry
->other_id
,
813 (uintptr_t)entry
->other
->get_family(entry
->other
)) == SUCCESS
)
815 connected_peers
= current
;
816 if (connected_peers
->sas
->find_first(connected_peers
->sas
,
817 (linked_list_match_t
)entry
->ike_sa_id
->equals
,
818 NULL
, entry
->ike_sa_id
) == SUCCESS
)
827 list
= this->connected_peers_table
[row
] = linked_list_create();
830 if (!connected_peers
)
832 INIT(connected_peers
,
833 .my_id
= entry
->my_id
->clone(entry
->my_id
),
834 .other_id
= entry
->other_id
->clone(entry
->other_id
),
835 .family
= entry
->other
->get_family(entry
->other
),
836 .sas
= linked_list_create(),
838 list
->insert_last(list
, connected_peers
);
840 connected_peers
->sas
->insert_last(connected_peers
->sas
,
841 entry
->ike_sa_id
->clone(entry
->ike_sa_id
));
842 this->connected_peers_segments
[segment
].count
++;
847 * Remove an SA between two peers from the hash table.
849 static void remove_connected_peers(private_ike_sa_manager_t
*this, entry_t
*entry
)
851 chunk_t my_id
, other_id
;
856 my_id
= entry
->my_id
->get_encoding(entry
->my_id
);
857 other_id
= entry
->other_id
->get_encoding(entry
->other_id
);
858 row
= chunk_hash_inc(other_id
, chunk_hash(my_id
)) & this->table_mask
;
859 segment
= row
& this->segment_mask
;
861 lock
= this->connected_peers_segments
[segment
].lock
;
862 lock
->write_lock(lock
);
863 list
= this->connected_peers_table
[row
];
866 connected_peers_t
*current
;
867 enumerator_t
*enumerator
;
869 enumerator
= list
->create_enumerator(list
);
870 while (enumerator
->enumerate(enumerator
, ¤t
))
872 if (connected_peers_match(current
, entry
->my_id
, entry
->other_id
,
873 (uintptr_t)entry
->other
->get_family(entry
->other
)))
875 ike_sa_id_t
*ike_sa_id
;
878 inner
= current
->sas
->create_enumerator(current
->sas
);
879 while (inner
->enumerate(inner
, &ike_sa_id
))
881 if (ike_sa_id
->equals(ike_sa_id
, entry
->ike_sa_id
))
883 current
->sas
->remove_at(current
->sas
, inner
);
884 ike_sa_id
->destroy(ike_sa_id
);
885 this->connected_peers_segments
[segment
].count
--;
889 inner
->destroy(inner
);
890 if (current
->sas
->get_count(current
->sas
) == 0)
892 list
->remove_at(list
, enumerator
);
893 connected_peers_destroy(current
);
898 enumerator
->destroy(enumerator
);
904 * Get a random SPI for new IKE_SAs
906 static u_int64_t
get_spi(private_ike_sa_manager_t
*this)
912 this->rng
->get_bytes(this->rng
, sizeof(spi
), (u_int8_t
*)&spi
);
917 METHOD(ike_sa_manager_t
, checkout
, ike_sa_t
*,
918 private_ike_sa_manager_t
*this, ike_sa_id_t
*ike_sa_id
)
920 ike_sa_t
*ike_sa
= NULL
;
924 DBG2(DBG_MGR
, "checkout IKE_SA");
926 if (get_entry_by_id(this, ike_sa_id
, &entry
, &segment
) == SUCCESS
)
928 if (wait_for_entry(this, entry
, segment
))
930 entry
->checked_out
= TRUE
;
931 ike_sa
= entry
->ike_sa
;
932 DBG2(DBG_MGR
, "IKE_SA %s[%u] successfully checked out",
933 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
));
935 unlock_single_segment(this, segment
);
937 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
941 METHOD(ike_sa_manager_t
, checkout_new
, ike_sa_t
*,
942 private_ike_sa_manager_t
* this, ike_version_t version
, bool initiator
)
944 ike_sa_id_t
*ike_sa_id
;
949 ike_sa_id
= ike_sa_id_create(get_spi(this), 0, TRUE
);
953 ike_sa_id
= ike_sa_id_create(0, get_spi(this), FALSE
);
955 ike_sa
= ike_sa_create(ike_sa_id
, initiator
, version
);
956 ike_sa_id
->destroy(ike_sa_id
);
960 DBG2(DBG_MGR
, "created IKE_SA %s[%u]", ike_sa
->get_name(ike_sa
),
961 ike_sa
->get_unique_id(ike_sa
));
966 METHOD(ike_sa_manager_t
, checkout_by_message
, ike_sa_t
*,
967 private_ike_sa_manager_t
* this, message_t
*message
)
971 ike_sa_t
*ike_sa
= NULL
;
973 ike_version_t ike_version
;
974 bool is_init
= FALSE
;
976 id
= message
->get_ike_sa_id(message
);
978 id
->switch_initiator(id
);
980 DBG2(DBG_MGR
, "checkout IKE_SA by message");
982 if (id
->get_responder_spi(id
) == 0)
984 if (message
->get_major_version(message
) == IKEV2_MAJOR_VERSION
)
986 if (message
->get_exchange_type(message
) == IKE_SA_INIT
&&
987 message
->get_request(message
))
995 if (message
->get_exchange_type(message
) == ID_PROT
||
996 message
->get_exchange_type(message
) == AGGRESSIVE
)
1004 if (is_init
&& this->hasher
)
1006 /* First request. Check for an IKE_SA with such a message hash. */
1009 this->hasher
->allocate_hash(this->hasher
,
1010 message
->get_packet_data(message
), &hash
);
1012 if (get_entry_by_hash(this, id
, hash
, &entry
, &segment
) == SUCCESS
)
1014 if (message
->get_exchange_type(message
) == IKE_SA_INIT
&&
1015 entry
->message_id
== 0)
1017 unlock_single_segment(this, segment
);
1020 DBG1(DBG_MGR
, "ignoring IKE_SA_INIT, already processing");
1023 else if (wait_for_entry(this, entry
, segment
))
1025 entry
->checked_out
= TRUE
;
1026 entry
->message_id
= message
->get_message_id(message
);
1027 ike_sa
= entry
->ike_sa
;
1028 DBG2(DBG_MGR
, "IKE_SA %s[%u] checked out by hash",
1029 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
));
1032 unlock_single_segment(this, segment
);
1037 /* no IKE_SA found, create a new one */
1038 id
->set_responder_spi(id
, get_spi(this));
1039 ike_sa
= ike_sa_create(id
, FALSE
, ike_version
);
1042 entry
= entry_create();
1043 /* a new SA checked out by message is a responder SA */
1044 entry
->ike_sa
= ike_sa
;
1045 entry
->ike_sa_id
= id
->clone(id
);
1047 segment
= put_entry(this, entry
);
1048 entry
->checked_out
= TRUE
;
1049 unlock_single_segment(this, segment
);
1051 entry
->message_id
= message
->get_message_id(message
);
1052 entry
->init_hash
= hash
;
1054 DBG2(DBG_MGR
, "created IKE_SA %s[%u]",
1055 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
));
1061 DBG1(DBG_MGR
, "ignoring message, no such IKE_SA");
1064 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1068 if (get_entry_by_id(this, id
, &entry
, &segment
) == SUCCESS
)
1070 /* only check out in IKEv2 if we are not already processing it */
1071 if (message
->get_request(message
) &&
1072 message
->get_message_id(message
) == entry
->message_id
)
1074 DBG1(DBG_MGR
, "ignoring request with ID %u, already processing",
1077 else if (wait_for_entry(this, entry
, segment
))
1079 ike_sa_id_t
*ike_id
;
1081 ike_id
= entry
->ike_sa
->get_id(entry
->ike_sa
);
1082 entry
->checked_out
= TRUE
;
1083 entry
->message_id
= message
->get_message_id(message
);
1084 if (ike_id
->get_responder_spi(ike_id
) == 0)
1086 ike_id
->set_responder_spi(ike_id
, id
->get_responder_spi(id
));
1088 ike_sa
= entry
->ike_sa
;
1089 DBG2(DBG_MGR
, "IKE_SA %s[%u] successfully checked out",
1090 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
));
1092 unlock_single_segment(this, segment
);
1095 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1099 METHOD(ike_sa_manager_t
, checkout_by_config
, ike_sa_t
*,
1100 private_ike_sa_manager_t
*this, peer_cfg_t
*peer_cfg
)
1102 enumerator_t
*enumerator
;
1104 ike_sa_t
*ike_sa
= NULL
;
1105 peer_cfg_t
*current_peer
;
1106 ike_cfg_t
*current_ike
;
1109 DBG2(DBG_MGR
, "checkout IKE_SA by config");
1111 if (!this->reuse_ikesa
)
1112 { /* IKE_SA reuse disable by config */
1113 ike_sa
= checkout_new(this, peer_cfg
->get_ike_version(peer_cfg
), TRUE
);
1114 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1118 enumerator
= create_table_enumerator(this);
1119 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1121 if (!wait_for_entry(this, entry
, segment
))
1125 if (entry
->ike_sa
->get_state(entry
->ike_sa
) == IKE_DELETING
)
1126 { /* skip IKE_SAs which are not usable */
1130 current_peer
= entry
->ike_sa
->get_peer_cfg(entry
->ike_sa
);
1131 if (current_peer
&& current_peer
->equals(current_peer
, peer_cfg
))
1133 current_ike
= current_peer
->get_ike_cfg(current_peer
);
1134 if (current_ike
->equals(current_ike
, peer_cfg
->get_ike_cfg(peer_cfg
)))
1136 entry
->checked_out
= TRUE
;
1137 ike_sa
= entry
->ike_sa
;
1138 DBG2(DBG_MGR
, "found existing IKE_SA %u with a '%s' config",
1139 ike_sa
->get_unique_id(ike_sa
),
1140 current_peer
->get_name(current_peer
));
1145 enumerator
->destroy(enumerator
);
1148 { /* no IKE_SA using such a config, hand out a new */
1149 ike_sa
= checkout_new(this, peer_cfg
->get_ike_version(peer_cfg
), TRUE
);
1151 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1155 METHOD(ike_sa_manager_t
, checkout_by_id
, ike_sa_t
*,
1156 private_ike_sa_manager_t
*this, u_int32_t id
, bool child
)
1158 enumerator_t
*enumerator
, *children
;
1160 ike_sa_t
*ike_sa
= NULL
;
1161 child_sa_t
*child_sa
;
1164 DBG2(DBG_MGR
, "checkout IKE_SA by ID");
1166 enumerator
= create_table_enumerator(this);
1167 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1169 if (wait_for_entry(this, entry
, segment
))
1171 /* look for a child with such a reqid ... */
1174 children
= entry
->ike_sa
->create_child_sa_enumerator(entry
->ike_sa
);
1175 while (children
->enumerate(children
, (void**)&child_sa
))
1177 if (child_sa
->get_reqid(child_sa
) == id
)
1179 ike_sa
= entry
->ike_sa
;
1183 children
->destroy(children
);
1185 else /* ... or for a IKE_SA with such a unique id */
1187 if (entry
->ike_sa
->get_unique_id(entry
->ike_sa
) == id
)
1189 ike_sa
= entry
->ike_sa
;
1192 /* got one, return */
1195 entry
->checked_out
= TRUE
;
1196 DBG2(DBG_MGR
, "IKE_SA %s[%u] successfully checked out",
1197 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
));
1202 enumerator
->destroy(enumerator
);
1204 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1208 METHOD(ike_sa_manager_t
, checkout_by_name
, ike_sa_t
*,
1209 private_ike_sa_manager_t
*this, char *name
, bool child
)
1211 enumerator_t
*enumerator
, *children
;
1213 ike_sa_t
*ike_sa
= NULL
;
1214 child_sa_t
*child_sa
;
1217 enumerator
= create_table_enumerator(this);
1218 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1220 if (wait_for_entry(this, entry
, segment
))
1222 /* look for a child with such a policy name ... */
1225 children
= entry
->ike_sa
->create_child_sa_enumerator(entry
->ike_sa
);
1226 while (children
->enumerate(children
, (void**)&child_sa
))
1228 if (streq(child_sa
->get_name(child_sa
), name
))
1230 ike_sa
= entry
->ike_sa
;
1234 children
->destroy(children
);
1236 else /* ... or for a IKE_SA with such a connection name */
1238 if (streq(entry
->ike_sa
->get_name(entry
->ike_sa
), name
))
1240 ike_sa
= entry
->ike_sa
;
1243 /* got one, return */
1246 entry
->checked_out
= TRUE
;
1247 DBG2(DBG_MGR
, "IKE_SA %s[%u] successfully checked out",
1248 ike_sa
->get_name(ike_sa
), ike_sa
->get_unique_id(ike_sa
));
1253 enumerator
->destroy(enumerator
);
1255 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1260 * enumerator filter function, waiting variant
1262 static bool enumerator_filter_wait(private_ike_sa_manager_t
*this,
1263 entry_t
**in
, ike_sa_t
**out
, u_int
*segment
)
1265 if (wait_for_entry(this, *in
, *segment
))
1267 *out
= (*in
)->ike_sa
;
1274 * enumerator filter function, skipping variant
1276 static bool enumerator_filter_skip(private_ike_sa_manager_t
*this,
1277 entry_t
**in
, ike_sa_t
**out
, u_int
*segment
)
1279 if (!(*in
)->driveout_new_threads
&&
1280 !(*in
)->driveout_waiting_threads
&&
1281 !(*in
)->checked_out
)
1283 *out
= (*in
)->ike_sa
;
1289 METHOD(ike_sa_manager_t
, create_enumerator
, enumerator_t
*,
1290 private_ike_sa_manager_t
* this, bool wait
)
1292 return enumerator_create_filter(create_table_enumerator(this),
1293 wait ?
(void*)enumerator_filter_wait
: (void*)enumerator_filter_skip
,
1297 METHOD(ike_sa_manager_t
, checkin
, void,
1298 private_ike_sa_manager_t
*this, ike_sa_t
*ike_sa
)
1300 /* to check the SA back in, we look for the pointer of the ike_sa
1302 * The lookup is done by initiator SPI, so even if the SPI has changed (e.g.
1303 * on reception of a IKE_SA_INIT response) the lookup will work but
1304 * updating of the SPI MAY be necessary...
1307 ike_sa_id_t
*ike_sa_id
;
1309 identification_t
*my_id
, *other_id
;
1312 ike_sa_id
= ike_sa
->get_id(ike_sa
);
1313 my_id
= ike_sa
->get_my_id(ike_sa
);
1314 other_id
= ike_sa
->get_other_id(ike_sa
);
1315 other
= ike_sa
->get_other_host(ike_sa
);
1317 DBG2(DBG_MGR
, "checkin IKE_SA %s[%u]", ike_sa
->get_name(ike_sa
),
1318 ike_sa
->get_unique_id(ike_sa
));
1320 /* look for the entry */
1321 if (get_entry_by_sa(this, ike_sa_id
, ike_sa
, &entry
, &segment
) == SUCCESS
)
1323 /* ike_sa_id must be updated */
1324 entry
->ike_sa_id
->replace_values(entry
->ike_sa_id
, ike_sa
->get_id(ike_sa
));
1325 /* signal waiting threads */
1326 entry
->checked_out
= FALSE
;
1327 entry
->message_id
= -1;
1328 /* check if this SA is half-open */
1329 if (entry
->half_open
&& ike_sa
->get_state(ike_sa
) != IKE_CONNECTING
)
1331 /* not half open anymore */
1332 entry
->half_open
= FALSE
;
1333 remove_half_open(this, entry
);
1335 else if (entry
->half_open
&& !other
->ip_equals(other
, entry
->other
))
1337 /* the other host's IP has changed, we must update the hash table */
1338 remove_half_open(this, entry
);
1339 DESTROY_IF(entry
->other
);
1340 entry
->other
= other
->clone(other
);
1341 put_half_open(this, entry
);
1343 else if (!entry
->half_open
&&
1344 !entry
->ike_sa_id
->is_initiator(entry
->ike_sa_id
) &&
1345 ike_sa
->get_state(ike_sa
) == IKE_CONNECTING
)
1347 /* this is a new half-open SA */
1348 entry
->half_open
= TRUE
;
1349 entry
->other
= other
->clone(other
);
1350 put_half_open(this, entry
);
1352 DBG2(DBG_MGR
, "check-in of IKE_SA successful.");
1353 entry
->condvar
->signal(entry
->condvar
);
1357 entry
= entry_create();
1358 entry
->ike_sa_id
= ike_sa_id
->clone(ike_sa_id
);
1359 entry
->ike_sa
= ike_sa
;
1360 segment
= put_entry(this, entry
);
1363 /* apply identities for duplicate test */
1364 if (ike_sa
->get_state(ike_sa
) == IKE_ESTABLISHED
&&
1365 entry
->my_id
== NULL
&& entry
->other_id
== NULL
)
1367 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
1369 /* If authenticated and received INITIAL_CONTACT,
1370 * delete any existing IKE_SAs with that peer. */
1371 if (ike_sa
->has_condition(ike_sa
, COND_INIT_CONTACT_SEEN
))
1373 this->public.check_uniqueness(&this->public, ike_sa
, TRUE
);
1374 ike_sa
->set_condition(ike_sa
, COND_INIT_CONTACT_SEEN
, FALSE
);
1378 entry
->my_id
= my_id
->clone(my_id
);
1379 entry
->other_id
= other_id
->clone(other_id
);
1382 entry
->other
= other
->clone(other
);
1384 put_connected_peers(this, entry
);
1387 unlock_single_segment(this, segment
);
1389 charon
->bus
->set_sa(charon
->bus
, NULL
);
1392 METHOD(ike_sa_manager_t
, checkin_and_destroy
, void,
1393 private_ike_sa_manager_t
*this, ike_sa_t
*ike_sa
)
1395 /* deletion is a bit complex, we must ensure that no thread is waiting for
1397 * We take this SA from the table, and start signaling while threads
1398 * are in the condvar.
1401 ike_sa_id_t
*ike_sa_id
;
1404 ike_sa_id
= ike_sa
->get_id(ike_sa
);
1406 DBG2(DBG_MGR
, "checkin and destroy IKE_SA %s[%u]", ike_sa
->get_name(ike_sa
),
1407 ike_sa
->get_unique_id(ike_sa
));
1409 if (get_entry_by_sa(this, ike_sa_id
, ike_sa
, &entry
, &segment
) == SUCCESS
)
1411 /* drive out waiting threads, as we are in hurry */
1412 entry
->driveout_waiting_threads
= TRUE
;
1413 /* mark it, so no new threads can get this entry */
1414 entry
->driveout_new_threads
= TRUE
;
1415 /* wait until all workers have done their work */
1416 while (entry
->waiting_threads
)
1419 entry
->condvar
->broadcast(entry
->condvar
);
1420 /* they will wake us again when their work is done */
1421 entry
->condvar
->wait(entry
->condvar
, this->segments
[segment
].mutex
);
1423 remove_entry(this, entry
);
1424 unlock_single_segment(this, segment
);
1426 if (entry
->half_open
)
1428 remove_half_open(this, entry
);
1430 if (entry
->my_id
&& entry
->other_id
)
1432 remove_connected_peers(this, entry
);
1435 entry_destroy(entry
);
1437 DBG2(DBG_MGR
, "check-in and destroy of IKE_SA successful");
1441 DBG1(DBG_MGR
, "tried to check-in and delete nonexisting IKE_SA");
1442 ike_sa
->destroy(ike_sa
);
1444 charon
->bus
->set_sa(charon
->bus
, NULL
);
1448 * Cleanup function for create_id_enumerator
1450 static void id_enumerator_cleanup(linked_list_t
*ids
)
1452 ids
->destroy_offset(ids
, offsetof(ike_sa_id_t
, destroy
));
1455 METHOD(ike_sa_manager_t
, create_id_enumerator
, enumerator_t
*,
1456 private_ike_sa_manager_t
*this, identification_t
*me
,
1457 identification_t
*other
, int family
)
1459 linked_list_t
*list
, *ids
= NULL
;
1460 connected_peers_t
*current
;
1464 row
= chunk_hash_inc(other
->get_encoding(other
),
1465 chunk_hash(me
->get_encoding(me
))) & this->table_mask
;
1466 segment
= row
& this->segment_mask
;
1468 lock
= this->connected_peers_segments
[segment
& this->segment_mask
].lock
;
1469 lock
->read_lock(lock
);
1470 list
= this->connected_peers_table
[row
];
1473 if (list
->find_first(list
, (linked_list_match_t
)connected_peers_match
,
1474 (void**)¤t
, me
, other
, (uintptr_t)family
) == SUCCESS
)
1476 ids
= current
->sas
->clone_offset(current
->sas
,
1477 offsetof(ike_sa_id_t
, clone
));
1484 return enumerator_create_empty();
1486 return enumerator_create_cleaner(ids
->create_enumerator(ids
),
1487 (void*)id_enumerator_cleanup
, ids
);
1490 METHOD(ike_sa_manager_t
, check_uniqueness
, bool,
1491 private_ike_sa_manager_t
*this, ike_sa_t
*ike_sa
, bool force_replace
)
1493 bool cancel
= FALSE
;
1494 peer_cfg_t
*peer_cfg
;
1495 unique_policy_t policy
;
1496 enumerator_t
*enumerator
;
1497 ike_sa_id_t
*id
= NULL
;
1498 identification_t
*me
, *other
;
1501 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
1502 policy
= peer_cfg
->get_unique_policy(peer_cfg
);
1503 if (policy
== UNIQUE_NO
&& !force_replace
)
1507 me
= ike_sa
->get_my_id(ike_sa
);
1508 other
= ike_sa
->get_other_id(ike_sa
);
1509 other_host
= ike_sa
->get_other_host(ike_sa
);
1511 enumerator
= create_id_enumerator(this, me
, other
,
1512 other_host
->get_family(other_host
));
1513 while (enumerator
->enumerate(enumerator
, &id
))
1515 status_t status
= SUCCESS
;
1516 ike_sa_t
*duplicate
;
1518 duplicate
= checkout(this, id
);
1525 DBG1(DBG_IKE
, "destroying duplicate IKE_SA for peer '%Y', "
1526 "received INITIAL_CONTACT", other
);
1527 checkin_and_destroy(this, duplicate
);
1530 peer_cfg
= duplicate
->get_peer_cfg(duplicate
);
1531 if (peer_cfg
&& peer_cfg
->equals(peer_cfg
, ike_sa
->get_peer_cfg(ike_sa
)))
1533 switch (duplicate
->get_state(duplicate
))
1535 case IKE_ESTABLISHED
:
1539 case UNIQUE_REPLACE
:
1540 DBG1(DBG_IKE
, "deleting duplicate IKE_SA for peer "
1541 "'%Y' due to uniqueness policy", other
);
1542 status
= duplicate
->delete(duplicate
);
1546 /* we keep the first IKE_SA and delete all
1547 * other duplicates that might exist */
1548 policy
= UNIQUE_REPLACE
;
1558 if (status
== DESTROY_ME
)
1560 checkin_and_destroy(this, duplicate
);
1564 checkin(this, duplicate
);
1567 enumerator
->destroy(enumerator
);
1568 /* reset thread's current IKE_SA after checkin */
1569 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1573 METHOD(ike_sa_manager_t
, has_contact
, bool,
1574 private_ike_sa_manager_t
*this, identification_t
*me
,
1575 identification_t
*other
, int family
)
1577 linked_list_t
*list
;
1582 row
= chunk_hash_inc(other
->get_encoding(other
),
1583 chunk_hash(me
->get_encoding(me
))) & this->table_mask
;
1584 segment
= row
& this->segment_mask
;
1585 lock
= this->connected_peers_segments
[segment
& this->segment_mask
].lock
;
1586 lock
->read_lock(lock
);
1587 list
= this->connected_peers_table
[row
];
1590 if (list
->find_first(list
, (linked_list_match_t
)connected_peers_match
,
1591 NULL
, me
, other
, family
) == SUCCESS
)
1601 METHOD(ike_sa_manager_t
, get_count
, u_int
,
1602 private_ike_sa_manager_t
*this)
1604 u_int segment
, count
= 0;
1607 for (segment
= 0; segment
< this->segment_count
; segment
++)
1609 mutex
= this->segments
[segment
& this->segment_mask
].mutex
;
1611 count
+= this->segments
[segment
].count
;
1612 mutex
->unlock(mutex
);
1617 METHOD(ike_sa_manager_t
, get_half_open_count
, u_int
,
1618 private_ike_sa_manager_t
*this, host_t
*ip
)
1620 linked_list_t
*list
;
1628 addr
= ip
->get_address(ip
);
1629 row
= chunk_hash(addr
) & this->table_mask
;
1630 segment
= row
& this->segment_mask
;
1631 lock
= this->half_open_segments
[segment
& this->segment_mask
].lock
;
1632 lock
->read_lock(lock
);
1633 if ((list
= this->half_open_table
[row
]) != NULL
)
1635 half_open_t
*current
;
1637 if (list
->find_first(list
, (linked_list_match_t
)half_open_match
,
1638 (void**)¤t
, &addr
) == SUCCESS
)
1640 count
= current
->count
;
1647 for (segment
= 0; segment
< this->segment_count
; segment
++)
1649 lock
= this->half_open_segments
[segment
& this->segment_mask
].lock
;
1650 lock
->read_lock(lock
);
1651 count
+= this->half_open_segments
[segment
].count
;
1658 METHOD(ike_sa_manager_t
, flush
, void,
1659 private_ike_sa_manager_t
*this)
1661 /* destroy all list entries */
1662 enumerator_t
*enumerator
;
1666 lock_all_segments(this);
1667 DBG2(DBG_MGR
, "going to destroy IKE_SA manager and all managed IKE_SA's");
1668 /* Step 1: drive out all waiting threads */
1669 DBG2(DBG_MGR
, "set driveout flags for all stored IKE_SA's");
1670 enumerator
= create_table_enumerator(this);
1671 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1673 /* do not accept new threads, drive out waiting threads */
1674 entry
->driveout_new_threads
= TRUE
;
1675 entry
->driveout_waiting_threads
= TRUE
;
1677 enumerator
->destroy(enumerator
);
1678 DBG2(DBG_MGR
, "wait for all threads to leave IKE_SA's");
1679 /* Step 2: wait until all are gone */
1680 enumerator
= create_table_enumerator(this);
1681 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1683 while (entry
->waiting_threads
|| entry
->checked_out
)
1686 entry
->condvar
->broadcast(entry
->condvar
);
1687 /* go sleeping until they are gone */
1688 entry
->condvar
->wait(entry
->condvar
, this->segments
[segment
].mutex
);
1691 enumerator
->destroy(enumerator
);
1692 DBG2(DBG_MGR
, "delete all IKE_SA's");
1693 /* Step 3: initiate deletion of all IKE_SAs */
1694 enumerator
= create_table_enumerator(this);
1695 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1697 charon
->bus
->set_sa(charon
->bus
, entry
->ike_sa
);
1698 if (entry
->ike_sa
->get_version(entry
->ike_sa
) == IKEV2
)
1699 { /* as the delete never gets processed, fire down events */
1700 switch (entry
->ike_sa
->get_state(entry
->ike_sa
))
1702 case IKE_ESTABLISHED
:
1705 charon
->bus
->ike_updown(charon
->bus
, entry
->ike_sa
, FALSE
);
1711 entry
->ike_sa
->delete(entry
->ike_sa
);
1713 enumerator
->destroy(enumerator
);
1715 DBG2(DBG_MGR
, "destroy all entries");
1716 /* Step 4: destroy all entries */
1717 enumerator
= create_table_enumerator(this);
1718 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1720 charon
->bus
->set_sa(charon
->bus
, entry
->ike_sa
);
1721 if (entry
->half_open
)
1723 remove_half_open(this, entry
);
1725 if (entry
->my_id
&& entry
->other_id
)
1727 remove_connected_peers(this, entry
);
1729 remove_entry_at((private_enumerator_t
*)enumerator
);
1730 entry_destroy(entry
);
1732 enumerator
->destroy(enumerator
);
1733 charon
->bus
->set_sa(charon
->bus
, NULL
);
1734 unlock_all_segments(this);
1736 this->rng
->destroy(this->rng
);
1738 this->hasher
->destroy(this->hasher
);
1739 this->hasher
= NULL
;
1742 METHOD(ike_sa_manager_t
, destroy
, void,
1743 private_ike_sa_manager_t
*this)
1747 for (i
= 0; i
< this->table_size
; i
++)
1749 DESTROY_IF(this->ike_sa_table
[i
]);
1750 DESTROY_IF(this->half_open_table
[i
]);
1751 DESTROY_IF(this->connected_peers_table
[i
]);
1753 free(this->ike_sa_table
);
1754 free(this->half_open_table
);
1755 free(this->connected_peers_table
);
1756 for (i
= 0; i
< this->segment_count
; i
++)
1758 this->segments
[i
].mutex
->destroy(this->segments
[i
].mutex
);
1759 this->half_open_segments
[i
].lock
->destroy(this->half_open_segments
[i
].lock
);
1760 this->connected_peers_segments
[i
].lock
->destroy(this->connected_peers_segments
[i
].lock
);
1762 free(this->segments
);
1763 free(this->half_open_segments
);
1764 free(this->connected_peers_segments
);
1770 * This function returns the next-highest power of two for the given number.
1771 * The algorithm works by setting all bits on the right-hand side of the most
1772 * significant 1 to 1 and then increments the whole number so it rolls over
1773 * to the nearest power of two. Note: returns 0 for n == 0
1775 static u_int
get_nearest_powerof2(u_int n
)
1780 for (i
= 1; i
< sizeof(u_int
) * 8; i
<<= 1)
1788 * Described in header.
1790 ike_sa_manager_t
*ike_sa_manager_create()
1792 private_ike_sa_manager_t
*this;
1797 .checkout
= _checkout
,
1798 .checkout_new
= _checkout_new
,
1799 .checkout_by_message
= _checkout_by_message
,
1800 .checkout_by_config
= _checkout_by_config
,
1801 .checkout_by_id
= _checkout_by_id
,
1802 .checkout_by_name
= _checkout_by_name
,
1803 .check_uniqueness
= _check_uniqueness
,
1804 .has_contact
= _has_contact
,
1805 .create_enumerator
= _create_enumerator
,
1806 .create_id_enumerator
= _create_id_enumerator
,
1807 .checkin
= _checkin
,
1808 .checkin_and_destroy
= _checkin_and_destroy
,
1809 .get_count
= _get_count
,
1810 .get_half_open_count
= _get_half_open_count
,
1812 .destroy
= _destroy
,
1816 this->hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_PREFERRED
);
1817 if (this->hasher
== NULL
)
1819 DBG1(DBG_MGR
, "manager initialization failed, no hasher supported");
1823 this->rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
1824 if (this->rng
== NULL
)
1826 DBG1(DBG_MGR
, "manager initialization failed, no RNG supported");
1827 this->hasher
->destroy(this->hasher
);
1832 this->table_size
= get_nearest_powerof2(lib
->settings
->get_int(lib
->settings
,
1833 "charon.ikesa_table_size", DEFAULT_HASHTABLE_SIZE
));
1834 this->table_size
= max(1, min(this->table_size
, MAX_HASHTABLE_SIZE
));
1835 this->table_mask
= this->table_size
- 1;
1837 this->segment_count
= get_nearest_powerof2(lib
->settings
->get_int(lib
->settings
,
1838 "charon.ikesa_table_segments", DEFAULT_SEGMENT_COUNT
));
1839 this->segment_count
= max(1, min(this->segment_count
, this->table_size
));
1840 this->segment_mask
= this->segment_count
- 1;
1841 this->ike_sa_table
= calloc(this->table_size
, sizeof(linked_list_t
*));
1843 this->segments
= (segment_t
*)calloc(this->segment_count
, sizeof(segment_t
));
1844 for (i
= 0; i
< this->segment_count
; i
++)
1846 this->segments
[i
].mutex
= mutex_create(MUTEX_TYPE_RECURSIVE
);
1847 this->segments
[i
].count
= 0;
1850 /* we use the same table parameters for the table to track half-open SAs */
1851 this->half_open_table
= calloc(this->table_size
, sizeof(linked_list_t
*));
1852 this->half_open_segments
= calloc(this->segment_count
, sizeof(shareable_segment_t
));
1853 for (i
= 0; i
< this->segment_count
; i
++)
1855 this->half_open_segments
[i
].lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
);
1856 this->half_open_segments
[i
].count
= 0;
1859 /* also for the hash table used for duplicate tests */
1860 this->connected_peers_table
= calloc(this->table_size
, sizeof(linked_list_t
*));
1861 this->connected_peers_segments
= calloc(this->segment_count
, sizeof(shareable_segment_t
));
1862 for (i
= 0; i
< this->segment_count
; i
++)
1864 this->connected_peers_segments
[i
].lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
);
1865 this->connected_peers_segments
[i
].count
= 0;
1868 this->reuse_ikesa
= lib
->settings
->get_bool(lib
->settings
,
1869 "charon.reuse_ikesa", TRUE
);
1870 return &this->public;