2 * @file delete_child_sa.c
4 * @brief Implementation of the delete_child_sa transaction.
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include "delete_child_sa.h"
26 #include <encoding/payloads/delete_payload.h>
29 typedef struct private_delete_child_sa_t private_delete_child_sa_t
;
32 * Private members of a delete_child_sa_t object..
34 struct private_delete_child_sa_t
{
37 * Public methods and transaction_t interface.
39 delete_child_sa_t
public;
47 * Message sent by our peer, if already generated
52 * Message ID this transaction uses
57 * Times we did send the request
73 * Implementation of transaction_t.get_message_id.
75 static u_int32_t
get_message_id(private_delete_child_sa_t
*this)
77 return this->message_id
;
81 * Implementation of transaction_t.requested.
83 static u_int32_t
requested(private_delete_child_sa_t
*this)
85 return this->requested
++;
89 * Implementation of delete_child_sa_t.set_child_sa.
91 static void set_child_sa(private_delete_child_sa_t
*this, child_sa_t
*child_sa
)
93 this->child_sa
= child_sa
;
97 * Implementation of transaction_t.get_request.
99 static status_t
get_request(private_delete_child_sa_t
*this, message_t
**result
)
102 connection_t
*connection
;
105 /* check if we already have built a message (retransmission) */
108 *result
= this->message
;
112 connection
= this->ike_sa
->get_connection(this->ike_sa
);
113 me
= connection
->get_my_host(connection
);
114 other
= connection
->get_other_host(connection
);
116 /* build the request */
117 request
= message_create();
118 request
->set_source(request
, me
->clone(me
));
119 request
->set_destination(request
, other
->clone(other
));
120 request
->set_exchange_type(request
, INFORMATIONAL
);
121 request
->set_request(request
, TRUE
);
122 request
->set_message_id(request
, this->message_id
);
123 request
->set_ike_sa_id(request
, this->ike_sa
->get_id(this->ike_sa
));
125 this->message
= request
;
127 { /* add delete payload */
128 delete_payload_t
*delete_payload
;
129 protocol_id_t protocol
;
132 protocol
= this->child_sa
->get_protocol(this->child_sa
);
133 spi
= this->child_sa
->get_spi(this->child_sa
, TRUE
);
134 delete_payload
= delete_payload_create(protocol
);
136 this->logger
->log(this->logger
, CONTROL
,
137 "created DELETE payload for %s CHILD_SA with SPI 0x%x",
138 mapping_find(protocol_id_m
, protocol
), htonl(spi
));
139 delete_payload
->add_spi(delete_payload
, spi
);
140 request
->add_payload(request
, (payload_t
*)delete_payload
);
147 * process a delete payload
149 static status_t
process_delete(private_delete_child_sa_t
*this, delete_payload_t
*delete_request
, message_t
*response
)
151 protocol_id_t protocol
;
153 iterator_t
*iterator
;
154 delete_payload_t
*delete_response
;
156 /* get requested CHILD */
157 protocol
= delete_request
->get_protocol_id(delete_request
);
158 if (protocol
!= PROTO_ESP
&& protocol
!= PROTO_AH
)
160 this->logger
->log(this->logger
, CONTROL
,
161 "CHILD_SA delete response contained unexpected protocol");
165 /* prepare response payload */
168 delete_response
= delete_payload_create(protocol
);
169 response
->add_payload(response
, (payload_t
*)delete_response
);
172 iterator
= delete_request
->create_spi_iterator(delete_request
);
173 while (iterator
->iterate(iterator
, (void**)&spi
))
175 child_sa_t
*child_sa
;
177 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
, spi
, FALSE
);
179 if (child_sa
!= NULL
)
181 this->logger
->log(this->logger
, CONTROL
,
182 "received DELETE for %s CHILD_SA with SPI 0x%x, deleting",
183 mapping_find(protocol_id_m
, protocol
), ntohl(spi
));
184 /* delete it, with inbound spi */
185 spi
= child_sa
->get_spi(child_sa
, TRUE
);
186 this->ike_sa
->destroy_child_sa(this->ike_sa
, protocol
, spi
);
187 /* add delete response to message, if we are responding */
190 delete_response
->add_spi(delete_response
, spi
);
195 this->logger
->log(this->logger
, ERROR
,
196 "received DELETE for %s CHILD_SA with SPI 0x%x, but no such SA",
197 mapping_find(protocol_id_m
, protocol
), ntohl(spi
));
200 iterator
->destroy(iterator
);
205 * Implementation of transaction_t.get_response.
207 static status_t
get_response(private_delete_child_sa_t
*this, message_t
*request
,
208 message_t
**result
, transaction_t
**next
)
212 iterator_t
*payloads
;
213 connection_t
*connection
;
215 /* check if we already have built a response (retransmission) */
218 *result
= this->message
;
222 connection
= this->ike_sa
->get_connection(this->ike_sa
);
223 me
= connection
->get_my_host(connection
);
224 other
= connection
->get_other_host(connection
);
226 /* set up response */
227 response
= message_create();
228 response
->set_source(response
, me
->clone(me
));
229 response
->set_destination(response
, other
->clone(other
));
230 response
->set_exchange_type(response
, INFORMATIONAL
);
231 response
->set_request(response
, FALSE
);
232 response
->set_message_id(response
, this->message_id
);
233 response
->set_ike_sa_id(response
, this->ike_sa
->get_id(this->ike_sa
));
234 this->message
= response
;
237 if (request
->get_exchange_type(request
) != INFORMATIONAL
)
239 this->logger
->log(this->logger
, ERROR
,
240 "INFORMATIONAL response of invalid type, aborting");
244 /* iterate over all payloads */
245 payloads
= request
->get_payload_iterator(request
);
246 while (payloads
->has_next(payloads
))
249 payloads
->current(payloads
, (void**)&payload
);
251 switch (payload
->get_type(payload
))
255 process_delete(this, (delete_payload_t
*)payload
, response
);
260 this->logger
->log(this->logger
, ERROR
|LEVEL1
, "ignoring payload %s (%d)",
261 mapping_find(payload_type_m
, payload
->get_type(payload
)),
262 payload
->get_type(payload
));
267 payloads
->destroy(payloads
);
272 * Implementation of transaction_t.conclude
274 static status_t
conclude(private_delete_child_sa_t
*this, message_t
*response
,
275 transaction_t
**transaction
)
277 iterator_t
*payloads
;
279 /* check message type */
280 if (response
->get_exchange_type(response
) != INFORMATIONAL
)
282 this->logger
->log(this->logger
, ERROR
,
283 "INFORMATIONAL response of invalid type, aborting");
287 /* iterate over all payloads */
288 payloads
= response
->get_payload_iterator(response
);
289 while (payloads
->has_next(payloads
))
292 payloads
->current(payloads
, (void**)&payload
);
294 switch (payload
->get_type(payload
))
298 process_delete(this, (delete_payload_t
*)payload
, NULL
);
303 this->logger
->log(this->logger
, ERROR
|LEVEL1
, "ignoring payload %s (%d)",
304 mapping_find(payload_type_m
, payload
->get_type(payload
)),
305 payload
->get_type(payload
));
310 payloads
->destroy(payloads
);
315 * implements transaction_t.destroy
317 static void destroy(private_delete_child_sa_t
*this)
321 this->message
->destroy(this->message
);
327 * Described in header.
329 delete_child_sa_t
*delete_child_sa_create(ike_sa_t
*ike_sa
, u_int32_t message_id
)
331 private_delete_child_sa_t
*this = malloc_thing(private_delete_child_sa_t
);
333 /* transaction interface functions */
334 this->public.transaction
.get_request
= (status_t(*)(transaction_t
*,message_t
**))get_request
;
335 this->public.transaction
.get_response
= (status_t(*)(transaction_t
*,message_t
*,message_t
**,transaction_t
**))get_response
;
336 this->public.transaction
.conclude
= (status_t(*)(transaction_t
*,message_t
*,transaction_t
**))conclude
;
337 this->public.transaction
.get_message_id
= (u_int32_t(*)(transaction_t
*))get_message_id
;
338 this->public.transaction
.requested
= (u_int32_t(*)(transaction_t
*))requested
;
339 this->public.transaction
.destroy
= (void(*)(transaction_t
*))destroy
;
342 this->public.set_child_sa
= (void(*)(delete_child_sa_t
*,child_sa_t
*))set_child_sa
;
345 this->ike_sa
= ike_sa
;
346 this->message_id
= message_id
;
347 this->message
= NULL
;
349 this->logger
= logger_manager
->get_logger(logger_manager
, IKE_SA
);
351 return &this->public;