summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/ha/ha_dispatcher.c
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2010-05-25 19:01:36 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2010-05-25 19:01:36 +0000
commit1ac70afcc1f7d6d2738a34308810719b0976d29f (patch)
tree805f6ce2a15d1a717781d7cbceac8408a74b6b0c /src/libcharon/plugins/ha/ha_dispatcher.c
parented7d79f96177044949744da10f4431c1d6242241 (diff)
downloadvyos-strongswan-1ac70afcc1f7d6d2738a34308810719b0976d29f.tar.gz
vyos-strongswan-1ac70afcc1f7d6d2738a34308810719b0976d29f.zip
[svn-upgrade] Integrating new upstream version, strongswan (4.4.0)
Diffstat (limited to 'src/libcharon/plugins/ha/ha_dispatcher.c')
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c737
1 files changed, 737 insertions, 0 deletions
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
new file mode 100644
index 000000000..7df2f1fa8
--- /dev/null
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -0,0 +1,737 @@
+/*
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "ha_dispatcher.h"
+
+#include <daemon.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_ha_dispatcher_t private_ha_dispatcher_t;
+
+/**
+ * Private data of an ha_dispatcher_t object.
+ */
+struct private_ha_dispatcher_t {
+
+ /**
+ * Public ha_dispatcher_t interface.
+ */
+ ha_dispatcher_t public;
+
+ /**
+ * socket to pull messages from
+ */
+ ha_socket_t *socket;
+
+ /**
+ * segments to control
+ */
+ ha_segments_t *segments;
+
+ /**
+ * Dispatcher job
+ */
+ callback_job_t *job;
+};
+
+/**
+ * Quick and dirty hack implementation of diffie_hellman_t.get_shared_secret
+ */
+static status_t get_shared_secret(diffie_hellman_t *this, chunk_t *secret)
+{
+ *secret = chunk_clone((*(chunk_t*)this->destroy));
+ return SUCCESS;
+}
+
+/**
+ * Process messages of type IKE_ADD
+ */
+static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL, *old_sa = NULL;
+ u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED;
+ chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
+ chunk_t secret = chunk_empty, old_skd = chunk_empty;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = ike_sa_create(value.ike_sa_id);
+ break;
+ case HA_IKE_REKEY_ID:
+ old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_NONCE_I:
+ nonce_i = value.chunk;
+ break;
+ case HA_NONCE_R:
+ nonce_r = value.chunk;
+ break;
+ case HA_SECRET:
+ secret = value.chunk;
+ break;
+ case HA_OLD_SKD:
+ old_skd = value.chunk;
+ break;
+ case HA_ALG_ENCR:
+ encr = value.u16;
+ break;
+ case HA_ALG_ENCR_LEN:
+ len = value.u16;
+ break;
+ case HA_ALG_INTEG:
+ integ = value.u16;
+ break;
+ case HA_ALG_PRF:
+ prf = value.u16;
+ break;
+ case HA_ALG_OLD_PRF:
+ old_prf = value.u16;
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ike_sa)
+ {
+ proposal_t *proposal;
+ keymat_t *keymat;
+ /* quick and dirty hack of a DH implementation ;-) */
+ diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
+ .destroy = (void*)&secret };
+
+ proposal = proposal_create(PROTO_IKE);
+ keymat = ike_sa->get_keymat(ike_sa);
+ if (integ)
+ {
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
+ }
+ if (encr)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
+ }
+ if (prf)
+ {
+ proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
+ }
+ charon->bus->set_sa(charon->bus, ike_sa);
+ if (keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r,
+ ike_sa->get_id(ike_sa), old_prf, old_skd))
+ {
+ if (old_sa)
+ {
+ peer_cfg_t *peer_cfg = old_sa->get_peer_cfg(old_sa);
+
+ if (peer_cfg)
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ ike_sa->inherit(ike_sa, old_sa);
+ }
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, old_sa);
+ old_sa = NULL;
+ }
+ ike_sa->set_state(ike_sa, IKE_CONNECTING);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "HA keymat derivation failed");
+ ike_sa->destroy(ike_sa);
+ }
+ charon->bus->set_sa(charon->bus, NULL);
+ proposal->destroy(proposal);
+ }
+ if (old_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa);
+ }
+}
+
+/**
+ * Apply a condition flag to the IKE_SA if it is in set
+ */
+static void set_condition(ike_sa_t *ike_sa, ike_condition_t set,
+ ike_condition_t flag)
+{
+ ike_sa->set_condition(ike_sa, flag, flag & set);
+}
+
+/**
+ * Apply a extension flag to the IKE_SA if it is in set
+ */
+static void set_extension(ike_sa_t *ike_sa, ike_extension_t set,
+ ike_extension_t flag)
+{
+ if (flag & set)
+ {
+ ike_sa->enable_extension(ike_sa, flag);
+ }
+}
+
+/**
+ * Process messages of type IKE_UPDATE
+ */
+static void process_ike_update(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+ peer_cfg_t *peer_cfg = NULL;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ if (attribute != HA_IKE_ID && ike_sa == NULL)
+ {
+ /* must be first attribute */
+ break;
+ }
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_LOCAL_ID:
+ ike_sa->set_my_id(ike_sa, value.id->clone(value.id));
+ break;
+ case HA_REMOTE_ID:
+ ike_sa->set_other_id(ike_sa, value.id->clone(value.id));
+ break;
+ case HA_LOCAL_ADDR:
+ ike_sa->set_my_host(ike_sa, value.host->clone(value.host));
+ break;
+ case HA_REMOTE_ADDR:
+ ike_sa->set_other_host(ike_sa, value.host->clone(value.host));
+ break;
+ case HA_LOCAL_VIP:
+ ike_sa->set_virtual_ip(ike_sa, TRUE, value.host);
+ break;
+ case HA_REMOTE_VIP:
+ ike_sa->set_virtual_ip(ike_sa, FALSE, value.host);
+ break;
+ case HA_ADDITIONAL_ADDR:
+ ike_sa->add_additional_address(ike_sa,
+ value.host->clone(value.host));
+ break;
+ case HA_CONFIG_NAME:
+ peer_cfg = charon->backends->get_peer_cfg_by_name(
+ charon->backends, value.str);
+ if (peer_cfg)
+ {
+ ike_sa->set_peer_cfg(ike_sa, peer_cfg);
+ peer_cfg->destroy(peer_cfg);
+ }
+ else
+ {
+ DBG1(DBG_IKE, "HA is missing nodes peer configuration");
+ }
+ break;
+ case HA_EXTENSIONS:
+ set_extension(ike_sa, value.u32, EXT_NATT);
+ set_extension(ike_sa, value.u32, EXT_MOBIKE);
+ set_extension(ike_sa, value.u32, EXT_HASH_AND_URL);
+ break;
+ case HA_CONDITIONS:
+ set_condition(ike_sa, value.u32, COND_NAT_ANY);
+ set_condition(ike_sa, value.u32, COND_NAT_HERE);
+ set_condition(ike_sa, value.u32, COND_NAT_THERE);
+ set_condition(ike_sa, value.u32, COND_NAT_FAKE);
+ set_condition(ike_sa, value.u32, COND_EAP_AUTHENTICATED);
+ set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN);
+ set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR);
+ break;
+ case HA_INITIATE_MID:
+ ike_sa->set_message_id(ike_sa, TRUE, value.u32);
+ break;
+ case HA_RESPOND_MID:
+ ike_sa->set_message_id(ike_sa, FALSE, value.u32);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ike_sa)
+ {
+ if (ike_sa->get_state(ike_sa) == IKE_CONNECTING &&
+ ike_sa->get_peer_cfg(ike_sa))
+ {
+ ike_sa->set_state(ike_sa, IKE_PASSIVE);
+ }
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+}
+
+/**
+ * Process messages of type IKE_DELETE
+ */
+static void process_ike_delete(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(
+ charon->ike_sa_manager, value.ike_sa_id);
+ if (ike_sa)
+ {
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Lookup a child cfg from the peer cfg by name
+ */
+static child_cfg_t* find_child_cfg(ike_sa_t *ike_sa, char *name)
+{
+ peer_cfg_t *peer_cfg;
+ child_cfg_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+ if (peer_cfg)
+ {
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(current->get_name(current), name))
+ {
+ found = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return found;
+}
+
+/**
+ * Process messages of type CHILD_ADD
+ */
+static void process_child_add(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+ char *config_name = "";
+ child_cfg_t *config = NULL;
+ child_sa_t *child_sa;
+ proposal_t *proposal;
+ keymat_t *keymat;
+ bool initiator = FALSE, failed = FALSE;
+ u_int32_t inbound_spi = 0, outbound_spi = 0;
+ u_int16_t inbound_cpi = 0, outbound_cpi = 0;
+ u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
+ u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0;
+ chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
+ chunk_t encr_i, integ_i, encr_r, integ_r;
+ linked_list_t *local_ts, *remote_ts;
+ /* quick and dirty hack of a DH implementation */
+ diffie_hellman_t dh = { .get_shared_secret = get_shared_secret,
+ .destroy = (void*)&secret };
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ initiator = value.ike_sa_id->is_initiator(value.ike_sa_id);
+ break;
+ case HA_CONFIG_NAME:
+ config_name = value.str;
+ break;
+ case HA_INBOUND_SPI:
+ inbound_spi = value.u32;
+ break;
+ case HA_OUTBOUND_SPI:
+ outbound_spi = value.u32;
+ break;
+ case HA_INBOUND_CPI:
+ inbound_cpi = value.u32;
+ break;
+ case HA_OUTBOUND_CPI:
+ outbound_cpi = value.u32;
+ break;
+ case HA_IPSEC_MODE:
+ mode = value.u8;
+ break;
+ case HA_IPCOMP:
+ ipcomp = value.u8;
+ break;
+ case HA_ALG_ENCR:
+ encr = value.u16;
+ break;
+ case HA_ALG_ENCR_LEN:
+ len = value.u16;
+ break;
+ case HA_ALG_INTEG:
+ integ = value.u16;
+ break;
+ case HA_NONCE_I:
+ nonce_i = value.chunk;
+ break;
+ case HA_NONCE_R:
+ nonce_r = value.chunk;
+ break;
+ case HA_SECRET:
+ secret = value.chunk;
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!ike_sa)
+ {
+ DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found");
+ return;
+ }
+ config = find_child_cfg(ike_sa, config_name);
+ if (!config)
+ {
+ DBG1(DBG_CHD, "HA is missing nodes child configuration");
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return;
+ }
+
+ child_sa = child_sa_create(ike_sa->get_my_host(ike_sa),
+ ike_sa->get_other_host(ike_sa), config, 0,
+ ike_sa->has_condition(ike_sa, COND_NAT_ANY));
+ child_sa->set_mode(child_sa, mode);
+ child_sa->set_protocol(child_sa, PROTO_ESP);
+ child_sa->set_ipcomp(child_sa, ipcomp);
+
+ proposal = proposal_create(PROTO_ESP);
+ if (integ)
+ {
+ proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
+ }
+ if (encr)
+ {
+ proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
+ }
+ keymat = ike_sa->get_keymat(ike_sa);
+
+ if (!keymat->derive_child_keys(keymat, proposal, secret.ptr ? &dh : NULL,
+ nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
+ {
+ DBG1(DBG_CHD, "HA CHILD_SA key derivation failed");
+ child_sa->destroy(child_sa);
+ proposal->destroy(proposal);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return;
+ }
+ child_sa->set_proposal(child_sa, proposal);
+ child_sa->set_state(child_sa, CHILD_INSTALLING);
+ proposal->destroy(proposal);
+
+ /* TODO: Change CHILD_SA API to avoid cloning twice */
+ local_ts = linked_list_create();
+ remote_ts = linked_list_create();
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_LOCAL_TS:
+ local_ts->insert_last(local_ts, value.ts->clone(value.ts));
+ break;
+ case HA_REMOTE_TS:
+ remote_ts->insert_last(remote_ts, value.ts->clone(value.ts));
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (initiator)
+ {
+ if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi,
+ inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS ||
+ child_sa->install(child_sa, encr_i, integ_i, outbound_spi,
+ outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS)
+ {
+ failed = TRUE;
+ }
+ }
+ else
+ {
+ if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi,
+ inbound_cpi, TRUE, local_ts, remote_ts) != SUCCESS ||
+ child_sa->install(child_sa, encr_r, integ_r, outbound_spi,
+ outbound_cpi, FALSE, local_ts, remote_ts) != SUCCESS)
+ {
+ failed = TRUE;
+ }
+ }
+ chunk_clear(&encr_i);
+ chunk_clear(&integ_i);
+ chunk_clear(&encr_r);
+ chunk_clear(&integ_r);
+
+ if (failed)
+ {
+ DBG1(DBG_CHD, "HA CHILD_SA installation failed");
+ child_sa->destroy(child_sa);
+ local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
+ remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ return;
+ }
+
+ child_sa->add_policies(child_sa, local_ts, remote_ts);
+ local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
+ remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
+
+ child_sa->set_state(child_sa, CHILD_INSTALLED);
+ ike_sa->add_child_sa(ike_sa, child_sa);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+}
+
+/**
+ * Process messages of type CHILD_DELETE
+ */
+static void process_child_delete(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_INBOUND_SPI:
+ if (ike_sa)
+ {
+ ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, value.u32);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (ike_sa)
+ {
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Process messages of type SEGMENT_TAKE/DROP
+ */
+static void process_segment(private_ha_dispatcher_t *this,
+ ha_message_t *message, bool take)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_SEGMENT:
+ if (take)
+ {
+ DBG1(DBG_CFG, "remote node takes segment %d", value.u16);
+ this->segments->deactivate(this->segments, value.u16, FALSE);
+ }
+ else
+ {
+ DBG1(DBG_CFG, "remote node drops segment %d", value.u16);
+ this->segments->activate(this->segments, value.u16, FALSE);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Process messages of type STATUS
+ */
+static void process_status(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ segment_mask_t mask = 0;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_SEGMENT:
+ mask |= SEGMENTS_BIT(value.u16);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ this->segments->handle_status(this->segments, mask);
+}
+
+/**
+ * Process messages of type RESYNC
+ */
+static void process_resync(private_ha_dispatcher_t *this,
+ ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_SEGMENT:
+ this->segments->resync(this->segments, value.u16);
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Dispatcher job function
+ */
+static job_requeue_t dispatch(private_ha_dispatcher_t *this)
+{
+ ha_message_t *message;
+
+ message = this->socket->pull(this->socket);
+ switch (message->get_type(message))
+ {
+ case HA_IKE_ADD:
+ process_ike_add(this, message);
+ break;
+ case HA_IKE_UPDATE:
+ process_ike_update(this, message);
+ break;
+ case HA_IKE_DELETE:
+ process_ike_delete(this, message);
+ break;
+ case HA_CHILD_ADD:
+ process_child_add(this, message);
+ break;
+ case HA_CHILD_DELETE:
+ process_child_delete(this, message);
+ break;
+ case HA_SEGMENT_DROP:
+ process_segment(this, message, FALSE);
+ break;
+ case HA_SEGMENT_TAKE:
+ process_segment(this, message, TRUE);
+ break;
+ case HA_STATUS:
+ process_status(this, message);
+ break;
+ case HA_RESYNC:
+ process_resync(this, message);
+ break;
+ default:
+ DBG1(DBG_CFG, "received unknown HA message type %d",
+ message->get_type(message));
+ break;
+ }
+ message->destroy(message);
+
+ return JOB_REQUEUE_DIRECT;
+}
+
+/**
+ * Implementation of ha_dispatcher_t.destroy.
+ */
+static void destroy(private_ha_dispatcher_t *this)
+{
+ this->job->cancel(this->job);
+ free(this);
+}
+
+/**
+ * See header
+ */
+ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
+ ha_segments_t *segments)
+{
+ private_ha_dispatcher_t *this = malloc_thing(private_ha_dispatcher_t);
+
+ this->public.destroy = (void(*)(ha_dispatcher_t*))destroy;
+
+ this->socket = socket;
+ this->segments = segments;
+ this->job = callback_job_create((callback_job_cb_t)dispatch,
+ this, NULL, NULL);
+ charon->processor->queue_job(charon->processor, (job_t*)this->job);
+
+ return &this->public;
+}
+