2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
16 #include "ike_mobike.h"
22 #include <sa/ikev2/tasks/ike_natd.h>
23 #include <encoding/payloads/notify_payload.h>
25 #define COOKIE2_SIZE 16
26 #define MAX_ADDITIONAL_ADDRS 8
28 typedef struct private_ike_mobike_t private_ike_mobike_t
;
31 * Private members of a ike_mobike_t task.
33 struct private_ike_mobike_t
{
36 * Public methods and task_t interface.
46 * Are we the initiator?
51 * cookie2 value to verify new addresses
56 * NAT discovery reusing the TASK_IKE_NATD task
61 * use task to update addresses
66 * do routability check
71 * include address list update
76 * additional addresses got updated
78 bool addresses_updated
;
82 * read notifys from message and evaluate them
84 static void process_payloads(private_ike_mobike_t
*this, message_t
*message
)
86 enumerator_t
*enumerator
;
90 enumerator
= message
->create_payload_enumerator(message
);
91 while (enumerator
->enumerate(enumerator
, &payload
))
94 notify_payload_t
*notify
;
98 if (payload
->get_type(payload
) != NOTIFY
)
102 notify
= (notify_payload_t
*)payload
;
103 switch (notify
->get_notify_type(notify
))
105 case MOBIKE_SUPPORTED
:
107 peer_cfg_t
*peer_cfg
;
109 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
110 if (!this->initiator
&&
111 peer_cfg
&& !peer_cfg
->use_mobike(peer_cfg
))
113 DBG1(DBG_IKE
, "peer supports MOBIKE, but disabled in config");
117 DBG1(DBG_IKE
, "peer supports MOBIKE");
118 this->ike_sa
->enable_extension(this->ike_sa
, EXT_MOBIKE
);
124 chunk_free(&this->cookie2
);
125 this->cookie2
= chunk_clone(notify
->get_notification_data(notify
));
128 case ADDITIONAL_IP6_ADDRESS
:
133 case ADDITIONAL_IP4_ADDRESS
:
136 { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
137 this->ike_sa
->remove_additional_addresses(this->ike_sa
);
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
);
144 this->addresses_updated
= TRUE
;
147 case UPDATE_SA_ADDRESSES
:
152 case NO_ADDITIONAL_ADDRESSES
:
154 this->ike_sa
->remove_additional_addresses(this->ike_sa
);
155 this->addresses_updated
= TRUE
;
158 case NAT_DETECTION_SOURCE_IP
:
159 case NAT_DETECTION_DESTINATION_IP
:
161 /* NAT check in this MOBIKE exchange, create subtask for it */
162 if (this->natd
== NULL
)
164 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
172 enumerator
->destroy(enumerator
);
176 * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
178 static void build_address_list(private_ike_mobike_t
*this, message_t
*message
)
180 enumerator_t
*enumerator
;
185 me
= this->ike_sa
->get_my_host(this->ike_sa
);
186 enumerator
= hydra
->kernel_interface
->create_address_enumerator(
187 hydra
->kernel_interface
, FALSE
, FALSE
);
188 while (enumerator
->enumerate(enumerator
, (void**)&host
))
190 if (me
->ip_equals(me
, host
))
191 { /* "ADDITIONAL" means do not include IKE_SAs host */
194 switch (host
->get_family(host
))
197 type
= ADDITIONAL_IP4_ADDRESS
;
200 type
= ADDITIONAL_IP6_ADDRESS
;
205 message
->add_notify(message
, FALSE
, type
, host
->get_address(host
));
206 if (++added
>= MAX_ADDITIONAL_ADDRS
)
207 { /* limit number of notifys, some implementations do not like too
208 * many of them (f.e. strongSwan ;-) */
214 message
->add_notify(message
, FALSE
, NO_ADDITIONAL_ADDRESSES
, chunk_empty
);
216 enumerator
->destroy(enumerator
);
220 * build a cookie and add it to the message
222 static void build_cookie(private_ike_mobike_t
*this, message_t
*message
)
226 chunk_free(&this->cookie2
);
227 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_STRONG
);
230 rng
->allocate_bytes(rng
, COOKIE2_SIZE
, &this->cookie2
);
232 message
->add_notify(message
, FALSE
, COOKIE2
, this->cookie2
);
237 * update addresses of associated CHILD_SAs
239 static void update_children(private_ike_mobike_t
*this)
241 enumerator_t
*enumerator
;
242 child_sa_t
*child_sa
;
244 enumerator
= this->ike_sa
->create_child_sa_enumerator(this->ike_sa
);
245 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
247 if (child_sa
->update(child_sa
,
248 this->ike_sa
->get_my_host(this->ike_sa
),
249 this->ike_sa
->get_other_host(this->ike_sa
),
250 this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
),
251 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
)) == NOT_SUPPORTED
)
253 this->ike_sa
->rekey_child_sa(this->ike_sa
,
254 child_sa
->get_protocol(child_sa
),
255 child_sa
->get_spi(child_sa
, TRUE
));
258 enumerator
->destroy(enumerator
);
262 * Apply the port of the old host, if its ip equals the new, use port otherwise.
264 static void apply_port(host_t
*host
, host_t
*old
, u_int16_t port
)
266 if (host
->ip_equals(host
, old
))
268 port
= old
->get_port(old
);
270 else if (port
== IKEV2_UDP_PORT
)
272 port
= IKEV2_NATT_PORT
;
274 host
->set_port(host
, port
);
277 METHOD(ike_mobike_t
, transmit
, void,
278 private_ike_mobike_t
*this, packet_t
*packet
)
280 host_t
*me
, *other
, *me_old
, *other_old
;
281 enumerator_t
*enumerator
;
290 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
291 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
292 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
294 me
= hydra
->kernel_interface
->get_source_addr(
295 hydra
->kernel_interface
, other_old
, NULL
);
298 apply_port(me
, me_old
, ike_cfg
->get_my_port(ike_cfg
));
299 DBG1(DBG_IKE
, "checking original path %#H - %#H", me
, other_old
);
300 copy
= packet
->clone(packet
);
301 copy
->set_source(copy
, me
);
302 charon
->sender
->send(charon
->sender
, copy
);
305 enumerator
= this->ike_sa
->create_additional_address_enumerator(this->ike_sa
);
306 while (enumerator
->enumerate(enumerator
, (void**)&other
))
308 me
= hydra
->kernel_interface
->get_source_addr(
309 hydra
->kernel_interface
, other
, NULL
);
312 if (me
->get_family(me
) != other
->get_family(other
))
317 /* reuse port for an active address, 4500 otherwise */
318 apply_port(me
, me_old
, ike_cfg
->get_my_port(ike_cfg
));
319 other
= other
->clone(other
);
320 apply_port(other
, other_old
, ike_cfg
->get_other_port(ike_cfg
));
321 DBG1(DBG_IKE
, "checking path %#H - %#H", me
, other
);
322 copy
= packet
->clone(packet
);
323 copy
->set_source(copy
, me
);
324 copy
->set_destination(copy
, other
);
325 charon
->sender
->send(charon
->sender
, copy
);
328 enumerator
->destroy(enumerator
);
331 METHOD(task_t
, build_i
, status_t
,
332 private_ike_mobike_t
*this, message_t
*message
)
334 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
335 message
->get_message_id(message
) == 1)
336 { /* only in first IKE_AUTH */
337 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
338 build_address_list(this, message
);
340 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
344 /* we check if the existing address is still valid */
345 old
= message
->get_source(message
);
346 new = hydra
->kernel_interface
->get_source_addr(hydra
->kernel_interface
,
347 message
->get_destination(message
), old
);
350 if (!new->ip_equals(new, old
))
352 new->set_port(new, old
->get_port(old
));
353 message
->set_source(message
, new);
362 message
->add_notify(message
, FALSE
, UPDATE_SA_ADDRESSES
,
364 build_cookie(this, message
);
365 update_children(this);
367 if (this->address
&& !this->check
)
369 build_address_list(this, message
);
373 this->natd
->task
.build(&this->natd
->task
, message
);
379 METHOD(task_t
, process_r
, status_t
,
380 private_ike_mobike_t
*this, message_t
*message
)
382 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
383 message
->get_message_id(message
) == 1)
384 { /* only first IKE_AUTH */
385 process_payloads(this, message
);
387 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
389 process_payloads(this, message
);
394 me
= message
->get_destination(message
);
395 other
= message
->get_source(message
);
396 this->ike_sa
->set_my_host(this->ike_sa
, me
->clone(me
));
397 this->ike_sa
->set_other_host(this->ike_sa
, other
->clone(other
));
402 this->natd
->task
.process(&this->natd
->task
, message
);
404 if (this->addresses_updated
&& this->ike_sa
->has_condition(this->ike_sa
,
405 COND_ORIGINAL_INITIATOR
))
407 host_t
*other
= message
->get_source(message
);
408 host_t
*other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
409 if (!other
->equals(other
, other_old
))
411 DBG1(DBG_IKE
, "remote address changed from %H to %H", other_old
,
413 this->ike_sa
->set_other_host(this->ike_sa
, other
->clone(other
));
421 METHOD(task_t
, build_r
, status_t
,
422 private_ike_mobike_t
*this, message_t
*message
)
424 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
425 this->ike_sa
->get_state(this->ike_sa
) == IKE_ESTABLISHED
)
427 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_MOBIKE
))
429 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
430 build_address_list(this, message
);
434 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
438 this->natd
->task
.build(&this->natd
->task
, message
);
440 if (this->cookie2
.ptr
)
442 message
->add_notify(message
, FALSE
, COOKIE2
, this->cookie2
);
443 chunk_free(&this->cookie2
);
447 update_children(this);
454 METHOD(task_t
, process_i
, status_t
,
455 private_ike_mobike_t
*this, message_t
*message
)
457 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
458 this->ike_sa
->get_state(this->ike_sa
) == IKE_ESTABLISHED
)
460 process_payloads(this, message
);
463 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
465 u_int32_t updates
= this->ike_sa
->get_pending_updates(this->ike_sa
) - 1;
466 this->ike_sa
->set_pending_updates(this->ike_sa
, updates
);
469 /* newer update queued, ignore this one */
472 if (this->cookie2
.ptr
)
473 { /* check cookie if we included one */
476 cookie2
= this->cookie2
;
477 this->cookie2
= chunk_empty
;
478 process_payloads(this, message
);
479 if (!chunk_equals(cookie2
, this->cookie2
))
481 chunk_free(&cookie2
);
482 DBG1(DBG_IKE
, "COOKIE2 mismatch, closing IKE_SA");
485 chunk_free(&cookie2
);
489 process_payloads(this, message
);
493 this->natd
->task
.process(&this->natd
->task
, message
);
494 if (this->natd
->has_mapping_changed(this->natd
))
496 /* force an update if mappings have changed */
497 this->update
= this->check
= TRUE
;
498 DBG1(DBG_IKE
, "detected changes in NAT mappings, "
499 "initiating MOBIKE update");
504 /* update again, as NAT state may have changed */
505 update_children(this);
509 host_t
*me_new
, *me_old
, *other_new
, *other_old
;
511 me_new
= message
->get_destination(message
);
512 other_new
= message
->get_source(message
);
513 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
514 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
516 if (!me_new
->equals(me_new
, me_old
))
519 this->ike_sa
->set_my_host(this->ike_sa
, me_new
->clone(me_new
));
521 if (!other_new
->equals(other_new
, other_old
))
524 this->ike_sa
->set_other_host(this->ike_sa
, other_new
->clone(other_new
));
528 /* use the same task to ... */
529 if (!this->ike_sa
->has_condition(this->ike_sa
,
530 COND_ORIGINAL_INITIATOR
))
531 { /*... send an updated list of addresses as responder */
532 update_children(this);
533 this->update
= FALSE
;
536 { /* ... send the update as original initiator */
539 this->natd
->task
.destroy(&this->natd
->task
);
541 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
544 this->ike_sa
->set_pending_updates(this->ike_sa
, 1);
553 METHOD(ike_mobike_t
, addresses
, void,
554 private_ike_mobike_t
*this)
556 this->address
= TRUE
;
557 this->ike_sa
->set_pending_updates(this->ike_sa
,
558 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
561 METHOD(ike_mobike_t
, roam
, void,
562 private_ike_mobike_t
*this, bool address
)
565 this->address
= address
;
566 this->ike_sa
->set_pending_updates(this->ike_sa
,
567 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
570 METHOD(ike_mobike_t
, dpd
, void,
571 private_ike_mobike_t
*this)
575 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
577 this->ike_sa
->set_pending_updates(this->ike_sa
,
578 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
581 METHOD(ike_mobike_t
, is_probing
, bool,
582 private_ike_mobike_t
*this)
587 METHOD(task_t
, get_type
, task_type_t
,
588 private_ike_mobike_t
*this)
590 return TASK_IKE_MOBIKE
;
593 METHOD(task_t
, migrate
, void,
594 private_ike_mobike_t
*this, ike_sa_t
*ike_sa
)
596 chunk_free(&this->cookie2
);
597 this->ike_sa
= ike_sa
;
600 this->natd
->task
.migrate(&this->natd
->task
, ike_sa
);
604 METHOD(task_t
, destroy
, void,
605 private_ike_mobike_t
*this)
607 chunk_free(&this->cookie2
);
610 this->natd
->task
.destroy(&this->natd
->task
);
616 * Described in header.
618 ike_mobike_t
*ike_mobike_create(ike_sa_t
*ike_sa
, bool initiator
)
620 private_ike_mobike_t
*this;
625 .get_type
= _get_type
,
629 .addresses
= _addresses
,
632 .transmit
= _transmit
,
633 .is_probing
= _is_probing
,
636 .initiator
= initiator
,
641 this->public.task
.build
= _build_i
;
642 this->public.task
.process
= _process_i
;
646 this->public.task
.build
= _build_r
;
647 this->public.task
.process
= _process_r
;
650 return &this->public;