]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/charon/sa/tasks/ike_mobike.c
support of right=%<FQDN> wildcard
[thirdparty/strongswan.git] / src / charon / sa / tasks / ike_mobike.c
CommitLineData
17d92e97
MW
1/**
2 * @file ike_mobike.c
3 *
4 * @brief Implementation of the ike_mobike task.
5 *
6 */
7
8/*
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
22
23#include "ike_mobike.h"
24
25#include <string.h>
26
27#include <daemon.h>
28#include <encoding/payloads/notify_payload.h>
29
30
31typedef struct private_ike_mobike_t private_ike_mobike_t;
32
33/**
34 * Private members of a ike_mobike_t task.
35 */
36struct private_ike_mobike_t {
37
38 /**
39 * Public methods and task_t interface.
40 */
41 ike_mobike_t public;
42
43 /**
44 * Assigned IKE_SA.
45 */
46 ike_sa_t *ike_sa;
47
48 /**
49 * Are we the initiator?
50 */
51 bool initiator;
52
53 /**
54 * local host to roam to
55 */
56 host_t *me;
57
58 /**
59 * remote host to roam to
60 */
61 host_t *other;
62};
63
64/**
65 * flush the IKE_SAs list of additional addresses
66 */
67static void flush_additional_addresses(private_ike_mobike_t *this)
68{
69 iterator_t *iterator;
70 host_t *host;
71
72 iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa);
73 while (iterator->iterate(iterator, (void**)&host))
74 {
75 iterator->remove(iterator);
76 host->destroy(host);
77 }
78 iterator->destroy(iterator);
79}
80
81
82/**
83 * read notifys from message and evaluate them
84 */
85static void process_payloads(private_ike_mobike_t *this, message_t *message)
86{
87 iterator_t *iterator;
88 payload_t *payload;
89 bool first = TRUE;
90
91 iterator = message->get_payload_iterator(message);
92 while (iterator->iterate(iterator, (void**)&payload))
93 {
94 int family = AF_INET;
95 notify_payload_t *notify;
96 chunk_t data;
97 host_t *host;
98
99 if (payload->get_type(payload) != NOTIFY)
100 {
101 continue;
102 }
103 notify = (notify_payload_t*)payload;
104 switch (notify->get_notify_type(notify))
105 {
106 case MOBIKE_SUPPORTED:
107 {
108 DBG2(DBG_IKE, "peer supports MOBIKE");
109 this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
110 break;
111 }
112 case ADDITIONAL_IP6_ADDRESS:
113 {
114 family = AF_INET6;
115 /* fall through */
116 }
117 case ADDITIONAL_IP4_ADDRESS:
118 {
119 if (first)
120 { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
121 flush_additional_addresses(this);
122 }
123 data = notify->get_notification_data(notify);
124 host = host_create_from_chunk(family, data, 0);
125 DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
126 this->ike_sa->add_additional_address(this->ike_sa, host);
127 break;
128 }
129 case NO_ADDITIONAL_ADDRESSES:
130 {
131 flush_additional_addresses(this);
132 break;
133 }
134 default:
135 break;
136 }
137 }
138 iterator->destroy(iterator);
139}
140
141/**
142 * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
143 */
144static void build_address_list(private_ike_mobike_t *this, message_t *message)
145{
146 iterator_t *iterator;
147 host_t *host, *me;
148 notify_type_t type;
149 bool additional = FALSE;
150
151 me = this->ike_sa->get_my_host(this->ike_sa);
152 iterator = charon->kernel_interface->create_address_iterator(
153 charon->kernel_interface);
154 while (iterator->iterate(iterator, (void**)&host))
155 {
156 if (me->ip_equals(me, host))
157 { /* "ADDITIONAL" means do not include IKE_SAs host */
158 continue;
159 }
160 switch (host->get_family(host))
161 {
162 case AF_INET:
163 type = ADDITIONAL_IP4_ADDRESS;
164 break;
165 case AF_INET6:
166 type = ADDITIONAL_IP6_ADDRESS;
167 break;
168 default:
169 continue;
170 }
171 message->add_notify(message, FALSE, type, host->get_address(host));
172 additional = TRUE;
173 }
174 if (!additional)
175 {
176 message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
177 }
178 iterator->destroy(iterator);
179}
180
181/**
182 * Implementation of task_t.process for initiator
183 */
184static status_t build_i(private_ike_mobike_t *this, message_t *message)
185{
186 if (message->get_exchange_type(message) == IKE_AUTH &&
187 message->get_payload(message, SECURITY_ASSOCIATION))
188 {
189 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
190 build_address_list(this, message);
191 }
192
193 return NEED_MORE;
194}
195
196/**
197 * Implementation of task_t.process for responder
198 */
199static status_t process_r(private_ike_mobike_t *this, message_t *message)
200{
201 process_payloads(this, message);
202
203 return NEED_MORE;
204}
205
206/**
207 * Implementation of task_t.build for responder
208 */
209static status_t build_r(private_ike_mobike_t *this, message_t *message)
210{
211 if (message->get_exchange_type(message) == IKE_AUTH &&
212 message->get_payload(message, SECURITY_ASSOCIATION))
213 {
214 if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
215 {
216 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
217 build_address_list(this, message);
218 }
219 return SUCCESS;
220 }
221 return NEED_MORE;
222}
223
224/**
225 * Implementation of task_t.process for initiator
226 */
227static status_t process_i(private_ike_mobike_t *this, message_t *message)
228{
229 if (message->get_exchange_type(message) == IKE_AUTH &&
230 message->get_payload(message, SECURITY_ASSOCIATION))
231 {
232 process_payloads(this, message);
233 return SUCCESS;
234 }
235 return NEED_MORE;
236}
237
238/**
239 * Implementation of ike_mobike_t.roam.
240 */
241static void roam(private_ike_mobike_t *this, host_t *me, host_t *other)
242{
243 this->me = me;
244 this->other = other;
245}
246
247/**
248 * Implementation of task_t.get_type
249 */
250static task_type_t get_type(private_ike_mobike_t *this)
251{
252 return IKE_MOBIKE;
253}
254
255/**
256 * Implementation of task_t.migrate
257 */
258static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa)
259{
260 DESTROY_IF(this->me);
261 DESTROY_IF(this->other);
262 this->ike_sa = ike_sa;
263 this->me = NULL;
264 this->other = NULL;
265}
266
267/**
268 * Implementation of task_t.destroy
269 */
270static void destroy(private_ike_mobike_t *this)
271{
272 DESTROY_IF(this->me);
273 DESTROY_IF(this->other);
274 free(this);
275}
276
277/*
278 * Described in header.
279 */
280ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
281{
282 private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t);
283
284 this->public.roam = (void(*)(ike_mobike_t*, host_t *, host_t *))roam;
285 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
286 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
287 this->public.task.destroy = (void(*)(task_t*))destroy;
288
289 if (initiator)
290 {
291 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
292 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
293 }
294 else
295 {
296 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
297 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
298 }
299
300 this->ike_sa = ike_sa;
301 this->initiator = initiator;
302 this->me = NULL;
303 this->other = NULL;
304
305 return &this->public;
306}
307