2 * Copyright (C) 2008 Martin Willi
3 * HSR 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 "ha_dispatcher.h"
19 #include <sa/ikev2/keymat_v2.h>
20 #include <sa/ikev1/keymat_v1.h>
21 #include <processing/jobs/callback_job.h>
22 #include <processing/jobs/adopt_children_job.h>
24 typedef struct private_ha_dispatcher_t private_ha_dispatcher_t
;
25 typedef struct ha_diffie_hellman_t ha_diffie_hellman_t
;
28 * Private data of an ha_dispatcher_t object.
30 struct private_ha_dispatcher_t
{
33 * Public ha_dispatcher_t interface.
35 ha_dispatcher_t
public;
38 * socket to pull messages from
45 ha_segments_t
*segments
;
64 * DH implementation for HA synced DH values
66 struct ha_diffie_hellman_t
{
69 * Implements diffie_hellman_t
84 METHOD(diffie_hellman_t
, dh_get_shared_secret
, bool,
85 ha_diffie_hellman_t
*this, chunk_t
*secret
)
87 *secret
= chunk_clone(this->secret
);
91 METHOD(diffie_hellman_t
, dh_get_my_public_value
, bool,
92 ha_diffie_hellman_t
*this, chunk_t
*value
)
94 *value
= chunk_clone(this->pub
);
98 METHOD(diffie_hellman_t
, dh_destroy
, void,
99 ha_diffie_hellman_t
*this)
105 * Create a HA synced DH implementation
107 static diffie_hellman_t
*ha_diffie_hellman_create(chunk_t secret
, chunk_t pub
)
109 ha_diffie_hellman_t
*this;
113 .get_shared_secret
= _dh_get_shared_secret
,
114 .get_my_public_value
= _dh_get_my_public_value
,
115 .destroy
= _dh_destroy
,
125 * Process messages of type IKE_ADD
127 static void process_ike_add(private_ha_dispatcher_t
*this, ha_message_t
*message
)
129 ha_message_attribute_t attribute
;
130 ha_message_value_t value
;
131 enumerator_t
*enumerator
;
132 ike_sa_t
*ike_sa
= NULL
, *old_sa
= NULL
;
133 ike_version_t version
= IKEV2
;
134 uint16_t encr
= 0, len
= 0, integ
= 0, prf
= 0, old_prf
= PRF_UNDEFINED
;
136 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
;
137 chunk_t secret
= chunk_empty
, old_skd
= chunk_empty
;
138 chunk_t dh_local
= chunk_empty
, dh_remote
= chunk_empty
, psk
= chunk_empty
;
139 host_t
*other
= NULL
;
141 auth_method_t method
= AUTH_RSA
;
143 enumerator
= message
->create_attribute_enumerator(message
);
144 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
149 ike_sa
= ike_sa_create(value
.ike_sa_id
,
150 value
.ike_sa_id
->is_initiator(value
.ike_sa_id
), version
);
152 case HA_IKE_REKEY_ID
:
153 old_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
157 other
= value
.host
->clone(value
.host
);
163 nonce_i
= value
.chunk
;
166 nonce_r
= value
.chunk
;
169 secret
= value
.chunk
;
172 dh_local
= value
.chunk
;
175 dh_remote
= value
.chunk
;
181 old_skd
= value
.chunk
;
186 case HA_ALG_ENCR_LEN
:
207 enumerator
->destroy(enumerator
);
211 proposal_t
*proposal
;
212 diffie_hellman_t
*dh
;
214 proposal
= proposal_create(PROTO_IKE
, 0);
217 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
221 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
225 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, prf
, 0);
229 proposal
->add_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, dh_grp
, 0);
231 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
232 dh
= ha_diffie_hellman_create(secret
, dh_local
);
233 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
235 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
237 ok
= keymat_v2
->derive_ike_keys(keymat_v2
, proposal
, dh
, nonce_i
,
238 nonce_r
, ike_sa
->get_id(ike_sa
), old_prf
, old_skd
);
240 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
242 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
243 shared_key_t
*shared
= NULL
;
248 shared
= shared_key_create(SHARED_IKE
, chunk_clone(psk
));
250 if (keymat_v1
->create_hasher(keymat_v1
, proposal
))
252 ok
= keymat_v1
->derive_ike_keys(keymat_v1
, proposal
,
253 dh
, dh_remote
, nonce_i
, nonce_r
,
254 ike_sa
->get_id(ike_sa
), method
, shared
);
263 ike_sa
->inherit_pre(ike_sa
, old_sa
);
264 ike_sa
->inherit_post(ike_sa
, old_sa
);
265 charon
->ike_sa_manager
->checkin_and_destroy(
266 charon
->ike_sa_manager
, old_sa
);
271 ike_sa
->set_other_host(ike_sa
, other
);
274 ike_sa
->set_state(ike_sa
, IKE_CONNECTING
);
275 ike_sa
->set_proposal(ike_sa
, proposal
);
276 this->cache
->cache(this->cache
, ike_sa
, message
);
278 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
282 DBG1(DBG_IKE
, "HA keymat derivation failed");
283 ike_sa
->destroy(ike_sa
);
285 charon
->bus
->set_sa(charon
->bus
, NULL
);
286 proposal
->destroy(proposal
);
290 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, old_sa
);
297 * Apply a condition flag to the IKE_SA if it is in set
299 static void set_condition(ike_sa_t
*ike_sa
, ike_condition_t set
,
300 ike_condition_t flag
)
302 ike_sa
->set_condition(ike_sa
, flag
, flag
& set
);
306 * Apply a extension flag to the IKE_SA if it is in set
308 static void set_extension(ike_sa_t
*ike_sa
, ike_extension_t set
,
309 ike_extension_t flag
)
313 ike_sa
->enable_extension(ike_sa
, flag
);
318 * Process messages of type IKE_UPDATE
320 static void process_ike_update(private_ha_dispatcher_t
*this,
321 ha_message_t
*message
)
323 ha_message_attribute_t attribute
;
324 ha_message_value_t value
;
325 enumerator_t
*enumerator
;
326 ike_sa_t
*ike_sa
= NULL
;
327 peer_cfg_t
*peer_cfg
= NULL
;
329 bool received_vip
= FALSE
, first_local_vip
= TRUE
, first_peer_addr
= TRUE
;
331 enumerator
= message
->create_attribute_enumerator(message
);
332 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
334 if (attribute
!= HA_IKE_ID
&& ike_sa
== NULL
)
336 /* must be first attribute */
342 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
346 ike_sa
->set_my_id(ike_sa
, value
.id
->clone(value
.id
));
349 ike_sa
->set_other_id(ike_sa
, value
.id
->clone(value
.id
));
351 case HA_REMOTE_EAP_ID
:
352 auth
= auth_cfg_create();
353 auth
->add(auth
, AUTH_RULE_EAP_IDENTITY
, value
.id
->clone(value
.id
));
354 ike_sa
->add_auth_cfg(ike_sa
, FALSE
, auth
);
357 ike_sa
->set_my_host(ike_sa
, value
.host
->clone(value
.host
));
360 ike_sa
->set_other_host(ike_sa
, value
.host
->clone(value
.host
));
365 ike_sa
->clear_virtual_ips(ike_sa
, TRUE
);
366 first_local_vip
= FALSE
;
368 ike_sa
->add_virtual_ip(ike_sa
, TRUE
, value
.host
);
373 ike_sa
->clear_virtual_ips(ike_sa
, FALSE
);
375 ike_sa
->add_virtual_ip(ike_sa
, FALSE
, value
.host
);
381 ike_sa
->clear_peer_addresses(ike_sa
);
382 first_peer_addr
= FALSE
;
384 ike_sa
->add_peer_address(ike_sa
, value
.host
->clone(value
.host
));
387 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(
388 charon
->backends
, value
.str
);
391 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
392 peer_cfg
->destroy(peer_cfg
);
396 DBG1(DBG_IKE
, "HA is missing nodes peer configuration");
397 charon
->ike_sa_manager
->checkin_and_destroy(
398 charon
->ike_sa_manager
, ike_sa
);
403 set_extension(ike_sa
, value
.u32
, EXT_NATT
);
404 set_extension(ike_sa
, value
.u32
, EXT_MOBIKE
);
405 set_extension(ike_sa
, value
.u32
, EXT_HASH_AND_URL
);
406 set_extension(ike_sa
, value
.u32
, EXT_MULTIPLE_AUTH
);
407 set_extension(ike_sa
, value
.u32
, EXT_STRONGSWAN
);
408 set_extension(ike_sa
, value
.u32
, EXT_EAP_ONLY_AUTHENTICATION
);
409 set_extension(ike_sa
, value
.u32
, EXT_MS_WINDOWS
);
410 set_extension(ike_sa
, value
.u32
, EXT_XAUTH
);
411 set_extension(ike_sa
, value
.u32
, EXT_DPD
);
414 set_condition(ike_sa
, value
.u32
, COND_NAT_ANY
);
415 set_condition(ike_sa
, value
.u32
, COND_NAT_HERE
);
416 set_condition(ike_sa
, value
.u32
, COND_NAT_THERE
);
417 set_condition(ike_sa
, value
.u32
, COND_NAT_FAKE
);
418 set_condition(ike_sa
, value
.u32
, COND_EAP_AUTHENTICATED
);
419 set_condition(ike_sa
, value
.u32
, COND_CERTREQ_SEEN
);
420 set_condition(ike_sa
, value
.u32
, COND_ORIGINAL_INITIATOR
);
421 set_condition(ike_sa
, value
.u32
, COND_STALE
);
422 set_condition(ike_sa
, value
.u32
, COND_INIT_CONTACT_SEEN
);
423 set_condition(ike_sa
, value
.u32
, COND_XAUTH_AUTHENTICATED
);
429 enumerator
->destroy(enumerator
);
433 if (ike_sa
->get_state(ike_sa
) == IKE_CONNECTING
&&
434 ike_sa
->get_peer_cfg(ike_sa
))
436 DBG1(DBG_CFG
, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
437 ike_sa
->get_name(ike_sa
),
438 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
439 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
440 ike_sa
->set_state(ike_sa
, IKE_PASSIVE
);
444 enumerator_t
*pools
, *vips
;
448 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
451 pools
= peer_cfg
->create_pool_enumerator(peer_cfg
);
452 while (pools
->enumerate(pools
, &pool
))
454 vips
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, FALSE
);
455 while (vips
->enumerate(vips
, &vip
))
457 this->attr
->reserve(this->attr
, pool
, vip
);
461 pools
->destroy(pools
);
465 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
467 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
468 adopt_children_job_create(ike_sa
->get_id(ike_sa
)));
470 #endif /* USE_IKEV1 */
471 this->cache
->cache(this->cache
, ike_sa
, message
);
472 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
476 DBG1(DBG_CFG
, "passive HA IKE_SA to update not found");
477 message
->destroy(message
);
482 * Process messages of type IKE_MID_INITIATOR/RESPONDER
484 static void process_ike_mid(private_ha_dispatcher_t
*this,
485 ha_message_t
*message
, bool initiator
)
487 ha_message_attribute_t attribute
;
488 ha_message_value_t value
;
489 enumerator_t
*enumerator
;
490 ike_sa_t
*ike_sa
= NULL
;
493 enumerator
= message
->create_attribute_enumerator(message
);
494 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
499 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
509 enumerator
->destroy(enumerator
);
515 ike_sa
->set_message_id(ike_sa
, initiator
, mid
);
517 this->cache
->cache(this->cache
, ike_sa
, message
);
518 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
522 message
->destroy(message
);
527 * Process messages of type IKE_IV
529 static void process_ike_iv(private_ha_dispatcher_t
*this, ha_message_t
*message
)
531 ha_message_attribute_t attribute
;
532 ha_message_value_t value
;
533 enumerator_t
*enumerator
;
534 ike_sa_t
*ike_sa
= NULL
;
535 chunk_t iv
= chunk_empty
;
537 enumerator
= message
->create_attribute_enumerator(message
);
538 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
543 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
553 enumerator
->destroy(enumerator
);
557 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
563 keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
564 if (keymat
->update_iv(keymat
, 0, iv
))
566 keymat
->confirm_iv(keymat
, 0);
570 this->cache
->cache(this->cache
, ike_sa
, message
);
571 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
575 message
->destroy(message
);
580 * Process messages of type IKE_DELETE
582 static void process_ike_delete(private_ha_dispatcher_t
*this,
583 ha_message_t
*message
)
585 ha_message_attribute_t attribute
;
586 ha_message_value_t value
;
587 enumerator_t
*enumerator
;
588 ike_sa_t
*ike_sa
= NULL
;
590 enumerator
= message
->create_attribute_enumerator(message
);
591 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
596 ike_sa
= charon
->ike_sa_manager
->checkout(
597 charon
->ike_sa_manager
, value
.ike_sa_id
);
603 enumerator
->destroy(enumerator
);
606 this->cache
->cache(this->cache
, ike_sa
, message
);
607 charon
->ike_sa_manager
->checkin_and_destroy(
608 charon
->ike_sa_manager
, ike_sa
);
612 message
->destroy(message
);
617 * Lookup a child cfg from the peer cfg by name
619 static child_cfg_t
* find_child_cfg(ike_sa_t
*ike_sa
, char *name
)
621 peer_cfg_t
*peer_cfg
;
622 child_cfg_t
*current
, *found
= NULL
;
623 enumerator_t
*enumerator
;
625 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
628 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
629 while (enumerator
->enumerate(enumerator
, ¤t
))
631 if (streq(current
->get_name(current
), name
))
637 enumerator
->destroy(enumerator
);
643 * Process messages of type CHILD_ADD
645 static void process_child_add(private_ha_dispatcher_t
*this,
646 ha_message_t
*message
)
648 ha_message_attribute_t attribute
;
649 ha_message_value_t value
;
650 enumerator_t
*enumerator
;
651 ike_sa_t
*ike_sa
= NULL
;
652 char *config_name
= "";
653 child_cfg_t
*config
= NULL
;
654 child_sa_t
*child_sa
;
655 proposal_t
*proposal
;
656 bool initiator
= FALSE
, failed
= FALSE
, ok
= FALSE
;
657 uint32_t inbound_spi
= 0, outbound_spi
= 0;
658 uint16_t inbound_cpi
= 0, outbound_cpi
= 0;
659 uint8_t mode
= MODE_TUNNEL
, ipcomp
= 0;
660 uint16_t encr
= 0, integ
= 0, len
= 0, dh_grp
= 0;
661 uint16_t esn
= NO_EXT_SEQ_NUMBERS
;
663 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
, secret
= chunk_empty
;
664 chunk_t encr_i
, integ_i
, encr_r
, integ_r
;
665 linked_list_t
*local_ts
, *remote_ts
;
666 diffie_hellman_t
*dh
= NULL
;
668 enumerator
= message
->create_attribute_enumerator(message
);
669 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
674 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
678 config_name
= value
.str
;
681 initiator
= value
.u8
;
684 inbound_spi
= value
.u32
;
686 case HA_OUTBOUND_SPI
:
687 outbound_spi
= value
.u32
;
690 inbound_cpi
= value
.u32
;
692 case HA_OUTBOUND_CPI
:
693 outbound_cpi
= value
.u32
;
704 case HA_ALG_ENCR_LEN
:
717 nonce_i
= value
.chunk
;
720 nonce_r
= value
.chunk
;
723 secret
= value
.chunk
;
729 enumerator
->destroy(enumerator
);
733 DBG1(DBG_CHD
, "IKE_SA for HA CHILD_SA not found");
734 message
->destroy(message
);
737 config
= find_child_cfg(ike_sa
, config_name
);
740 DBG1(DBG_CHD
, "HA is missing nodes child configuration");
741 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
742 message
->destroy(message
);
746 child_sa_create_t data
= {
747 .encap
= ike_sa
->has_condition(ike_sa
, COND_NAT_ANY
),
749 child_sa
= child_sa_create(ike_sa
->get_my_host(ike_sa
),
750 ike_sa
->get_other_host(ike_sa
), config
, &data
);
751 child_sa
->set_mode(child_sa
, mode
);
752 child_sa
->set_protocol(child_sa
, PROTO_ESP
);
753 child_sa
->set_ipcomp(child_sa
, ipcomp
);
755 proposal
= proposal_create(PROTO_ESP
, 0);
758 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
762 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
766 proposal
->add_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, dh_grp
, 0);
768 proposal
->add_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
, esn
, 0);
771 dh
= ha_diffie_hellman_create(secret
, chunk_empty
);
773 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
775 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
777 ok
= keymat_v2
->derive_child_keys(keymat_v2
, proposal
, dh
,
778 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
780 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
782 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
783 uint32_t spi_i
, spi_r
;
785 spi_i
= initiator
? inbound_spi
: outbound_spi
;
786 spi_r
= initiator
? outbound_spi
: inbound_spi
;
788 ok
= keymat_v1
->derive_child_keys(keymat_v1
, proposal
, dh
, spi_i
, spi_r
,
789 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
794 DBG1(DBG_CHD
, "HA CHILD_SA key derivation failed");
795 child_sa
->destroy(child_sa
);
796 proposal
->destroy(proposal
);
797 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
800 child_sa
->set_proposal(child_sa
, proposal
);
801 child_sa
->set_state(child_sa
, CHILD_INSTALLING
);
802 proposal
->destroy(proposal
);
804 /* TODO: Change CHILD_SA API to avoid cloning twice */
805 local_ts
= linked_list_create();
806 remote_ts
= linked_list_create();
807 enumerator
= message
->create_attribute_enumerator(message
);
808 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
813 local_ts
->insert_last(local_ts
, value
.ts
->clone(value
.ts
));
816 remote_ts
->insert_last(remote_ts
, value
.ts
->clone(value
.ts
));
822 enumerator
->destroy(enumerator
);
824 child_sa
->set_policies(child_sa
, local_ts
, remote_ts
);
828 if (child_sa
->install(child_sa
, encr_r
, integ_r
, inbound_spi
,
829 inbound_cpi
, initiator
, TRUE
, TRUE
) != SUCCESS
||
830 child_sa
->install(child_sa
, encr_i
, integ_i
, outbound_spi
,
831 outbound_cpi
, initiator
, FALSE
, TRUE
) != SUCCESS
)
838 if (child_sa
->install(child_sa
, encr_i
, integ_i
, inbound_spi
,
839 inbound_cpi
, initiator
, TRUE
, TRUE
) != SUCCESS
||
840 child_sa
->install(child_sa
, encr_r
, integ_r
, outbound_spi
,
841 outbound_cpi
, initiator
, FALSE
, TRUE
) != SUCCESS
)
846 chunk_clear(&encr_i
);
847 chunk_clear(&integ_i
);
848 chunk_clear(&encr_r
);
849 chunk_clear(&integ_r
);
853 DBG1(DBG_CHD
, "HA CHILD_SA installation failed");
854 child_sa
->destroy(child_sa
);
855 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
856 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
857 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
858 message
->destroy(message
);
862 seg_i
= this->kernel
->get_segment_spi(this->kernel
,
863 ike_sa
->get_my_host(ike_sa
), inbound_spi
);
864 seg_o
= this->kernel
->get_segment_spi(this->kernel
,
865 ike_sa
->get_other_host(ike_sa
), outbound_spi
);
867 DBG1(DBG_CFG
, "installed HA CHILD_SA %s{%d} %#R === %#R "
868 "(segment in: %d%s, out: %d%s)", child_sa
->get_name(child_sa
),
869 child_sa
->get_unique_id(child_sa
), local_ts
, remote_ts
,
870 seg_i
, this->segments
->is_active(this->segments
, seg_i
) ? "*" : "",
871 seg_o
, this->segments
->is_active(this->segments
, seg_o
) ? "*" : "");
872 child_sa
->install_policies(child_sa
);
873 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
874 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
876 child_sa
->set_state(child_sa
, CHILD_INSTALLED
);
877 ike_sa
->add_child_sa(ike_sa
, child_sa
);
878 message
->destroy(message
);
879 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
883 * Process messages of type CHILD_DELETE
885 static void process_child_delete(private_ha_dispatcher_t
*this,
886 ha_message_t
*message
)
888 ha_message_attribute_t attribute
;
889 ha_message_value_t value
;
890 enumerator_t
*enumerator
;
891 ike_sa_t
*ike_sa
= NULL
;
892 child_sa_t
*child_sa
;
895 enumerator
= message
->create_attribute_enumerator(message
);
896 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
901 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
911 enumerator
->destroy(enumerator
);
915 child_sa
= ike_sa
->get_child_sa(ike_sa
, PROTO_ESP
, spi
, TRUE
);
918 ike_sa
->destroy_child_sa(ike_sa
, PROTO_ESP
, spi
);
920 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
922 message
->destroy(message
);
926 * Process messages of type SEGMENT_TAKE/DROP
928 static void process_segment(private_ha_dispatcher_t
*this,
929 ha_message_t
*message
, bool take
)
931 ha_message_attribute_t attribute
;
932 ha_message_value_t value
;
933 enumerator_t
*enumerator
;
935 enumerator
= message
->create_attribute_enumerator(message
);
936 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
943 DBG1(DBG_CFG
, "remote node takes segment %d", value
.u16
);
944 this->segments
->deactivate(this->segments
, value
.u16
, FALSE
);
948 DBG1(DBG_CFG
, "remote node drops segment %d", value
.u16
);
949 this->segments
->activate(this->segments
, value
.u16
, FALSE
);
956 enumerator
->destroy(enumerator
);
957 message
->destroy(message
);
961 * Process messages of type STATUS
963 static void process_status(private_ha_dispatcher_t
*this,
964 ha_message_t
*message
)
966 ha_message_attribute_t attribute
;
967 ha_message_value_t value
;
968 enumerator_t
*enumerator
;
969 segment_mask_t mask
= 0;
971 enumerator
= message
->create_attribute_enumerator(message
);
972 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
977 mask
|= SEGMENTS_BIT(value
.u16
);
983 enumerator
->destroy(enumerator
);
985 this->segments
->handle_status(this->segments
, mask
);
986 message
->destroy(message
);
990 * Process messages of type RESYNC
992 static void process_resync(private_ha_dispatcher_t
*this,
993 ha_message_t
*message
)
995 ha_message_attribute_t attribute
;
996 ha_message_value_t value
;
997 enumerator_t
*enumerator
;
999 enumerator
= message
->create_attribute_enumerator(message
);
1000 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
1005 this->cache
->resync(this->cache
, value
.u16
);
1011 enumerator
->destroy(enumerator
);
1012 message
->destroy(message
);
1016 * Dispatcher job function
1018 static job_requeue_t
dispatch(private_ha_dispatcher_t
*this)
1020 ha_message_t
*message
;
1021 ha_message_type_t type
;
1023 message
= this->socket
->pull(this->socket
);
1024 type
= message
->get_type(message
);
1025 if (type
!= HA_STATUS
)
1027 DBG2(DBG_CFG
, "received HA %N message", ha_message_type_names
,
1028 message
->get_type(message
));
1033 process_ike_add(this, message
);
1036 process_ike_update(this, message
);
1038 case HA_IKE_MID_INITIATOR
:
1039 process_ike_mid(this, message
, TRUE
);
1041 case HA_IKE_MID_RESPONDER
:
1042 process_ike_mid(this, message
, FALSE
);
1045 process_ike_iv(this, message
);
1048 process_ike_delete(this, message
);
1051 process_child_add(this, message
);
1053 case HA_CHILD_DELETE
:
1054 process_child_delete(this, message
);
1056 case HA_SEGMENT_DROP
:
1057 process_segment(this, message
, FALSE
);
1059 case HA_SEGMENT_TAKE
:
1060 process_segment(this, message
, TRUE
);
1063 process_status(this, message
);
1066 process_resync(this, message
);
1069 DBG1(DBG_CFG
, "received unknown HA message type %d", type
);
1070 message
->destroy(message
);
1073 return JOB_REQUEUE_DIRECT
;
1076 METHOD(ha_dispatcher_t
, destroy
, void,
1077 private_ha_dispatcher_t
*this)
1085 ha_dispatcher_t
*ha_dispatcher_create(ha_socket_t
*socket
,
1086 ha_segments_t
*segments
, ha_cache_t
*cache
,
1087 ha_kernel_t
*kernel
, ha_attribute_t
*attr
)
1089 private_ha_dispatcher_t
*this;
1094 .destroy
= _destroy
,
1097 .segments
= segments
,
1102 lib
->processor
->queue_job(lib
->processor
,
1103 (job_t
*)callback_job_create_with_prio((callback_job_cb_t
)dispatch
, this,
1104 NULL
, (callback_job_cancel_t
)return_false
, JOB_PRIO_CRITICAL
));
1106 return &this->public;