2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
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 "quick_delete.h"
19 #include <encoding/payloads/delete_payload.h>
21 typedef struct private_quick_delete_t private_quick_delete_t
;
24 * Private members of a quick_delete_t task.
26 struct private_quick_delete_t
{
29 * Public methods and task_t interface.
31 quick_delete_t
public;
39 * Are we the initiator?
44 * Protocol of CHILD_SA to delete
46 protocol_id_t protocol
;
49 * Inbound SPI of CHILD_SA to delete
54 * Send delete even if SA does not exist
65 * Delete the specified CHILD_SA, if found
67 static bool delete_child(private_quick_delete_t
*this,
68 protocol_id_t protocol
, u_int32_t spi
)
70 u_int64_t bytes_in
, bytes_out
;
74 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
, spi
, TRUE
);
76 { /* fallback and check for outbound SA */
77 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
, spi
, FALSE
);
82 this->spi
= spi
= child_sa
->get_spi(child_sa
, TRUE
);
85 rekeyed
= child_sa
->get_state(child_sa
) == CHILD_REKEYING
;
86 child_sa
->set_state(child_sa
, CHILD_DELETING
);
90 DBG0(DBG_IKE
, "closing expired CHILD_SA %s{%d} "
91 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
92 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
93 ntohl(child_sa
->get_spi(child_sa
, TRUE
)),
94 ntohl(child_sa
->get_spi(child_sa
, FALSE
)),
95 child_sa
->get_traffic_selectors(child_sa
, TRUE
),
96 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
100 child_sa
->get_usestats(child_sa
, TRUE
, NULL
, &bytes_in
);
101 child_sa
->get_usestats(child_sa
, FALSE
, NULL
, &bytes_out
);
103 DBG0(DBG_IKE
, "closing CHILD_SA %s{%d} with SPIs "
104 "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R=== %#R",
105 child_sa
->get_name(child_sa
), child_sa
->get_reqid(child_sa
),
106 ntohl(child_sa
->get_spi(child_sa
, TRUE
)), bytes_in
,
107 ntohl(child_sa
->get_spi(child_sa
, FALSE
)), bytes_out
,
108 child_sa
->get_traffic_selectors(child_sa
, TRUE
),
109 child_sa
->get_traffic_selectors(child_sa
, FALSE
));
114 charon
->bus
->child_updown(charon
->bus
, child_sa
, FALSE
);
117 this->ike_sa
->destroy_child_sa(this->ike_sa
, protocol
, spi
);
119 /* TODO-IKEv1: handle close action? */
124 METHOD(task_t
, build_i
, status_t
,
125 private_quick_delete_t
*this, message_t
*message
)
127 if (delete_child(this, this->protocol
, this->spi
) || this->force
)
129 delete_payload_t
*delete_payload
;
131 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
132 protocol_id_names
, this->protocol
, ntohl(this->spi
));
134 delete_payload
= delete_payload_create(DELETE_V1
, PROTO_ESP
);
135 delete_payload
->add_spi(delete_payload
, this->spi
);
136 message
->add_payload(message
, &delete_payload
->payload_interface
);
143 METHOD(task_t
, process_i
, status_t
,
144 private_quick_delete_t
*this, message_t
*message
)
149 METHOD(task_t
, process_r
, status_t
,
150 private_quick_delete_t
*this, message_t
*message
)
152 enumerator_t
*payloads
, *spis
;
154 delete_payload_t
*delete_payload
;
155 protocol_id_t protocol
;
158 payloads
= message
->create_payload_enumerator(message
);
159 while (payloads
->enumerate(payloads
, &payload
))
161 if (payload
->get_type(payload
) == DELETE_V1
)
163 delete_payload
= (delete_payload_t
*)payload
;
164 protocol
= delete_payload
->get_protocol_id(delete_payload
);
165 if (protocol
!= PROTO_ESP
&& protocol
!= PROTO_AH
)
169 spis
= delete_payload
->create_spi_enumerator(delete_payload
);
170 while (spis
->enumerate(spis
, &spi
))
172 DBG1(DBG_IKE
, "received DELETE for %N CHILD_SA with SPI %.8x",
173 protocol_id_names
, protocol
, ntohl(spi
));
174 if (!delete_child(this, protocol
, spi
))
176 DBG1(DBG_IKE
, "CHILD_SA not found, ignored");
183 payloads
->destroy(payloads
);
188 METHOD(task_t
, build_r
, status_t
,
189 private_quick_delete_t
*this, message_t
*message
)
194 METHOD(task_t
, get_type
, task_type_t
,
195 private_quick_delete_t
*this)
197 return TASK_QUICK_DELETE
;
200 METHOD(task_t
, migrate
, void,
201 private_quick_delete_t
*this, ike_sa_t
*ike_sa
)
203 this->ike_sa
= ike_sa
;
206 METHOD(task_t
, destroy
, void,
207 private_quick_delete_t
*this)
213 * Described in header.
215 quick_delete_t
*quick_delete_create(ike_sa_t
*ike_sa
, protocol_id_t protocol
,
216 u_int32_t spi
, bool force
, bool expired
)
218 private_quick_delete_t
*this;
223 .get_type
= _get_type
,
229 .protocol
= protocol
,
235 if (protocol
!= PROTO_NONE
)
237 this->public.task
.build
= _build_i
;
238 this->public.task
.process
= _process_i
;
242 this->public.task
.build
= _build_r
;
243 this->public.task
.process
= _process_r
;
245 return &this->public;