2 * Copyright (C) 2016-2024 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
5 * Copyright (C) secunet Security Networks AG
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "ha_dispatcher.h"
21 #include <sa/ikev2/keymat_v2.h>
22 #include <sa/ikev1/keymat_v1.h>
23 #include <processing/jobs/callback_job.h>
24 #include <processing/jobs/adopt_children_job.h>
26 typedef struct private_ha_dispatcher_t private_ha_dispatcher_t
;
27 typedef struct ha_key_exchange_t ha_key_exchange_t
;
30 * Private data of an ha_dispatcher_t object.
32 struct private_ha_dispatcher_t
{
35 * Public ha_dispatcher_t interface.
37 ha_dispatcher_t
public;
40 * socket to pull messages from
47 ha_segments_t
*segments
;
66 * KE implementation for HA synced KE shared secrets
68 struct ha_key_exchange_t
{
81 * Own public value (IKEv1 only)
86 METHOD(key_exchange_t
, ke_get_shared_secret
, bool,
87 ha_key_exchange_t
*this, chunk_t
*secret
)
89 *secret
= chunk_clone(this->secret
);
93 METHOD(key_exchange_t
, ke_get_public_key
, bool,
94 ha_key_exchange_t
*this, chunk_t
*value
)
96 *value
= chunk_clone(this->pub
);
100 METHOD(key_exchange_t
, ke_destroy
, void,
101 ha_key_exchange_t
*this)
107 * Create a HA synced KE implementation
109 static key_exchange_t
*ha_key_exchange_create(chunk_t secret
, chunk_t pub
)
111 ha_key_exchange_t
*this;
115 .get_shared_secret
= _ke_get_shared_secret
,
116 .get_public_key
= _ke_get_public_key
,
117 .destroy
= _ke_destroy
,
127 * Add the given KE methods to a proposal
129 static void add_ke_methods_to_proposal(proposal_t
*proposal
, uint16_t ke_alg
,
136 proposal
->add_algorithm(proposal
, KEY_EXCHANGE_METHOD
, ke_alg
, 0);
138 count
= min(add_kes
.len
/ sizeof(uint16_t), MAX_ADDITIONAL_KEY_EXCHANGES
);
139 for (i
= 0; i
< count
; i
++)
141 ke_alg
= ntohs(((uint16_t*)add_kes
.ptr
)[i
]);
144 proposal
->add_algorithm(proposal
, i
+ ADDITIONAL_KEY_EXCHANGE_1
,
151 * Process messages of type IKE_ADD
153 static void process_ike_add(private_ha_dispatcher_t
*this, ha_message_t
*message
)
155 ha_message_attribute_t attribute
;
156 ha_message_value_t value
;
157 enumerator_t
*enumerator
;
158 ike_sa_t
*ike_sa
= NULL
, *old_sa
= NULL
;
159 ike_version_t version
= IKEV2
;
160 uint16_t encr
= 0, len
= 0, integ
= 0, prf
= 0, old_prf
= PRF_UNDEFINED
;
162 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
;
163 chunk_t secret
= chunk_empty
, old_skd
= chunk_empty
;
164 chunk_t add_secret
= chunk_empty
, add_kes
= chunk_empty
;
165 chunk_t dh_local
= chunk_empty
, dh_remote
= chunk_empty
, psk
= chunk_empty
;
166 host_t
*other
= NULL
;
168 auth_method_t method
= AUTH_RSA
;
170 enumerator
= message
->create_attribute_enumerator(message
);
171 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
176 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
180 ike_sa
= ike_sa_create(value
.ike_sa_id
,
181 value
.ike_sa_id
->is_initiator(value
.ike_sa_id
), version
);
184 case HA_IKE_REKEY_ID
:
185 old_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
189 other
= value
.host
->clone(value
.host
);
195 nonce_i
= value
.chunk
;
198 nonce_r
= value
.chunk
;
201 secret
= value
.chunk
;
204 add_secret
= value
.chunk
;
207 dh_local
= value
.chunk
;
210 dh_remote
= value
.chunk
;
216 old_skd
= value
.chunk
;
221 case HA_ALG_ENCR_LEN
:
237 add_kes
= value
.chunk
;
246 enumerator
->destroy(enumerator
);
250 proposal_t
*proposal
;
253 bool key_update
= FALSE
;
255 proposal
= ike_sa
->get_proposal(ike_sa
);
258 proposal
= proposal_create(PROTO_IKE
, 0);
261 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
265 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
269 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, prf
, 0);
271 add_ke_methods_to_proposal(proposal
, ke_alg
, add_kes
);
277 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
278 ke
= ha_key_exchange_create(secret
, dh_local
);
279 array_insert_create(&kes
, ARRAY_HEAD
, ke
);
280 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
282 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
286 ke
= ha_key_exchange_create(add_secret
, chunk_empty
);
287 array_insert_create(&kes
, ARRAY_TAIL
, ke
);
291 old_prf
= keymat_v2
->get_skd(keymat_v2
, &old_skd
);
293 ok
= keymat_v2
->derive_ike_keys(keymat_v2
, proposal
, kes
, nonce_i
,
294 nonce_r
, ike_sa
->get_id(ike_sa
), old_prf
, old_skd
);
296 else if (ike_sa
->get_version(ike_sa
) == IKEV1
)
298 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
299 shared_key_t
*shared
= NULL
;
304 shared
= shared_key_create(SHARED_IKE
, chunk_clone(psk
));
306 if (keymat_v1
->create_hasher(keymat_v1
, proposal
))
308 ok
= keymat_v1
->derive_ike_keys(keymat_v1
, proposal
,
309 ke
, dh_remote
, nonce_i
, nonce_r
,
310 ike_sa
->get_id(ike_sa
), method
, shared
);
314 array_destroy_offset(kes
, offsetof(key_exchange_t
, destroy
));
318 { /* register IKE_SA before calling inherit_post() so no scheduled
320 charon
->ike_sa_manager
->checkout_new(charon
->ike_sa_manager
,
322 ike_sa
->inherit_pre(ike_sa
, old_sa
);
323 ike_sa
->inherit_post(ike_sa
, old_sa
);
324 charon
->ike_sa_manager
->checkin_and_destroy(
325 charon
->ike_sa_manager
, old_sa
);
330 ike_sa
->set_other_host(ike_sa
, other
);
335 ike_sa
->set_state(ike_sa
, IKE_CONNECTING
);
336 ike_sa
->set_proposal(ike_sa
, proposal
);
338 this->cache
->cache(this->cache
, ike_sa
, message
);
340 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
344 DBG1(DBG_IKE
, "HA keymat derivation failed");
347 charon
->ike_sa_manager
->checkin_and_destroy(charon
->ike_sa_manager
,
352 ike_sa
->destroy(ike_sa
);
353 charon
->bus
->set_sa(charon
->bus
, NULL
);
358 proposal
->destroy(proposal
);
363 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, old_sa
);
370 * Apply all set conditions to the IKE_SA
372 static void set_conditions(ike_sa_t
*ike_sa
, ike_condition_t conditions
)
374 ike_condition_t i
, private = (conditions
& COND_PRIVATE_MARKER
);
376 for (i
= 0; i
< (sizeof(i
) * 8) - 1; ++i
)
378 ike_condition_t cond
= (1 << i
) | private;
380 ike_sa
->set_condition(ike_sa
, cond
, (conditions
& cond
) == cond
);
385 * Apply all enabled extensions to the IKE_SA
387 static void set_extensions(ike_sa_t
*ike_sa
, ike_extension_t extensions
)
389 ike_extension_t i
, private = (extensions
& EXT_PRIVATE_MARKER
);
391 for (i
= 0; i
< (sizeof(i
) * 8) - 1; ++i
)
393 ike_extension_t ext
= (1 << i
) | private;
395 if ((extensions
& ext
) == ext
)
397 ike_sa
->enable_extension(ike_sa
, ext
);
403 * Process messages of type IKE_UPDATE
405 static void process_ike_update(private_ha_dispatcher_t
*this,
406 ha_message_t
*message
)
408 ha_message_attribute_t attribute
;
409 ha_message_value_t value
;
410 enumerator_t
*enumerator
;
411 ike_sa_t
*ike_sa
= NULL
;
412 peer_cfg_t
*peer_cfg
= NULL
;
414 bool received_vip
= FALSE
, first_local_vip
= TRUE
, first_peer_addr
= TRUE
;
416 enumerator
= message
->create_attribute_enumerator(message
);
417 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
419 if (attribute
!= HA_IKE_ID
&& ike_sa
== NULL
)
421 /* must be first attribute */
427 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
431 ike_sa
->set_my_id(ike_sa
, value
.id
->clone(value
.id
));
434 ike_sa
->set_other_id(ike_sa
, value
.id
->clone(value
.id
));
436 case HA_REMOTE_EAP_ID
:
437 auth
= auth_cfg_create();
438 auth
->add(auth
, AUTH_RULE_EAP_IDENTITY
, value
.id
->clone(value
.id
));
439 ike_sa
->add_auth_cfg(ike_sa
, FALSE
, auth
);
442 ike_sa
->set_my_host(ike_sa
, value
.host
->clone(value
.host
));
445 ike_sa
->set_other_host(ike_sa
, value
.host
->clone(value
.host
));
450 ike_sa
->clear_virtual_ips(ike_sa
, TRUE
);
451 first_local_vip
= FALSE
;
453 ike_sa
->add_virtual_ip(ike_sa
, TRUE
, value
.host
);
458 ike_sa
->clear_virtual_ips(ike_sa
, FALSE
);
460 ike_sa
->add_virtual_ip(ike_sa
, FALSE
, value
.host
);
466 ike_sa
->clear_peer_addresses(ike_sa
);
467 first_peer_addr
= FALSE
;
469 ike_sa
->add_peer_address(ike_sa
, value
.host
->clone(value
.host
));
472 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(
473 charon
->backends
, value
.str
);
476 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
477 peer_cfg
->destroy(peer_cfg
);
481 DBG1(DBG_IKE
, "HA is missing nodes peer configuration");
482 charon
->ike_sa_manager
->checkin_and_destroy(
483 charon
->ike_sa_manager
, ike_sa
);
488 set_extensions(ike_sa
, value
.u32
);
491 set_conditions(ike_sa
, value
.u32
);
497 enumerator
->destroy(enumerator
);
501 if (ike_sa
->get_state(ike_sa
) == IKE_CONNECTING
&&
502 ike_sa
->get_peer_cfg(ike_sa
))
504 DBG1(DBG_CFG
, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
505 ike_sa
->get_name(ike_sa
),
506 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
507 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
508 ike_sa
->set_state(ike_sa
, IKE_PASSIVE
);
512 enumerator_t
*pools
, *vips
;
516 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
519 pools
= peer_cfg
->create_pool_enumerator(peer_cfg
);
520 while (pools
->enumerate(pools
, &pool
))
522 vips
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, FALSE
);
523 while (vips
->enumerate(vips
, &vip
))
525 this->attr
->reserve(this->attr
, pool
, vip
);
529 pools
->destroy(pools
);
533 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
535 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
536 adopt_children_job_create(ike_sa
->get_id(ike_sa
)));
538 #endif /* USE_IKEV1 */
539 this->cache
->cache(this->cache
, ike_sa
, message
);
540 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
544 DBG1(DBG_CFG
, "passive HA IKE_SA to update not found");
545 message
->destroy(message
);
550 * Process messages of type IKE_MID_INITIATOR/RESPONDER
552 static void process_ike_mid(private_ha_dispatcher_t
*this,
553 ha_message_t
*message
, bool initiator
)
555 ha_message_attribute_t attribute
;
556 ha_message_value_t value
;
557 enumerator_t
*enumerator
;
558 ike_sa_t
*ike_sa
= NULL
;
561 enumerator
= message
->create_attribute_enumerator(message
);
562 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
567 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
577 enumerator
->destroy(enumerator
);
583 ike_sa
->set_message_id(ike_sa
, initiator
, mid
);
585 this->cache
->cache(this->cache
, ike_sa
, message
);
586 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
590 message
->destroy(message
);
595 * Process messages of type IKE_IV
597 static void process_ike_iv(private_ha_dispatcher_t
*this, ha_message_t
*message
)
599 ha_message_attribute_t attribute
;
600 ha_message_value_t value
;
601 enumerator_t
*enumerator
;
602 ike_sa_t
*ike_sa
= NULL
;
603 chunk_t iv
= chunk_empty
;
605 enumerator
= message
->create_attribute_enumerator(message
);
606 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
611 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
621 enumerator
->destroy(enumerator
);
625 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
631 keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
632 if (keymat
->update_iv(keymat
, 0, iv
))
634 keymat
->confirm_iv(keymat
, 0);
638 this->cache
->cache(this->cache
, ike_sa
, message
);
639 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
643 message
->destroy(message
);
648 * Process messages of type IKE_DELETE
650 static void process_ike_delete(private_ha_dispatcher_t
*this,
651 ha_message_t
*message
)
653 ha_message_attribute_t attribute
;
654 ha_message_value_t value
;
655 enumerator_t
*enumerator
;
656 ike_sa_t
*ike_sa
= NULL
;
658 enumerator
= message
->create_attribute_enumerator(message
);
659 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
664 ike_sa
= charon
->ike_sa_manager
->checkout(
665 charon
->ike_sa_manager
, value
.ike_sa_id
);
671 enumerator
->destroy(enumerator
);
674 this->cache
->cache(this->cache
, ike_sa
, message
);
675 charon
->ike_sa_manager
->checkin_and_destroy(
676 charon
->ike_sa_manager
, ike_sa
);
680 message
->destroy(message
);
685 * Lookup a child cfg from the peer cfg by name
687 static child_cfg_t
* find_child_cfg(ike_sa_t
*ike_sa
, char *name
)
689 peer_cfg_t
*peer_cfg
;
690 child_cfg_t
*current
, *found
= NULL
;
691 enumerator_t
*enumerator
;
693 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
696 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
697 while (enumerator
->enumerate(enumerator
, ¤t
))
699 if (streq(current
->get_name(current
), name
))
705 enumerator
->destroy(enumerator
);
711 * Process messages of type CHILD_ADD
713 static void process_child_add(private_ha_dispatcher_t
*this,
714 ha_message_t
*message
)
716 ha_message_attribute_t attribute
;
717 ha_message_value_t value
;
718 enumerator_t
*enumerator
;
719 ike_sa_t
*ike_sa
= NULL
;
720 char *config_name
= "";
721 child_cfg_t
*config
= NULL
;
722 child_sa_t
*child_sa
;
723 proposal_t
*proposal
;
724 bool initiator
= FALSE
, failed
= FALSE
, ok
= FALSE
;
725 uint32_t inbound_spi
= 0, outbound_spi
= 0;
726 uint16_t inbound_cpi
= 0, outbound_cpi
= 0;
727 uint8_t mode
= MODE_TUNNEL
, ipcomp
= 0;
728 uint16_t encr
= 0, integ
= 0, len
= 0, ke_alg
= 0;
729 uint16_t esn
= NO_EXT_SEQ_NUMBERS
;
730 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
, secret
= chunk_empty
;
731 chunk_t add_secret
= chunk_empty
, add_kes
= chunk_empty
;
732 chunk_t encr_i
, integ_i
, encr_r
, integ_r
;
733 linked_list_t
*local_ts
, *remote_ts
;
734 key_exchange_t
*ke
= NULL
;
737 enumerator
= message
->create_attribute_enumerator(message
);
738 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
743 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
747 config_name
= value
.str
;
750 initiator
= value
.u8
;
753 inbound_spi
= value
.u32
;
755 case HA_OUTBOUND_SPI
:
756 outbound_spi
= value
.u32
;
759 inbound_cpi
= value
.u32
;
761 case HA_OUTBOUND_CPI
:
762 outbound_cpi
= value
.u32
;
773 case HA_ALG_ENCR_LEN
:
783 add_kes
= value
.chunk
;
789 nonce_i
= value
.chunk
;
792 nonce_r
= value
.chunk
;
795 secret
= value
.chunk
;
798 add_secret
= value
.chunk
;
804 enumerator
->destroy(enumerator
);
808 DBG1(DBG_CHD
, "IKE_SA for HA CHILD_SA not found");
809 message
->destroy(message
);
812 config
= find_child_cfg(ike_sa
, config_name
);
815 DBG1(DBG_CHD
, "HA is missing nodes child configuration");
816 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
817 message
->destroy(message
);
821 child_sa_create_t data
= {
822 .encap
= ike_sa
->has_condition(ike_sa
, COND_NAT_ANY
),
825 child_sa
= child_sa_create(ike_sa
->get_my_host(ike_sa
),
826 ike_sa
->get_other_host(ike_sa
), config
, &data
);
827 child_sa
->set_mode(child_sa
, mode
);
828 child_sa
->set_protocol(child_sa
, PROTO_ESP
);
829 child_sa
->set_ipcomp(child_sa
, ipcomp
);
831 proposal
= proposal_create(PROTO_ESP
, 0);
834 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
838 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
840 add_ke_methods_to_proposal(proposal
, ke_alg
, add_kes
);
841 proposal
->add_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
, esn
, 0);
845 ke
= ha_key_exchange_create(secret
, chunk_empty
);
846 array_insert_create(&kes
, ARRAY_HEAD
, ke
);
850 ke
= ha_key_exchange_create(add_secret
, chunk_empty
);
851 array_insert_create(&kes
, ARRAY_TAIL
, ke
);
853 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
855 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
857 ok
= keymat_v2
->derive_child_keys(keymat_v2
, proposal
, kes
,
858 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
860 else if (ike_sa
->get_version(ike_sa
) == IKEV1
)
862 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
863 uint32_t spi_i
, spi_r
;
865 spi_i
= initiator
? inbound_spi
: outbound_spi
;
866 spi_r
= initiator
? outbound_spi
: inbound_spi
;
868 ok
= keymat_v1
->derive_child_keys(keymat_v1
, proposal
, ke
, spi_i
, spi_r
,
869 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
871 array_destroy_offset(kes
, offsetof(key_exchange_t
, destroy
));
874 DBG1(DBG_CHD
, "HA CHILD_SA key derivation failed");
875 child_sa
->destroy(child_sa
);
876 proposal
->destroy(proposal
);
877 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
880 child_sa
->set_proposal(child_sa
, proposal
);
881 child_sa
->set_state(child_sa
, CHILD_INSTALLING
);
882 proposal
->destroy(proposal
);
884 /* TODO: Change CHILD_SA API to avoid cloning twice */
885 local_ts
= linked_list_create();
886 remote_ts
= linked_list_create();
887 enumerator
= message
->create_attribute_enumerator(message
);
888 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
893 local_ts
->insert_last(local_ts
, value
.ts
->clone(value
.ts
));
896 remote_ts
->insert_last(remote_ts
, value
.ts
->clone(value
.ts
));
902 enumerator
->destroy(enumerator
);
904 child_sa
->set_policies(child_sa
, local_ts
, remote_ts
);
908 if (child_sa
->install(child_sa
, encr_r
, integ_r
, inbound_spi
,
909 inbound_cpi
, initiator
, TRUE
, TRUE
) != SUCCESS
||
910 child_sa
->install(child_sa
, encr_i
, integ_i
, outbound_spi
,
911 outbound_cpi
, initiator
, FALSE
, TRUE
) != SUCCESS
)
918 if (child_sa
->install(child_sa
, encr_i
, integ_i
, inbound_spi
,
919 inbound_cpi
, initiator
, TRUE
, TRUE
) != SUCCESS
||
920 child_sa
->install(child_sa
, encr_r
, integ_r
, outbound_spi
,
921 outbound_cpi
, initiator
, FALSE
, TRUE
) != SUCCESS
)
926 chunk_clear(&encr_i
);
927 chunk_clear(&integ_i
);
928 chunk_clear(&encr_r
);
929 chunk_clear(&integ_r
);
933 DBG1(DBG_CHD
, "HA CHILD_SA installation failed");
934 child_sa
->destroy(child_sa
);
935 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
936 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
937 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
938 message
->destroy(message
);
945 seg_i
= this->kernel
->get_segment_spi(this->kernel
,
946 ike_sa
->get_my_host(ike_sa
), inbound_spi
);
947 seg_o
= this->kernel
->get_segment_spi(this->kernel
,
948 ike_sa
->get_other_host(ike_sa
), outbound_spi
);
949 DBG1(DBG_CFG
, "installed HA CHILD_SA %s{%d} %#R === %#R "
950 "(segment in: %d%s, out: %d%s)", child_sa
->get_name(child_sa
),
951 child_sa
->get_unique_id(child_sa
), local_ts
, remote_ts
,
952 seg_i
, this->segments
->is_active(this->segments
, seg_i
) ? "*" : "",
953 seg_o
, this->segments
->is_active(this->segments
, seg_o
) ? "*" : "");
954 #endif /* DEBUG_LEVEL */
956 child_sa
->install_policies(child_sa
);
957 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
958 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
960 child_sa
->set_state(child_sa
, CHILD_INSTALLED
);
961 ike_sa
->add_child_sa(ike_sa
, child_sa
);
962 message
->destroy(message
);
963 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
967 * Process messages of type CHILD_DELETE
969 static void process_child_delete(private_ha_dispatcher_t
*this,
970 ha_message_t
*message
)
972 ha_message_attribute_t attribute
;
973 ha_message_value_t value
;
974 enumerator_t
*enumerator
;
975 ike_sa_t
*ike_sa
= NULL
;
976 child_sa_t
*child_sa
;
979 enumerator
= message
->create_attribute_enumerator(message
);
980 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
985 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
995 enumerator
->destroy(enumerator
);
999 child_sa
= ike_sa
->get_child_sa(ike_sa
, PROTO_ESP
, spi
, TRUE
);
1002 ike_sa
->destroy_child_sa(ike_sa
, PROTO_ESP
, spi
);
1004 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
1006 message
->destroy(message
);
1010 * Process messages of type SEGMENT_TAKE/DROP
1012 static void process_segment(private_ha_dispatcher_t
*this,
1013 ha_message_t
*message
, bool take
)
1015 ha_message_attribute_t attribute
;
1016 ha_message_value_t value
;
1017 enumerator_t
*enumerator
;
1019 enumerator
= message
->create_attribute_enumerator(message
);
1020 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
1027 DBG1(DBG_CFG
, "remote node takes segment %d", value
.u16
);
1028 this->segments
->deactivate(this->segments
, value
.u16
, FALSE
);
1032 DBG1(DBG_CFG
, "remote node drops segment %d", value
.u16
);
1033 this->segments
->activate(this->segments
, value
.u16
, FALSE
);
1040 enumerator
->destroy(enumerator
);
1041 message
->destroy(message
);
1045 * Process messages of type STATUS
1047 static void process_status(private_ha_dispatcher_t
*this,
1048 ha_message_t
*message
)
1050 ha_message_attribute_t attribute
;
1051 ha_message_value_t value
;
1052 enumerator_t
*enumerator
;
1053 segment_mask_t mask
= 0;
1055 enumerator
= message
->create_attribute_enumerator(message
);
1056 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
1061 mask
|= SEGMENTS_BIT(value
.u16
);
1067 enumerator
->destroy(enumerator
);
1069 this->segments
->handle_status(this->segments
, mask
);
1070 message
->destroy(message
);
1074 * Process messages of type RESYNC
1076 static void process_resync(private_ha_dispatcher_t
*this,
1077 ha_message_t
*message
)
1079 ha_message_attribute_t attribute
;
1080 ha_message_value_t value
;
1081 enumerator_t
*enumerator
;
1083 enumerator
= message
->create_attribute_enumerator(message
);
1084 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
1089 this->cache
->resync(this->cache
, value
.u16
);
1095 enumerator
->destroy(enumerator
);
1096 message
->destroy(message
);
1100 * Dispatcher job function
1102 static job_requeue_t
dispatch(private_ha_dispatcher_t
*this)
1104 ha_message_t
*message
;
1105 ha_message_type_t type
;
1107 message
= this->socket
->pull(this->socket
);
1108 type
= message
->get_type(message
);
1109 if (type
!= HA_STATUS
)
1111 DBG2(DBG_CFG
, "received HA %N message", ha_message_type_names
,
1112 message
->get_type(message
));
1117 process_ike_add(this, message
);
1120 process_ike_update(this, message
);
1122 case HA_IKE_MID_INITIATOR
:
1123 process_ike_mid(this, message
, TRUE
);
1125 case HA_IKE_MID_RESPONDER
:
1126 process_ike_mid(this, message
, FALSE
);
1129 process_ike_iv(this, message
);
1132 process_ike_delete(this, message
);
1135 process_child_add(this, message
);
1137 case HA_CHILD_DELETE
:
1138 process_child_delete(this, message
);
1140 case HA_SEGMENT_DROP
:
1141 process_segment(this, message
, FALSE
);
1143 case HA_SEGMENT_TAKE
:
1144 process_segment(this, message
, TRUE
);
1147 process_status(this, message
);
1150 process_resync(this, message
);
1153 DBG1(DBG_CFG
, "received unknown HA message type %d", type
);
1154 message
->destroy(message
);
1157 return JOB_REQUEUE_DIRECT
;
1160 METHOD(ha_dispatcher_t
, destroy
, void,
1161 private_ha_dispatcher_t
*this)
1169 ha_dispatcher_t
*ha_dispatcher_create(ha_socket_t
*socket
,
1170 ha_segments_t
*segments
, ha_cache_t
*cache
,
1171 ha_kernel_t
*kernel
, ha_attribute_t
*attr
)
1173 private_ha_dispatcher_t
*this;
1178 .destroy
= _destroy
,
1181 .segments
= segments
,
1186 lib
->processor
->queue_job(lib
->processor
,
1187 (job_t
*)callback_job_create_with_prio((callback_job_cb_t
)dispatch
, this,
1188 NULL
, callback_job_cancel_thread
, JOB_PRIO_CRITICAL
));
1190 return &this->public;