2 * Copyright (C) 2010-2012 Tobias Brunner
3 * Copyright (C) 2007 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "ike_mobike.h"
23 #include <sa/ikev2/tasks/ike_natd.h>
24 #include <encoding/payloads/notify_payload.h>
26 #define COOKIE2_SIZE 16
27 #define MAX_ADDITIONAL_ADDRS 8
29 typedef struct private_ike_mobike_t private_ike_mobike_t
;
32 * Private members of a ike_mobike_t task.
34 struct private_ike_mobike_t
{
37 * Public methods and task_t interface.
47 * Are we the initiator?
52 * cookie2 value to verify new addresses
57 * NAT discovery reusing the TASK_IKE_NATD task
62 * use task to update addresses
67 * do routability check
72 * include address list update
77 * additional addresses got updated
79 bool addresses_updated
;
83 * read notifys from message and evaluate them
85 static void process_payloads(private_ike_mobike_t
*this, message_t
*message
)
87 enumerator_t
*enumerator
;
91 enumerator
= message
->create_payload_enumerator(message
);
92 while (enumerator
->enumerate(enumerator
, &payload
))
95 notify_payload_t
*notify
;
99 if (payload
->get_type(payload
) != NOTIFY
)
103 notify
= (notify_payload_t
*)payload
;
104 switch (notify
->get_notify_type(notify
))
106 case MOBIKE_SUPPORTED
:
108 peer_cfg_t
*peer_cfg
;
110 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
111 if (!this->initiator
&&
112 peer_cfg
&& !peer_cfg
->use_mobike(peer_cfg
))
114 DBG1(DBG_IKE
, "peer supports MOBIKE, but disabled in config");
118 DBG1(DBG_IKE
, "peer supports MOBIKE");
119 this->ike_sa
->enable_extension(this->ike_sa
, EXT_MOBIKE
);
125 chunk_free(&this->cookie2
);
126 this->cookie2
= chunk_clone(notify
->get_notification_data(notify
));
129 case ADDITIONAL_IP6_ADDRESS
:
134 case ADDITIONAL_IP4_ADDRESS
:
137 { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
138 this->ike_sa
->clear_peer_addresses(this->ike_sa
);
140 /* add the peer's current address to the list */
141 host
= message
->get_source(message
);
142 this->ike_sa
->add_peer_address(this->ike_sa
,
145 data
= notify
->get_notification_data(notify
);
146 host
= host_create_from_chunk(family
, data
, 0);
147 DBG2(DBG_IKE
, "got additional MOBIKE peer address: %H", host
);
148 this->ike_sa
->add_peer_address(this->ike_sa
, host
);
149 this->addresses_updated
= TRUE
;
152 case UPDATE_SA_ADDRESSES
:
157 case NO_ADDITIONAL_ADDRESSES
:
159 this->ike_sa
->clear_peer_addresses(this->ike_sa
);
160 /* add the peer's current address to the list */
161 host
= message
->get_source(message
);
162 this->ike_sa
->add_peer_address(this->ike_sa
, host
->clone(host
));
163 this->addresses_updated
= TRUE
;
166 case NAT_DETECTION_SOURCE_IP
:
167 case NAT_DETECTION_DESTINATION_IP
:
169 /* NAT check in this MOBIKE exchange, create subtask for it */
170 if (this->natd
== NULL
)
172 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
180 enumerator
->destroy(enumerator
);
184 * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
186 static void build_address_list(private_ike_mobike_t
*this, message_t
*message
)
188 enumerator_t
*enumerator
;
193 me
= this->ike_sa
->get_my_host(this->ike_sa
);
194 enumerator
= hydra
->kernel_interface
->create_address_enumerator(
195 hydra
->kernel_interface
, FALSE
, FALSE
);
196 while (enumerator
->enumerate(enumerator
, (void**)&host
))
198 if (me
->ip_equals(me
, host
))
199 { /* "ADDITIONAL" means do not include IKE_SAs host */
202 switch (host
->get_family(host
))
205 type
= ADDITIONAL_IP4_ADDRESS
;
208 type
= ADDITIONAL_IP6_ADDRESS
;
213 message
->add_notify(message
, FALSE
, type
, host
->get_address(host
));
214 if (++added
>= MAX_ADDITIONAL_ADDRS
)
215 { /* limit number of notifys, some implementations do not like too
216 * many of them (f.e. strongSwan ;-) */
222 message
->add_notify(message
, FALSE
, NO_ADDITIONAL_ADDRESSES
, chunk_empty
);
224 enumerator
->destroy(enumerator
);
228 * build a cookie and add it to the message
230 static bool build_cookie(private_ike_mobike_t
*this, message_t
*message
)
234 chunk_free(&this->cookie2
);
235 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_STRONG
);
236 if (!rng
|| !rng
->allocate_bytes(rng
, COOKIE2_SIZE
, &this->cookie2
))
241 message
->add_notify(message
, FALSE
, COOKIE2
, this->cookie2
);
247 * update addresses of associated CHILD_SAs
249 static void update_children(private_ike_mobike_t
*this)
251 enumerator_t
*enumerator
;
252 child_sa_t
*child_sa
;
254 enumerator
= this->ike_sa
->create_child_sa_enumerator(this->ike_sa
);
255 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
257 if (child_sa
->update(child_sa
,
258 this->ike_sa
->get_my_host(this->ike_sa
),
259 this->ike_sa
->get_other_host(this->ike_sa
),
260 this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
),
261 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
)) == NOT_SUPPORTED
)
263 this->ike_sa
->rekey_child_sa(this->ike_sa
,
264 child_sa
->get_protocol(child_sa
),
265 child_sa
->get_spi(child_sa
, TRUE
));
268 enumerator
->destroy(enumerator
);
272 * Apply the port of the old host, if its ip equals the new, use port otherwise.
274 static void apply_port(host_t
*host
, host_t
*old
, u_int16_t port
)
276 if (host
->ip_equals(host
, old
))
278 port
= old
->get_port(old
);
280 else if (port
== IKEV2_UDP_PORT
)
282 port
= IKEV2_NATT_PORT
;
284 host
->set_port(host
, port
);
287 METHOD(ike_mobike_t
, transmit
, void,
288 private_ike_mobike_t
*this, packet_t
*packet
)
290 host_t
*me
, *other
, *me_old
, *other_old
;
291 enumerator_t
*enumerator
;
300 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
301 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
302 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
304 enumerator
= this->ike_sa
->create_peer_address_enumerator(this->ike_sa
);
305 while (enumerator
->enumerate(enumerator
, (void**)&other
))
307 me
= hydra
->kernel_interface
->get_source_addr(
308 hydra
->kernel_interface
, other
, NULL
);
311 if (me
->get_family(me
) != other
->get_family(other
))
316 /* reuse port for an active address, 4500 otherwise */
317 apply_port(me
, me_old
, ike_cfg
->get_my_port(ike_cfg
));
318 other
= other
->clone(other
);
319 apply_port(other
, other_old
, ike_cfg
->get_other_port(ike_cfg
));
320 DBG1(DBG_IKE
, "checking path %#H - %#H", me
, other
);
321 copy
= packet
->clone(packet
);
322 copy
->set_source(copy
, me
);
323 copy
->set_destination(copy
, other
);
324 charon
->sender
->send(charon
->sender
, copy
);
327 enumerator
->destroy(enumerator
);
330 METHOD(task_t
, build_i
, status_t
,
331 private_ike_mobike_t
*this, message_t
*message
)
333 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
334 message
->get_message_id(message
) == 1)
335 { /* only in first IKE_AUTH */
336 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
337 build_address_list(this, message
);
339 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
343 /* we check if the existing address is still valid */
344 old
= message
->get_source(message
);
345 new = hydra
->kernel_interface
->get_source_addr(hydra
->kernel_interface
,
346 message
->get_destination(message
), old
);
349 if (!new->ip_equals(new, old
))
351 new->set_port(new, old
->get_port(old
));
352 message
->set_source(message
, new);
361 message
->add_notify(message
, FALSE
, UPDATE_SA_ADDRESSES
,
363 if (!build_cookie(this, message
))
367 update_children(this);
369 if (this->address
&& !this->check
)
371 build_address_list(this, message
);
375 this->natd
->task
.build(&this->natd
->task
, message
);
381 METHOD(task_t
, process_r
, status_t
,
382 private_ike_mobike_t
*this, message_t
*message
)
384 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
385 message
->get_message_id(message
) == 1)
386 { /* only first IKE_AUTH */
387 process_payloads(this, message
);
389 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
391 process_payloads(this, message
);
396 me
= message
->get_destination(message
);
397 other
= message
->get_source(message
);
398 this->ike_sa
->set_my_host(this->ike_sa
, me
->clone(me
));
399 this->ike_sa
->set_other_host(this->ike_sa
, other
->clone(other
));
404 this->natd
->task
.process(&this->natd
->task
, message
);
406 if (this->addresses_updated
&& this->ike_sa
->has_condition(this->ike_sa
,
407 COND_ORIGINAL_INITIATOR
))
409 host_t
*other
= message
->get_source(message
);
410 host_t
*other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
411 if (!other
->equals(other
, other_old
))
413 DBG1(DBG_IKE
, "remote address changed from %H to %H", other_old
,
415 this->ike_sa
->set_other_host(this->ike_sa
, other
->clone(other
));
423 METHOD(task_t
, build_r
, status_t
,
424 private_ike_mobike_t
*this, message_t
*message
)
426 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
427 this->ike_sa
->get_state(this->ike_sa
) == IKE_ESTABLISHED
)
429 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_MOBIKE
))
431 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
432 build_address_list(this, message
);
436 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
440 this->natd
->task
.build(&this->natd
->task
, message
);
442 if (this->cookie2
.ptr
)
444 message
->add_notify(message
, FALSE
, COOKIE2
, this->cookie2
);
445 chunk_free(&this->cookie2
);
449 update_children(this);
456 METHOD(task_t
, process_i
, status_t
,
457 private_ike_mobike_t
*this, message_t
*message
)
459 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
460 this->ike_sa
->get_state(this->ike_sa
) == IKE_ESTABLISHED
)
462 process_payloads(this, message
);
465 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
467 u_int32_t updates
= this->ike_sa
->get_pending_updates(this->ike_sa
) - 1;
468 this->ike_sa
->set_pending_updates(this->ike_sa
, updates
);
471 /* newer update queued, ignore this one */
474 if (this->cookie2
.ptr
)
475 { /* check cookie if we included one */
478 cookie2
= this->cookie2
;
479 this->cookie2
= chunk_empty
;
480 process_payloads(this, message
);
481 if (!chunk_equals(cookie2
, this->cookie2
))
483 chunk_free(&cookie2
);
484 DBG1(DBG_IKE
, "COOKIE2 mismatch, closing IKE_SA");
487 chunk_free(&cookie2
);
491 process_payloads(this, message
);
495 this->natd
->task
.process(&this->natd
->task
, message
);
496 if (this->natd
->has_mapping_changed(this->natd
))
498 /* force an update if mappings have changed */
499 this->update
= this->check
= TRUE
;
500 DBG1(DBG_IKE
, "detected changes in NAT mappings, "
501 "initiating MOBIKE update");
506 /* update again, as NAT state may have changed */
507 update_children(this);
511 host_t
*me_new
, *me_old
, *other_new
, *other_old
;
513 me_new
= message
->get_destination(message
);
514 other_new
= message
->get_source(message
);
515 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
516 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
518 if (!me_new
->equals(me_new
, me_old
))
521 this->ike_sa
->set_my_host(this->ike_sa
, me_new
->clone(me_new
));
523 if (!other_new
->equals(other_new
, other_old
))
526 this->ike_sa
->set_other_host(this->ike_sa
, other_new
->clone(other_new
));
530 /* use the same task to ... */
531 if (!this->ike_sa
->has_condition(this->ike_sa
,
532 COND_ORIGINAL_INITIATOR
))
533 { /*... send an updated list of addresses as responder */
534 update_children(this);
535 this->update
= FALSE
;
538 { /* ... send the update as original initiator */
541 this->natd
->task
.destroy(&this->natd
->task
);
543 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
546 this->ike_sa
->set_pending_updates(this->ike_sa
, 1);
555 METHOD(ike_mobike_t
, addresses
, void,
556 private_ike_mobike_t
*this)
558 this->address
= TRUE
;
559 this->ike_sa
->set_pending_updates(this->ike_sa
,
560 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
563 METHOD(ike_mobike_t
, roam
, void,
564 private_ike_mobike_t
*this, bool address
)
567 this->address
= address
;
568 this->ike_sa
->set_pending_updates(this->ike_sa
,
569 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
572 METHOD(ike_mobike_t
, dpd
, void,
573 private_ike_mobike_t
*this)
577 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
579 this->ike_sa
->set_pending_updates(this->ike_sa
,
580 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
583 METHOD(ike_mobike_t
, is_probing
, bool,
584 private_ike_mobike_t
*this)
589 METHOD(task_t
, get_type
, task_type_t
,
590 private_ike_mobike_t
*this)
592 return TASK_IKE_MOBIKE
;
595 METHOD(task_t
, migrate
, void,
596 private_ike_mobike_t
*this, ike_sa_t
*ike_sa
)
598 chunk_free(&this->cookie2
);
599 this->ike_sa
= ike_sa
;
602 this->natd
->task
.migrate(&this->natd
->task
, ike_sa
);
606 METHOD(task_t
, destroy
, void,
607 private_ike_mobike_t
*this)
609 chunk_free(&this->cookie2
);
612 this->natd
->task
.destroy(&this->natd
->task
);
618 * Described in header.
620 ike_mobike_t
*ike_mobike_create(ike_sa_t
*ike_sa
, bool initiator
)
622 private_ike_mobike_t
*this;
627 .get_type
= _get_type
,
631 .addresses
= _addresses
,
634 .transmit
= _transmit
,
635 .is_probing
= _is_probing
,
638 .initiator
= initiator
,
643 this->public.task
.build
= _build_i
;
644 this->public.task
.process
= _process_i
;
648 this->public.task
.build
= _build_r
;
649 this->public.task
.process
= _process_r
;
652 return &this->public;