2 * Copyright (C) 2008 Martin Willi
3 * 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 u_int16_t encr
= 0, len
= 0, integ
= 0, prf
= 0, old_prf
= PRF_UNDEFINED
;
135 u_int16_t dh_grp
= 0;
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
;
142 enumerator
= message
->create_attribute_enumerator(message
);
143 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
148 ike_sa
= ike_sa_create(value
.ike_sa_id
,
149 value
.ike_sa_id
->is_initiator(value
.ike_sa_id
), version
);
151 case HA_IKE_REKEY_ID
:
152 old_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
156 other
= value
.host
->clone(value
.host
);
162 nonce_i
= value
.chunk
;
165 nonce_r
= value
.chunk
;
168 secret
= value
.chunk
;
171 dh_local
= value
.chunk
;
174 dh_remote
= value
.chunk
;
180 old_skd
= value
.chunk
;
185 case HA_ALG_ENCR_LEN
:
204 enumerator
->destroy(enumerator
);
208 proposal_t
*proposal
;
209 diffie_hellman_t
*dh
;
211 proposal
= proposal_create(PROTO_IKE
, 0);
214 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
218 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
222 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, prf
, 0);
226 proposal
->add_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, dh_grp
, 0);
228 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
229 dh
= ha_diffie_hellman_create(secret
, dh_local
);
230 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
232 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
234 ok
= keymat_v2
->derive_ike_keys(keymat_v2
, proposal
, dh
, nonce_i
,
235 nonce_r
, ike_sa
->get_id(ike_sa
), old_prf
, old_skd
);
237 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
239 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
240 shared_key_t
*shared
= NULL
;
241 auth_method_t method
= AUTH_RSA
;
246 shared
= shared_key_create(SHARED_IKE
, chunk_clone(psk
));
248 if (keymat_v1
->create_hasher(keymat_v1
, proposal
))
250 ok
= keymat_v1
->derive_ike_keys(keymat_v1
, proposal
,
251 dh
, dh_remote
, nonce_i
, nonce_r
,
252 ike_sa
->get_id(ike_sa
), method
, shared
);
261 ike_sa
->inherit_pre(ike_sa
, old_sa
);
262 ike_sa
->inherit_post(ike_sa
, old_sa
);
263 charon
->ike_sa_manager
->checkin_and_destroy(
264 charon
->ike_sa_manager
, old_sa
);
269 ike_sa
->set_other_host(ike_sa
, other
);
272 ike_sa
->set_state(ike_sa
, IKE_CONNECTING
);
273 ike_sa
->set_proposal(ike_sa
, proposal
);
274 this->cache
->cache(this->cache
, ike_sa
, message
);
276 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
280 DBG1(DBG_IKE
, "HA keymat derivation failed");
281 ike_sa
->destroy(ike_sa
);
283 charon
->bus
->set_sa(charon
->bus
, NULL
);
284 proposal
->destroy(proposal
);
288 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, old_sa
);
295 * Apply a condition flag to the IKE_SA if it is in set
297 static void set_condition(ike_sa_t
*ike_sa
, ike_condition_t set
,
298 ike_condition_t flag
)
300 ike_sa
->set_condition(ike_sa
, flag
, flag
& set
);
304 * Apply a extension flag to the IKE_SA if it is in set
306 static void set_extension(ike_sa_t
*ike_sa
, ike_extension_t set
,
307 ike_extension_t flag
)
311 ike_sa
->enable_extension(ike_sa
, flag
);
316 * Process messages of type IKE_UPDATE
318 static void process_ike_update(private_ha_dispatcher_t
*this,
319 ha_message_t
*message
)
321 ha_message_attribute_t attribute
;
322 ha_message_value_t value
;
323 enumerator_t
*enumerator
;
324 ike_sa_t
*ike_sa
= NULL
;
325 peer_cfg_t
*peer_cfg
= NULL
;
327 bool received_vip
= FALSE
, first_local_vip
= TRUE
, first_peer_addr
= TRUE
;
329 enumerator
= message
->create_attribute_enumerator(message
);
330 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
332 if (attribute
!= HA_IKE_ID
&& ike_sa
== NULL
)
334 /* must be first attribute */
340 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
344 ike_sa
->set_my_id(ike_sa
, value
.id
->clone(value
.id
));
347 ike_sa
->set_other_id(ike_sa
, value
.id
->clone(value
.id
));
349 case HA_REMOTE_EAP_ID
:
350 auth
= auth_cfg_create();
351 auth
->add(auth
, AUTH_RULE_EAP_IDENTITY
, value
.id
->clone(value
.id
));
352 ike_sa
->add_auth_cfg(ike_sa
, FALSE
, auth
);
355 ike_sa
->set_my_host(ike_sa
, value
.host
->clone(value
.host
));
358 ike_sa
->set_other_host(ike_sa
, value
.host
->clone(value
.host
));
363 ike_sa
->clear_virtual_ips(ike_sa
, TRUE
);
364 first_local_vip
= FALSE
;
366 ike_sa
->add_virtual_ip(ike_sa
, TRUE
, value
.host
);
371 ike_sa
->clear_virtual_ips(ike_sa
, FALSE
);
373 ike_sa
->add_virtual_ip(ike_sa
, FALSE
, value
.host
);
379 ike_sa
->clear_peer_addresses(ike_sa
);
380 first_peer_addr
= FALSE
;
382 ike_sa
->add_peer_address(ike_sa
, value
.host
->clone(value
.host
));
385 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(
386 charon
->backends
, value
.str
);
389 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
390 peer_cfg
->destroy(peer_cfg
);
394 DBG1(DBG_IKE
, "HA is missing nodes peer configuration");
395 charon
->ike_sa_manager
->checkin_and_destroy(
396 charon
->ike_sa_manager
, ike_sa
);
401 set_extension(ike_sa
, value
.u32
, EXT_NATT
);
402 set_extension(ike_sa
, value
.u32
, EXT_MOBIKE
);
403 set_extension(ike_sa
, value
.u32
, EXT_HASH_AND_URL
);
404 set_extension(ike_sa
, value
.u32
, EXT_MULTIPLE_AUTH
);
405 set_extension(ike_sa
, value
.u32
, EXT_STRONGSWAN
);
406 set_extension(ike_sa
, value
.u32
, EXT_EAP_ONLY_AUTHENTICATION
);
407 set_extension(ike_sa
, value
.u32
, EXT_MS_WINDOWS
);
408 set_extension(ike_sa
, value
.u32
, EXT_XAUTH
);
409 set_extension(ike_sa
, value
.u32
, EXT_DPD
);
412 set_condition(ike_sa
, value
.u32
, COND_NAT_ANY
);
413 set_condition(ike_sa
, value
.u32
, COND_NAT_HERE
);
414 set_condition(ike_sa
, value
.u32
, COND_NAT_THERE
);
415 set_condition(ike_sa
, value
.u32
, COND_NAT_FAKE
);
416 set_condition(ike_sa
, value
.u32
, COND_EAP_AUTHENTICATED
);
417 set_condition(ike_sa
, value
.u32
, COND_CERTREQ_SEEN
);
418 set_condition(ike_sa
, value
.u32
, COND_ORIGINAL_INITIATOR
);
419 set_condition(ike_sa
, value
.u32
, COND_STALE
);
420 set_condition(ike_sa
, value
.u32
, COND_INIT_CONTACT_SEEN
);
421 set_condition(ike_sa
, value
.u32
, COND_XAUTH_AUTHENTICATED
);
427 enumerator
->destroy(enumerator
);
431 if (ike_sa
->get_state(ike_sa
) == IKE_CONNECTING
&&
432 ike_sa
->get_peer_cfg(ike_sa
))
434 DBG1(DBG_CFG
, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
435 ike_sa
->get_name(ike_sa
),
436 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
437 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
438 ike_sa
->set_state(ike_sa
, IKE_PASSIVE
);
442 enumerator_t
*pools
, *vips
;
446 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
449 pools
= peer_cfg
->create_pool_enumerator(peer_cfg
);
450 while (pools
->enumerate(pools
, &pool
))
452 vips
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, FALSE
);
453 while (vips
->enumerate(vips
, &vip
))
455 this->attr
->reserve(this->attr
, pool
, vip
);
459 pools
->destroy(pools
);
463 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
465 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
466 adopt_children_job_create(ike_sa
->get_id(ike_sa
)));
468 #endif /* USE_IKEV1 */
469 this->cache
->cache(this->cache
, ike_sa
, message
);
470 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
474 DBG1(DBG_CFG
, "passive HA IKE_SA to update not found");
475 message
->destroy(message
);
480 * Process messages of type IKE_MID_INITIATOR/RESPONDER
482 static void process_ike_mid(private_ha_dispatcher_t
*this,
483 ha_message_t
*message
, bool initiator
)
485 ha_message_attribute_t attribute
;
486 ha_message_value_t value
;
487 enumerator_t
*enumerator
;
488 ike_sa_t
*ike_sa
= NULL
;
491 enumerator
= message
->create_attribute_enumerator(message
);
492 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
497 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
507 enumerator
->destroy(enumerator
);
513 ike_sa
->set_message_id(ike_sa
, initiator
, mid
);
515 this->cache
->cache(this->cache
, ike_sa
, message
);
516 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
520 message
->destroy(message
);
525 * Process messages of type IKE_IV
527 static void process_ike_iv(private_ha_dispatcher_t
*this, ha_message_t
*message
)
529 ha_message_attribute_t attribute
;
530 ha_message_value_t value
;
531 enumerator_t
*enumerator
;
532 ike_sa_t
*ike_sa
= NULL
;
533 chunk_t iv
= chunk_empty
;
535 enumerator
= message
->create_attribute_enumerator(message
);
536 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
541 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
551 enumerator
->destroy(enumerator
);
555 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
561 keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
562 if (keymat
->update_iv(keymat
, 0, iv
))
564 keymat
->confirm_iv(keymat
, 0);
568 this->cache
->cache(this->cache
, ike_sa
, message
);
569 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
573 message
->destroy(message
);
578 * Process messages of type IKE_DELETE
580 static void process_ike_delete(private_ha_dispatcher_t
*this,
581 ha_message_t
*message
)
583 ha_message_attribute_t attribute
;
584 ha_message_value_t value
;
585 enumerator_t
*enumerator
;
586 ike_sa_t
*ike_sa
= NULL
;
588 enumerator
= message
->create_attribute_enumerator(message
);
589 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
594 ike_sa
= charon
->ike_sa_manager
->checkout(
595 charon
->ike_sa_manager
, value
.ike_sa_id
);
601 enumerator
->destroy(enumerator
);
604 this->cache
->cache(this->cache
, ike_sa
, message
);
605 charon
->ike_sa_manager
->checkin_and_destroy(
606 charon
->ike_sa_manager
, ike_sa
);
610 message
->destroy(message
);
615 * Lookup a child cfg from the peer cfg by name
617 static child_cfg_t
* find_child_cfg(ike_sa_t
*ike_sa
, char *name
)
619 peer_cfg_t
*peer_cfg
;
620 child_cfg_t
*current
, *found
= NULL
;
621 enumerator_t
*enumerator
;
623 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
626 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
627 while (enumerator
->enumerate(enumerator
, ¤t
))
629 if (streq(current
->get_name(current
), name
))
635 enumerator
->destroy(enumerator
);
641 * Process messages of type CHILD_ADD
643 static void process_child_add(private_ha_dispatcher_t
*this,
644 ha_message_t
*message
)
646 ha_message_attribute_t attribute
;
647 ha_message_value_t value
;
648 enumerator_t
*enumerator
;
649 ike_sa_t
*ike_sa
= NULL
;
650 char *config_name
= "";
651 child_cfg_t
*config
= NULL
;
652 child_sa_t
*child_sa
;
653 proposal_t
*proposal
;
654 bool initiator
= FALSE
, failed
= FALSE
, ok
= FALSE
;
655 u_int32_t inbound_spi
= 0, outbound_spi
= 0;
656 u_int16_t inbound_cpi
= 0, outbound_cpi
= 0;
657 u_int8_t mode
= MODE_TUNNEL
, ipcomp
= 0;
658 u_int16_t encr
= 0, integ
= 0, len
= 0;
659 u_int16_t esn
= NO_EXT_SEQ_NUMBERS
;
661 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
, secret
= chunk_empty
;
662 chunk_t encr_i
, integ_i
, encr_r
, integ_r
;
663 linked_list_t
*local_ts
, *remote_ts
;
664 diffie_hellman_t
*dh
= NULL
;
666 enumerator
= message
->create_attribute_enumerator(message
);
667 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
672 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
676 config_name
= value
.str
;
679 initiator
= value
.u8
;
682 inbound_spi
= value
.u32
;
684 case HA_OUTBOUND_SPI
:
685 outbound_spi
= value
.u32
;
688 inbound_cpi
= value
.u32
;
690 case HA_OUTBOUND_CPI
:
691 outbound_cpi
= value
.u32
;
702 case HA_ALG_ENCR_LEN
:
712 nonce_i
= value
.chunk
;
715 nonce_r
= value
.chunk
;
718 secret
= value
.chunk
;
724 enumerator
->destroy(enumerator
);
728 DBG1(DBG_CHD
, "IKE_SA for HA CHILD_SA not found");
729 message
->destroy(message
);
732 config
= find_child_cfg(ike_sa
, config_name
);
735 DBG1(DBG_CHD
, "HA is missing nodes child configuration");
736 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
737 message
->destroy(message
);
741 child_sa
= child_sa_create(ike_sa
->get_my_host(ike_sa
),
742 ike_sa
->get_other_host(ike_sa
), config
, 0,
743 ike_sa
->has_condition(ike_sa
, COND_NAT_ANY
),
745 child_sa
->set_mode(child_sa
, mode
);
746 child_sa
->set_protocol(child_sa
, PROTO_ESP
);
747 child_sa
->set_ipcomp(child_sa
, ipcomp
);
749 proposal
= proposal_create(PROTO_ESP
, 0);
752 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
756 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
758 proposal
->add_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
, esn
, 0);
761 dh
= ha_diffie_hellman_create(secret
, chunk_empty
);
763 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
765 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
767 ok
= keymat_v2
->derive_child_keys(keymat_v2
, proposal
, dh
,
768 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
770 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
772 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
773 u_int32_t spi_i
, spi_r
;
775 spi_i
= initiator ? inbound_spi
: outbound_spi
;
776 spi_r
= initiator ? outbound_spi
: inbound_spi
;
778 ok
= keymat_v1
->derive_child_keys(keymat_v1
, proposal
, dh
, spi_i
, spi_r
,
779 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
784 DBG1(DBG_CHD
, "HA CHILD_SA key derivation failed");
785 child_sa
->destroy(child_sa
);
786 proposal
->destroy(proposal
);
787 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
790 child_sa
->set_proposal(child_sa
, proposal
);
791 child_sa
->set_state(child_sa
, CHILD_INSTALLING
);
792 proposal
->destroy(proposal
);
794 /* TODO: Change CHILD_SA API to avoid cloning twice */
795 local_ts
= linked_list_create();
796 remote_ts
= linked_list_create();
797 enumerator
= message
->create_attribute_enumerator(message
);
798 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
803 local_ts
->insert_last(local_ts
, value
.ts
->clone(value
.ts
));
806 remote_ts
->insert_last(remote_ts
, value
.ts
->clone(value
.ts
));
812 enumerator
->destroy(enumerator
);
816 if (child_sa
->install(child_sa
, encr_r
, integ_r
, inbound_spi
,
817 inbound_cpi
, initiator
, TRUE
, TRUE
,
818 local_ts
, remote_ts
) != SUCCESS
||
819 child_sa
->install(child_sa
, encr_i
, integ_i
, outbound_spi
,
820 outbound_cpi
, initiator
, FALSE
, TRUE
,
821 local_ts
, remote_ts
) != SUCCESS
)
828 if (child_sa
->install(child_sa
, encr_i
, integ_i
, inbound_spi
,
829 inbound_cpi
, initiator
, TRUE
, TRUE
,
830 local_ts
, remote_ts
) != SUCCESS
||
831 child_sa
->install(child_sa
, encr_r
, integ_r
, outbound_spi
,
832 outbound_cpi
, initiator
, FALSE
, TRUE
,
833 local_ts
, remote_ts
) != SUCCESS
)
838 chunk_clear(&encr_i
);
839 chunk_clear(&integ_i
);
840 chunk_clear(&encr_r
);
841 chunk_clear(&integ_r
);
845 DBG1(DBG_CHD
, "HA CHILD_SA installation failed");
846 child_sa
->destroy(child_sa
);
847 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
848 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
849 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
850 message
->destroy(message
);
854 seg_i
= this->kernel
->get_segment_spi(this->kernel
,
855 ike_sa
->get_my_host(ike_sa
), inbound_spi
);
856 seg_o
= this->kernel
->get_segment_spi(this->kernel
,
857 ike_sa
->get_other_host(ike_sa
), outbound_spi
);
859 DBG1(DBG_CFG
, "installed HA CHILD_SA %s{%d} %#R === %#R "
860 "(segment in: %d%s, out: %d%s)", child_sa
->get_name(child_sa
),
861 child_sa
->get_unique_id(child_sa
), local_ts
, remote_ts
,
862 seg_i
, this->segments
->is_active(this->segments
, seg_i
) ?
"*" : "",
863 seg_o
, this->segments
->is_active(this->segments
, seg_o
) ?
"*" : "");
864 child_sa
->add_policies(child_sa
, local_ts
, remote_ts
);
865 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
866 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
868 child_sa
->set_state(child_sa
, CHILD_INSTALLED
);
869 ike_sa
->add_child_sa(ike_sa
, child_sa
);
870 message
->destroy(message
);
871 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
875 * Process messages of type CHILD_DELETE
877 static void process_child_delete(private_ha_dispatcher_t
*this,
878 ha_message_t
*message
)
880 ha_message_attribute_t attribute
;
881 ha_message_value_t value
;
882 enumerator_t
*enumerator
;
883 ike_sa_t
*ike_sa
= NULL
;
884 child_sa_t
*child_sa
;
887 enumerator
= message
->create_attribute_enumerator(message
);
888 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
893 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
903 enumerator
->destroy(enumerator
);
907 child_sa
= ike_sa
->get_child_sa(ike_sa
, PROTO_ESP
, spi
, TRUE
);
910 ike_sa
->destroy_child_sa(ike_sa
, PROTO_ESP
, spi
);
912 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
914 message
->destroy(message
);
918 * Process messages of type SEGMENT_TAKE/DROP
920 static void process_segment(private_ha_dispatcher_t
*this,
921 ha_message_t
*message
, bool take
)
923 ha_message_attribute_t attribute
;
924 ha_message_value_t value
;
925 enumerator_t
*enumerator
;
927 enumerator
= message
->create_attribute_enumerator(message
);
928 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
935 DBG1(DBG_CFG
, "remote node takes segment %d", value
.u16
);
936 this->segments
->deactivate(this->segments
, value
.u16
, FALSE
);
940 DBG1(DBG_CFG
, "remote node drops segment %d", value
.u16
);
941 this->segments
->activate(this->segments
, value
.u16
, FALSE
);
948 enumerator
->destroy(enumerator
);
949 message
->destroy(message
);
953 * Process messages of type STATUS
955 static void process_status(private_ha_dispatcher_t
*this,
956 ha_message_t
*message
)
958 ha_message_attribute_t attribute
;
959 ha_message_value_t value
;
960 enumerator_t
*enumerator
;
961 segment_mask_t mask
= 0;
963 enumerator
= message
->create_attribute_enumerator(message
);
964 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
969 mask
|= SEGMENTS_BIT(value
.u16
);
975 enumerator
->destroy(enumerator
);
977 this->segments
->handle_status(this->segments
, mask
);
978 message
->destroy(message
);
982 * Process messages of type RESYNC
984 static void process_resync(private_ha_dispatcher_t
*this,
985 ha_message_t
*message
)
987 ha_message_attribute_t attribute
;
988 ha_message_value_t value
;
989 enumerator_t
*enumerator
;
991 enumerator
= message
->create_attribute_enumerator(message
);
992 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
997 this->cache
->resync(this->cache
, value
.u16
);
1003 enumerator
->destroy(enumerator
);
1004 message
->destroy(message
);
1008 * Dispatcher job function
1010 static job_requeue_t
dispatch(private_ha_dispatcher_t
*this)
1012 ha_message_t
*message
;
1013 ha_message_type_t type
;
1015 message
= this->socket
->pull(this->socket
);
1016 type
= message
->get_type(message
);
1017 if (type
!= HA_STATUS
)
1019 DBG2(DBG_CFG
, "received HA %N message", ha_message_type_names
,
1020 message
->get_type(message
));
1025 process_ike_add(this, message
);
1028 process_ike_update(this, message
);
1030 case HA_IKE_MID_INITIATOR
:
1031 process_ike_mid(this, message
, TRUE
);
1033 case HA_IKE_MID_RESPONDER
:
1034 process_ike_mid(this, message
, FALSE
);
1037 process_ike_iv(this, message
);
1040 process_ike_delete(this, message
);
1043 process_child_add(this, message
);
1045 case HA_CHILD_DELETE
:
1046 process_child_delete(this, message
);
1048 case HA_SEGMENT_DROP
:
1049 process_segment(this, message
, FALSE
);
1051 case HA_SEGMENT_TAKE
:
1052 process_segment(this, message
, TRUE
);
1055 process_status(this, message
);
1058 process_resync(this, message
);
1061 DBG1(DBG_CFG
, "received unknown HA message type %d", type
);
1062 message
->destroy(message
);
1065 return JOB_REQUEUE_DIRECT
;
1068 METHOD(ha_dispatcher_t
, destroy
, void,
1069 private_ha_dispatcher_t
*this)
1077 ha_dispatcher_t
*ha_dispatcher_create(ha_socket_t
*socket
,
1078 ha_segments_t
*segments
, ha_cache_t
*cache
,
1079 ha_kernel_t
*kernel
, ha_attribute_t
*attr
)
1081 private_ha_dispatcher_t
*this;
1086 .destroy
= _destroy
,
1089 .segments
= segments
,
1094 lib
->processor
->queue_job(lib
->processor
,
1095 (job_t
*)callback_job_create_with_prio((callback_job_cb_t
)dispatch
, this,
1096 NULL
, (callback_job_cancel_t
)return_false
, JOB_PRIO_CRITICAL
));
1098 return &this->public;