2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2006 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 #include "ike_sa_manager.h"
25 #include <sa/ike_sa_id.h>
27 #include <utils/mutex.h>
28 #include <utils/linked_list.h>
29 #include <crypto/hashers/hasher.h>
31 /* the default size of the hash table (MUST be a power of 2) */
32 #define DEFAULT_HASHTABLE_SIZE 1
34 /* the maximum size of the hash table (MUST be a power of 2) */
35 #define MAX_HASHTABLE_SIZE (1 << 30)
37 /* the default number of segments (MUST be a power of 2) */
38 #define DEFAULT_SEGMENT_COUNT 1
40 typedef struct entry_t entry_t
;
43 * An entry in the linked list, contains IKE_SA, locking and lookup data.
48 * Number of threads waiting for this ike_sa_t object.
53 * Condvar where threads can wait until ike_sa_t object is free for use again.
58 * Is this ike_sa currently checked out?
63 * Does this SA drives out new threads?
65 bool driveout_new_threads
;
68 * Does this SA drives out waiting threads?
70 bool driveout_waiting_threads
;
73 * Identification of an IKE_SA (SPIs).
75 ike_sa_id_t
*ike_sa_id
;
78 * The contained ike_sa_t object.
83 * hash of the IKE_SA_INIT message, used to detect retransmissions
88 * remote host address, required for DoS detection
93 * As responder: Is this SA half-open?
98 * own identity, required for duplicate checking
100 identification_t
*my_id
;
103 * remote identity, required for duplicate checking
105 identification_t
*other_id
;
108 * message ID currently processing, if any
110 u_int32_t message_id
;
114 * Implementation of entry_t.destroy.
116 static status_t
entry_destroy(entry_t
*this)
118 /* also destroy IKE SA */
119 this->ike_sa
->destroy(this->ike_sa
);
120 this->ike_sa_id
->destroy(this->ike_sa_id
);
121 chunk_free(&this->init_hash
);
122 DESTROY_IF(this->other
);
123 DESTROY_IF(this->my_id
);
124 DESTROY_IF(this->other_id
);
125 this->condvar
->destroy(this->condvar
);
131 * Creates a new entry for the ike_sa_t list.
133 static entry_t
*entry_create()
135 entry_t
*this = malloc_thing(entry_t
);
137 this->waiting_threads
= 0;
138 this->condvar
= condvar_create(CONDVAR_DEFAULT
);
140 /* we set checkout flag when we really give it out */
141 this->checked_out
= FALSE
;
142 this->driveout_new_threads
= FALSE
;
143 this->driveout_waiting_threads
= FALSE
;
144 this->message_id
= -1;
145 this->init_hash
= chunk_empty
;
147 this->half_open
= FALSE
;
149 this->other_id
= NULL
;
150 this->ike_sa_id
= NULL
;
157 * Function that matches entry_t objects by initiator SPI and the hash of the
158 * IKE_SA_INIT message.
160 static bool entry_match_by_hash(entry_t
*entry
, ike_sa_id_t
*id
, chunk_t
*hash
)
162 return id
->get_responder_spi(id
) == 0 &&
163 id
->is_initiator(id
) == entry
->ike_sa_id
->is_initiator(entry
->ike_sa_id
) &&
164 id
->get_initiator_spi(id
) == entry
->ike_sa_id
->get_initiator_spi(entry
->ike_sa_id
) &&
165 chunk_equals(*hash
, entry
->init_hash
);
169 * Function that matches entry_t objects by ike_sa_id_t.
171 static bool entry_match_by_id(entry_t
*entry
, ike_sa_id_t
*id
)
173 if (id
->equals(id
, entry
->ike_sa_id
))
177 if (entry
->ike_sa_id
->get_responder_spi(entry
->ike_sa_id
) == 0 &&
178 id
->is_initiator(id
) == entry
->ike_sa_id
->is_initiator(entry
->ike_sa_id
) &&
179 id
->get_initiator_spi(id
) == entry
->ike_sa_id
->get_initiator_spi(entry
->ike_sa_id
))
181 /* this is TRUE for IKE_SAs that we initiated but have not yet received a response */
188 * Function that matches entry_t objects by ike_sa_t pointers.
190 static bool entry_match_by_sa(entry_t
*entry
, ike_sa_t
*ike_sa
)
192 return entry
->ike_sa
== ike_sa
;
196 * Hash function for ike_sa_id_t objects.
198 static u_int
ike_sa_id_hash(ike_sa_id_t
*ike_sa_id
)
200 /* we always use initiator spi as key */
201 return ike_sa_id
->get_initiator_spi(ike_sa_id
);
204 typedef struct half_open_t half_open_t
;
207 * Struct to manage half-open IKE_SAs per peer.
210 /** chunk of remote host address */
213 /** the number of half-open IKE_SAs with that host */
218 * Destroys a half_open_t object.
220 static void half_open_destroy(half_open_t
*this)
222 chunk_free(&this->other
);
227 * Function that matches half_open_t objects by the given IP address chunk.
229 static bool half_open_match(half_open_t
*half_open
, chunk_t
*addr
)
231 return chunk_equals(*addr
, half_open
->other
);
234 typedef struct connected_peers_t connected_peers_t
;
236 struct connected_peers_t
{
238 identification_t
*my_id
;
240 /** remote identity */
241 identification_t
*other_id
;
243 /** list of ike_sa_id_t objects of IKE_SAs between the two identities */
247 static void connected_peers_destroy(connected_peers_t
*this)
249 this->my_id
->destroy(this->my_id
);
250 this->other_id
->destroy(this->other_id
);
251 this->sas
->destroy(this->sas
);
256 * Function that matches connected_peers_t objects by the given ids.
258 static bool connected_peers_match(connected_peers_t
*connected_peers
,
259 identification_t
*my_id
, identification_t
*other_id
)
261 return my_id
->equals(my_id
, connected_peers
->my_id
) &&
262 other_id
->equals(other_id
, connected_peers
->other_id
);
265 typedef struct segment_t segment_t
;
268 * Struct to manage segments of the hash table.
271 /** mutex to access a segment exclusively */
274 /** the number of entries in this segment */
278 typedef struct shareable_segment_t shareable_segment_t
;
281 * Struct to manage segments of the "half-open" and "connected peers" hash tables.
283 struct shareable_segment_t
{
284 /** rwlock to access a segment non-/exclusively */
287 /** the number of entries in this segment - in case of the "half-open table"
288 * it's the sum of all half_open_t.count in a segment. */
292 typedef struct private_ike_sa_manager_t private_ike_sa_manager_t
;
295 * Additional private members of ike_sa_manager_t.
297 struct private_ike_sa_manager_t
{
299 * Public interface of ike_sa_manager_t.
301 ike_sa_manager_t
public;
304 * Hash table with entries for the ike_sa_t objects.
306 linked_list_t
**ike_sa_table
;
309 * The size of the hash table.
314 * Mask to map the hashes to table rows.
319 * Segments of the hash table.
324 * The number of segments.
329 * Mask to map a table row to a segment.
334 * Hash table with half_open_t objects.
336 linked_list_t
**half_open_table
;
339 * Segments of the "half-open" hash table.
341 shareable_segment_t
*half_open_segments
;
344 * Hash table with connected_peers_t objects.
346 linked_list_t
**connected_peers_table
;
349 * Segments of the "connected peers" hash table.
351 shareable_segment_t
*connected_peers_segments
;
354 * RNG to get random SPIs for our side
359 * SHA1 hasher for IKE_SA_INIT retransmit detection
364 * reuse existing IKE_SAs in checkout_by_config
370 * Acquire a lock to access the segment of the table row with the given index.
371 * It also works with the segment index directly.
373 static void lock_single_segment(private_ike_sa_manager_t
*this, u_int index
)
375 mutex_t
*lock
= this->segments
[index
& this->segment_mask
].mutex
;
381 * Release the lock required to access the segment of the table row with the given index.
382 * It also works with the segment index directly.
384 static void unlock_single_segment(private_ike_sa_manager_t
*this, u_int index
)
386 mutex_t
*lock
= this->segments
[index
& this->segment_mask
].mutex
;
394 static void lock_all_segments(private_ike_sa_manager_t
*this)
398 for (i
= 0; i
< this->segment_count
; ++i
)
400 this->segments
[i
].mutex
->lock(this->segments
[i
].mutex
);
405 * Unlock all segments
407 static void unlock_all_segments(private_ike_sa_manager_t
*this)
411 for (i
= 0; i
< this->segment_count
; ++i
)
413 this->segments
[i
].mutex
->unlock(this->segments
[i
].mutex
);
417 typedef struct private_enumerator_t private_enumerator_t
;
420 * hash table enumerator implementation
422 struct private_enumerator_t
{
425 * implements enumerator interface
427 enumerator_t enumerator
;
430 * associated ike_sa_manager_t
432 private_ike_sa_manager_t
*manager
;
435 * current segment index
440 * current table row index
445 * enumerator for the current table row
447 enumerator_t
*current
;
451 * Implementation of private_enumerator_t.enumerator.enumerate.
453 static bool enumerate(private_enumerator_t
*this, entry_t
**entry
, u_int
*segment
)
455 while (this->segment
< this->manager
->segment_count
)
457 while (this->row
< this->manager
->table_size
)
463 if (this->current
->enumerate(this->current
, (void**)&item
))
466 *segment
= this->segment
;
469 this->current
->destroy(this->current
);
470 this->current
= NULL
;
471 unlock_single_segment(this->manager
, this->segment
);
477 lock_single_segment(this->manager
, this->segment
);
478 if ((list
= this->manager
->ike_sa_table
[this->row
]) != NULL
&&
479 list
->get_count(list
))
481 this->current
= list
->create_enumerator(list
);
484 unlock_single_segment(this->manager
, this->segment
);
486 this->row
+= this->manager
->segment_count
;
489 this->row
= this->segment
;
495 * Implementation of private_enumerator_t.enumerator.destroy.
497 static void enumerator_destroy(private_enumerator_t
*this)
501 this->current
->destroy(this->current
);
502 unlock_single_segment(this->manager
, this->segment
);
508 * Creates an enumerator to enumerate the entries in the hash table.
510 static enumerator_t
* create_table_enumerator(private_ike_sa_manager_t
*this)
512 private_enumerator_t
*enumerator
= malloc_thing(private_enumerator_t
);
514 enumerator
->enumerator
.enumerate
= (void*)enumerate
;
515 enumerator
->enumerator
.destroy
= (void*)enumerator_destroy
;
516 enumerator
->manager
= this;
517 enumerator
->segment
= 0;
519 enumerator
->current
= NULL
;
521 return &enumerator
->enumerator
;
525 * Put an entry into the hash table.
526 * Note: The caller has to unlock the returned segment.
528 static u_int
put_entry(private_ike_sa_manager_t
*this, entry_t
*entry
)
531 u_int row
= ike_sa_id_hash(entry
->ike_sa_id
) & this->table_mask
;
532 u_int segment
= row
& this->segment_mask
;
534 lock_single_segment(this, segment
);
535 if ((list
= this->ike_sa_table
[row
]) == NULL
)
537 list
= this->ike_sa_table
[row
] = linked_list_create();
539 list
->insert_last(list
, entry
);
540 this->segments
[segment
].count
++;
545 * Remove an entry from the hash table.
546 * Note: The caller MUST have a lock on the segment of this entry.
548 static void remove_entry(private_ike_sa_manager_t
*this, entry_t
*entry
)
551 u_int row
= ike_sa_id_hash(entry
->ike_sa_id
) & this->table_mask
;
552 u_int segment
= row
& this->segment_mask
;
554 if ((list
= this->ike_sa_table
[row
]) != NULL
)
558 enumerator_t
*enumerator
= list
->create_enumerator(list
);
559 while (enumerator
->enumerate(enumerator
, ¤t
))
561 if (current
== entry
)
563 list
->remove_at(list
, enumerator
);
564 this->segments
[segment
].count
--;
568 enumerator
->destroy(enumerator
);
573 * Remove the entry at the current enumerator position.
575 static void remove_entry_at(private_enumerator_t
*this)
579 linked_list_t
*list
= this->manager
->ike_sa_table
[this->row
];
580 list
->remove_at(list
, this->current
);
581 this->manager
->segments
[this->segment
].count
--;
586 * Find an entry using the provided match function to compare the entries for
589 static status_t
get_entry_by_match_function(private_ike_sa_manager_t
*this,
590 ike_sa_id_t
*ike_sa_id
, entry_t
**entry
, u_int
*segment
,
591 linked_list_match_t match
, void *p1
, void *p2
)
595 u_int row
= ike_sa_id_hash(ike_sa_id
) & this->table_mask
;
596 u_int seg
= row
& this->segment_mask
;
598 lock_single_segment(this, seg
);
599 if ((list
= this->ike_sa_table
[row
]) != NULL
)
601 if (list
->find_first(list
, match
, (void**)¤t
, p1
, p2
) == SUCCESS
)
605 /* the locked segment has to be unlocked by the caller */
609 unlock_single_segment(this, seg
);
614 * Find an entry by ike_sa_id_t.
615 * Note: On SUCCESS, the caller has to unlock the segment.
617 static status_t
get_entry_by_id(private_ike_sa_manager_t
*this,
618 ike_sa_id_t
*ike_sa_id
, entry_t
**entry
, u_int
*segment
)
620 return get_entry_by_match_function(this, ike_sa_id
, entry
, segment
,
621 (linked_list_match_t
)entry_match_by_id
, ike_sa_id
, NULL
);
625 * Find an entry by initiator SPI and IKE_SA_INIT hash.
626 * Note: On SUCCESS, the caller has to unlock the segment.
628 static status_t
get_entry_by_hash(private_ike_sa_manager_t
*this,
629 ike_sa_id_t
*ike_sa_id
, chunk_t hash
, entry_t
**entry
, u_int
*segment
)
631 return get_entry_by_match_function(this, ike_sa_id
, entry
, segment
,
632 (linked_list_match_t
)entry_match_by_hash
, ike_sa_id
, &hash
);
636 * Find an entry by IKE_SA pointer.
637 * Note: On SUCCESS, the caller has to unlock the segment.
639 static status_t
get_entry_by_sa(private_ike_sa_manager_t
*this,
640 ike_sa_id_t
*ike_sa_id
, ike_sa_t
*ike_sa
, entry_t
**entry
, u_int
*segment
)
642 return get_entry_by_match_function(this, ike_sa_id
, entry
, segment
,
643 (linked_list_match_t
)entry_match_by_sa
, ike_sa
, NULL
);
647 * Wait until no other thread is using an IKE_SA, return FALSE if entry not
650 static bool wait_for_entry(private_ike_sa_manager_t
*this, entry_t
*entry
,
653 if (entry
->driveout_new_threads
)
655 /* we are not allowed to get this */
658 while (entry
->checked_out
&& !entry
->driveout_waiting_threads
)
660 /* so wait until we can get it for us.
661 * we register us as waiting. */
662 entry
->waiting_threads
++;
663 entry
->condvar
->wait(entry
->condvar
, this->segments
[segment
].mutex
);
664 entry
->waiting_threads
--;
666 /* hm, a deletion request forbids us to get this SA, get next one */
667 if (entry
->driveout_waiting_threads
)
669 /* we must signal here, others may be waiting on it, too */
670 entry
->condvar
->signal(entry
->condvar
);
677 * Put a half-open SA into the hash table.
679 static void put_half_open(private_ike_sa_manager_t
*this, entry_t
*entry
)
681 half_open_t
*half_open
= NULL
;
683 chunk_t addr
= entry
->other
->get_address(entry
->other
);
684 u_int row
= chunk_hash(addr
) & this->table_mask
;
685 u_int segment
= row
& this->segment_mask
;
687 rwlock_t
*lock
= this->half_open_segments
[segment
].lock
;
688 lock
->write_lock(lock
);
689 if ((list
= this->half_open_table
[row
]) == NULL
)
691 list
= this->half_open_table
[row
] = linked_list_create();
695 half_open_t
*current
;
696 if (list
->find_first(list
, (linked_list_match_t
)half_open_match
,
697 (void**)¤t
, &addr
) == SUCCESS
)
701 this->half_open_segments
[segment
].count
++;
707 half_open
= malloc_thing(half_open_t
);
708 half_open
->other
= chunk_clone(addr
);
709 half_open
->count
= 1;
710 list
->insert_last(list
, half_open
);
711 this->half_open_segments
[segment
].count
++;
717 * Remove a half-open SA from the hash table.
719 static void remove_half_open(private_ike_sa_manager_t
*this, entry_t
*entry
)
722 chunk_t addr
= entry
->other
->get_address(entry
->other
);
723 u_int row
= chunk_hash(addr
) & this->table_mask
;
724 u_int segment
= row
& this->segment_mask
;
726 rwlock_t
*lock
= this->half_open_segments
[segment
].lock
;
727 lock
->write_lock(lock
);
728 if ((list
= this->half_open_table
[row
]) != NULL
)
730 half_open_t
*current
;
731 enumerator_t
*enumerator
= list
->create_enumerator(list
);
732 while (enumerator
->enumerate(enumerator
, ¤t
))
734 if (half_open_match(current
, &addr
))
736 if (--current
->count
== 0)
738 list
->remove_at(list
, enumerator
);
739 half_open_destroy(current
);
741 this->half_open_segments
[segment
].count
--;
745 enumerator
->destroy(enumerator
);
751 * Put an SA between two peers into the hash table.
753 static void put_connected_peers(private_ike_sa_manager_t
*this, entry_t
*entry
)
756 connected_peers_t
*connected_peers
= NULL
;
757 chunk_t my_id
= entry
->my_id
->get_encoding(entry
->my_id
),
758 other_id
= entry
->other_id
->get_encoding(entry
->other_id
);
759 u_int row
= chunk_hash_inc(other_id
, chunk_hash(my_id
)) & this->table_mask
;
760 u_int segment
= row
& this->segment_mask
;
762 rwlock_t
*lock
= this->connected_peers_segments
[segment
].lock
;
763 lock
->write_lock(lock
);
764 if ((list
= this->connected_peers_table
[row
]) == NULL
)
766 list
= this->connected_peers_table
[row
] = linked_list_create();
770 connected_peers_t
*current
;
771 if (list
->find_first(list
, (linked_list_match_t
)connected_peers_match
,
772 (void**)¤t
, entry
->my_id
, entry
->other_id
) == SUCCESS
)
774 connected_peers
= current
;
775 if (connected_peers
->sas
->find_first(connected_peers
->sas
,
776 (linked_list_match_t
)entry
->ike_sa_id
->equals
,
777 NULL
, entry
->ike_sa_id
) == SUCCESS
)
785 if (!connected_peers
)
787 connected_peers
= malloc_thing(connected_peers_t
);
788 connected_peers
->my_id
= entry
->my_id
->clone(entry
->my_id
);
789 connected_peers
->other_id
= entry
->other_id
->clone(entry
->other_id
);
790 connected_peers
->sas
= linked_list_create();
791 list
->insert_last(list
, connected_peers
);
793 connected_peers
->sas
->insert_last(connected_peers
->sas
,
794 entry
->ike_sa_id
->clone(entry
->ike_sa_id
));
795 this->connected_peers_segments
[segment
].count
++;
800 * Remove an SA between two peers from the hash table.
802 static void remove_connected_peers(private_ike_sa_manager_t
*this, entry_t
*entry
)
805 chunk_t my_id
= entry
->my_id
->get_encoding(entry
->my_id
),
806 other_id
= entry
->other_id
->get_encoding(entry
->other_id
);
807 u_int row
= chunk_hash_inc(other_id
, chunk_hash(my_id
)) & this->table_mask
;
808 u_int segment
= row
& this->segment_mask
;
810 rwlock_t
*lock
= this->connected_peers_segments
[segment
].lock
;
811 lock
->write_lock(lock
);
812 if ((list
= this->connected_peers_table
[row
]) != NULL
)
814 connected_peers_t
*current
;
815 enumerator_t
*enumerator
= list
->create_enumerator(list
);
816 while (enumerator
->enumerate(enumerator
, ¤t
))
818 if (connected_peers_match(current
, entry
->my_id
, entry
->other_id
))
820 ike_sa_id_t
*ike_sa_id
;
821 enumerator_t
*inner
= current
->sas
->create_enumerator(current
->sas
);
822 while (inner
->enumerate(inner
, &ike_sa_id
))
824 if (ike_sa_id
->equals(ike_sa_id
, entry
->ike_sa_id
))
826 current
->sas
->remove_at(current
->sas
, inner
);
827 ike_sa_id
->destroy(ike_sa_id
);
828 this->connected_peers_segments
[segment
].count
--;
832 inner
->destroy(inner
);
833 if (current
->sas
->get_count(current
->sas
) == 0)
835 list
->remove_at(list
, enumerator
);
836 connected_peers_destroy(current
);
841 enumerator
->destroy(enumerator
);
847 * Implementation of private_ike_sa_manager_t.get_next_spi.
849 static u_int64_t
get_next_spi(private_ike_sa_manager_t
*this)
853 this->rng
->get_bytes(this->rng
, sizeof(spi
), (u_int8_t
*)&spi
);
858 * Implementation of of ike_sa_manager.checkout.
860 static ike_sa_t
* checkout(private_ike_sa_manager_t
*this, ike_sa_id_t
*ike_sa_id
)
862 ike_sa_t
*ike_sa
= NULL
;
866 DBG2(DBG_MGR
, "checkout IKE_SA");
868 if (get_entry_by_id(this, ike_sa_id
, &entry
, &segment
) == SUCCESS
)
870 if (wait_for_entry(this, entry
, segment
))
872 DBG2(DBG_MGR
, "IKE_SA successfully checked out");
873 entry
->checked_out
= TRUE
;
874 ike_sa
= entry
->ike_sa
;
876 unlock_single_segment(this, segment
);
878 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
883 * Implementation of of ike_sa_manager.checkout_new.
885 static ike_sa_t
*checkout_new(private_ike_sa_manager_t
* this, bool initiator
)
890 entry
= entry_create();
893 entry
->ike_sa_id
= ike_sa_id_create(get_next_spi(this), 0, TRUE
);
897 entry
->ike_sa_id
= ike_sa_id_create(0, get_next_spi(this), FALSE
);
899 entry
->ike_sa
= ike_sa_create(entry
->ike_sa_id
);
901 segment
= put_entry(this, entry
);
902 entry
->checked_out
= TRUE
;
903 unlock_single_segment(this, segment
);
905 DBG2(DBG_MGR
, "created IKE_SA");
906 return entry
->ike_sa
;
910 * Implementation of of ike_sa_manager.checkout_by_message.
912 static ike_sa_t
* checkout_by_message(private_ike_sa_manager_t
* this,
917 ike_sa_t
*ike_sa
= NULL
;
918 ike_sa_id_t
*id
= message
->get_ike_sa_id(message
);
921 id
->switch_initiator(id
);
923 DBG2(DBG_MGR
, "checkout IKE_SA by message");
925 if (message
->get_request(message
) &&
926 message
->get_exchange_type(message
) == IKE_SA_INIT
)
928 /* IKE_SA_INIT request. Check for an IKE_SA with such a message hash. */
931 data
= message
->get_packet_data(message
);
932 this->hasher
->allocate_hash(this->hasher
, data
, &hash
);
935 if (get_entry_by_hash(this, id
, hash
, &entry
, &segment
) == SUCCESS
)
937 if (entry
->message_id
== 0)
939 unlock_single_segment(this, segment
);
942 DBG1(DBG_MGR
, "ignoring IKE_SA_INIT, already processing");
945 else if (wait_for_entry(this, entry
, segment
))
947 DBG2(DBG_MGR
, "IKE_SA checked out by hash");
948 entry
->checked_out
= TRUE
;
949 entry
->message_id
= message
->get_message_id(message
);
950 ike_sa
= entry
->ike_sa
;
952 unlock_single_segment(this, segment
);
957 if (id
->get_responder_spi(id
) == 0 &&
958 message
->get_exchange_type(message
) == IKE_SA_INIT
)
960 /* no IKE_SA found, create a new one */
961 id
->set_responder_spi(id
, get_next_spi(this));
962 entry
= entry_create();
963 entry
->ike_sa
= ike_sa_create(id
);
964 entry
->ike_sa_id
= id
->clone(id
);
966 segment
= put_entry(this, entry
);
967 entry
->checked_out
= TRUE
;
968 unlock_single_segment(this, segment
);
970 entry
->message_id
= message
->get_message_id(message
);
971 entry
->init_hash
= hash
;
972 ike_sa
= entry
->ike_sa
;
974 DBG2(DBG_MGR
, "created IKE_SA");
979 DBG1(DBG_MGR
, "ignoring message, no such IKE_SA");
987 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
991 if (get_entry_by_id(this, id
, &entry
, &segment
) == SUCCESS
)
993 /* only check out if we are not processing this request */
994 if (message
->get_request(message
) &&
995 message
->get_message_id(message
) == entry
->message_id
)
997 DBG1(DBG_MGR
, "ignoring request with ID %d, already processing",
1000 else if (wait_for_entry(this, entry
, segment
))
1002 ike_sa_id_t
*ike_id
= entry
->ike_sa
->get_id(entry
->ike_sa
);
1003 DBG2(DBG_MGR
, "IKE_SA successfully checked out");
1004 entry
->checked_out
= TRUE
;
1005 entry
->message_id
= message
->get_message_id(message
);
1006 if (ike_id
->get_responder_spi(ike_id
) == 0)
1008 ike_id
->set_responder_spi(ike_id
, id
->get_responder_spi(id
));
1010 ike_sa
= entry
->ike_sa
;
1012 unlock_single_segment(this, segment
);
1015 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1020 * Implementation of of ike_sa_manager.checkout_by_config.
1022 static ike_sa_t
* checkout_by_config(private_ike_sa_manager_t
*this,
1023 peer_cfg_t
*peer_cfg
)
1025 enumerator_t
*enumerator
;
1027 ike_sa_t
*ike_sa
= NULL
;
1028 identification_t
*my_id
, *other_id
;
1029 host_t
*my_host
, *other_host
;
1033 ike_cfg
= peer_cfg
->get_ike_cfg(peer_cfg
);
1034 my_id
= peer_cfg
->get_my_id(peer_cfg
);
1035 other_id
= peer_cfg
->get_other_id(peer_cfg
);
1036 my_host
= host_create_from_dns(ike_cfg
->get_my_addr(ike_cfg
), 0, 0);
1037 other_host
= host_create_from_dns(ike_cfg
->get_other_addr(ike_cfg
), 0, 0);
1039 if (my_host
&& other_host
&& this->reuse_ikesa
)
1041 enumerator
= create_table_enumerator(this);
1042 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1044 identification_t
*found_my_id
, *found_other_id
;
1045 host_t
*found_my_host
, *found_other_host
;
1047 if (!wait_for_entry(this, entry
, segment
))
1052 if (entry
->ike_sa
->get_state(entry
->ike_sa
) == IKE_DELETING
)
1054 /* skip IKE_SAs which are not usable */
1058 found_my_id
= entry
->ike_sa
->get_my_id(entry
->ike_sa
);
1059 found_other_id
= entry
->ike_sa
->get_other_id(entry
->ike_sa
);
1060 found_my_host
= entry
->ike_sa
->get_my_host(entry
->ike_sa
);
1061 found_other_host
= entry
->ike_sa
->get_other_host(entry
->ike_sa
);
1063 if (found_my_id
->get_type(found_my_id
) == ID_ANY
&&
1064 found_other_id
->get_type(found_other_id
) == ID_ANY
)
1066 /* IKE_SA has no IDs yet, so we can't use it */
1069 DBG2(DBG_MGR
, "candidate IKE_SA for \n"
1070 " %H[%D]...%H[%D]\n"
1072 my_host
, my_id
, other_host
, other_id
,
1073 found_my_host
, found_my_id
, found_other_host
, found_other_id
);
1074 /* compare ID and hosts. Supplied ID may contain wildcards, and IP
1076 if ((my_host
->is_anyaddr(my_host
) ||
1077 my_host
->ip_equals(my_host
, found_my_host
)) &&
1078 (other_host
->is_anyaddr(other_host
) ||
1079 other_host
->ip_equals(other_host
, found_other_host
)) &&
1080 found_my_id
->matches(found_my_id
, my_id
) &&
1081 found_other_id
->matches(found_other_id
, other_id
) &&
1082 streq(peer_cfg
->get_name(peer_cfg
),
1083 entry
->ike_sa
->get_name(entry
->ike_sa
)))
1085 /* looks good, we take this one */
1086 DBG2(DBG_MGR
, "found an existing IKE_SA for %H[%D]...%H[%D]",
1087 my_host
, my_id
, other_host
, other_id
);
1088 entry
->checked_out
= TRUE
;
1089 ike_sa
= entry
->ike_sa
;
1093 enumerator
->destroy(enumerator
);
1095 DESTROY_IF(my_host
);
1096 DESTROY_IF(other_host
);
1100 entry
= entry_create();
1101 entry
->ike_sa_id
= ike_sa_id_create(get_next_spi(this), 0, TRUE
);
1102 entry
->ike_sa
= ike_sa_create(entry
->ike_sa_id
);
1104 segment
= put_entry(this, entry
);
1106 /* check ike_sa out */
1107 DBG2(DBG_MGR
, "new IKE_SA created for IDs [%D]...[%D]", my_id
, other_id
);
1108 entry
->checked_out
= TRUE
;
1109 ike_sa
= entry
->ike_sa
;
1110 unlock_single_segment(this, segment
);
1112 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1117 * Implementation of of ike_sa_manager.checkout_by_id.
1119 static ike_sa_t
* checkout_by_id(private_ike_sa_manager_t
*this, u_int32_t id
,
1122 enumerator_t
*enumerator
;
1123 iterator_t
*children
;
1125 ike_sa_t
*ike_sa
= NULL
;
1126 child_sa_t
*child_sa
;
1129 enumerator
= create_table_enumerator(this);
1130 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1132 if (wait_for_entry(this, entry
, segment
))
1134 /* look for a child with such a reqid ... */
1137 children
= entry
->ike_sa
->create_child_sa_iterator(entry
->ike_sa
);
1138 while (children
->iterate(children
, (void**)&child_sa
))
1140 if (child_sa
->get_reqid(child_sa
) == id
)
1142 ike_sa
= entry
->ike_sa
;
1146 children
->destroy(children
);
1148 else /* ... or for a IKE_SA with such a unique id */
1150 if (entry
->ike_sa
->get_unique_id(entry
->ike_sa
) == id
)
1152 ike_sa
= entry
->ike_sa
;
1155 /* got one, return */
1158 entry
->checked_out
= TRUE
;
1163 enumerator
->destroy(enumerator
);
1165 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1170 * Implementation of of ike_sa_manager.checkout_by_name.
1172 static ike_sa_t
* checkout_by_name(private_ike_sa_manager_t
*this, char *name
,
1175 enumerator_t
*enumerator
;
1176 iterator_t
*children
;
1178 ike_sa_t
*ike_sa
= NULL
;
1179 child_sa_t
*child_sa
;
1182 enumerator
= create_table_enumerator(this);
1183 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1185 if (wait_for_entry(this, entry
, segment
))
1187 /* look for a child with such a policy name ... */
1190 children
= entry
->ike_sa
->create_child_sa_iterator(entry
->ike_sa
);
1191 while (children
->iterate(children
, (void**)&child_sa
))
1193 if (streq(child_sa
->get_name(child_sa
), name
))
1195 ike_sa
= entry
->ike_sa
;
1199 children
->destroy(children
);
1201 else /* ... or for a IKE_SA with such a connection name */
1203 if (streq(entry
->ike_sa
->get_name(entry
->ike_sa
), name
))
1205 ike_sa
= entry
->ike_sa
;
1208 /* got one, return */
1211 entry
->checked_out
= TRUE
;
1216 enumerator
->destroy(enumerator
);
1218 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
1223 * Implementation of ike_sa_manager_t.checkout_duplicate.
1225 static ike_sa_t
* checkout_duplicate(private_ike_sa_manager_t
*this,
1228 linked_list_t
*list
;
1230 ike_sa_id_t
*duplicate_id
= NULL
;
1231 ike_sa_t
*duplicate
= NULL
;
1232 identification_t
*me
, *other
;
1236 me
= ike_sa
->get_my_id(ike_sa
);
1237 other
= ike_sa
->get_other_id(ike_sa
);
1239 row
= chunk_hash_inc(other
->get_encoding(other
),
1240 chunk_hash(me
->get_encoding(me
))) & this->table_mask
;
1241 segment
= row
& this->segment_mask
;
1243 lock
= this->connected_peers_segments
[segment
& this->segment_mask
].lock
;
1244 lock
->read_lock(lock
);
1245 if ((list
= this->connected_peers_table
[row
]) != NULL
)
1247 connected_peers_t
*current
;
1248 if (list
->find_first(list
, (linked_list_match_t
)connected_peers_match
,
1249 (void**)¤t
, me
, other
) == SUCCESS
)
1251 /* we just return the first ike_sa_id we have cached for these ids */
1252 current
->sas
->get_first(current
->sas
, (void**)&duplicate_id
);
1259 if (get_entry_by_id(this, duplicate_id
, &entry
, &segment
) == SUCCESS
)
1261 if (wait_for_entry(this, entry
, segment
))
1263 duplicate
= entry
->ike_sa
;
1264 entry
->checked_out
= TRUE
;
1266 unlock_single_segment(this, segment
);
1273 * enumerator filter function
1275 static bool enumerator_filter(private_ike_sa_manager_t
*this,
1276 entry_t
**in
, ike_sa_t
**out
, u_int
*segment
)
1278 if (wait_for_entry(this, *in
, *segment
))
1280 *out
= (*in
)->ike_sa
;
1287 * Implementation of ike_sa_manager_t.create_enumerator.
1289 static enumerator_t
*create_enumerator(private_ike_sa_manager_t
* this)
1291 return enumerator_create_filter(
1292 create_table_enumerator(this),
1293 (void*)enumerator_filter
, this, NULL
);
1297 * Implementation of ike_sa_manager_t.checkin.
1299 static void checkin(private_ike_sa_manager_t
*this, ike_sa_t
*ike_sa
)
1301 /* to check the SA back in, we look for the pointer of the ike_sa
1303 * The lookup is done by initiator SPI, so even if the SPI has changed (e.g.
1304 * on reception of a IKE_SA_INIT response) the lookup will work but
1305 * updating of the SPI MAY be necessary...
1308 ike_sa_id_t
*ike_sa_id
;
1310 identification_t
*my_id
, *other_id
;
1313 ike_sa_id
= ike_sa
->get_id(ike_sa
);
1314 my_id
= ike_sa
->get_my_id(ike_sa
);
1315 other_id
= ike_sa
->get_other_id(ike_sa
);
1316 other
= ike_sa
->get_other_host(ike_sa
);
1318 DBG2(DBG_MGR
, "checkin 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 (only as responder) */
1364 if (!entry
->ike_sa_id
->is_initiator(entry
->ike_sa_id
) &&
1365 (!entry
->my_id
|| !entry
->other_id
))
1367 if (!entry
->my_id
&& my_id
->get_type(my_id
) != ID_ANY
)
1369 entry
->my_id
= my_id
->clone(my_id
);
1371 if (!entry
->other_id
&& other_id
->get_type(other_id
) != ID_ANY
)
1373 entry
->other_id
= other_id
->clone(other_id
);
1375 if (entry
->my_id
&& entry
->other_id
)
1377 put_connected_peers(this, entry
);
1381 unlock_single_segment(this, segment
);
1383 charon
->bus
->set_sa(charon
->bus
, NULL
);
1387 * Implementation of ike_sa_manager_t.checkin_and_destroy.
1389 static void checkin_and_destroy(private_ike_sa_manager_t
*this, ike_sa_t
*ike_sa
)
1391 /* deletion is a bit complex, we must ensure that no thread is waiting for
1393 * We take this SA from the table, and start signaling while threads
1394 * are in the condvar.
1397 ike_sa_id_t
*ike_sa_id
;
1400 ike_sa_id
= ike_sa
->get_id(ike_sa
);
1402 DBG2(DBG_MGR
, "checkin and destroy IKE_SA");
1404 if (get_entry_by_sa(this, ike_sa_id
, ike_sa
, &entry
, &segment
) == SUCCESS
)
1406 /* drive out waiting threads, as we are in hurry */
1407 entry
->driveout_waiting_threads
= TRUE
;
1408 /* mark it, so no new threads can get this entry */
1409 entry
->driveout_new_threads
= TRUE
;
1410 /* wait until all workers have done their work */
1411 while (entry
->waiting_threads
)
1414 entry
->condvar
->broadcast(entry
->condvar
);
1415 /* they will wake us again when their work is done */
1416 entry
->condvar
->wait(entry
->condvar
, this->segments
[segment
].mutex
);
1419 if (entry
->half_open
)
1421 remove_half_open(this, entry
);
1423 if (!entry
->ike_sa_id
->is_initiator(entry
->ike_sa_id
) &&
1424 entry
->my_id
&& entry
->other_id
)
1426 remove_connected_peers(this, entry
);
1429 remove_entry(this, entry
);
1430 entry_destroy(entry
);
1431 unlock_single_segment(this, segment
);
1433 DBG2(DBG_MGR
, "check-in and destroy of IKE_SA successful");
1437 DBG1(DBG_MGR
, "tried to check-in and delete nonexisting IKE_SA");
1438 ike_sa
->destroy(ike_sa
);
1440 charon
->bus
->set_sa(charon
->bus
, NULL
);
1444 * Implementation of ike_sa_manager_t.get_half_open_count.
1446 static int get_half_open_count(private_ike_sa_manager_t
*this, host_t
*ip
)
1452 linked_list_t
*list
;
1453 chunk_t addr
= ip
->get_address(ip
);
1454 u_int row
= chunk_hash(addr
) & this->table_mask
;
1455 u_int segment
= row
& this->segment_mask
;
1457 rwlock_t
*lock
= this->half_open_segments
[segment
& this->segment_mask
].lock
;
1458 lock
->read_lock(lock
);
1459 if ((list
= this->half_open_table
[row
]) != NULL
)
1461 half_open_t
*current
;
1463 if (list
->find_first(list
, (linked_list_match_t
)half_open_match
,
1464 (void**)¤t
, &addr
) == SUCCESS
)
1466 count
= current
->count
;
1475 for (segment
= 0; segment
< this->segment_count
; ++segment
)
1478 lock
= this->half_open_segments
[segment
& this->segment_mask
].lock
;
1479 lock
->read_lock(lock
);
1480 count
+= this->half_open_segments
[segment
].count
;
1489 * Implementation of ike_sa_manager_t.flush.
1491 static void flush(private_ike_sa_manager_t
*this)
1493 /* destroy all list entries */
1494 enumerator_t
*enumerator
;
1498 lock_all_segments(this);
1499 DBG2(DBG_MGR
, "going to destroy IKE_SA manager and all managed IKE_SA's");
1500 /* Step 1: drive out all waiting threads */
1501 DBG2(DBG_MGR
, "set driveout flags for all stored IKE_SA's");
1502 enumerator
= create_table_enumerator(this);
1503 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1505 /* do not accept new threads, drive out waiting threads */
1506 entry
->driveout_new_threads
= TRUE
;
1507 entry
->driveout_waiting_threads
= TRUE
;
1509 enumerator
->destroy(enumerator
);
1510 DBG2(DBG_MGR
, "wait for all threads to leave IKE_SA's");
1511 /* Step 2: wait until all are gone */
1512 enumerator
= create_table_enumerator(this);
1513 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1515 while (entry
->waiting_threads
)
1518 entry
->condvar
->broadcast(entry
->condvar
);
1519 /* go sleeping until they are gone */
1520 entry
->condvar
->wait(entry
->condvar
, this->segments
[segment
].mutex
);
1523 enumerator
->destroy(enumerator
);
1524 DBG2(DBG_MGR
, "delete all IKE_SA's");
1525 /* Step 3: initiate deletion of all IKE_SAs */
1526 enumerator
= create_table_enumerator(this);
1527 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1529 charon
->bus
->set_sa(charon
->bus
, entry
->ike_sa
);
1530 entry
->ike_sa
->delete(entry
->ike_sa
);
1532 enumerator
->destroy(enumerator
);
1534 DBG2(DBG_MGR
, "destroy all entries");
1535 /* Step 4: destroy all entries */
1536 enumerator
= create_table_enumerator(this);
1537 while (enumerator
->enumerate(enumerator
, &entry
, &segment
))
1539 charon
->bus
->set_sa(charon
->bus
, entry
->ike_sa
);
1540 if (entry
->half_open
)
1542 remove_half_open(this, entry
);
1544 if (!entry
->ike_sa_id
->is_initiator(entry
->ike_sa_id
) &&
1545 entry
->my_id
&& entry
->other_id
)
1547 remove_connected_peers(this, entry
);
1549 remove_entry_at((private_enumerator_t
*)enumerator
);
1550 entry_destroy(entry
);
1552 enumerator
->destroy(enumerator
);
1553 charon
->bus
->set_sa(charon
->bus
, NULL
);
1554 unlock_all_segments(this);
1558 * Implementation of ike_sa_manager_t.destroy.
1560 static void destroy(private_ike_sa_manager_t
*this)
1564 for (i
= 0; i
< this->table_size
; ++i
)
1566 linked_list_t
*list
;
1568 if ((list
= this->ike_sa_table
[i
]) != NULL
)
1570 list
->destroy(list
);
1572 if ((list
= this->half_open_table
[i
]) != NULL
)
1574 list
->destroy(list
);
1576 if ((list
= this->connected_peers_table
[i
]) != NULL
)
1578 list
->destroy(list
);
1581 free(this->ike_sa_table
);
1582 free(this->half_open_table
);
1583 free(this->connected_peers_table
);
1584 for (i
= 0; i
< this->segment_count
; ++i
)
1586 this->segments
[i
].mutex
->destroy(this->segments
[i
].mutex
);
1587 this->half_open_segments
[i
].lock
->destroy(this->half_open_segments
[i
].lock
);
1588 this->connected_peers_segments
[i
].lock
->destroy(this->connected_peers_segments
[i
].lock
);
1590 free(this->segments
);
1591 free(this->half_open_segments
);
1592 free(this->connected_peers_segments
);
1594 this->rng
->destroy(this->rng
);
1595 this->hasher
->destroy(this->hasher
);
1600 * This function returns the next-highest power of two for the given number.
1601 * The algorithm works by setting all bits on the right-hand side of the most
1602 * significant 1 to 1 and then increments the whole number so it rolls over
1603 * to the nearest power of two. Note: returns 0 for n == 0
1605 static u_int
get_nearest_powerof2(u_int n
)
1610 for (i
= 1; i
< sizeof(u_int
) * 8; i
<<= 1)
1618 * Described in header.
1620 ike_sa_manager_t
*ike_sa_manager_create()
1623 private_ike_sa_manager_t
*this = malloc_thing(private_ike_sa_manager_t
);
1625 /* assign public functions */
1626 this->public.flush
= (void(*)(ike_sa_manager_t
*))flush
;
1627 this->public.destroy
= (void(*)(ike_sa_manager_t
*))destroy
;
1628 this->public.checkout
= (ike_sa_t
*(*)(ike_sa_manager_t
*, ike_sa_id_t
*))checkout
;
1629 this->public.checkout_new
= (ike_sa_t
*(*)(ike_sa_manager_t
*,bool))checkout_new
;
1630 this->public.checkout_by_message
= (ike_sa_t
*(*)(ike_sa_manager_t
*,message_t
*))checkout_by_message
;
1631 this->public.checkout_by_config
= (ike_sa_t
*(*)(ike_sa_manager_t
*,peer_cfg_t
*))checkout_by_config
;
1632 this->public.checkout_by_id
= (ike_sa_t
*(*)(ike_sa_manager_t
*,u_int32_t
,bool))checkout_by_id
;
1633 this->public.checkout_by_name
= (ike_sa_t
*(*)(ike_sa_manager_t
*,char*,bool))checkout_by_name
;
1634 this->public.checkout_duplicate
= (ike_sa_t
*(*)(ike_sa_manager_t
*, ike_sa_t
*ike_sa
))checkout_duplicate
;
1635 this->public.create_enumerator
= (enumerator_t
*(*)(ike_sa_manager_t
*))create_enumerator
;
1636 this->public.checkin
= (void(*)(ike_sa_manager_t
*,ike_sa_t
*))checkin
;
1637 this->public.checkin_and_destroy
= (void(*)(ike_sa_manager_t
*,ike_sa_t
*))checkin_and_destroy
;
1638 this->public.get_half_open_count
= (int(*)(ike_sa_manager_t
*,host_t
*))get_half_open_count
;
1640 /* initialize private variables */
1641 this->hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_PREFERRED
);
1642 if (this->hasher
== NULL
)
1644 DBG1(DBG_MGR
, "manager initialization failed, no hasher supported");
1648 this->rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
1649 if (this->rng
== NULL
)
1651 DBG1(DBG_MGR
, "manager initialization failed, no RNG supported");
1652 this->hasher
->destroy(this->hasher
);
1656 this->table_size
= get_nearest_powerof2(lib
->settings
->get_int(lib
->settings
,
1657 "charon.ikesa_table_size",
1658 DEFAULT_HASHTABLE_SIZE
));
1659 this->table_size
= max(1, min(this->table_size
, MAX_HASHTABLE_SIZE
));
1660 this->table_mask
= this->table_size
- 1;
1662 this->segment_count
= get_nearest_powerof2(lib
->settings
->get_int(lib
->settings
,
1663 "charon.ikesa_table_segments",
1664 DEFAULT_SEGMENT_COUNT
));
1665 this->segment_count
= max(1, min(this->segment_count
, this->table_size
));
1666 this->segment_mask
= this->segment_count
- 1;
1668 this->ike_sa_table
= (linked_list_t
**)calloc(this->table_size
, sizeof(linked_list_t
*));
1669 memset(this->ike_sa_table
, 0, this->table_size
* sizeof(linked_list_t
*));
1671 this->segments
= (segment_t
*)calloc(this->segment_count
, sizeof(segment_t
));
1672 for (i
= 0; i
< this->segment_count
; ++i
)
1674 this->segments
[i
].mutex
= mutex_create(MUTEX_RECURSIVE
);
1675 this->segments
[i
].count
= 0;
1678 /* we use the same parameters as above for the hash table to track half-open SAs */
1679 this->half_open_table
= (linked_list_t
**)calloc(this->table_size
, sizeof(linked_list_t
*));
1680 memset(this->half_open_table
, 0, this->table_size
* sizeof(linked_list_t
*));
1682 this->half_open_segments
= (shareable_segment_t
*)calloc(this->segment_count
, sizeof(shareable_segment_t
));
1683 for (i
= 0; i
< this->segment_count
; ++i
)
1685 this->half_open_segments
[i
].lock
= rwlock_create(RWLOCK_DEFAULT
);
1686 this->half_open_segments
[i
].count
= 0;
1689 /* also for the hash table used for duplicate tests */
1690 this->connected_peers_table
= (linked_list_t
**)calloc(this->table_size
, sizeof(linked_list_t
*));
1691 memset(this->connected_peers_table
, 0, this->table_size
* sizeof(linked_list_t
*));
1693 this->connected_peers_segments
= (shareable_segment_t
*)calloc(this->segment_count
, sizeof(shareable_segment_t
));
1694 for (i
= 0; i
< this->segment_count
; ++i
)
1696 this->connected_peers_segments
[i
].lock
= rwlock_create(RWLOCK_DEFAULT
);
1697 this->connected_peers_segments
[i
].count
= 0;
1700 this->reuse_ikesa
= lib
->settings
->get_bool(lib
->settings
,
1701 "charon.reuse_ikesa", TRUE
);
1702 return &this->public;