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
= this->ike_sa
->get_other_host(this->ike_sa
);
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
= this->ike_sa
->get_other_host(this->ike_sa
);
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 void 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
);
238 rng
->allocate_bytes(rng
, COOKIE2_SIZE
, &this->cookie2
);
240 message
->add_notify(message
, FALSE
, COOKIE2
, this->cookie2
);
245 * update addresses of associated CHILD_SAs
247 static void update_children(private_ike_mobike_t
*this)
249 enumerator_t
*enumerator
;
250 child_sa_t
*child_sa
;
252 enumerator
= this->ike_sa
->create_child_sa_enumerator(this->ike_sa
);
253 while (enumerator
->enumerate(enumerator
, (void**)&child_sa
))
255 if (child_sa
->update(child_sa
,
256 this->ike_sa
->get_my_host(this->ike_sa
),
257 this->ike_sa
->get_other_host(this->ike_sa
),
258 this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
),
259 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
)) == NOT_SUPPORTED
)
261 this->ike_sa
->rekey_child_sa(this->ike_sa
,
262 child_sa
->get_protocol(child_sa
),
263 child_sa
->get_spi(child_sa
, TRUE
));
266 enumerator
->destroy(enumerator
);
270 * Apply the port of the old host, if its ip equals the new, use port otherwise.
272 static void apply_port(host_t
*host
, host_t
*old
, u_int16_t port
)
274 if (host
->ip_equals(host
, old
))
276 port
= old
->get_port(old
);
278 else if (port
== IKEV2_UDP_PORT
)
280 port
= IKEV2_NATT_PORT
;
282 host
->set_port(host
, port
);
285 METHOD(ike_mobike_t
, transmit
, void,
286 private_ike_mobike_t
*this, packet_t
*packet
)
288 host_t
*me
, *other
, *me_old
, *other_old
;
289 enumerator_t
*enumerator
;
298 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
299 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
300 ike_cfg
= this->ike_sa
->get_ike_cfg(this->ike_sa
);
302 enumerator
= this->ike_sa
->create_peer_address_enumerator(this->ike_sa
);
303 while (enumerator
->enumerate(enumerator
, (void**)&other
))
305 me
= hydra
->kernel_interface
->get_source_addr(
306 hydra
->kernel_interface
, other
, NULL
);
309 if (me
->get_family(me
) != other
->get_family(other
))
314 /* reuse port for an active address, 4500 otherwise */
315 apply_port(me
, me_old
, ike_cfg
->get_my_port(ike_cfg
));
316 other
= other
->clone(other
);
317 apply_port(other
, other_old
, ike_cfg
->get_other_port(ike_cfg
));
318 DBG1(DBG_IKE
, "checking path %#H - %#H", me
, other
);
319 copy
= packet
->clone(packet
);
320 copy
->set_source(copy
, me
);
321 copy
->set_destination(copy
, other
);
322 charon
->sender
->send(charon
->sender
, copy
);
325 enumerator
->destroy(enumerator
);
328 METHOD(task_t
, build_i
, status_t
,
329 private_ike_mobike_t
*this, message_t
*message
)
331 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
332 message
->get_message_id(message
) == 1)
333 { /* only in first IKE_AUTH */
334 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
335 build_address_list(this, message
);
337 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
341 /* we check if the existing address is still valid */
342 old
= message
->get_source(message
);
343 new = hydra
->kernel_interface
->get_source_addr(hydra
->kernel_interface
,
344 message
->get_destination(message
), old
);
347 if (!new->ip_equals(new, old
))
349 new->set_port(new, old
->get_port(old
));
350 message
->set_source(message
, new);
359 message
->add_notify(message
, FALSE
, UPDATE_SA_ADDRESSES
,
361 build_cookie(this, message
);
362 update_children(this);
364 if (this->address
&& !this->check
)
366 build_address_list(this, message
);
370 this->natd
->task
.build(&this->natd
->task
, message
);
376 METHOD(task_t
, process_r
, status_t
,
377 private_ike_mobike_t
*this, message_t
*message
)
379 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
380 message
->get_message_id(message
) == 1)
381 { /* only first IKE_AUTH */
382 process_payloads(this, message
);
384 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
386 process_payloads(this, message
);
391 me
= message
->get_destination(message
);
392 other
= message
->get_source(message
);
393 this->ike_sa
->set_my_host(this->ike_sa
, me
->clone(me
));
394 this->ike_sa
->set_other_host(this->ike_sa
, other
->clone(other
));
399 this->natd
->task
.process(&this->natd
->task
, message
);
401 if (this->addresses_updated
&& this->ike_sa
->has_condition(this->ike_sa
,
402 COND_ORIGINAL_INITIATOR
))
404 host_t
*other
= message
->get_source(message
);
405 host_t
*other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
406 if (!other
->equals(other
, other_old
))
408 DBG1(DBG_IKE
, "remote address changed from %H to %H", other_old
,
410 this->ike_sa
->set_other_host(this->ike_sa
, other
->clone(other
));
418 METHOD(task_t
, build_r
, status_t
,
419 private_ike_mobike_t
*this, message_t
*message
)
421 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
422 this->ike_sa
->get_state(this->ike_sa
) == IKE_ESTABLISHED
)
424 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_MOBIKE
))
426 message
->add_notify(message
, FALSE
, MOBIKE_SUPPORTED
, chunk_empty
);
427 build_address_list(this, message
);
431 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
435 this->natd
->task
.build(&this->natd
->task
, message
);
437 if (this->cookie2
.ptr
)
439 message
->add_notify(message
, FALSE
, COOKIE2
, this->cookie2
);
440 chunk_free(&this->cookie2
);
444 update_children(this);
451 METHOD(task_t
, process_i
, status_t
,
452 private_ike_mobike_t
*this, message_t
*message
)
454 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
455 this->ike_sa
->get_state(this->ike_sa
) == IKE_ESTABLISHED
)
457 process_payloads(this, message
);
460 else if (message
->get_exchange_type(message
) == INFORMATIONAL
)
462 u_int32_t updates
= this->ike_sa
->get_pending_updates(this->ike_sa
) - 1;
463 this->ike_sa
->set_pending_updates(this->ike_sa
, updates
);
466 /* newer update queued, ignore this one */
469 if (this->cookie2
.ptr
)
470 { /* check cookie if we included one */
473 cookie2
= this->cookie2
;
474 this->cookie2
= chunk_empty
;
475 process_payloads(this, message
);
476 if (!chunk_equals(cookie2
, this->cookie2
))
478 chunk_free(&cookie2
);
479 DBG1(DBG_IKE
, "COOKIE2 mismatch, closing IKE_SA");
482 chunk_free(&cookie2
);
486 process_payloads(this, message
);
490 this->natd
->task
.process(&this->natd
->task
, message
);
491 if (this->natd
->has_mapping_changed(this->natd
))
493 /* force an update if mappings have changed */
494 this->update
= this->check
= TRUE
;
495 DBG1(DBG_IKE
, "detected changes in NAT mappings, "
496 "initiating MOBIKE update");
501 /* update again, as NAT state may have changed */
502 update_children(this);
506 host_t
*me_new
, *me_old
, *other_new
, *other_old
;
508 me_new
= message
->get_destination(message
);
509 other_new
= message
->get_source(message
);
510 me_old
= this->ike_sa
->get_my_host(this->ike_sa
);
511 other_old
= this->ike_sa
->get_other_host(this->ike_sa
);
513 if (!me_new
->equals(me_new
, me_old
))
516 this->ike_sa
->set_my_host(this->ike_sa
, me_new
->clone(me_new
));
518 if (!other_new
->equals(other_new
, other_old
))
521 this->ike_sa
->set_other_host(this->ike_sa
, other_new
->clone(other_new
));
525 /* use the same task to ... */
526 if (!this->ike_sa
->has_condition(this->ike_sa
,
527 COND_ORIGINAL_INITIATOR
))
528 { /*... send an updated list of addresses as responder */
529 update_children(this);
530 this->update
= FALSE
;
533 { /* ... send the update as original initiator */
536 this->natd
->task
.destroy(&this->natd
->task
);
538 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
541 this->ike_sa
->set_pending_updates(this->ike_sa
, 1);
550 METHOD(ike_mobike_t
, addresses
, void,
551 private_ike_mobike_t
*this)
553 this->address
= TRUE
;
554 this->ike_sa
->set_pending_updates(this->ike_sa
,
555 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
558 METHOD(ike_mobike_t
, roam
, void,
559 private_ike_mobike_t
*this, bool address
)
562 this->address
= address
;
563 this->ike_sa
->set_pending_updates(this->ike_sa
,
564 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
567 METHOD(ike_mobike_t
, dpd
, void,
568 private_ike_mobike_t
*this)
572 this->natd
= ike_natd_create(this->ike_sa
, this->initiator
);
574 this->ike_sa
->set_pending_updates(this->ike_sa
,
575 this->ike_sa
->get_pending_updates(this->ike_sa
) + 1);
578 METHOD(ike_mobike_t
, is_probing
, bool,
579 private_ike_mobike_t
*this)
584 METHOD(task_t
, get_type
, task_type_t
,
585 private_ike_mobike_t
*this)
587 return TASK_IKE_MOBIKE
;
590 METHOD(task_t
, migrate
, void,
591 private_ike_mobike_t
*this, ike_sa_t
*ike_sa
)
593 chunk_free(&this->cookie2
);
594 this->ike_sa
= ike_sa
;
597 this->natd
->task
.migrate(&this->natd
->task
, ike_sa
);
601 METHOD(task_t
, destroy
, void,
602 private_ike_mobike_t
*this)
604 chunk_free(&this->cookie2
);
607 this->natd
->task
.destroy(&this->natd
->task
);
613 * Described in header.
615 ike_mobike_t
*ike_mobike_create(ike_sa_t
*ike_sa
, bool initiator
)
617 private_ike_mobike_t
*this;
622 .get_type
= _get_type
,
626 .addresses
= _addresses
,
629 .transmit
= _transmit
,
630 .is_probing
= _is_probing
,
633 .initiator
= initiator
,
638 this->public.task
.build
= _build_i
;
639 this->public.task
.process
= _process_i
;
643 this->public.task
.build
= _build_r
;
644 this->public.task
.process
= _process_r
;
647 return &this->public;