2 * Copyright (C) 2006-2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "child_delete.h"
19 #include <encoding/payloads/delete_payload.h>
22 typedef struct private_child_delete_t private_child_delete_t
;
25 * Private members of a child_delete_t task.
27 struct private_child_delete_t
{
30 * Public methods and task_t interface.
32 child_delete_t
public;
40 * Are we the initiator?
45 * Protocol of CHILD_SA to delete
47 protocol_id_t protocol
;
50 * Inbound SPI of CHILD_SA to delete
55 * whether to enforce delete action policy
57 bool check_delete_action
;
60 * is this delete exchange following a rekey?
65 * CHILD_SAs which get deleted
67 linked_list_t
*child_sas
;
71 * build the delete payloads from the listed child_sas
73 static void build_payloads(private_child_delete_t
*this, message_t
*message
)
75 delete_payload_t
*ah
= NULL
, *esp
= NULL
;
76 enumerator_t
*enumerator
;
79 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
80 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
82 protocol_id_t protocol
= child_sa
->get_protocol(child_sa
);
83 u_int32_t spi
= child_sa
->get_spi(child_sa
, TRUE
);
90 esp
= delete_payload_create(DELETE
, PROTO_ESP
);
91 message
->add_payload(message
, (payload_t
*)esp
);
93 esp
->add_spi(esp
, spi
);
94 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
95 protocol_id_names
, protocol
, ntohl(spi
));
100 ah
= delete_payload_create(DELETE
, PROTO_AH
);
101 message
->add_payload(message
, (payload_t
*)ah
);
103 ah
->add_spi(ah
, spi
);
104 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
105 protocol_id_names
, protocol
, ntohl(spi
));
110 child_sa
->set_state(child_sa
, CHILD_DELETING
);
112 enumerator
->destroy(enumerator
);
116 * read in payloads and find the children to delete
118 static void process_payloads(private_child_delete_t
*this, message_t
*message
)
120 enumerator_t
*payloads
, *spis
;
122 delete_payload_t
*delete_payload
;
124 protocol_id_t protocol
;
125 child_sa_t
*child_sa
;
127 payloads
= message
->create_payload_enumerator(message
);
128 while (payloads
->enumerate(payloads
, &payload
))
130 if (payload
->get_type(payload
) == DELETE
)
132 delete_payload
= (delete_payload_t
*)payload
;
133 protocol
= delete_payload
->get_protocol_id(delete_payload
);
134 if (protocol
!= PROTO_ESP
&& protocol
!= PROTO_AH
)
138 spis
= delete_payload
->create_spi_enumerator(delete_payload
);
139 while (spis
->enumerate(spis
, &spi
))
141 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
,
143 if (child_sa
== NULL
)
145 DBG1(DBG_IKE
, "received DELETE for %N CHILD_SA with SPI %.8x, "
146 "but no such SA", protocol_id_names
, protocol
, ntohl(spi
));
149 DBG1(DBG_IKE
, "received DELETE for %N CHILD_SA with SPI %.8x",
150 protocol_id_names
, protocol
, ntohl(spi
));
152 switch (child_sa
->get_state(child_sa
))
155 this->rekeyed
= TRUE
;
156 /* we reply as usual, rekeying will fail */
159 /* we don't send back a delete if we initiated ourself */
160 if (!this->initiator
)
162 this->ike_sa
->destroy_child_sa(this->ike_sa
,
167 case CHILD_INSTALLED
:
168 if (!this->initiator
)
169 { /* reestablish installed children if required */
170 this->check_delete_action
= TRUE
;
176 this->child_sas
->insert_last(this->child_sas
, child_sa
);
181 payloads
->destroy(payloads
);
185 * destroy the children listed in this->child_sas, reestablish by policy
187 static status_t
destroy_and_reestablish(private_child_delete_t
*this)
189 enumerator_t
*enumerator
;
190 child_sa_t
*child_sa
;
191 child_cfg_t
*child_cfg
;
192 protocol_id_t protocol
;
195 status_t status
= SUCCESS
;
197 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
198 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
200 /* signal child down event if we are not rekeying */
203 charon
->bus
->child_updown(charon
->bus
, child_sa
, FALSE
);
205 spi
= child_sa
->get_spi(child_sa
, TRUE
);
206 protocol
= child_sa
->get_protocol(child_sa
);
207 child_cfg
= child_sa
->get_config(child_sa
);
208 child_cfg
->get_ref(child_cfg
);
209 action
= child_sa
->get_close_action(child_sa
);
210 this->ike_sa
->destroy_child_sa(this->ike_sa
, protocol
, spi
);
211 if (this->check_delete_action
)
212 { /* enforce child_cfg policy if deleted passively */
216 child_cfg
->get_ref(child_cfg
);
217 status
= this->ike_sa
->initiate(this->ike_sa
, child_cfg
, 0,
221 charon
->traps
->install(charon
->traps
,
222 this->ike_sa
->get_peer_cfg(this->ike_sa
), child_cfg
);
228 child_cfg
->destroy(child_cfg
);
229 if (status
!= SUCCESS
)
234 enumerator
->destroy(enumerator
);
239 * send closing signals for all CHILD_SAs over the bus
241 static void log_children(private_child_delete_t
*this)
243 enumerator_t
*enumerator
;
244 child_sa_t
*child_sa
;
245 u_int64_t bytes_in
, bytes_out
;
247 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
248 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
250 child_sa
->get_usestats(child_sa
, TRUE
, NULL
, &bytes_in
);
251 child_sa
->get_usestats(child_sa
, FALSE
, NULL
, &bytes_out
);
253 DBG0(DBG_IKE
, "closing CHILD_SA %s{%d} "
254 "with SPIs %.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
255 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
256 ntohl(child_sa
->get_spi(child_sa
, TRUE
)), bytes_in
,
257 ntohl(child_sa
->get_spi(child_sa
, FALSE
)), bytes_out
,
258 child_sa
->get_traffic_selectors(child_sa
, TRUE
),
259 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
261 enumerator
->destroy(enumerator
);
264 METHOD(task_t
, build_i
, status_t
,
265 private_child_delete_t
*this, message_t
*message
)
267 child_sa_t
*child_sa
;
269 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, this->protocol
,
272 { /* check if it is an outbound sa */
273 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, this->protocol
,
276 { /* child does not exist anymore */
279 /* we work only with the inbound SPI */
280 this->spi
= child_sa
->get_spi(child_sa
, TRUE
);
282 this->child_sas
->insert_last(this->child_sas
, child_sa
);
283 if (child_sa
->get_state(child_sa
) == CHILD_REKEYING
)
285 this->rekeyed
= TRUE
;
288 build_payloads(this, message
);
292 METHOD(task_t
, process_i
, status_t
,
293 private_child_delete_t
*this, message_t
*message
)
295 /* flush the list before adding new SAs */
296 this->child_sas
->destroy(this->child_sas
);
297 this->child_sas
= linked_list_create();
299 process_payloads(this, message
);
300 DBG1(DBG_IKE
, "CHILD_SA closed");
301 return destroy_and_reestablish(this);
304 METHOD(task_t
, process_r
, status_t
,
305 private_child_delete_t
*this, message_t
*message
)
307 process_payloads(this, message
);
312 METHOD(task_t
, build_r
, status_t
,
313 private_child_delete_t
*this, message_t
*message
)
315 /* if we are rekeying, we send an empty informational */
316 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_REKEYING
)
318 build_payloads(this, message
);
320 DBG1(DBG_IKE
, "CHILD_SA closed");
321 return destroy_and_reestablish(this);
324 METHOD(task_t
, get_type
, task_type_t
,
325 private_child_delete_t
*this)
327 return TASK_CHILD_DELETE
;
330 METHOD(child_delete_t
, get_child
, child_sa_t
*,
331 private_child_delete_t
*this)
333 child_sa_t
*child_sa
= NULL
;
334 this->child_sas
->get_first(this->child_sas
, (void**)&child_sa
);
338 METHOD(task_t
, migrate
, void,
339 private_child_delete_t
*this, ike_sa_t
*ike_sa
)
341 this->check_delete_action
= FALSE
;
342 this->ike_sa
= ike_sa
;
344 this->child_sas
->destroy(this->child_sas
);
345 this->child_sas
= linked_list_create();
348 METHOD(task_t
, destroy
, void,
349 private_child_delete_t
*this)
351 this->child_sas
->destroy(this->child_sas
);
356 * Described in header.
358 child_delete_t
*child_delete_create(ike_sa_t
*ike_sa
, protocol_id_t protocol
,
361 private_child_delete_t
*this;
366 .get_type
= _get_type
,
370 .get_child
= _get_child
,
373 .child_sas
= linked_list_create(),
374 .protocol
= protocol
,
378 if (protocol
!= PROTO_NONE
)
380 this->public.task
.build
= _build_i
;
381 this->public.task
.process
= _process_i
;
382 this->initiator
= TRUE
;
386 this->public.task
.build
= _build_r
;
387 this->public.task
.process
= _process_r
;
388 this->initiator
= FALSE
;
390 return &this->public;