2 * Copyright (C) 2014 Martin Willi
4 * Copyright (C) secunet Security Networks AG
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "child_sa_manager.h"
20 #include <threading/mutex.h>
21 #include <collections/hashtable.h>
23 typedef struct private_child_sa_manager_t private_child_sa_manager_t
;
26 * Private data of an child_sa_manager_t object.
28 struct private_child_sa_manager_t
{
31 * Public child_sa_manager_t interface.
33 child_sa_manager_t
public;
36 * CHILD_SAs by inbound SPI/dst, child_entry_t => child_entry_t
41 * CHILD_SAs by outbound SPI/dst, child_entry_t => child_entry_t
46 * CHILD_SAs by unique ID, child_entry_t => child_entry_t
51 * Mutex to access any hashtable
57 * Hashtable entry for a known CHILD_SA
60 /** the associated IKE_SA */
62 /** unique CHILD_SA identifier */
68 /** inbound host address */
70 /** outbound host address and port */
72 /** IPsec protocol, AH|ESP */
77 * Destroy a CHILD_SA entry
79 static void child_entry_destroy(child_entry_t
*entry
)
81 entry
->ike_id
->destroy(entry
->ike_id
);
82 entry
->host_in
->destroy(entry
->host_in
);
83 entry
->host_out
->destroy(entry
->host_out
);
88 * Hashtable hash function for inbound SAs
90 static u_int
hash_in(child_entry_t
*entry
)
92 return chunk_hash_inc(chunk_from_thing(entry
->spi_in
),
93 chunk_hash_inc(entry
->host_in
->get_address(entry
->host_in
),
94 chunk_hash(chunk_from_thing(entry
->proto
))));
98 * Hashtable equals function for inbound SAs
100 static bool equals_in(child_entry_t
*a
, child_entry_t
*b
)
102 return a
->spi_in
== b
->spi_in
&&
103 a
->proto
== b
->proto
&&
104 a
->host_in
->ip_equals(a
->host_in
, b
->host_in
);
108 * Hashtable hash function for outbound SAs
110 static u_int
hash_out(child_entry_t
*entry
)
112 return chunk_hash_inc(chunk_from_thing(entry
->spi_out
),
113 chunk_hash_inc(entry
->host_out
->get_address(entry
->host_out
),
114 chunk_hash(chunk_from_thing(entry
->proto
))));
118 * Hashtable equals function for outbound SAs
120 static bool equals_out(child_entry_t
*a
, child_entry_t
*b
)
122 return a
->spi_out
== b
->spi_out
&&
123 a
->proto
== b
->proto
&&
124 a
->host_out
->ip_equals(a
->host_out
, b
->host_out
);
128 * Hashtable hash function for SAs by unique ID
130 static u_int
hash_id(child_entry_t
*entry
)
132 return chunk_hash(chunk_from_thing(entry
->unique_id
));
136 * Hashtable equals function for SAs by unique ID
138 static bool equals_id(child_entry_t
*a
, child_entry_t
*b
)
140 return a
->unique_id
== b
->unique_id
;
143 METHOD(child_sa_manager_t
, add
, void,
144 private_child_sa_manager_t
*this, child_sa_t
*child_sa
, ike_sa_t
*ike_sa
)
146 child_entry_t
*entry
;
150 id
= ike_sa
->get_id(ike_sa
);
151 in
= ike_sa
->get_my_host(ike_sa
);
152 out
= ike_sa
->get_other_host(ike_sa
);
155 .ike_id
= id
->clone(id
),
156 .unique_id
= child_sa
->get_unique_id(child_sa
),
157 .proto
= child_sa
->get_protocol(child_sa
),
158 .spi_in
= child_sa
->get_spi(child_sa
, TRUE
),
159 .spi_out
= child_sa
->get_spi(child_sa
, FALSE
),
160 .host_in
= in
->clone(in
),
161 .host_out
= out
->clone(out
),
164 this->mutex
->lock(this->mutex
);
165 if (!this->in
->get(this->in
, entry
) &&
166 !this->out
->get(this->out
, entry
))
168 this->in
->put(this->in
, entry
, entry
);
169 this->out
->put(this->out
, entry
, entry
);
170 entry
= this->ids
->put(this->ids
, entry
, entry
);
172 this->mutex
->unlock(this->mutex
);
176 child_entry_destroy(entry
);
180 METHOD(child_sa_manager_t
, remove_
, void,
181 private_child_sa_manager_t
*this, child_sa_t
*child_sa
)
183 child_entry_t
*entry
, key
= {
184 .unique_id
= child_sa
->get_unique_id(child_sa
),
187 this->mutex
->lock(this->mutex
);
188 entry
= this->ids
->remove(this->ids
, &key
);
191 this->in
->remove(this->in
, entry
);
192 this->out
->remove(this->out
, entry
);
194 this->mutex
->unlock(this->mutex
);
198 child_entry_destroy(entry
);
203 * Check out an IKE_SA for a given CHILD_SA
205 static ike_sa_t
*checkout_ikesa(private_child_sa_manager_t
*this,
206 ike_sa_id_t
*id
, uint32_t unique_id
, child_sa_t
**child_sa
)
208 enumerator_t
*enumerator
;
213 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
, id
);
217 enumerator
= ike_sa
->create_child_sa_enumerator(ike_sa
);
218 while (enumerator
->enumerate(enumerator
, ¤t
))
220 found
= current
->get_unique_id(current
) == unique_id
;
230 enumerator
->destroy(enumerator
);
236 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
241 METHOD(child_sa_manager_t
, checkout_by_id
, ike_sa_t
*,
242 private_child_sa_manager_t
*this, uint32_t unique_id
,
243 child_sa_t
**child_sa
)
246 child_entry_t
*entry
, key
= {
247 .unique_id
= unique_id
,
250 this->mutex
->lock(this->mutex
);
251 entry
= this->ids
->get(this->ids
, &key
);
254 id
= entry
->ike_id
->clone(entry
->ike_id
);
256 this->mutex
->unlock(this->mutex
);
260 return checkout_ikesa(this, id
, unique_id
, child_sa
);
265 METHOD(child_sa_manager_t
, checkout
, ike_sa_t
*,
266 private_child_sa_manager_t
*this, protocol_id_t protocol
, uint32_t spi
,
267 host_t
*dst
, child_sa_t
**child_sa
)
271 child_entry_t
*entry
, key
= {
279 this->mutex
->lock(this->mutex
);
280 entry
= this->in
->get(this->in
, &key
);
283 entry
= this->out
->get(this->out
, &key
);
287 unique_id
= entry
->unique_id
;
288 id
= entry
->ike_id
->clone(entry
->ike_id
);
290 this->mutex
->unlock(this->mutex
);
294 return checkout_ikesa(this, id
, unique_id
, child_sa
);
299 METHOD(child_sa_manager_t
, destroy
, void,
300 private_child_sa_manager_t
*this)
302 this->in
->destroy(this->in
);
303 this->out
->destroy(this->out
);
304 this->ids
->destroy(this->ids
);
305 this->mutex
->destroy(this->mutex
);
312 child_sa_manager_t
*child_sa_manager_create()
314 private_child_sa_manager_t
*this;
320 .checkout
= _checkout
,
321 .checkout_by_id
= _checkout_by_id
,
324 .in
= hashtable_create((hashtable_hash_t
)hash_in
,
325 (hashtable_equals_t
)equals_in
, 8),
326 .out
= hashtable_create((hashtable_hash_t
)hash_out
,
327 (hashtable_equals_t
)equals_out
, 8),
328 .ids
= hashtable_create((hashtable_hash_t
)hash_id
,
329 (hashtable_equals_t
)equals_id
, 8),
330 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
333 return &this->public;