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
, status_t
,
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
, void,
92 ha_diffie_hellman_t
*this, chunk_t
*value
)
94 *value
= chunk_clone(this->pub
);
97 METHOD(diffie_hellman_t
, dh_destroy
, void,
98 ha_diffie_hellman_t
*this)
104 * Create a HA synced DH implementation
106 static diffie_hellman_t
*ha_diffie_hellman_create(chunk_t secret
, chunk_t pub
)
108 ha_diffie_hellman_t
*this;
112 .get_shared_secret
= _dh_get_shared_secret
,
113 .get_my_public_value
= _dh_get_my_public_value
,
114 .destroy
= _dh_destroy
,
124 * Process messages of type IKE_ADD
126 static void process_ike_add(private_ha_dispatcher_t
*this, ha_message_t
*message
)
128 ha_message_attribute_t attribute
;
129 ha_message_value_t value
;
130 enumerator_t
*enumerator
;
131 ike_sa_t
*ike_sa
= NULL
, *old_sa
= NULL
;
132 ike_version_t version
= IKEV2
;
133 u_int16_t encr
= 0, len
= 0, integ
= 0, prf
= 0, old_prf
= PRF_UNDEFINED
;
134 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
;
135 chunk_t secret
= chunk_empty
, old_skd
= chunk_empty
;
136 chunk_t dh_local
= chunk_empty
, dh_remote
= chunk_empty
, psk
= chunk_empty
;
139 enumerator
= message
->create_attribute_enumerator(message
);
140 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
145 ike_sa
= ike_sa_create(value
.ike_sa_id
,
146 value
.ike_sa_id
->is_initiator(value
.ike_sa_id
), version
);
148 case HA_IKE_REKEY_ID
:
149 old_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
156 nonce_i
= value
.chunk
;
159 nonce_r
= value
.chunk
;
162 secret
= value
.chunk
;
165 dh_local
= value
.chunk
;
168 dh_remote
= value
.chunk
;
174 old_skd
= value
.chunk
;
179 case HA_ALG_ENCR_LEN
:
195 enumerator
->destroy(enumerator
);
199 proposal_t
*proposal
;
200 diffie_hellman_t
*dh
;
202 proposal
= proposal_create(PROTO_IKE
, 0);
205 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
209 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
213 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
, prf
, 0);
215 charon
->bus
->set_sa(charon
->bus
, ike_sa
);
216 dh
= ha_diffie_hellman_create(secret
, dh_local
);
217 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
219 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
221 ok
= keymat_v2
->derive_ike_keys(keymat_v2
, proposal
, dh
, nonce_i
,
222 nonce_r
, ike_sa
->get_id(ike_sa
), old_prf
, old_skd
);
224 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
226 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
227 shared_key_t
*shared
= NULL
;
228 auth_method_t method
= AUTH_RSA
;
233 shared
= shared_key_create(SHARED_IKE
, chunk_clone(psk
));
235 if (keymat_v1
->create_hasher(keymat_v1
, proposal
))
237 ok
= keymat_v1
->derive_ike_keys(keymat_v1
, proposal
,
238 dh
, dh_remote
, nonce_i
, nonce_r
,
239 ike_sa
->get_id(ike_sa
), method
, shared
);
248 ike_sa
->inherit_pre(ike_sa
, old_sa
);
249 ike_sa
->inherit_post(ike_sa
, old_sa
);
250 charon
->ike_sa_manager
->checkin_and_destroy(
251 charon
->ike_sa_manager
, old_sa
);
254 ike_sa
->set_state(ike_sa
, IKE_CONNECTING
);
255 ike_sa
->set_proposal(ike_sa
, proposal
);
256 this->cache
->cache(this->cache
, ike_sa
, message
);
258 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
262 DBG1(DBG_IKE
, "HA keymat derivation failed");
263 ike_sa
->destroy(ike_sa
);
265 charon
->bus
->set_sa(charon
->bus
, NULL
);
266 proposal
->destroy(proposal
);
270 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, old_sa
);
276 * Apply a condition flag to the IKE_SA if it is in set
278 static void set_condition(ike_sa_t
*ike_sa
, ike_condition_t set
,
279 ike_condition_t flag
)
281 ike_sa
->set_condition(ike_sa
, flag
, flag
& set
);
285 * Apply a extension flag to the IKE_SA if it is in set
287 static void set_extension(ike_sa_t
*ike_sa
, ike_extension_t set
,
288 ike_extension_t flag
)
292 ike_sa
->enable_extension(ike_sa
, flag
);
297 * Process messages of type IKE_UPDATE
299 static void process_ike_update(private_ha_dispatcher_t
*this,
300 ha_message_t
*message
)
302 ha_message_attribute_t attribute
;
303 ha_message_value_t value
;
304 enumerator_t
*enumerator
;
305 ike_sa_t
*ike_sa
= NULL
;
306 peer_cfg_t
*peer_cfg
= NULL
;
308 bool received_vip
= FALSE
, first_local_vip
= TRUE
, first_peer_addr
= TRUE
;
310 enumerator
= message
->create_attribute_enumerator(message
);
311 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
313 if (attribute
!= HA_IKE_ID
&& ike_sa
== NULL
)
315 /* must be first attribute */
321 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
325 ike_sa
->set_my_id(ike_sa
, value
.id
->clone(value
.id
));
328 ike_sa
->set_other_id(ike_sa
, value
.id
->clone(value
.id
));
330 case HA_REMOTE_EAP_ID
:
331 auth
= auth_cfg_create();
332 auth
->add(auth
, AUTH_RULE_EAP_IDENTITY
, value
.id
->clone(value
.id
));
333 ike_sa
->add_auth_cfg(ike_sa
, FALSE
, auth
);
336 ike_sa
->set_my_host(ike_sa
, value
.host
->clone(value
.host
));
339 ike_sa
->set_other_host(ike_sa
, value
.host
->clone(value
.host
));
344 ike_sa
->clear_virtual_ips(ike_sa
, TRUE
);
345 first_local_vip
= FALSE
;
347 ike_sa
->add_virtual_ip(ike_sa
, TRUE
, value
.host
);
352 ike_sa
->clear_virtual_ips(ike_sa
, FALSE
);
354 ike_sa
->add_virtual_ip(ike_sa
, FALSE
, value
.host
);
360 ike_sa
->clear_peer_addresses(ike_sa
);
361 first_peer_addr
= FALSE
;
363 ike_sa
->add_peer_address(ike_sa
, value
.host
->clone(value
.host
));
366 peer_cfg
= charon
->backends
->get_peer_cfg_by_name(
367 charon
->backends
, value
.str
);
370 ike_sa
->set_peer_cfg(ike_sa
, peer_cfg
);
371 peer_cfg
->destroy(peer_cfg
);
375 DBG1(DBG_IKE
, "HA is missing nodes peer configuration");
379 set_extension(ike_sa
, value
.u32
, EXT_NATT
);
380 set_extension(ike_sa
, value
.u32
, EXT_MOBIKE
);
381 set_extension(ike_sa
, value
.u32
, EXT_HASH_AND_URL
);
382 set_extension(ike_sa
, value
.u32
, EXT_MULTIPLE_AUTH
);
383 set_extension(ike_sa
, value
.u32
, EXT_STRONGSWAN
);
384 set_extension(ike_sa
, value
.u32
, EXT_EAP_ONLY_AUTHENTICATION
);
385 set_extension(ike_sa
, value
.u32
, EXT_MS_WINDOWS
);
386 set_extension(ike_sa
, value
.u32
, EXT_XAUTH
);
387 set_extension(ike_sa
, value
.u32
, EXT_DPD
);
390 set_condition(ike_sa
, value
.u32
, COND_NAT_ANY
);
391 set_condition(ike_sa
, value
.u32
, COND_NAT_HERE
);
392 set_condition(ike_sa
, value
.u32
, COND_NAT_THERE
);
393 set_condition(ike_sa
, value
.u32
, COND_NAT_FAKE
);
394 set_condition(ike_sa
, value
.u32
, COND_EAP_AUTHENTICATED
);
395 set_condition(ike_sa
, value
.u32
, COND_CERTREQ_SEEN
);
396 set_condition(ike_sa
, value
.u32
, COND_ORIGINAL_INITIATOR
);
397 set_condition(ike_sa
, value
.u32
, COND_STALE
);
398 set_condition(ike_sa
, value
.u32
, COND_INIT_CONTACT_SEEN
);
399 set_condition(ike_sa
, value
.u32
, COND_XAUTH_AUTHENTICATED
);
405 enumerator
->destroy(enumerator
);
409 if (ike_sa
->get_state(ike_sa
) == IKE_CONNECTING
&&
410 ike_sa
->get_peer_cfg(ike_sa
))
412 DBG1(DBG_CFG
, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
413 ike_sa
->get_name(ike_sa
),
414 ike_sa
->get_my_host(ike_sa
), ike_sa
->get_my_id(ike_sa
),
415 ike_sa
->get_other_host(ike_sa
), ike_sa
->get_other_id(ike_sa
));
416 ike_sa
->set_state(ike_sa
, IKE_PASSIVE
);
420 enumerator_t
*pools
, *vips
;
424 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
427 pools
= peer_cfg
->create_pool_enumerator(peer_cfg
);
428 while (pools
->enumerate(pools
, &pool
))
430 vips
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, FALSE
);
431 while (vips
->enumerate(vips
, &vip
))
433 this->attr
->reserve(this->attr
, pool
, vip
);
437 pools
->destroy(pools
);
441 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
443 lib
->processor
->queue_job(lib
->processor
, (job_t
*)
444 adopt_children_job_create(ike_sa
->get_id(ike_sa
)));
446 #endif /* USE_IKEV1 */
447 this->cache
->cache(this->cache
, ike_sa
, message
);
448 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
452 DBG1(DBG_CFG
, "passive HA IKE_SA to update not found");
453 message
->destroy(message
);
458 * Process messages of type IKE_MID_INITIATOR/RESPONDER
460 static void process_ike_mid(private_ha_dispatcher_t
*this,
461 ha_message_t
*message
, bool initiator
)
463 ha_message_attribute_t attribute
;
464 ha_message_value_t value
;
465 enumerator_t
*enumerator
;
466 ike_sa_t
*ike_sa
= NULL
;
469 enumerator
= message
->create_attribute_enumerator(message
);
470 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
475 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
485 enumerator
->destroy(enumerator
);
491 ike_sa
->set_message_id(ike_sa
, initiator
, mid
);
493 this->cache
->cache(this->cache
, ike_sa
, message
);
494 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
498 message
->destroy(message
);
503 * Process messages of type IKE_IV
505 static void process_ike_iv(private_ha_dispatcher_t
*this, ha_message_t
*message
)
507 ha_message_attribute_t attribute
;
508 ha_message_value_t value
;
509 enumerator_t
*enumerator
;
510 ike_sa_t
*ike_sa
= NULL
;
511 chunk_t iv
= chunk_empty
;
513 enumerator
= message
->create_attribute_enumerator(message
);
514 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
519 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
529 enumerator
->destroy(enumerator
);
533 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
539 keymat
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
540 if (keymat
->update_iv(keymat
, 0, iv
))
542 keymat
->confirm_iv(keymat
, 0);
546 this->cache
->cache(this->cache
, ike_sa
, message
);
547 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
551 message
->destroy(message
);
556 * Process messages of type IKE_DELETE
558 static void process_ike_delete(private_ha_dispatcher_t
*this,
559 ha_message_t
*message
)
561 ha_message_attribute_t attribute
;
562 ha_message_value_t value
;
563 enumerator_t
*enumerator
;
564 ike_sa_t
*ike_sa
= NULL
;
566 enumerator
= message
->create_attribute_enumerator(message
);
567 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
572 ike_sa
= charon
->ike_sa_manager
->checkout(
573 charon
->ike_sa_manager
, value
.ike_sa_id
);
579 enumerator
->destroy(enumerator
);
582 this->cache
->cache(this->cache
, ike_sa
, message
);
583 charon
->ike_sa_manager
->checkin_and_destroy(
584 charon
->ike_sa_manager
, ike_sa
);
588 message
->destroy(message
);
593 * Lookup a child cfg from the peer cfg by name
595 static child_cfg_t
* find_child_cfg(ike_sa_t
*ike_sa
, char *name
)
597 peer_cfg_t
*peer_cfg
;
598 child_cfg_t
*current
, *found
= NULL
;
599 enumerator_t
*enumerator
;
601 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
604 enumerator
= peer_cfg
->create_child_cfg_enumerator(peer_cfg
);
605 while (enumerator
->enumerate(enumerator
, ¤t
))
607 if (streq(current
->get_name(current
), name
))
613 enumerator
->destroy(enumerator
);
619 * Process messages of type CHILD_ADD
621 static void process_child_add(private_ha_dispatcher_t
*this,
622 ha_message_t
*message
)
624 ha_message_attribute_t attribute
;
625 ha_message_value_t value
;
626 enumerator_t
*enumerator
;
627 ike_sa_t
*ike_sa
= NULL
;
628 char *config_name
= "";
629 child_cfg_t
*config
= NULL
;
630 child_sa_t
*child_sa
;
631 proposal_t
*proposal
;
632 bool initiator
= FALSE
, failed
= FALSE
, ok
= FALSE
;
633 u_int32_t inbound_spi
= 0, outbound_spi
= 0;
634 u_int16_t inbound_cpi
= 0, outbound_cpi
= 0;
635 u_int8_t mode
= MODE_TUNNEL
, ipcomp
= 0;
636 u_int16_t encr
= ENCR_UNDEFINED
, integ
= AUTH_UNDEFINED
, len
= 0;
637 u_int16_t esn
= NO_EXT_SEQ_NUMBERS
;
639 chunk_t nonce_i
= chunk_empty
, nonce_r
= chunk_empty
, secret
= chunk_empty
;
640 chunk_t encr_i
, integ_i
, encr_r
, integ_r
;
641 linked_list_t
*local_ts
, *remote_ts
;
642 diffie_hellman_t
*dh
= NULL
;
644 enumerator
= message
->create_attribute_enumerator(message
);
645 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
650 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
654 config_name
= value
.str
;
657 initiator
= value
.u8
;
660 inbound_spi
= value
.u32
;
662 case HA_OUTBOUND_SPI
:
663 outbound_spi
= value
.u32
;
666 inbound_cpi
= value
.u32
;
668 case HA_OUTBOUND_CPI
:
669 outbound_cpi
= value
.u32
;
680 case HA_ALG_ENCR_LEN
:
690 nonce_i
= value
.chunk
;
693 nonce_r
= value
.chunk
;
696 secret
= value
.chunk
;
702 enumerator
->destroy(enumerator
);
706 DBG1(DBG_CHD
, "IKE_SA for HA CHILD_SA not found");
707 message
->destroy(message
);
710 config
= find_child_cfg(ike_sa
, config_name
);
713 DBG1(DBG_CHD
, "HA is missing nodes child configuration");
714 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
715 message
->destroy(message
);
719 child_sa
= child_sa_create(ike_sa
->get_my_host(ike_sa
),
720 ike_sa
->get_other_host(ike_sa
), config
, 0,
721 ike_sa
->has_condition(ike_sa
, COND_NAT_ANY
),
723 child_sa
->set_mode(child_sa
, mode
);
724 child_sa
->set_protocol(child_sa
, PROTO_ESP
);
725 child_sa
->set_ipcomp(child_sa
, ipcomp
);
727 proposal
= proposal_create(PROTO_ESP
, 0);
730 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
, integ
, 0);
734 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, len
);
736 proposal
->add_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
, esn
, 0);
739 dh
= ha_diffie_hellman_create(secret
, chunk_empty
);
741 if (ike_sa
->get_version(ike_sa
) == IKEV2
)
743 keymat_v2_t
*keymat_v2
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
745 ok
= keymat_v2
->derive_child_keys(keymat_v2
, proposal
, dh
,
746 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
748 if (ike_sa
->get_version(ike_sa
) == IKEV1
)
750 keymat_v1_t
*keymat_v1
= (keymat_v1_t
*)ike_sa
->get_keymat(ike_sa
);
751 u_int32_t spi_i
, spi_r
;
753 spi_i
= initiator ? inbound_spi
: outbound_spi
;
754 spi_r
= initiator ? outbound_spi
: inbound_spi
;
756 ok
= keymat_v1
->derive_child_keys(keymat_v1
, proposal
, dh
, spi_i
, spi_r
,
757 nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
);
762 DBG1(DBG_CHD
, "HA CHILD_SA key derivation failed");
763 child_sa
->destroy(child_sa
);
764 proposal
->destroy(proposal
);
765 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
768 child_sa
->set_proposal(child_sa
, proposal
);
769 child_sa
->set_state(child_sa
, CHILD_INSTALLING
);
770 proposal
->destroy(proposal
);
772 /* TODO: Change CHILD_SA API to avoid cloning twice */
773 local_ts
= linked_list_create();
774 remote_ts
= linked_list_create();
775 enumerator
= message
->create_attribute_enumerator(message
);
776 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
781 local_ts
->insert_last(local_ts
, value
.ts
->clone(value
.ts
));
784 remote_ts
->insert_last(remote_ts
, value
.ts
->clone(value
.ts
));
790 enumerator
->destroy(enumerator
);
794 if (child_sa
->install(child_sa
, encr_r
, integ_r
, inbound_spi
,
795 inbound_cpi
, initiator
, FALSE
, TRUE
,
796 local_ts
, remote_ts
) != SUCCESS
||
797 child_sa
->install(child_sa
, encr_i
, integ_i
, outbound_spi
,
798 outbound_cpi
, initiator
, FALSE
, TRUE
,
799 local_ts
, remote_ts
) != SUCCESS
)
806 if (child_sa
->install(child_sa
, encr_i
, integ_i
, inbound_spi
,
807 inbound_cpi
, initiator
, FALSE
, TRUE
,
808 local_ts
, remote_ts
) != SUCCESS
||
809 child_sa
->install(child_sa
, encr_r
, integ_r
, outbound_spi
,
810 outbound_cpi
, initiator
, FALSE
, TRUE
,
811 local_ts
, remote_ts
) != SUCCESS
)
816 chunk_clear(&encr_i
);
817 chunk_clear(&integ_i
);
818 chunk_clear(&encr_r
);
819 chunk_clear(&integ_r
);
823 DBG1(DBG_CHD
, "HA CHILD_SA installation failed");
824 child_sa
->destroy(child_sa
);
825 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
826 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
827 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
828 message
->destroy(message
);
832 seg_i
= this->kernel
->get_segment_spi(this->kernel
,
833 ike_sa
->get_my_host(ike_sa
), inbound_spi
);
834 seg_o
= this->kernel
->get_segment_spi(this->kernel
,
835 ike_sa
->get_other_host(ike_sa
), outbound_spi
);
837 DBG1(DBG_CFG
, "installed HA CHILD_SA %s{%d} %#R=== %#R "
838 "(segment in: %d%s, out: %d%s)", child_sa
->get_name(child_sa
),
839 child_sa
->get_unique_id(child_sa
), local_ts
, remote_ts
,
840 seg_i
, this->segments
->is_active(this->segments
, seg_i
) ?
"*" : "",
841 seg_o
, this->segments
->is_active(this->segments
, seg_o
) ?
"*" : "");
842 child_sa
->add_policies(child_sa
, local_ts
, remote_ts
);
843 local_ts
->destroy_offset(local_ts
, offsetof(traffic_selector_t
, destroy
));
844 remote_ts
->destroy_offset(remote_ts
, offsetof(traffic_selector_t
, destroy
));
846 child_sa
->set_state(child_sa
, CHILD_INSTALLED
);
847 ike_sa
->add_child_sa(ike_sa
, child_sa
);
848 message
->destroy(message
);
849 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
853 * Process messages of type CHILD_DELETE
855 static void process_child_delete(private_ha_dispatcher_t
*this,
856 ha_message_t
*message
)
858 ha_message_attribute_t attribute
;
859 ha_message_value_t value
;
860 enumerator_t
*enumerator
;
861 ike_sa_t
*ike_sa
= NULL
;
862 child_sa_t
*child_sa
;
865 enumerator
= message
->create_attribute_enumerator(message
);
866 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
871 ike_sa
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
,
881 enumerator
->destroy(enumerator
);
885 child_sa
= ike_sa
->get_child_sa(ike_sa
, PROTO_ESP
, spi
, TRUE
);
888 ike_sa
->destroy_child_sa(ike_sa
, PROTO_ESP
, spi
);
890 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
892 message
->destroy(message
);
896 * Process messages of type SEGMENT_TAKE/DROP
898 static void process_segment(private_ha_dispatcher_t
*this,
899 ha_message_t
*message
, bool take
)
901 ha_message_attribute_t attribute
;
902 ha_message_value_t value
;
903 enumerator_t
*enumerator
;
905 enumerator
= message
->create_attribute_enumerator(message
);
906 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
913 DBG1(DBG_CFG
, "remote node takes segment %d", value
.u16
);
914 this->segments
->deactivate(this->segments
, value
.u16
, FALSE
);
918 DBG1(DBG_CFG
, "remote node drops segment %d", value
.u16
);
919 this->segments
->activate(this->segments
, value
.u16
, FALSE
);
926 enumerator
->destroy(enumerator
);
927 message
->destroy(message
);
931 * Process messages of type STATUS
933 static void process_status(private_ha_dispatcher_t
*this,
934 ha_message_t
*message
)
936 ha_message_attribute_t attribute
;
937 ha_message_value_t value
;
938 enumerator_t
*enumerator
;
939 segment_mask_t mask
= 0;
941 enumerator
= message
->create_attribute_enumerator(message
);
942 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
947 mask
|= SEGMENTS_BIT(value
.u16
);
953 enumerator
->destroy(enumerator
);
955 this->segments
->handle_status(this->segments
, mask
);
956 message
->destroy(message
);
960 * Process messages of type RESYNC
962 static void process_resync(private_ha_dispatcher_t
*this,
963 ha_message_t
*message
)
965 ha_message_attribute_t attribute
;
966 ha_message_value_t value
;
967 enumerator_t
*enumerator
;
969 enumerator
= message
->create_attribute_enumerator(message
);
970 while (enumerator
->enumerate(enumerator
, &attribute
, &value
))
975 this->cache
->resync(this->cache
, value
.u16
);
981 enumerator
->destroy(enumerator
);
982 message
->destroy(message
);
986 * Dispatcher job function
988 static job_requeue_t
dispatch(private_ha_dispatcher_t
*this)
990 ha_message_t
*message
;
991 ha_message_type_t type
;
993 message
= this->socket
->pull(this->socket
);
994 type
= message
->get_type(message
);
995 if (type
!= HA_STATUS
)
997 DBG2(DBG_CFG
, "received HA %N message", ha_message_type_names
,
998 message
->get_type(message
));
1003 process_ike_add(this, message
);
1006 process_ike_update(this, message
);
1008 case HA_IKE_MID_INITIATOR
:
1009 process_ike_mid(this, message
, TRUE
);
1011 case HA_IKE_MID_RESPONDER
:
1012 process_ike_mid(this, message
, FALSE
);
1015 process_ike_iv(this, message
);
1018 process_ike_delete(this, message
);
1021 process_child_add(this, message
);
1023 case HA_CHILD_DELETE
:
1024 process_child_delete(this, message
);
1026 case HA_SEGMENT_DROP
:
1027 process_segment(this, message
, FALSE
);
1029 case HA_SEGMENT_TAKE
:
1030 process_segment(this, message
, TRUE
);
1033 process_status(this, message
);
1036 process_resync(this, message
);
1039 DBG1(DBG_CFG
, "received unknown HA message type %d", type
);
1040 message
->destroy(message
);
1043 return JOB_REQUEUE_DIRECT
;
1046 METHOD(ha_dispatcher_t
, destroy
, void,
1047 private_ha_dispatcher_t
*this)
1055 ha_dispatcher_t
*ha_dispatcher_create(ha_socket_t
*socket
,
1056 ha_segments_t
*segments
, ha_cache_t
*cache
,
1057 ha_kernel_t
*kernel
, ha_attribute_t
*attr
)
1059 private_ha_dispatcher_t
*this;
1064 .destroy
= _destroy
,
1067 .segments
= segments
,
1072 lib
->processor
->queue_job(lib
->processor
,
1073 (job_t
*)callback_job_create_with_prio((callback_job_cb_t
)dispatch
, this,
1074 NULL
, (callback_job_cancel_t
)return_false
, JOB_PRIO_CRITICAL
));
1076 return &this->public;