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
;
69 * DH implementation for HA synced DH values
71 struct ha_diffie_hellman_t
{
74 * Implements diffie_hellman_t
89 METHOD(diffie_hellman_t
, dh_get_shared_secret
, status_t
,
90 ha_diffie_hellman_t
*this, chunk_t
*secret
)
92 *secret
= chunk_clone(this->secret
);
96 METHOD(diffie_hellman_t
, dh_get_my_public_value
, void,
97 ha_diffie_hellman_t
*this, chunk_t
*value
)
99 *value
= chunk_clone(this->pub
);
102 METHOD(diffie_hellman_t
, dh_destroy
, void,
103 ha_diffie_hellman_t
*this)
109 * Create a HA synced DH implementation
111 static diffie_hellman_t
*ha_diffie_hellman_create(chunk_t secret
, chunk_t pub
)
113 ha_diffie_hellman_t
*this;
117 .get_shared_secret
= _dh_get_shared_secret
,
118 .get_my_public_value
= _dh_get_my_public_value
,
119 .destroy
= _dh_destroy
,
129 * Process messages of type IKE_ADD
131 static void process_ike_add(private_ha_dispatcher_t
*this, ha_message_t
*message
)
133 ha_message_attribute_t attribute
;
134 ha_message_value_t value
;
135 enumerator_t
*enumerator
;
136 ike_sa_t
*ike_sa
= NULL
, *old_sa
= NULL
;
137 ike_version_t version
= IKEV2
;
138 u_int16_t encr
= 0, len
= 0, integ
= 0, prf
= 0, old_prf
= PRF_UNDEFINED
;
139 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
;
140 chunk_t secret
= chunk_empty
, old_skd
= chunk_empty
;
141 chunk_t dh_local
= chunk_empty
, dh_remote
= chunk_empty
, psk
= chunk_empty
;
144 enumerator
= message
->create_attribute_enumerator(message
);
145 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
150 ike_sa
= ike_sa_create(value
.ike_sa_id
,
151 value
.ike_sa_id
->is_initiator(value
.ike_sa_id
), version
);
153 case HA_IKE_REKEY_ID
:
154 old_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
161 nonce_i
= value
.chunk
;
164 nonce_r
= value
.chunk
;
167 secret
= value
.chunk
;
170 dh_local
= value
.chunk
;
173 dh_remote
= value
.chunk
;
179 old_skd
= value
.chunk
;
184 case HA_ALG_ENCR_LEN
:
200 enumerator
->destroy(enumerator
);
204 proposal_t
*proposal
;
205 diffie_hellman_t
*dh
;
207 proposal
= proposal_create(PROTO_IKE
, 0);
210 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
214 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
218 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, prf
, 0);
220 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
221 dh
= ha_diffie_hellman_create(secret
, dh_local
);
222 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
224 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
226 ok
= keymat_v2
->derive_ike_keys(keymat_v2
, proposal
, dh
, nonce_i
,
227 nonce_r
, ike_sa
->get_id(ike_sa
), old_prf
, old_skd
);
229 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
231 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
232 shared_key_t
*shared
= NULL
;
233 auth_method_t method
= AUTH_RSA
;
238 shared
= shared_key_create(SHARED_IKE
, chunk_clone(psk
));
240 if (keymat_v1
->create_hasher(keymat_v1
, proposal
))
242 ok
= keymat_v1
->derive_ike_keys(keymat_v1
, proposal
,
243 dh
, dh_remote
, nonce_i
, nonce_r
,
244 ike_sa
->get_id(ike_sa
), method
, shared
);
253 peer_cfg_t
*peer_cfg
= old_sa
->get_peer_cfg(old_sa
);
257 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
258 ike_sa
->inherit(ike_sa
, old_sa
);
260 charon
->ike_sa_manager
->checkin_and_destroy(
261 charon
->ike_sa_manager
, old_sa
);
264 ike_sa
->set_state(ike_sa
, IKE_CONNECTING
);
265 ike_sa
->set_proposal(ike_sa
, proposal
);
266 this->cache
->cache(this->cache
, ike_sa
, message
);
268 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
272 DBG1(DBG_IKE
, "HA keymat derivation failed");
273 ike_sa
->destroy(ike_sa
);
275 charon
->bus
->set_sa(charon
->bus
, NULL
);
276 proposal
->destroy(proposal
);
280 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, old_sa
);
286 * Apply a condition flag to the IKE_SA if it is in set
288 static void set_condition(ike_sa_t
*ike_sa
, ike_condition_t set
,
289 ike_condition_t flag
)
291 ike_sa
->set_condition(ike_sa
, flag
, flag
& set
);
295 * Apply a extension flag to the IKE_SA if it is in set
297 static void set_extension(ike_sa_t
*ike_sa
, ike_extension_t set
,
298 ike_extension_t flag
)
302 ike_sa
->enable_extension(ike_sa
, flag
);
307 * Process messages of type IKE_UPDATE
309 static void process_ike_update(private_ha_dispatcher_t
*this,
310 ha_message_t
*message
)
312 ha_message_attribute_t attribute
;
313 ha_message_value_t value
;
314 enumerator_t
*enumerator
;
315 ike_sa_t
*ike_sa
= NULL
;
316 peer_cfg_t
*peer_cfg
= NULL
;
318 bool received_vip
= FALSE
, first_peer_addr
= TRUE
;
320 enumerator
= message
->create_attribute_enumerator(message
);
321 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
323 if (attribute
!= HA_IKE_ID
&& ike_sa
== NULL
)
325 /* must be first attribute */
331 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
335 ike_sa
->set_my_id(ike_sa
, value
.id
->clone(value
.id
));
338 ike_sa
->set_other_id(ike_sa
, value
.id
->clone(value
.id
));
340 case HA_REMOTE_EAP_ID
:
341 auth
= auth_cfg_create();
342 auth
->add(auth
, AUTH_RULE_EAP_IDENTITY
, value
.id
->clone(value
.id
));
343 ike_sa
->add_auth_cfg(ike_sa
, FALSE
, auth
);
346 ike_sa
->set_my_host(ike_sa
, value
.host
->clone(value
.host
));
349 ike_sa
->set_other_host(ike_sa
, value
.host
->clone(value
.host
));
352 ike_sa
->set_virtual_ip(ike_sa
, TRUE
, value
.host
);
355 ike_sa
->set_virtual_ip(ike_sa
, FALSE
, value
.host
);
361 ike_sa
->clear_peer_addresses(ike_sa
);
362 first_peer_addr
= FALSE
;
364 ike_sa
->add_peer_address(ike_sa
, value
.host
->clone(value
.host
));
367 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(
368 charon
->backends
, value
.str
);
371 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
372 peer_cfg
->destroy(peer_cfg
);
376 DBG1(DBG_IKE
, "HA is missing nodes peer configuration");
380 set_extension(ike_sa
, value
.u32
, EXT_NATT
);
381 set_extension(ike_sa
, value
.u32
, EXT_MOBIKE
);
382 set_extension(ike_sa
, value
.u32
, EXT_HASH_AND_URL
);
383 set_extension(ike_sa
, value
.u32
, EXT_MULTIPLE_AUTH
);
384 set_extension(ike_sa
, value
.u32
, EXT_STRONGSWAN
);
385 set_extension(ike_sa
, value
.u32
, EXT_EAP_ONLY_AUTHENTICATION
);
386 set_extension(ike_sa
, value
.u32
, EXT_MS_WINDOWS
);
387 set_extension(ike_sa
, value
.u32
, EXT_XAUTH
);
388 set_extension(ike_sa
, value
.u32
, EXT_DPD
);
391 set_condition(ike_sa
, value
.u32
, COND_NAT_ANY
);
392 set_condition(ike_sa
, value
.u32
, COND_NAT_HERE
);
393 set_condition(ike_sa
, value
.u32
, COND_NAT_THERE
);
394 set_condition(ike_sa
, value
.u32
, COND_NAT_FAKE
);
395 set_condition(ike_sa
, value
.u32
, COND_EAP_AUTHENTICATED
);
396 set_condition(ike_sa
, value
.u32
, COND_CERTREQ_SEEN
);
397 set_condition(ike_sa
, value
.u32
, COND_ORIGINAL_INITIATOR
);
398 set_condition(ike_sa
, value
.u32
, COND_STALE
);
399 set_condition(ike_sa
, value
.u32
, COND_INIT_CONTACT_SEEN
);
400 set_condition(ike_sa
, value
.u32
, COND_XAUTH_AUTHENTICATED
);
406 enumerator
->destroy(enumerator
);
410 if (ike_sa
->get_state(ike_sa
) == IKE_CONNECTING
&&
411 ike_sa
->get_peer_cfg(ike_sa
))
413 DBG1(DBG_CFG
, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
414 ike_sa
->get_name(ike_sa
),
415 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
416 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
417 ike_sa
->set_state(ike_sa
, IKE_PASSIVE
);
424 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
425 vip
= ike_sa
->get_virtual_ip(ike_sa
, FALSE
);
428 pool
= peer_cfg
->get_pool(peer_cfg
);
431 this->attr
->reserve(this->attr
, pool
, vip
);
435 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
437 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
438 adopt_children_job_create(ike_sa
->get_id(ike_sa
)));
440 this->cache
->cache(this->cache
, ike_sa
, message
);
441 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
445 DBG1(DBG_CFG
, "passive HA IKE_SA to update not found");
446 message
->destroy(message
);
451 * Process messages of type IKE_MID_INITIATOR/RESPONDER
453 static void process_ike_mid(private_ha_dispatcher_t
*this,
454 ha_message_t
*message
, bool initiator
)
456 ha_message_attribute_t attribute
;
457 ha_message_value_t value
;
458 enumerator_t
*enumerator
;
459 ike_sa_t
*ike_sa
= NULL
;
462 enumerator
= message
->create_attribute_enumerator(message
);
463 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
468 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
478 enumerator
->destroy(enumerator
);
484 ike_sa
->set_message_id(ike_sa
, initiator
, mid
);
486 this->cache
->cache(this->cache
, ike_sa
, message
);
487 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
491 message
->destroy(message
);
496 * Process messages of type IKE_IV
498 static void process_ike_iv(private_ha_dispatcher_t
*this, ha_message_t
*message
)
500 ha_message_attribute_t attribute
;
501 ha_message_value_t value
;
502 enumerator_t
*enumerator
;
503 ike_sa_t
*ike_sa
= NULL
;
504 chunk_t iv
= chunk_empty
;
506 enumerator
= message
->create_attribute_enumerator(message
);
507 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
512 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
522 enumerator
->destroy(enumerator
);
526 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
532 keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
533 keymat
->update_iv(keymat
, 0, iv
);
534 keymat
->confirm_iv(keymat
, 0);
537 this->cache
->cache(this->cache
, ike_sa
, message
);
538 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
542 message
->destroy(message
);
547 * Process messages of type IKE_DELETE
549 static void process_ike_delete(private_ha_dispatcher_t
*this,
550 ha_message_t
*message
)
552 ha_message_attribute_t attribute
;
553 ha_message_value_t value
;
554 enumerator_t
*enumerator
;
555 ike_sa_t
*ike_sa
= NULL
;
557 enumerator
= message
->create_attribute_enumerator(message
);
558 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
563 ike_sa
= charon
->ike_sa_manager
->checkout(
564 charon
->ike_sa_manager
, value
.ike_sa_id
);
570 enumerator
->destroy(enumerator
);
573 this->cache
->cache(this->cache
, ike_sa
, message
);
574 charon
->ike_sa_manager
->checkin_and_destroy(
575 charon
->ike_sa_manager
, ike_sa
);
579 message
->destroy(message
);
584 * Lookup a child cfg from the peer cfg by name
586 static child_cfg_t
* find_child_cfg(ike_sa_t
*ike_sa
, char *name
)
588 peer_cfg_t
*peer_cfg
;
589 child_cfg_t
*current
, *found
= NULL
;
590 enumerator_t
*enumerator
;
592 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
595 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
596 while (enumerator
->enumerate(enumerator
, ¤t
))
598 if (streq(current
->get_name(current
), name
))
604 enumerator
->destroy(enumerator
);
610 * Process messages of type CHILD_ADD
612 static void process_child_add(private_ha_dispatcher_t
*this,
613 ha_message_t
*message
)
615 ha_message_attribute_t attribute
;
616 ha_message_value_t value
;
617 enumerator_t
*enumerator
;
618 ike_sa_t
*ike_sa
= NULL
;
619 char *config_name
= "";
620 child_cfg_t
*config
= NULL
;
621 child_sa_t
*child_sa
;
622 proposal_t
*proposal
;
623 bool initiator
= FALSE
, failed
= FALSE
, ok
= FALSE
;
624 u_int32_t inbound_spi
= 0, outbound_spi
= 0;
625 u_int16_t inbound_cpi
= 0, outbound_cpi
= 0;
626 u_int8_t mode
= MODE_TUNNEL
, ipcomp
= 0;
627 u_int16_t encr
= ENCR_UNDEFINED
, integ
= AUTH_UNDEFINED
, len
= 0;
628 u_int16_t esn
= NO_EXT_SEQ_NUMBERS
;
630 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
, secret
= chunk_empty
;
631 chunk_t encr_i
, integ_i
, encr_r
, integ_r
;
632 linked_list_t
*local_ts
, *remote_ts
;
633 diffie_hellman_t
*dh
= NULL
;
635 enumerator
= message
->create_attribute_enumerator(message
);
636 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
641 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
645 config_name
= value
.str
;
648 initiator
= value
.u8
;
651 inbound_spi
= value
.u32
;
653 case HA_OUTBOUND_SPI
:
654 outbound_spi
= value
.u32
;
657 inbound_cpi
= value
.u32
;
659 case HA_OUTBOUND_CPI
:
660 outbound_cpi
= value
.u32
;
671 case HA_ALG_ENCR_LEN
:
681 nonce_i
= value
.chunk
;
684 nonce_r
= value
.chunk
;
687 secret
= value
.chunk
;
693 enumerator
->destroy(enumerator
);
697 DBG1(DBG_CHD
, "IKE_SA for HA CHILD_SA not found");
698 message
->destroy(message
);
701 config
= find_child_cfg(ike_sa
, config_name
);
704 DBG1(DBG_CHD
, "HA is missing nodes child configuration");
705 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
706 message
->destroy(message
);
710 child_sa
= child_sa_create(ike_sa
->get_my_host(ike_sa
),
711 ike_sa
->get_other_host(ike_sa
), config
, 0,
712 ike_sa
->has_condition(ike_sa
, COND_NAT_ANY
));
713 child_sa
->set_mode(child_sa
, mode
);
714 child_sa
->set_protocol(child_sa
, PROTO_ESP
);
715 child_sa
->set_ipcomp(child_sa
, ipcomp
);
717 proposal
= proposal_create(PROTO_ESP
, 0);
720 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
724 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
726 proposal
->add_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
, esn
, 0);
729 dh
= ha_diffie_hellman_create(secret
, chunk_empty
);
731 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
733 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
735 ok
= keymat_v2
->derive_child_keys(keymat_v2
, proposal
, dh
,
736 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
738 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
740 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
741 u_int32_t spi_i
, spi_r
;
743 spi_i
= initiator
? inbound_spi
: outbound_spi
;
744 spi_r
= initiator
? outbound_spi
: inbound_spi
;
746 ok
= keymat_v1
->derive_child_keys(keymat_v1
, proposal
, dh
, spi_i
, spi_r
,
747 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
752 DBG1(DBG_CHD
, "HA CHILD_SA key derivation failed");
753 child_sa
->destroy(child_sa
);
754 proposal
->destroy(proposal
);
755 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
758 child_sa
->set_proposal(child_sa
, proposal
);
759 child_sa
->set_state(child_sa
, CHILD_INSTALLING
);
760 proposal
->destroy(proposal
);
762 /* TODO: Change CHILD_SA API to avoid cloning twice */
763 local_ts
= linked_list_create();
764 remote_ts
= linked_list_create();
765 enumerator
= message
->create_attribute_enumerator(message
);
766 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
771 local_ts
->insert_last(local_ts
, value
.ts
->clone(value
.ts
));
774 remote_ts
->insert_last(remote_ts
, value
.ts
->clone(value
.ts
));
780 enumerator
->destroy(enumerator
);
784 if (child_sa
->install(child_sa
, encr_r
, integ_r
, inbound_spi
,
785 inbound_cpi
, TRUE
, TRUE
, local_ts
, remote_ts
) != SUCCESS
||
786 child_sa
->install(child_sa
, encr_i
, integ_i
, outbound_spi
,
787 outbound_cpi
, FALSE
, TRUE
, local_ts
, remote_ts
) != SUCCESS
)
794 if (child_sa
->install(child_sa
, encr_i
, integ_i
, inbound_spi
,
795 inbound_cpi
, TRUE
, TRUE
, local_ts
, remote_ts
) != SUCCESS
||
796 child_sa
->install(child_sa
, encr_r
, integ_r
, outbound_spi
,
797 outbound_cpi
, FALSE
, TRUE
, local_ts
, remote_ts
) != SUCCESS
)
802 chunk_clear(&encr_i
);
803 chunk_clear(&integ_i
);
804 chunk_clear(&encr_r
);
805 chunk_clear(&integ_r
);
809 DBG1(DBG_CHD
, "HA CHILD_SA installation failed");
810 child_sa
->destroy(child_sa
);
811 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
812 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
813 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
814 message
->destroy(message
);
818 seg_i
= this->kernel
->get_segment_spi(this->kernel
,
819 ike_sa
->get_my_host(ike_sa
), inbound_spi
);
820 seg_o
= this->kernel
->get_segment_spi(this->kernel
,
821 ike_sa
->get_other_host(ike_sa
), outbound_spi
);
823 DBG1(DBG_CFG
, "installed HA CHILD_SA %s{%d} %#R=== %#R "
824 "(segment in: %d%s, out: %d%s)", child_sa
->get_name(child_sa
),
825 child_sa
->get_reqid(child_sa
), local_ts
, remote_ts
,
826 seg_i
, this->segments
->is_active(this->segments
, seg_i
) ? "*" : "",
827 seg_o
, this->segments
->is_active(this->segments
, seg_o
) ? "*" : "");
828 child_sa
->add_policies(child_sa
, local_ts
, remote_ts
);
829 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
830 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
832 child_sa
->set_state(child_sa
, CHILD_INSTALLED
);
833 ike_sa
->add_child_sa(ike_sa
, child_sa
);
834 message
->destroy(message
);
835 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
839 * Process messages of type CHILD_DELETE
841 static void process_child_delete(private_ha_dispatcher_t
*this,
842 ha_message_t
*message
)
844 ha_message_attribute_t attribute
;
845 ha_message_value_t value
;
846 enumerator_t
*enumerator
;
847 ike_sa_t
*ike_sa
= NULL
;
848 child_sa_t
*child_sa
;
851 enumerator
= message
->create_attribute_enumerator(message
);
852 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
857 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
867 enumerator
->destroy(enumerator
);
871 child_sa
= ike_sa
->get_child_sa(ike_sa
, PROTO_ESP
, spi
, TRUE
);
874 ike_sa
->destroy_child_sa(ike_sa
, PROTO_ESP
, spi
);
876 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
878 message
->destroy(message
);
882 * Process messages of type SEGMENT_TAKE/DROP
884 static void process_segment(private_ha_dispatcher_t
*this,
885 ha_message_t
*message
, bool take
)
887 ha_message_attribute_t attribute
;
888 ha_message_value_t value
;
889 enumerator_t
*enumerator
;
891 enumerator
= message
->create_attribute_enumerator(message
);
892 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
899 DBG1(DBG_CFG
, "remote node takes segment %d", value
.u16
);
900 this->segments
->deactivate(this->segments
, value
.u16
, FALSE
);
904 DBG1(DBG_CFG
, "remote node drops segment %d", value
.u16
);
905 this->segments
->activate(this->segments
, value
.u16
, FALSE
);
912 enumerator
->destroy(enumerator
);
913 message
->destroy(message
);
917 * Process messages of type STATUS
919 static void process_status(private_ha_dispatcher_t
*this,
920 ha_message_t
*message
)
922 ha_message_attribute_t attribute
;
923 ha_message_value_t value
;
924 enumerator_t
*enumerator
;
925 segment_mask_t mask
= 0;
927 enumerator
= message
->create_attribute_enumerator(message
);
928 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
933 mask
|= SEGMENTS_BIT(value
.u16
);
939 enumerator
->destroy(enumerator
);
941 this->segments
->handle_status(this->segments
, mask
);
942 message
->destroy(message
);
946 * Process messages of type RESYNC
948 static void process_resync(private_ha_dispatcher_t
*this,
949 ha_message_t
*message
)
951 ha_message_attribute_t attribute
;
952 ha_message_value_t value
;
953 enumerator_t
*enumerator
;
955 enumerator
= message
->create_attribute_enumerator(message
);
956 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
961 this->cache
->resync(this->cache
, value
.u16
);
967 enumerator
->destroy(enumerator
);
968 message
->destroy(message
);
972 * Dispatcher job function
974 static job_requeue_t
dispatch(private_ha_dispatcher_t
*this)
976 ha_message_t
*message
;
977 ha_message_type_t type
;
979 message
= this->socket
->pull(this->socket
);
980 type
= message
->get_type(message
);
981 if (type
!= HA_STATUS
)
983 DBG2(DBG_CFG
, "received HA %N message", ha_message_type_names
,
984 message
->get_type(message
));
989 process_ike_add(this, message
);
992 process_ike_update(this, message
);
994 case HA_IKE_MID_INITIATOR
:
995 process_ike_mid(this, message
, TRUE
);
997 case HA_IKE_MID_RESPONDER
:
998 process_ike_mid(this, message
, FALSE
);
1001 process_ike_iv(this, message
);
1004 process_ike_delete(this, message
);
1007 process_child_add(this, message
);
1009 case HA_CHILD_DELETE
:
1010 process_child_delete(this, message
);
1012 case HA_SEGMENT_DROP
:
1013 process_segment(this, message
, FALSE
);
1015 case HA_SEGMENT_TAKE
:
1016 process_segment(this, message
, TRUE
);
1019 process_status(this, message
);
1022 process_resync(this, message
);
1025 DBG1(DBG_CFG
, "received unknown HA message type %d", type
);
1026 message
->destroy(message
);
1029 return JOB_REQUEUE_DIRECT
;
1032 METHOD(ha_dispatcher_t
, destroy
, void,
1033 private_ha_dispatcher_t
*this)
1035 this->job
->cancel(this->job
);
1042 ha_dispatcher_t
*ha_dispatcher_create(ha_socket_t
*socket
,
1043 ha_segments_t
*segments
, ha_cache_t
*cache
,
1044 ha_kernel_t
*kernel
, ha_attribute_t
*attr
)
1046 private_ha_dispatcher_t
*this;
1051 .destroy
= _destroy
,
1054 .segments
= segments
,
1059 this->job
= callback_job_create_with_prio((callback_job_cb_t
)dispatch
,
1060 this, NULL
, NULL
, JOB_PRIO_CRITICAL
);
1061 lib
->processor
->queue_job(lib
->processor
, (job_t
*)this->job
);
1063 return &this->public;