4 * @brief Implementation of the ike_mobike task.
9 * Copyright (C) 2007 Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
23 #include "ike_mobike.h"
28 #include <sa/tasks/ike_natd.h>
29 #include <encoding/payloads/notify_payload.h>
32 typedef struct private_ike_mobike_t private_ike_mobike_t
;
35 * Private members of a ike_mobike_t task.
37 struct private_ike_mobike_t
{
40 * Public methods and task_t interface.
50 * Are we the initiator?
55 * cookie2 value to verify new addresses
60 * NAT discovery reusing the IKE_NATD task
65 * use task to update addresses
70 * do routability check
75 * include address list update
81 * flush the IKE_SAs list of additional addresses
83 static void flush_additional_addresses(private_ike_mobike_t
*this)
88 iterator
= this->ike_sa
->create_additional_address_iterator(this->ike_sa
);
89 while (iterator
->iterate(iterator
, (void**)&host
))
91 iterator
->remove(iterator
);
94 iterator
->destroy(iterator
);
99 * read notifys from message and evaluate them
101 static void process_payloads(private_ike_mobike_t
*this, message_t
*message
)
103 iterator_t
*iterator
;
107 iterator
= message
->get_payload_iterator(message
);
108 while (iterator
->iterate(iterator
, (void**)&payload
))
110 int family
= AF_INET
;
111 notify_payload_t
*notify
;
115 if (payload
->get_type(payload
) != NOTIFY
)
119 notify
= (notify_payload_t
*)payload
;
120 switch (notify
->get_notify_type(notify
))
122 case MOBIKE_SUPPORTED
:
124 DBG1(DBG_IKE
, "peer supports MOBIKE");
125 this->ike_sa
->enable_extension(this->ike_sa
, EXT_MOBIKE
);
128 case ADDITIONAL_IP6_ADDRESS
:
133 case ADDITIONAL_IP4_ADDRESS
:
136 { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
137 flush_additional_addresses(this);
140 data
= notify
->get_notification_data(notify
);
141 host
= host_create_from_chunk(family
, data
, 0);
142 DBG2(DBG_IKE
, "got additional MOBIKE peer address: %H", host
);
143 this->ike_sa
->add_additional_address(this->ike_sa
, host
);
146 case UPDATE_SA_ADDRESSES
:
151 case NO_ADDITIONAL_ADDRESSES
:
153 flush_additional_addresses(this);
156 case NAT_DETECTION_SOURCE_IP
:
157 case NAT_DETECTION_DESTINATION_IP
:
159 /* NAT check in this MOBIKE exchange, create subtask for it */
160 if (this->natd
== NULL
)
162 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
170 iterator
->destroy(iterator
);
174 * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
176 static void build_address_list(private_ike_mobike_t
*this, message_t
*message
)
178 iterator_t
*iterator
;
181 bool additional
= FALSE
;
183 me
= this->ike_sa
->get_my_host(this->ike_sa
);
184 iterator
= charon
->kernel_interface
->create_address_iterator(
185 charon
->kernel_interface
);
186 while (iterator
->iterate(iterator
, (void**)&host
))
188 if (me
->ip_equals(me
, host
))
189 { /* "ADDITIONAL" means do not include IKE_SAs host */
192 switch (host
->get_family(host
))
195 type
= ADDITIONAL_IP4_ADDRESS
;
198 type
= ADDITIONAL_IP6_ADDRESS
;
203 message
->add_notify(message
, FALSE
, type
, host
->get_address(host
));
208 message
->add_notify(message
, FALSE
, NO_ADDITIONAL_ADDRESSES
, chunk_empty
);
210 iterator
->destroy(iterator
);
214 * update addresses of associated CHILD_SAs
216 static void update_children(private_ike_mobike_t
*this)
218 iterator_t
*iterator
;
219 child_sa_t
*child_sa
;
221 iterator
= this->ike_sa
->create_child_sa_iterator(this->ike_sa
);
222 while (iterator
->iterate(iterator
, (void**)&child_sa
))
224 child_sa
->update_hosts(child_sa
,
225 this->ike_sa
->get_my_host(this->ike_sa
),
226 this->ike_sa
->get_other_host(this->ike_sa
),
227 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
229 iterator
->destroy(iterator
);
233 * Implementation of ike_mobike_t.transmit
235 static void transmit(private_ike_mobike_t
*this, packet_t
*packet
)
237 host_t
*me
, *other
, *me_old
, *other_old
;
238 iterator_t
*iterator
;
246 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
247 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
249 me
= charon
->kernel_interface
->get_source_addr(
250 charon
->kernel_interface
, other_old
);
253 me
->set_port(me
, me
->ip_equals(me
, me_old
) ?
254 me_old
->get_port(me_old
) : IKEV2_NATT_PORT
);
255 packet
->set_source(packet
, me
);
258 iterator
= this->ike_sa
->create_additional_address_iterator(this->ike_sa
);
259 while (iterator
->iterate(iterator
, (void**)&other
))
261 me
= charon
->kernel_interface
->get_source_addr(
262 charon
->kernel_interface
, other
);
265 /* reuse port for an active address, 4500 otherwise */
266 me
->set_port(me
, me
->ip_equals(me
, me_old
) ?
267 me_old
->get_port(me_old
) : IKEV2_NATT_PORT
);
268 other
= other
->clone(other
);
269 other
->set_port(other
, other
->ip_equals(other
, other_old
) ?
270 other_old
->get_port(other_old
) : IKEV2_NATT_PORT
);
271 copy
= packet
->clone(packet
);
272 copy
->set_source(copy
, me
);
273 copy
->set_destination(copy
, other
);
274 charon
->sender
->send(charon
->sender
, copy
);
277 iterator
->destroy(iterator
);
281 * Implementation of task_t.process for initiator
283 static status_t
build_i(private_ike_mobike_t
*this, message_t
*message
)
285 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
286 message
->get_payload(message
, SECURITY_ASSOCIATION
))
288 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
289 build_address_list(this, message
);
291 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
295 message
->add_notify(message
, FALSE
, UPDATE_SA_ADDRESSES
, chunk_empty
);
296 update_children(this);
300 build_address_list(this, message
);
304 this->natd
->task
.build(&this->natd
->task
, message
);
311 * Implementation of task_t.process for responder
313 static status_t
process_r(private_ike_mobike_t
*this, message_t
*message
)
315 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
316 message
->get_payload(message
, SECURITY_ASSOCIATION
))
318 process_payloads(this, message
);
320 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
322 process_payloads(this, message
);
327 me
= message
->get_destination(message
);
328 other
= message
->get_source(message
);
329 this->ike_sa
->set_my_host(this->ike_sa
, me
->clone(me
));
330 this->ike_sa
->set_other_host(this->ike_sa
, other
->clone(other
));
335 this->natd
->task
.process(&this->natd
->task
, message
);
342 * Implementation of task_t.build for responder
344 static status_t
build_r(private_ike_mobike_t
*this, message_t
*message
)
346 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
347 message
->get_payload(message
, SECURITY_ASSOCIATION
))
349 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_MOBIKE
))
351 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
352 build_address_list(this, message
);
356 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
360 this->natd
->task
.build(&this->natd
->task
, message
);
364 update_children(this);
372 * Implementation of task_t.process for initiator
374 static status_t
process_i(private_ike_mobike_t
*this, message_t
*message
)
376 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
377 message
->get_payload(message
, SECURITY_ASSOCIATION
))
379 process_payloads(this, message
);
382 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
384 u_int32_t updates
= this->ike_sa
->get_pending_updates(this->ike_sa
) - 1;
385 this->ike_sa
->set_pending_updates(this->ike_sa
, updates
);
388 /* newer update queued, ignore this one */
391 process_payloads(this, message
);
394 this->natd
->task
.process(&this->natd
->task
, message
);
398 /* update again, as NAT state may have changed */
399 update_children(this);
403 host_t
*me_new
, *me_old
, *other_new
, *other_old
;
405 me_new
= message
->get_destination(message
);
406 other_new
= message
->get_source(message
);
407 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
408 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
410 if (!me_new
->equals(me_new
, me_old
))
413 this->ike_sa
->set_my_host(this->ike_sa
, me_new
->clone(me_new
));
415 if (!other_new
->equals(other_new
, other_old
))
418 this->ike_sa
->set_other_host(this->ike_sa
, other_new
->clone(other_new
));
422 /* start the update with the same task */
424 this->address
= FALSE
;
425 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
426 this->ike_sa
->set_pending_updates(this->ike_sa
, 1);
436 * Implementation of ike_mobike_t.roam.
438 static void roam(private_ike_mobike_t
*this, bool address
)
441 this->address
= address
;
442 this->ike_sa
->set_pending_updates(this->ike_sa
,
443 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
447 * Implementation of task_t.get_type
449 static task_type_t
get_type(private_ike_mobike_t
*this)
455 * Implementation of task_t.migrate
457 static void migrate(private_ike_mobike_t
*this, ike_sa_t
*ike_sa
)
459 chunk_free(&this->cookie2
);
460 this->ike_sa
= ike_sa
;
463 this->natd
->task
.migrate(&this->natd
->task
, ike_sa
);
468 * Implementation of task_t.destroy
470 static void destroy(private_ike_mobike_t
*this)
472 chunk_free(&this->cookie2
);
475 this->natd
->task
.destroy(&this->natd
->task
);
481 * Described in header.
483 ike_mobike_t
*ike_mobike_create(ike_sa_t
*ike_sa
, bool initiator
)
485 private_ike_mobike_t
*this = malloc_thing(private_ike_mobike_t
);
487 this->public.roam
= (void(*)(ike_mobike_t
*,bool))roam
;
488 this->public.transmit
= (void(*)(ike_mobike_t
*,packet_t
*))transmit
;
489 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
490 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
491 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
495 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
496 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
500 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
501 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
504 this->ike_sa
= ike_sa
;
505 this->initiator
= initiator
;
506 this->update
= FALSE
;
508 this->address
= TRUE
;
509 this->cookie2
= chunk_empty
;
512 return &this->public;