Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/informational.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: #include "informational.h"
17:
18: #include <daemon.h>
19: #include <sa/ikev1/tasks/isakmp_delete.h>
20: #include <sa/ikev1/tasks/quick_delete.h>
21:
22: #include <encoding/payloads/delete_payload.h>
23:
24: typedef struct private_informational_t private_informational_t;
25:
26: /**
27: * Private members of a informational_t task.
28: */
29: struct private_informational_t {
30:
31: /**
32: * Public methods and task_t interface.
33: */
34: informational_t public;
35:
36: /**
37: * Assigned IKE_SA.
38: */
39: ike_sa_t *ike_sa;
40:
41: /**
42: * Notify payload to send
43: */
44: notify_payload_t *notify;
45:
46: /**
47: * Delete subtask
48: */
49: task_t *del;
50: };
51:
52: /**
53: * Cancel active quick mode after receiving an error
54: */
55: static void cancel_quick_mode(private_informational_t *this)
56: {
57: enumerator_t *enumerator;
58: task_t *task;
59:
60: enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
61: TASK_QUEUE_ACTIVE);
62: while (enumerator->enumerate(enumerator, &task))
63: {
64: if (task->get_type(task) == TASK_QUICK_MODE)
65: {
66: this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_ACTIVE);
67: break;
68: }
69: }
70: enumerator->destroy(enumerator);
71: }
72:
73: METHOD(task_t, build_i, status_t,
74: private_informational_t *this, message_t *message)
75: {
76: message->add_payload(message, &this->notify->payload_interface);
77: this->notify = NULL;
78: return SUCCESS;
79: }
80:
81: METHOD(task_t, process_r, status_t,
82: private_informational_t *this, message_t *message)
83: {
84: enumerator_t *enumerator;
85: delete_payload_t *delete;
86: notify_payload_t *notify;
87: notify_type_t type;
88: payload_t *payload;
89: status_t status = SUCCESS;
90:
91: enumerator = message->create_payload_enumerator(message);
92: while (enumerator->enumerate(enumerator, &payload))
93: {
94: switch (payload->get_type(payload))
95: {
96: case PLV1_NOTIFY:
97: notify = (notify_payload_t*)payload;
98: type = notify->get_notify_type(notify);
99:
100: if (type == INITIAL_CONTACT_IKEV1)
101: {
102: this->ike_sa->set_condition(this->ike_sa,
103: COND_INIT_CONTACT_SEEN, TRUE);
104: }
105: else if (type == UNITY_LOAD_BALANCE)
106: {
107: host_t *redirect, *me;
108: chunk_t data;
109:
110: data = notify->get_notification_data(notify);
111: redirect = host_create_from_chunk(AF_INET, data,
112: IKEV2_UDP_PORT);
113: if (redirect)
114: { /* treat the redirect as reauthentication */
115: DBG1(DBG_IKE, "received %N notify, redirected to %H",
116: notify_type_names, type, redirect);
117: /* Cisco boxes reject the first message from 4500 */
118: me = this->ike_sa->get_my_host(this->ike_sa);
119: me->set_port(me, charon->socket->get_port(
120: charon->socket, FALSE));
121: this->ike_sa->set_other_host(this->ike_sa, redirect);
122: status = this->ike_sa->reauth(this->ike_sa);
123: enumerator->destroy(enumerator);
124: return status;
125: }
126: else
127: {
128: DBG1(DBG_IKE, "received %N notify, invalid address");
129: }
130: }
131: else if (type < 16384)
132: {
133: DBG1(DBG_IKE, "received %N error notify",
134: notify_type_names, type);
135: if (this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING)
136: { /* only critical during main mode */
137: status = FAILED;
138: }
139: switch (type)
140: {
141: case INVALID_ID_INFORMATION:
142: case NO_PROPOSAL_CHOSEN:
143: cancel_quick_mode(this);
144: break;
145: default:
146: break;
147: }
148: break;
149: }
150: else
151: {
152: DBG1(DBG_IKE, "received %N notify",
153: notify_type_names, type);
154: }
155: continue;
156: case PLV1_DELETE:
157: if (!this->del)
158: {
159: delete = (delete_payload_t*)payload;
160: if (delete->get_protocol_id(delete) == PROTO_IKE)
161: {
162: this->del = (task_t*)isakmp_delete_create(this->ike_sa,
163: FALSE);
164: }
165: else
166: {
167: this->del = (task_t*)quick_delete_create(this->ike_sa,
168: PROTO_NONE, 0, FALSE, FALSE);
169: }
170: }
171: break;
172: default:
173: continue;
174: }
175: break;
176: }
177: enumerator->destroy(enumerator);
178:
179: if (this->del && status == SUCCESS)
180: {
181: return this->del->process(this->del, message);
182: }
183: return status;
184: }
185:
186: METHOD(task_t, build_r, status_t,
187: private_informational_t *this, message_t *message)
188: {
189: if (this->del)
190: {
191: return this->del->build(this->del, message);
192: }
193: return FAILED;
194: }
195:
196: METHOD(task_t, process_i, status_t,
197: private_informational_t *this, message_t *message)
198: {
199: return FAILED;
200: }
201:
202: METHOD(task_t, get_type, task_type_t,
203: private_informational_t *this)
204: {
205: return TASK_INFORMATIONAL;
206: }
207:
208: METHOD(task_t, migrate, void,
209: private_informational_t *this, ike_sa_t *ike_sa)
210: {
211: this->ike_sa = ike_sa;
212: }
213:
214: METHOD(task_t, destroy, void,
215: private_informational_t *this)
216: {
217: DESTROY_IF(this->notify);
218: DESTROY_IF(this->del);
219: free(this);
220: }
221:
222: /*
223: * Described in header.
224: */
225: informational_t *informational_create(ike_sa_t *ike_sa, notify_payload_t *notify)
226: {
227: private_informational_t *this;
228:
229: INIT(this,
230: .public = {
231: .task = {
232: .get_type = _get_type,
233: .migrate = _migrate,
234: .destroy = _destroy,
235: },
236: },
237: .ike_sa = ike_sa,
238: .notify = notify,
239: );
240:
241: if (notify)
242: {
243: this->public.task.build = _build_i;
244: this->public.task.process = _process_i;
245: }
246: else
247: {
248: this->public.task.build = _build_r;
249: this->public.task.process = _process_r;
250: }
251:
252: return &this->public;
253: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>