kernel-netlink: Use correct config option name for HW offloading check
[strongswan.git] / src / libcharon / sa / ikev2 / tasks / ike_mobike.c
1 /*
2 * Copyright (C) 2010-2018 Tobias Brunner
3 * Copyright (C) 2007 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 */
16
17 #include "ike_mobike.h"
18
19 #include <string.h>
20
21 #include <daemon.h>
22 #include <sa/ikev2/tasks/ike_natd.h>
23 #include <encoding/payloads/notify_payload.h>
24
25 #define COOKIE2_SIZE 16
26 #define MAX_ADDITIONAL_ADDRS 8
27
28 typedef struct private_ike_mobike_t private_ike_mobike_t;
29
30 /**
31 * Private members of a ike_mobike_t task.
32 */
33 struct private_ike_mobike_t {
34
35 /**
36 * Public methods and task_t interface.
37 */
38 ike_mobike_t public;
39
40 /**
41 * Assigned IKE_SA.
42 */
43 ike_sa_t *ike_sa;
44
45 /**
46 * Are we the initiator?
47 */
48 bool initiator;
49
50 /**
51 * cookie2 value to verify new addresses
52 */
53 chunk_t cookie2;
54
55 /**
56 * NAT discovery reusing the TASK_IKE_NATD task
57 */
58 ike_natd_t *natd;
59
60 /**
61 * use task to update addresses
62 */
63 bool update;
64
65 /**
66 * do routability check
67 */
68 bool check;
69
70 /**
71 * include address list update
72 */
73 bool address;
74
75 /**
76 * additional addresses got updated
77 */
78 bool addresses_updated;
79 };
80
81 /**
82 * Check if a newer MOBIKE update task is queued
83 */
84 static bool is_newer_update_queued(private_ike_mobike_t *this)
85 {
86 enumerator_t *enumerator;
87 private_ike_mobike_t *mobike;
88 task_t *task;
89 bool found = FALSE;
90
91 enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
92 TASK_QUEUE_QUEUED);
93 while (enumerator->enumerate(enumerator, &task))
94 {
95 if (task->get_type(task) == TASK_IKE_MOBIKE)
96 {
97 mobike = (private_ike_mobike_t*)task;
98 /* a queued check or update might invalidate the results of the
99 * current task */
100 found = mobike->check || mobike->update;
101 break;
102 }
103 }
104 enumerator->destroy(enumerator);
105 return found;
106 }
107
108 /**
109 * read notifys from message and evaluate them
110 */
111 static void process_payloads(private_ike_mobike_t *this, message_t *message)
112 {
113 enumerator_t *enumerator;
114 payload_t *payload;
115 bool first = TRUE;
116
117 enumerator = message->create_payload_enumerator(message);
118 while (enumerator->enumerate(enumerator, &payload))
119 {
120 int family = AF_INET;
121 notify_payload_t *notify;
122 chunk_t data;
123 host_t *host;
124
125 if (payload->get_type(payload) != PLV2_NOTIFY)
126 {
127 continue;
128 }
129 notify = (notify_payload_t*)payload;
130 switch (notify->get_notify_type(notify))
131 {
132 case MOBIKE_SUPPORTED:
133 {
134 peer_cfg_t *peer_cfg;
135
136 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
137 if (!this->initiator &&
138 peer_cfg && !peer_cfg->use_mobike(peer_cfg))
139 {
140 DBG1(DBG_IKE, "peer supports MOBIKE, but disabled in config");
141 }
142 else
143 {
144 DBG1(DBG_IKE, "peer supports MOBIKE");
145 this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
146 }
147 break;
148 }
149 case COOKIE2:
150 {
151 chunk_free(&this->cookie2);
152 this->cookie2 = chunk_clone(notify->get_notification_data(notify));
153 break;
154 }
155 case ADDITIONAL_IP6_ADDRESS:
156 {
157 family = AF_INET6;
158 /* fall through */
159 }
160 case ADDITIONAL_IP4_ADDRESS:
161 {
162 if (first)
163 { /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
164 this->ike_sa->clear_peer_addresses(this->ike_sa);
165 first = FALSE;
166 /* add the peer's current address to the list */
167 host = message->get_source(message);
168 this->ike_sa->add_peer_address(this->ike_sa,
169 host->clone(host));
170 }
171 data = notify->get_notification_data(notify);
172 host = host_create_from_chunk(family, data, 0);
173 DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
174 this->ike_sa->add_peer_address(this->ike_sa, host);
175 this->addresses_updated = TRUE;
176 break;
177 }
178 case UPDATE_SA_ADDRESSES:
179 {
180 this->update = TRUE;
181 break;
182 }
183 case NO_ADDITIONAL_ADDRESSES:
184 {
185 this->ike_sa->clear_peer_addresses(this->ike_sa);
186 /* add the peer's current address to the list */
187 host = message->get_source(message);
188 this->ike_sa->add_peer_address(this->ike_sa, host->clone(host));
189 this->addresses_updated = TRUE;
190 break;
191 }
192 case NAT_DETECTION_SOURCE_IP:
193 case NAT_DETECTION_DESTINATION_IP:
194 {
195 /* NAT check in this MOBIKE exchange, create subtask for it */
196 if (!this->natd)
197 {
198 this->natd = ike_natd_create(this->ike_sa, this->initiator);
199 }
200 break;
201 }
202 default:
203 break;
204 }
205 }
206 enumerator->destroy(enumerator);
207 }
208
209 /**
210 * Add ADDITIONAL_*_ADDRESS notifys depending on our address list
211 */
212 static void build_address_list(private_ike_mobike_t *this, message_t *message)
213 {
214 enumerator_t *enumerator;
215 host_t *host, *me;
216 notify_type_t type;
217 int added = 0;
218
219 me = this->ike_sa->get_my_host(this->ike_sa);
220 enumerator = charon->kernel->create_address_enumerator(charon->kernel,
221 ADDR_TYPE_REGULAR);
222 while (enumerator->enumerate(enumerator, (void**)&host))
223 {
224 if (me->ip_equals(me, host))
225 { /* "ADDITIONAL" means do not include IKE_SAs host */
226 continue;
227 }
228 switch (host->get_family(host))
229 {
230 case AF_INET:
231 type = ADDITIONAL_IP4_ADDRESS;
232 break;
233 case AF_INET6:
234 type = ADDITIONAL_IP6_ADDRESS;
235 break;
236 default:
237 continue;
238 }
239 message->add_notify(message, FALSE, type, host->get_address(host));
240 if (++added >= MAX_ADDITIONAL_ADDRS)
241 { /* limit number of notifys, some implementations do not like too
242 * many of them (f.e. strongSwan ;-) */
243 break;
244 }
245 }
246 if (!added)
247 {
248 message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
249 }
250 enumerator->destroy(enumerator);
251 }
252
253 /**
254 * build a cookie and add it to the message
255 */
256 static bool build_cookie(private_ike_mobike_t *this, message_t *message)
257 {
258 rng_t *rng;
259
260 chunk_free(&this->cookie2);
261 rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
262 if (!rng || !rng->allocate_bytes(rng, COOKIE2_SIZE, &this->cookie2))
263 {
264 DESTROY_IF(rng);
265 return FALSE;
266 }
267 message->add_notify(message, FALSE, COOKIE2, this->cookie2);
268 rng->destroy(rng);
269 return TRUE;
270 }
271
272 /**
273 * update addresses of associated CHILD_SAs
274 */
275 static void update_children(private_ike_mobike_t *this)
276 {
277 enumerator_t *enumerator;
278 child_sa_t *child_sa;
279 linked_list_t *vips;
280 status_t status;
281 host_t *host;
282
283 vips = linked_list_create();
284
285 enumerator = this->ike_sa->create_virtual_ip_enumerator(this->ike_sa, TRUE);
286 while (enumerator->enumerate(enumerator, &host))
287 {
288 vips->insert_last(vips, host);
289 }
290 enumerator->destroy(enumerator);
291
292 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
293 while (enumerator->enumerate(enumerator, (void**)&child_sa))
294 {
295 status = child_sa->update(child_sa,
296 this->ike_sa->get_my_host(this->ike_sa),
297 this->ike_sa->get_other_host(this->ike_sa), vips,
298 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
299 switch (status)
300 {
301 case NOT_SUPPORTED:
302 this->ike_sa->rekey_child_sa(this->ike_sa,
303 child_sa->get_protocol(child_sa),
304 child_sa->get_spi(child_sa, TRUE));
305 break;
306 case SUCCESS:
307 charon->child_sa_manager->remove(charon->child_sa_manager,
308 child_sa);
309 charon->child_sa_manager->add(charon->child_sa_manager,
310 child_sa, this->ike_sa);
311 break;
312 default:
313 break;
314 }
315 }
316 enumerator->destroy(enumerator);
317
318 vips->destroy(vips);
319 }
320
321 /**
322 * Apply the port of the old host, if its ip equals the new, use port otherwise.
323 */
324 static void apply_port(host_t *host, host_t *old, uint16_t port, bool local)
325 {
326 if (host->ip_equals(host, old))
327 {
328 port = old->get_port(old);
329 }
330 else if (local && port == charon->socket->get_port(charon->socket, FALSE))
331 {
332 port = charon->socket->get_port(charon->socket, TRUE);
333 }
334 else if (!local && port == IKEV2_UDP_PORT)
335 {
336 port = IKEV2_NATT_PORT;
337 }
338 host->set_port(host, port);
339 }
340
341 METHOD(ike_mobike_t, transmit, bool,
342 private_ike_mobike_t *this, packet_t *packet)
343 {
344 host_t *me, *other, *me_old, *other_old;
345 enumerator_t *enumerator;
346 ike_cfg_t *ike_cfg;
347 packet_t *copy;
348 int family = AF_UNSPEC;
349 bool found = FALSE;
350
351 me_old = this->ike_sa->get_my_host(this->ike_sa);
352 other_old = this->ike_sa->get_other_host(this->ike_sa);
353 ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
354
355 if (!this->check)
356 {
357 me = charon->kernel->get_source_addr(charon->kernel, other_old, me_old);
358 if (me)
359 {
360 if (me->ip_equals(me, me_old))
361 {
362 copy = packet->clone(packet);
363 /* hosts might have been updated by a peer's MOBIKE exchange */
364 copy->set_source(copy, me_old->clone(me_old));
365 copy->set_destination(copy, other_old->clone(other_old));
366 charon->sender->send(charon->sender, copy);
367 me->destroy(me);
368 return TRUE;
369 }
370 me->destroy(me);
371 }
372 this->check = TRUE;
373 }
374
375 switch (charon->socket->supported_families(charon->socket))
376 {
377 case SOCKET_FAMILY_IPV4:
378 family = AF_INET;
379 break;
380 case SOCKET_FAMILY_IPV6:
381 family = AF_INET6;
382 break;
383 case SOCKET_FAMILY_BOTH:
384 case SOCKET_FAMILY_NONE:
385 break;
386 }
387
388 enumerator = this->ike_sa->create_peer_address_enumerator(this->ike_sa);
389 while (enumerator->enumerate(enumerator, (void**)&other))
390 {
391 if (family != AF_UNSPEC && other->get_family(other) != family)
392 {
393 continue;
394 }
395 me = charon->kernel->get_source_addr(charon->kernel, other, NULL);
396 if (me)
397 {
398 /* reuse port for an active address, 4500 otherwise */
399 apply_port(me, me_old, ike_cfg->get_my_port(ike_cfg), TRUE);
400 other = other->clone(other);
401 apply_port(other, other_old, ike_cfg->get_other_port(ike_cfg), FALSE);
402 DBG1(DBG_IKE, "checking path %#H - %#H", me, other);
403 copy = packet->clone(packet);
404 copy->set_source(copy, me);
405 copy->set_destination(copy, other);
406 charon->sender->send(charon->sender, copy);
407 found = TRUE;
408 }
409 }
410 enumerator->destroy(enumerator);
411 return found;
412 }
413
414 METHOD(task_t, build_i, status_t,
415 private_ike_mobike_t *this, message_t *message)
416 {
417 if (message->get_exchange_type(message) == IKE_AUTH &&
418 message->get_message_id(message) == 1)
419 { /* only in first IKE_AUTH */
420 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
421 build_address_list(this, message);
422 }
423 else if (message->get_exchange_type(message) == INFORMATIONAL)
424 {
425 host_t *old, *new;
426
427 /* we check if the existing address is still valid */
428 old = message->get_source(message);
429 new = charon->kernel->get_source_addr(charon->kernel,
430 message->get_destination(message), old);
431 if (new)
432 {
433 if (!new->ip_equals(new, old))
434 {
435 new->set_port(new, old->get_port(old));
436 message->set_source(message, new);
437 }
438 else
439 {
440 new->destroy(new);
441 }
442 }
443 if (this->update)
444 {
445 message->add_notify(message, FALSE, UPDATE_SA_ADDRESSES,
446 chunk_empty);
447 if (!build_cookie(this, message))
448 {
449 return FAILED;
450 }
451 update_children(this);
452 }
453 if (this->address && !this->check)
454 {
455 build_address_list(this, message);
456 }
457 if (this->natd)
458 {
459 this->natd->task.build(&this->natd->task, message);
460 }
461 }
462 return NEED_MORE;
463 }
464
465 METHOD(task_t, process_r, status_t,
466 private_ike_mobike_t *this, message_t *message)
467 {
468 if (message->get_exchange_type(message) == IKE_AUTH &&
469 message->get_message_id(message) == 1)
470 { /* only first IKE_AUTH */
471 process_payloads(this, message);
472 }
473 else if (message->get_exchange_type(message) == INFORMATIONAL)
474 {
475 process_payloads(this, message);
476 if (this->update)
477 {
478 host_t *me, *other;
479
480 me = message->get_destination(message);
481 other = message->get_source(message);
482 this->ike_sa->set_my_host(this->ike_sa, me->clone(me));
483 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
484 }
485
486 if (this->natd)
487 {
488 this->natd->task.process(&this->natd->task, message);
489 }
490 if (this->addresses_updated && this->ike_sa->has_condition(this->ike_sa,
491 COND_ORIGINAL_INITIATOR))
492 {
493 host_t *other = message->get_source(message);
494 host_t *other_old = this->ike_sa->get_other_host(this->ike_sa);
495 if (!other->equals(other, other_old))
496 {
497 DBG1(DBG_IKE, "remote address changed from %H to %H", other_old,
498 other);
499 this->ike_sa->set_other_host(this->ike_sa, other->clone(other));
500 this->update = TRUE;
501 }
502 }
503 }
504 return NEED_MORE;
505 }
506
507 METHOD(task_t, build_r, status_t,
508 private_ike_mobike_t *this, message_t *message)
509 {
510 if (message->get_exchange_type(message) == IKE_AUTH &&
511 this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
512 {
513 if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
514 {
515 message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
516 build_address_list(this, message);
517 }
518 return SUCCESS;
519 }
520 else if (message->get_exchange_type(message) == INFORMATIONAL)
521 {
522 if (this->natd)
523 {
524 this->natd->task.build(&this->natd->task, message);
525 }
526 if (this->cookie2.ptr)
527 {
528 message->add_notify(message, FALSE, COOKIE2, this->cookie2);
529 chunk_free(&this->cookie2);
530 }
531 if (this->update)
532 {
533 update_children(this);
534 }
535 return SUCCESS;
536 }
537 return NEED_MORE;
538 }
539
540 METHOD(task_t, process_i, status_t,
541 private_ike_mobike_t *this, message_t *message)
542 {
543 if (message->get_exchange_type(message) == IKE_AUTH &&
544 this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED)
545 {
546 process_payloads(this, message);
547 return SUCCESS;
548 }
549 else if (message->get_exchange_type(message) == INFORMATIONAL)
550 {
551 if (is_newer_update_queued(this))
552 {
553 return SUCCESS;
554 }
555 if (this->cookie2.ptr)
556 { /* check cookie if we included one */
557 chunk_t cookie2;
558
559 cookie2 = this->cookie2;
560 this->cookie2 = chunk_empty;
561 process_payloads(this, message);
562 if (!chunk_equals_const(cookie2, this->cookie2))
563 {
564 chunk_free(&cookie2);
565 DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
566 return FAILED;
567 }
568 chunk_free(&cookie2);
569 }
570 else
571 {
572 process_payloads(this, message);
573 }
574 if (this->natd)
575 {
576 this->natd->task.process(&this->natd->task, message);
577 if (!this->update && this->natd->has_mapping_changed(this->natd))
578 {
579 /* force an update if mappings have changed */
580 this->update = this->check = TRUE;
581 DBG1(DBG_IKE, "detected changes in NAT mappings, "
582 "initiating MOBIKE update");
583 }
584 }
585 if (this->update)
586 {
587 /* update again, as NAT state may have changed */
588 update_children(this);
589 }
590 if (this->check)
591 {
592 host_t *me_new, *me_old, *other_new, *other_old;
593
594 me_new = message->get_destination(message);
595 other_new = message->get_source(message);
596 me_old = this->ike_sa->get_my_host(this->ike_sa);
597 other_old = this->ike_sa->get_other_host(this->ike_sa);
598
599 if (!me_new->equals(me_new, me_old))
600 {
601 this->update = TRUE;
602 this->ike_sa->set_my_host(this->ike_sa, me_new->clone(me_new));
603 }
604 if (!other_new->equals(other_new, other_old))
605 {
606 this->update = TRUE;
607 this->ike_sa->set_other_host(this->ike_sa, other_new->clone(other_new));
608 }
609 if (this->update)
610 {
611 /* use the same task to ... */
612 if (!this->ike_sa->has_condition(this->ike_sa,
613 COND_ORIGINAL_INITIATOR))
614 { /*... send an updated list of addresses as responder */
615 update_children(this);
616 this->update = FALSE;
617 }
618 else
619 { /* ... send the update as original initiator */
620 if (this->natd)
621 {
622 this->natd->task.destroy(&this->natd->task);
623 }
624 this->natd = ike_natd_create(this->ike_sa, this->initiator);
625 }
626 this->check = FALSE;
627 return NEED_MORE;
628 }
629 }
630 return SUCCESS;
631 }
632 return NEED_MORE;
633 }
634
635 METHOD(ike_mobike_t, addresses, void,
636 private_ike_mobike_t *this)
637 {
638 this->address = TRUE;
639 }
640
641 METHOD(ike_mobike_t, roam, void,
642 private_ike_mobike_t *this, bool address)
643 {
644 this->check = TRUE;
645 this->address |= address;
646 }
647
648 METHOD(ike_mobike_t, dpd, void,
649 private_ike_mobike_t *this)
650 {
651 if (!this->natd && this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
652 {
653 this->natd = ike_natd_create(this->ike_sa, this->initiator);
654 }
655 }
656
657 METHOD(ike_mobike_t, is_probing, bool,
658 private_ike_mobike_t *this)
659 {
660 return this->check;
661 }
662
663 METHOD(ike_mobike_t, enable_probing, void,
664 private_ike_mobike_t *this)
665 {
666 this->check = TRUE;
667 }
668
669 METHOD(task_t, get_type, task_type_t,
670 private_ike_mobike_t *this)
671 {
672 return TASK_IKE_MOBIKE;
673 }
674
675 METHOD(task_t, migrate, void,
676 private_ike_mobike_t *this, ike_sa_t *ike_sa)
677 {
678 chunk_free(&this->cookie2);
679 this->ike_sa = ike_sa;
680 if (this->natd)
681 {
682 this->natd->task.migrate(&this->natd->task, ike_sa);
683 }
684 }
685
686 METHOD(task_t, destroy, void,
687 private_ike_mobike_t *this)
688 {
689 chunk_free(&this->cookie2);
690 if (this->natd)
691 {
692 this->natd->task.destroy(&this->natd->task);
693 }
694 free(this);
695 }
696
697 /*
698 * Described in header.
699 */
700 ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
701 {
702 private_ike_mobike_t *this;
703
704 INIT(this,
705 .public = {
706 .task = {
707 .get_type = _get_type,
708 .migrate = _migrate,
709 .destroy = _destroy,
710 },
711 .addresses = _addresses,
712 .roam = _roam,
713 .dpd = _dpd,
714 .transmit = _transmit,
715 .is_probing = _is_probing,
716 .enable_probing = _enable_probing,
717 },
718 .ike_sa = ike_sa,
719 .initiator = initiator,
720 );
721
722 if (initiator)
723 {
724 this->public.task.build = _build_i;
725 this->public.task.process = _process_i;
726 }
727 else
728 {
729 this->public.task.build = _build_r;
730 this->public.task.process = _process_r;
731 }
732
733 return &this->public;
734 }