Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/quick_delete.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Copyright (C) 2011 Martin Willi
3: * Copyright (C) 2011 revosec AG
4: *
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>.
9: *
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
13: * for more details.
14: */
15: /*
16: * Copyright (C) 2013 Oliver Smith
17: *
18: * Permission is hereby granted, free of charge, to any person obtaining a copy
19: * of this software and associated documentation files (the "Software"), to deal
20: * in the Software without restriction, including without limitation the rights
21: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22: * copies of the Software, and to permit persons to whom the Software is
23: * furnished to do so, subject to the following conditions:
24: *
25: * The above copyright notice and this permission notice shall be included in
26: * all copies or substantial portions of the Software.
27: *
28: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34: * THE SOFTWARE.
35: */
36:
37: #include "quick_delete.h"
38:
39: #include <daemon.h>
40: #include <encoding/payloads/delete_payload.h>
41: #include <sa/ikev1/task_manager_v1.h>
42:
43: typedef struct private_quick_delete_t private_quick_delete_t;
44:
45: /**
46: * Private members of a quick_delete_t task.
47: */
48: struct private_quick_delete_t {
49:
50: /**
51: * Public methods and task_t interface.
52: */
53: quick_delete_t public;
54:
55: /**
56: * Assigned IKE_SA.
57: */
58: ike_sa_t *ike_sa;
59:
60: /**
61: * Are we the initiator?
62: */
63: bool initiator;
64:
65: /**
66: * Protocol of CHILD_SA to delete
67: */
68: protocol_id_t protocol;
69:
70: /**
71: * Inbound SPI of CHILD_SA to delete
72: */
73: uint32_t spi;
74:
75: /**
76: * Send delete even if SA does not exist
77: */
78: bool force;
79:
80: /**
81: * SA already expired?
82: */
83: bool expired;
84: };
85:
86: /**
87: * Delete the specified CHILD_SA, if found
88: */
1.1.1.2 ! misho 89: static status_t delete_child(private_quick_delete_t *this,
! 90: protocol_id_t protocol, uint32_t spi,
! 91: bool remote_close)
1.1 misho 92: {
93: uint64_t bytes_in, bytes_out;
94: child_sa_t *child_sa;
95: linked_list_t *my_ts, *other_ts;
96: child_cfg_t *child_cfg;
1.1.1.2 ! misho 97: status_t status = SUCCESS;
1.1 misho 98: bool rekeyed;
99:
100: child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE);
101: if (!child_sa)
102: { /* fallback and check for outbound SA */
103: child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE);
104: if (!child_sa)
105: {
1.1.1.2 ! misho 106: return NOT_FOUND;
1.1 misho 107: }
108: this->spi = spi = child_sa->get_spi(child_sa, TRUE);
109: }
110:
111: rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYED;
112: if (!rekeyed)
113: {
114: rekeyed = ikev1_child_sa_is_redundant(this->ike_sa, child_sa, NULL);
115: }
116: child_sa->set_state(child_sa, CHILD_DELETING);
117:
118: my_ts = linked_list_create_from_enumerator(
119: child_sa->create_ts_enumerator(child_sa, TRUE));
120: other_ts = linked_list_create_from_enumerator(
121: child_sa->create_ts_enumerator(child_sa, FALSE));
122: if (this->expired)
123: {
124: DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
125: "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
126: child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
127: ntohl(child_sa->get_spi(child_sa, TRUE)),
128: ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts);
129: }
130: else
131: {
132: child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, NULL);
133: child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL);
134:
135: DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs "
136: "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
137: child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
138: ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
139: ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
140: my_ts, other_ts);
141: }
142: my_ts->destroy(my_ts);
143: other_ts->destroy(other_ts);
144:
145: child_sa->set_state(child_sa, CHILD_DELETED);
146: if (!rekeyed)
147: {
148: charon->bus->child_updown(charon->bus, child_sa, FALSE);
149:
150: if (remote_close)
151: {
152: child_cfg = child_sa->get_config(child_sa);
153: child_cfg->get_ref(child_cfg);
154:
155: switch (child_sa->get_close_action(child_sa))
156: {
157: case ACTION_RESTART:
158: child_cfg->get_ref(child_cfg);
1.1.1.2 ! misho 159: status = this->ike_sa->initiate(this->ike_sa, child_cfg,
1.1 misho 160: child_sa->get_reqid(child_sa), NULL, NULL);
161: break;
162: case ACTION_ROUTE:
163: charon->traps->install(charon->traps,
164: this->ike_sa->get_peer_cfg(this->ike_sa),
165: child_cfg);
166: break;
167: default:
168: break;
169: }
170: child_cfg->destroy(child_cfg);
171: }
172: }
1.1.1.2 ! misho 173: if (status == SUCCESS)
! 174: {
! 175: this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
! 176: }
! 177: return status;
1.1 misho 178: }
179:
180: METHOD(task_t, build_i, status_t,
181: private_quick_delete_t *this, message_t *message)
182: {
1.1.1.2 ! misho 183: if (delete_child(this, this->protocol, this->spi, FALSE) == SUCCESS ||
! 184: this->force)
1.1 misho 185: {
186: delete_payload_t *delete_payload;
187:
188: DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
189: protocol_id_names, this->protocol, ntohl(this->spi));
190:
191: delete_payload = delete_payload_create(PLV1_DELETE, this->protocol);
192: delete_payload->add_spi(delete_payload, this->spi);
193: message->add_payload(message, &delete_payload->payload_interface);
194:
195: return SUCCESS;
196: }
197: this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
198: return ALREADY_DONE;
199: }
200:
201: METHOD(task_t, process_i, status_t,
202: private_quick_delete_t *this, message_t *message)
203: {
204: return FAILED;
205: }
206:
207: METHOD(task_t, process_r, status_t,
208: private_quick_delete_t *this, message_t *message)
209: {
210: enumerator_t *payloads, *spis;
211: payload_t *payload;
212: delete_payload_t *delete_payload;
213: protocol_id_t protocol;
1.1.1.2 ! misho 214: status_t status = SUCCESS;
1.1 misho 215: uint32_t spi;
216:
217: payloads = message->create_payload_enumerator(message);
218: while (payloads->enumerate(payloads, &payload))
219: {
220: if (payload->get_type(payload) == PLV1_DELETE)
221: {
222: delete_payload = (delete_payload_t*)payload;
223: protocol = delete_payload->get_protocol_id(delete_payload);
224: if (protocol != PROTO_ESP && protocol != PROTO_AH)
225: {
226: continue;
227: }
228: spis = delete_payload->create_spi_enumerator(delete_payload);
229: while (spis->enumerate(spis, &spi))
230: {
231: DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
232: protocol_id_names, protocol, ntohl(spi));
1.1.1.2 ! misho 233: status = delete_child(this, protocol, spi, TRUE);
! 234: if (status == NOT_FOUND)
1.1 misho 235: {
236: DBG1(DBG_IKE, "CHILD_SA not found, ignored");
1.1.1.2 ! misho 237: status = SUCCESS;
! 238: }
! 239: if (status != SUCCESS)
! 240: {
! 241: break;
1.1 misho 242: }
243: }
244: spis->destroy(spis);
245: }
1.1.1.2 ! misho 246: if (status != SUCCESS)
! 247: {
! 248: break;
! 249: }
1.1 misho 250: }
251: payloads->destroy(payloads);
252:
1.1.1.2 ! misho 253: return status;
1.1 misho 254: }
255:
256: METHOD(task_t, build_r, status_t,
257: private_quick_delete_t *this, message_t *message)
258: {
259: return FAILED;
260: }
261:
262: METHOD(task_t, get_type, task_type_t,
263: private_quick_delete_t *this)
264: {
265: return TASK_QUICK_DELETE;
266: }
267:
268: METHOD(task_t, migrate, void,
269: private_quick_delete_t *this, ike_sa_t *ike_sa)
270: {
271: this->ike_sa = ike_sa;
272: }
273:
274: METHOD(task_t, destroy, void,
275: private_quick_delete_t *this)
276: {
277: free(this);
278: }
279:
280: /*
281: * Described in header.
282: */
283: quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
284: uint32_t spi, bool force, bool expired)
285: {
286: private_quick_delete_t *this;
287:
288: INIT(this,
289: .public = {
290: .task = {
291: .get_type = _get_type,
292: .migrate = _migrate,
293: .destroy = _destroy,
294: },
295: },
296: .ike_sa = ike_sa,
297: .protocol = protocol,
298: .spi = spi,
299: .force = force,
300: .expired = expired,
301: );
302:
303: if (protocol != PROTO_NONE)
304: {
305: this->public.task.build = _build_i;
306: this->public.task.process = _process_i;
307: }
308: else
309: {
310: this->public.task.build = _build_r;
311: this->public.task.process = _process_r;
312: }
313: return &this->public;
314: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>