Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/quick_delete.c, revision 1.1.1.1
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: */
89: static bool delete_child(private_quick_delete_t *this, protocol_id_t protocol,
90: uint32_t spi, bool remote_close)
91: {
92: uint64_t bytes_in, bytes_out;
93: child_sa_t *child_sa;
94: linked_list_t *my_ts, *other_ts;
95: child_cfg_t *child_cfg;
96: bool rekeyed;
97:
98: child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, TRUE);
99: if (!child_sa)
100: { /* fallback and check for outbound SA */
101: child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol, spi, FALSE);
102: if (!child_sa)
103: {
104: return FALSE;
105: }
106: this->spi = spi = child_sa->get_spi(child_sa, TRUE);
107: }
108:
109: rekeyed = child_sa->get_state(child_sa) == CHILD_REKEYED;
110: if (!rekeyed)
111: {
112: rekeyed = ikev1_child_sa_is_redundant(this->ike_sa, child_sa, NULL);
113: }
114: child_sa->set_state(child_sa, CHILD_DELETING);
115:
116: my_ts = linked_list_create_from_enumerator(
117: child_sa->create_ts_enumerator(child_sa, TRUE));
118: other_ts = linked_list_create_from_enumerator(
119: child_sa->create_ts_enumerator(child_sa, FALSE));
120: if (this->expired)
121: {
122: DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
123: "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
124: child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
125: ntohl(child_sa->get_spi(child_sa, TRUE)),
126: ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts);
127: }
128: else
129: {
130: child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, NULL);
131: child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL);
132:
133: DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs "
134: "%.8x_i (%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
135: child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
136: ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
137: ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
138: my_ts, other_ts);
139: }
140: my_ts->destroy(my_ts);
141: other_ts->destroy(other_ts);
142:
143: child_sa->set_state(child_sa, CHILD_DELETED);
144: if (!rekeyed)
145: {
146: charon->bus->child_updown(charon->bus, child_sa, FALSE);
147:
148: if (remote_close)
149: {
150: child_cfg = child_sa->get_config(child_sa);
151: child_cfg->get_ref(child_cfg);
152:
153: switch (child_sa->get_close_action(child_sa))
154: {
155: case ACTION_RESTART:
156: child_cfg->get_ref(child_cfg);
157: this->ike_sa->initiate(this->ike_sa, child_cfg,
158: child_sa->get_reqid(child_sa), NULL, NULL);
159: break;
160: case ACTION_ROUTE:
161: charon->traps->install(charon->traps,
162: this->ike_sa->get_peer_cfg(this->ike_sa),
163: child_cfg);
164: break;
165: default:
166: break;
167: }
168: child_cfg->destroy(child_cfg);
169: }
170: }
171: this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
172:
173: return TRUE;
174: }
175:
176: METHOD(task_t, build_i, status_t,
177: private_quick_delete_t *this, message_t *message)
178: {
179: if (delete_child(this, this->protocol, this->spi, FALSE) || this->force)
180: {
181: delete_payload_t *delete_payload;
182:
183: DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
184: protocol_id_names, this->protocol, ntohl(this->spi));
185:
186: delete_payload = delete_payload_create(PLV1_DELETE, this->protocol);
187: delete_payload->add_spi(delete_payload, this->spi);
188: message->add_payload(message, &delete_payload->payload_interface);
189:
190: return SUCCESS;
191: }
192: this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
193: return ALREADY_DONE;
194: }
195:
196: METHOD(task_t, process_i, status_t,
197: private_quick_delete_t *this, message_t *message)
198: {
199: return FAILED;
200: }
201:
202: METHOD(task_t, process_r, status_t,
203: private_quick_delete_t *this, message_t *message)
204: {
205: enumerator_t *payloads, *spis;
206: payload_t *payload;
207: delete_payload_t *delete_payload;
208: protocol_id_t protocol;
209: uint32_t spi;
210:
211: payloads = message->create_payload_enumerator(message);
212: while (payloads->enumerate(payloads, &payload))
213: {
214: if (payload->get_type(payload) == PLV1_DELETE)
215: {
216: delete_payload = (delete_payload_t*)payload;
217: protocol = delete_payload->get_protocol_id(delete_payload);
218: if (protocol != PROTO_ESP && protocol != PROTO_AH)
219: {
220: continue;
221: }
222: spis = delete_payload->create_spi_enumerator(delete_payload);
223: while (spis->enumerate(spis, &spi))
224: {
225: DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
226: protocol_id_names, protocol, ntohl(spi));
227: if (!delete_child(this, protocol, spi, TRUE))
228: {
229: DBG1(DBG_IKE, "CHILD_SA not found, ignored");
230: continue;
231: }
232: }
233: spis->destroy(spis);
234: }
235: }
236: payloads->destroy(payloads);
237:
238: return SUCCESS;
239: }
240:
241: METHOD(task_t, build_r, status_t,
242: private_quick_delete_t *this, message_t *message)
243: {
244: return FAILED;
245: }
246:
247: METHOD(task_t, get_type, task_type_t,
248: private_quick_delete_t *this)
249: {
250: return TASK_QUICK_DELETE;
251: }
252:
253: METHOD(task_t, migrate, void,
254: private_quick_delete_t *this, ike_sa_t *ike_sa)
255: {
256: this->ike_sa = ike_sa;
257: }
258:
259: METHOD(task_t, destroy, void,
260: private_quick_delete_t *this)
261: {
262: free(this);
263: }
264:
265: /*
266: * Described in header.
267: */
268: quick_delete_t *quick_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
269: uint32_t spi, bool force, bool expired)
270: {
271: private_quick_delete_t *this;
272:
273: INIT(this,
274: .public = {
275: .task = {
276: .get_type = _get_type,
277: .migrate = _migrate,
278: .destroy = _destroy,
279: },
280: },
281: .ike_sa = ike_sa,
282: .protocol = protocol,
283: .spi = spi,
284: .force = force,
285: .expired = expired,
286: );
287:
288: if (protocol != PROTO_NONE)
289: {
290: this->public.task.build = _build_i;
291: this->public.task.process = _process_i;
292: }
293: else
294: {
295: this->public.task.build = _build_r;
296: this->public.task.process = _process_r;
297: }
298: return &this->public;
299: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>