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
18 #include "child_delete.h"
21 #include <encoding/payloads/delete_payload.h>
24 typedef struct private_child_delete_t private_child_delete_t
;
27 * Private members of a child_delete_t task.
29 struct private_child_delete_t
{
32 * Public methods and task_t interface.
34 child_delete_t
public;
42 * Are we the initiator?
47 * CHILD_SAs which get deleted
49 linked_list_t
*child_sas
;
53 * build the delete payloads from the listed child_sas
55 static void build_payloads(private_child_delete_t
*this, message_t
*message
)
57 delete_payload_t
*ah
= NULL
, *esp
= NULL
;
61 iterator
= this->child_sas
->create_iterator(this->child_sas
, TRUE
);
62 while (iterator
->iterate(iterator
, (void**)&child_sa
))
64 protocol_id_t protocol
= child_sa
->get_protocol(child_sa
);
65 u_int32_t spi
= child_sa
->get_spi(child_sa
, TRUE
);
72 esp
= delete_payload_create(PROTO_ESP
);
73 message
->add_payload(message
, (payload_t
*)esp
);
75 esp
->add_spi(esp
, spi
);
76 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
77 protocol_id_names
, protocol
, ntohl(spi
));
82 ah
= delete_payload_create(PROTO_AH
);
83 message
->add_payload(message
, (payload_t
*)ah
);
86 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
87 protocol_id_names
, protocol
, ntohl(spi
));
92 child_sa
->set_state(child_sa
, CHILD_DELETING
);
94 iterator
->destroy(iterator
);
98 * read in payloads and find the children to delete
100 static void process_payloads(private_child_delete_t
*this, message_t
*message
)
102 iterator_t
*payloads
, *spis
;
104 delete_payload_t
*delete_payload
;
106 protocol_id_t protocol
;
107 child_sa_t
*child_sa
;
109 payloads
= message
->get_payload_iterator(message
);
110 while (payloads
->iterate(payloads
, (void**)&payload
))
112 if (payload
->get_type(payload
) == DELETE
)
114 delete_payload
= (delete_payload_t
*)payload
;
115 protocol
= delete_payload
->get_protocol_id(delete_payload
);
116 if (protocol
!= PROTO_ESP
&& protocol
!= PROTO_AH
)
120 spis
= delete_payload
->create_spi_iterator(delete_payload
);
121 while (spis
->iterate(spis
, (void**)&spi
))
123 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
,
125 if (child_sa
== NULL
)
127 DBG1(DBG_IKE
, "received DELETE for %N CHILD_SA with SPI %.8x, "
128 "but no such SA", protocol_id_names
, protocol
, ntohl(*spi
));
131 DBG1(DBG_IKE
, "received DELETE for %N CHILD_SA with SPI %.8x",
132 protocol_id_names
, protocol
, ntohl(*spi
));
134 switch (child_sa
->get_state(child_sa
))
137 /* we reply as usual, rekeying will fail */
140 /* we don't send back a delete if we initiated ourself */
141 if (!this->initiator
)
143 this->ike_sa
->destroy_child_sa(this->ike_sa
,
151 this->child_sas
->insert_last(this->child_sas
, child_sa
);
156 payloads
->destroy(payloads
);
160 * destroy the children listed in this->child_sas, reestablish by policy
162 static status_t
destroy_and_reestablish(private_child_delete_t
*this)
164 iterator_t
*iterator
;
165 child_sa_t
*child_sa
;
166 child_cfg_t
*child_cfg
;
167 protocol_id_t protocol
;
169 status_t status
= SUCCESS
;
171 iterator
= this->child_sas
->create_iterator(this->child_sas
, TRUE
);
172 while (iterator
->iterate(iterator
, (void**)&child_sa
))
174 spi
= child_sa
->get_spi(child_sa
, TRUE
);
175 protocol
= child_sa
->get_protocol(child_sa
);
176 child_cfg
= child_sa
->get_config(child_sa
);
177 child_cfg
->get_ref(child_cfg
);
178 this->ike_sa
->destroy_child_sa(this->ike_sa
, protocol
, spi
);
179 if (!this->initiator
)
180 { /* enforce child_cfg policy if deleted passively */
181 switch (child_cfg
->get_close_action(child_cfg
))
184 child_cfg
->get_ref(child_cfg
);
185 status
= this->ike_sa
->initiate(this->ike_sa
, child_cfg
);
188 status
= this->ike_sa
->route(this->ike_sa
, child_cfg
);
194 child_cfg
->destroy(child_cfg
);
195 if (status
!= SUCCESS
)
200 iterator
->destroy(iterator
);
205 * send closing signals for all CHILD_SAs over the bus
207 static void log_children(private_child_delete_t
*this)
209 iterator_t
*iterator
;
210 child_sa_t
*child_sa
;
212 iterator
= this->child_sas
->create_iterator(this->child_sas
, TRUE
);
213 while (iterator
->iterate(iterator
, (void**)&child_sa
))
215 SIG_CHD(DOWN_START
, child_sa
, "closing CHILD_SA %s{%d} "
216 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
217 child_sa
->get_name(child_sa
),
218 child_sa
->get_reqid(child_sa
),
219 ntohl(child_sa
->get_spi(child_sa
, TRUE
)),
220 ntohl(child_sa
->get_spi(child_sa
, FALSE
)),
221 child_sa
->get_traffic_selectors(child_sa
, TRUE
),
222 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
224 iterator
->destroy(iterator
);
228 * Implementation of task_t.build for initiator
230 static status_t
build_i(private_child_delete_t
*this, message_t
*message
)
233 build_payloads(this, message
);
238 * Implementation of task_t.process for initiator
240 static status_t
process_i(private_child_delete_t
*this, message_t
*message
)
242 /* flush the list before adding new SAs */
243 this->child_sas
->destroy(this->child_sas
);
244 this->child_sas
= linked_list_create();
246 process_payloads(this, message
);
247 SIG_CHD(DOWN_SUCCESS
, NULL
, "CHILD_SA closed");
248 return destroy_and_reestablish(this);
252 * Implementation of task_t.process for initiator
254 static status_t
process_r(private_child_delete_t
*this, message_t
*message
)
256 process_payloads(this, message
);
262 * Implementation of task_t.build for responder
264 static status_t
build_r(private_child_delete_t
*this, message_t
*message
)
266 /* if we are rekeying, we send an empty informational */
267 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_REKEYING
)
269 build_payloads(this, message
);
271 SIG_CHD(DOWN_SUCCESS
, NULL
, "CHILD_SA closed");
272 return destroy_and_reestablish(this);
276 * Implementation of task_t.get_type
278 static task_type_t
get_type(private_child_delete_t
*this)
284 * Implementation of child_delete_t.get_child
286 static child_sa_t
* get_child(private_child_delete_t
*this)
288 child_sa_t
*child_sa
= NULL
;
289 this->child_sas
->get_first(this->child_sas
, (void**)&child_sa
);
294 * Implementation of task_t.migrate
296 static void migrate(private_child_delete_t
*this, ike_sa_t
*ike_sa
)
298 this->ike_sa
= ike_sa
;
300 this->child_sas
->destroy(this->child_sas
);
301 this->child_sas
= linked_list_create();
305 * Implementation of task_t.destroy
307 static void destroy(private_child_delete_t
*this)
309 this->child_sas
->destroy(this->child_sas
);
314 * Described in header.
316 child_delete_t
*child_delete_create(ike_sa_t
*ike_sa
, child_sa_t
*child_sa
)
318 private_child_delete_t
*this = malloc_thing(private_child_delete_t
);
320 this->public.get_child
= (child_sa_t
*(*)(child_delete_t
*))get_child
;
321 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
322 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
323 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
325 this->ike_sa
= ike_sa
;
326 this->child_sas
= linked_list_create();
328 if (child_sa
!= NULL
)
330 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
331 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
332 this->initiator
= TRUE
;
333 this->child_sas
->insert_last(this->child_sas
, child_sa
);
337 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
338 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
339 this->initiator
= FALSE
;
341 return &this->public;