From: Martin Willi Date: Thu, 13 Nov 2008 16:01:06 +0000 (+0000) Subject: added a dispatcher class to receive HA sync messages X-Git-Tag: 4.4.0~107 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=190edaf527262aed28f1313e00193de41a7ebc75;p=thirdparty%2Fstrongswan.git added a dispatcher class to receive HA sync messages simple attribute parser enumerator (probably needs a cleaner implementation) --- diff --git a/src/charon/plugins/ha_sync/Makefile.am b/src/charon/plugins/ha_sync/Makefile.am index d3c46496eb..fd15a6e286 100644 --- a/src/charon/plugins/ha_sync/Makefile.am +++ b/src/charon/plugins/ha_sync/Makefile.am @@ -8,6 +8,7 @@ libstrongswan_ha_sync_la_SOURCES = \ ha_sync_plugin.h ha_sync_plugin.c \ ha_sync_message.h ha_sync_message.c \ ha_sync_socket.h ha_sync_socket.c \ + ha_sync_dispatcher.h ha_sync_dispatcher.c \ ha_sync_ike.h ha_sync_ike.c \ ha_sync_child.h ha_sync_child.c libstrongswan_ha_sync_la_LDFLAGS = -module diff --git a/src/charon/plugins/ha_sync/ha_sync_dispatcher.c b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c new file mode 100644 index 0000000000..d5279da952 --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c @@ -0,0 +1,161 @@ +/* + * 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 . + * + * 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. + * + * $Id$ + */ + +#include "ha_sync_dispatcher.h" + +#include +#include + +typedef struct private_ha_sync_dispatcher_t private_ha_sync_dispatcher_t; + +/** + * Private data of an ha_sync_dispatcher_t object. + */ +struct private_ha_sync_dispatcher_t { + + /** + * Public ha_sync_dispatcher_t interface. + */ + ha_sync_dispatcher_t public; + + /** + * socket to pull messages from + */ + ha_sync_socket_t *socket; + + /** + * Dispatcher job + */ + callback_job_t *job; +}; + +/** + * Process messages of type IKE_ADD + */ +static void process_ike_add(private_ha_sync_dispatcher_t *this, + ha_sync_message_t *message) +{ + ha_sync_message_attribute_t attribute; + ha_sync_message_value_t value; + enumerator_t *enumerator; + + enumerator = message->create_attribute_enumerator(message); + while (enumerator->enumerate(enumerator, &attribute, &value)) + { + switch (attribute) + { + /* ike_sa_id_t* */ + case HA_SYNC_IKE_ID: + case HA_SYNC_IKE_REKEY_ID: + DBG1(DBG_IKE, " %d -> %llu:%llu %s", attribute, + value.ike_sa_id->get_initiator_spi(value.ike_sa_id), + value.ike_sa_id->get_responder_spi(value.ike_sa_id), + value.ike_sa_id->is_initiator(value.ike_sa_id) ? + "initiator" : "responder"); + break; + /* identification_t* */ + case HA_SYNC_LOCAL_ID: + case HA_SYNC_REMOTE_ID: + case HA_SYNC_EAP_ID: + DBG1(DBG_IKE, " %d -> %D", attribute, value.id); + break; + /* host_t* */ + case HA_SYNC_LOCAL_ADDR: + case HA_SYNC_REMOTE_ADDR: + case HA_SYNC_LOCAL_VIP: + case HA_SYNC_REMOTE_VIP: + case HA_SYNC_ADDITIONAL_ADDR: + DBG1(DBG_IKE, " %d -> %H", attribute, value.host); + break; + /* char* */ + case HA_SYNC_CONFIG_NAME: + DBG1(DBG_IKE, " %d -> %s", attribute, value.str); + break; + /** u_int32_t */ + case HA_SYNC_CONDITIONS: + case HA_SYNC_EXTENSIONS: + DBG1(DBG_IKE, " %d -> %lu", attribute, value.u32); + break; + /** chunk_t */ + case HA_SYNC_NONCE_I: + case HA_SYNC_NONCE_R: + case HA_SYNC_SECRET: + DBG1(DBG_IKE, " %d -> %B", attribute, &value.chunk); + break; + } + } + enumerator->destroy(enumerator); +} + +/** + * Dispatcher job function + */ +static job_requeue_t dispatch(private_ha_sync_dispatcher_t *this) +{ + ha_sync_message_t *message; + + message = this->socket->pull(this->socket); + switch (message->get_type(message)) + { + case HA_SYNC_IKE_ADD: + process_ike_add(this, message); + break; + case HA_SYNC_IKE_UPDATE: + break; + case HA_SYNC_IKE_DELETE: + break; + case HA_SYNC_IKE_REKEY: + break; + case HA_SYNC_CHILD_ADD: + break; + case HA_SYNC_CHILD_DELETE: + break; + default: + DBG1(DBG_CFG, "received unknown HA sync message type %d", + message->get_type(message)); + break; + } + message->destroy(message); + + return JOB_REQUEUE_DIRECT; +} + +/** + * Implementation of ha_sync_dispatcher_t.destroy. + */ +static void destroy(private_ha_sync_dispatcher_t *this) +{ + this->job->cancel(this->job); + free(this); +} + +/** + * See header + */ +ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket) +{ + private_ha_sync_dispatcher_t *this = malloc_thing(private_ha_sync_dispatcher_t); + + this->public.destroy = (void(*)(ha_sync_dispatcher_t*))destroy; + + this->socket = socket; + 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; +} diff --git a/src/charon/plugins/ha_sync/ha_sync_dispatcher.h b/src/charon/plugins/ha_sync/ha_sync_dispatcher.h new file mode 100644 index 0000000000..eb2817e916 --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_dispatcher.h @@ -0,0 +1,49 @@ +/* + * 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 . + * + * 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. + * + * $Id$ + */ + +/** + * @defgroup ha_sync_dispatcher ha_sync_dispatcher + * @{ @ingroup ha-sync + */ + +#ifndef HA_SYNC_DISPATCHER_H_ +#define HA_SYNC_DISPATCHER_H_ + +#include "ha_sync_socket.h" + +typedef struct ha_sync_dispatcher_t ha_sync_dispatcher_t; + +/** + * The dispatcher pulls sync message in a thread an processes them. + */ +struct ha_sync_dispatcher_t { + + /** + * Destroy a ha_sync_dispatcher_t. + */ + void (*destroy)(ha_sync_dispatcher_t *this); +}; + +/** + * Create a ha_sync_dispatcher instance pulling from socket. + * + * @param socket socket to pull messages from + * @return dispatcher object + */ +ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket); + +#endif /* HA_SYNC_DISPATCHER_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_ike.c b/src/charon/plugins/ha_sync/ha_sync_ike.c index 46af18694b..083b6a0fe7 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ike.c +++ b/src/charon/plugins/ha_sync/ha_sync_ike.c @@ -106,7 +106,6 @@ static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, m->add_attribute(m, HA_SYNC_REMOTE_ID, ike_sa->get_other_id(ike_sa)); m->add_attribute(m, HA_SYNC_LOCAL_ADDR, ike_sa->get_my_host(ike_sa)); m->add_attribute(m, HA_SYNC_REMOTE_ADDR, ike_sa->get_other_host(ike_sa)); - m->add_attribute(m, HA_SYNC_CONFIG_NAME, peer_cfg->get_name(peer_cfg)); m->add_attribute(m, HA_SYNC_CONDITIONS, condition); m->add_attribute(m, HA_SYNC_EXTENSIONS, extension); if (local_vip) diff --git a/src/charon/plugins/ha_sync/ha_sync_message.c b/src/charon/plugins/ha_sync/ha_sync_message.c index ee3aa245cb..f8a81dc74f 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.c +++ b/src/charon/plugins/ha_sync/ha_sync_message.c @@ -15,10 +15,12 @@ * $Id$ */ -#include "ha_sync_message.h" - +#define _GNU_SOURCE +#include #include +#include "ha_sync_message.h" + #include #define ALLOCATION_BLOCK 64 @@ -209,9 +211,11 @@ static void add_attribute(private_ha_sync_message_t *this, chunk_t chunk; chunk = va_arg(args, chunk_t); - check_buf(this, chunk.len); - memcpy(this->buf.ptr + this->buf.len, chunk.ptr, chunk.len); - this->buf.len += chunk.len; + check_buf(this, chunk.len + sizeof(u_int16_t)); + *(u_int16_t*)(this->buf.ptr + this->buf.len) = htons(chunk.len); + memcpy(this->buf.ptr + this->buf.len + sizeof(u_int16_t), + chunk.ptr, chunk.len); + this->buf.len += chunk.len + sizeof(u_int16_t);; break; } default: @@ -224,12 +228,197 @@ static void add_attribute(private_ha_sync_message_t *this, va_end(args); } +/** + * Attribute enumerator implementation + */ +typedef struct { + /** implementes enumerator_t */ + enumerator_t public; + /** position in message */ + chunk_t buf; + /** cleanup handler of current element, if any */ + void (*cleanup)(void* data); + /** data to pass to cleanup handler */ + void *cleanup_data; +} attribute_enumerator_t; + +/** + * Implementation of create_attribute_enumerator().enumerate + */ +static bool attribute_enumerate(attribute_enumerator_t *this, + ha_sync_message_attribute_t *attr_out, + ha_sync_message_value_t *value) +{ + ha_sync_message_attribute_t attr; + + if (this->cleanup) + { + this->cleanup(this->cleanup_data); + this->cleanup = NULL; + } + if (this->buf.len < 1) + { + return FALSE; + } + attr = this->buf.ptr[0]; + this->buf = chunk_skip(this->buf, 1); + switch (attr) + { + /* ike_sa_id_t* */ + case HA_SYNC_IKE_ID: + case HA_SYNC_IKE_REKEY_ID: + { + ike_sa_id_encoding_t *enc; + + if (this->buf.len < sizeof(ike_sa_id_encoding_t)) + { + return FALSE; + } + enc = (ike_sa_id_encoding_t*)(this->buf.ptr); + value->ike_sa_id = ike_sa_id_create(enc->initiator_spi, + enc->responder_spi, enc->initiator); + *attr_out = attr; + this->cleanup = (void*)value->ike_sa_id->destroy; + this->cleanup_data = value->ike_sa_id; + this->buf = chunk_skip(this->buf, sizeof(ike_sa_id_encoding_t)); + return TRUE; + } + /* identification_t* */ + case HA_SYNC_LOCAL_ID: + case HA_SYNC_REMOTE_ID: + case HA_SYNC_EAP_ID: + { + identification_encoding_t *enc; + + enc = (identification_encoding_t*)(this->buf.ptr); + if (this->buf.len < sizeof(identification_encoding_t) || + this->buf.len < sizeof(identification_encoding_t) + enc->len) + { + return FALSE; + } + value->id = identification_create_from_encoding(enc->type, + chunk_create(enc->encoding, enc->len)); + *attr_out = attr; + this->cleanup = (void*)value->id->destroy; + this->cleanup_data = value->id; + this->buf = chunk_skip(this->buf, + sizeof(identification_encoding_t) + enc->len); + return TRUE; + } + /* host_t* */ + case HA_SYNC_LOCAL_ADDR: + case HA_SYNC_REMOTE_ADDR: + case HA_SYNC_LOCAL_VIP: + case HA_SYNC_REMOTE_VIP: + case HA_SYNC_ADDITIONAL_ADDR: + { + host_encoding_t *enc; + + enc = (host_encoding_t*)(this->buf.ptr); + if (this->buf.len < sizeof(host_encoding_t)) + { + return FALSE; + } + value->host = host_create_from_chunk(enc->family, + chunk_create(enc->encoding, + this->buf.len - sizeof(host_encoding_t)), + ntohs(enc->port)); + if (!value->host) + { + return FALSE; + } + *attr_out = attr; + this->cleanup = (void*)value->host->destroy; + this->cleanup_data = value->host; + this->buf = chunk_skip(this->buf, sizeof(host_encoding_t) + + value->host->get_address(value->host).len); + return TRUE; + } + /* char* */ + case HA_SYNC_CONFIG_NAME: + { + size_t len; + + len = strnlen(this->buf.ptr, this->buf.len); + if (len >= this->buf.len) + { + return FALSE; + } + value->str = this->buf.ptr; + *attr_out = attr; + this->buf = chunk_skip(this->buf, len + 1); + return TRUE; + } + /** u_int32_t */ + case HA_SYNC_CONDITIONS: + case HA_SYNC_EXTENSIONS: + { + if (this->buf.len < sizeof(u_int32_t)) + { + return FALSE; + } + value->u32 = ntohl(*(u_int32_t*)this->buf.ptr); + *attr_out = attr; + this->buf = chunk_skip(this->buf, sizeof(u_int32_t)); + return TRUE; + } + /** chunk_t */ + case HA_SYNC_NONCE_I: + case HA_SYNC_NONCE_R: + case HA_SYNC_SECRET: + { + size_t len; + + if (this->buf.len < sizeof(u_int16_t)) + { + return FALSE; + } + len = ntohs(*(u_int16_t*)this->buf.ptr); + this->buf = chunk_skip(this->buf, sizeof(u_int16_t)); + if (this->buf.len < len) + { + return FALSE; + } + value->chunk.len = len; + value->chunk.ptr = this->buf.ptr; + *attr_out = attr; + this->buf = chunk_skip(this->buf, len); + return TRUE; + } + default: + { + return FALSE; + } + } +} + +/** + * Implementation of create_attribute_enumerator().destroy + */ +static void enum_destroy(attribute_enumerator_t *this) +{ + if (this->cleanup) + { + this->cleanup(this->cleanup_data); + } + free(this); +} + /** * Implementation of ha_sync_message_t.create_attribute_enumerator */ static enumerator_t* create_attribute_enumerator(private_ha_sync_message_t *this) { - return enumerator_create_empty(); + attribute_enumerator_t *e = malloc_thing(attribute_enumerator_t); + + e->public.enumerate = (void*)attribute_enumerate; + e->public.destroy = (void*)enum_destroy; + + e->buf = chunk_skip(this->buf, 2); + e->cleanup = NULL; + e->cleanup_data = NULL; + + return &e->public; } /** diff --git a/src/charon/plugins/ha_sync/ha_sync_message.h b/src/charon/plugins/ha_sync/ha_sync_message.h index ebe0c2df4a..53701e12df 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.h +++ b/src/charon/plugins/ha_sync/ha_sync_message.h @@ -98,14 +98,12 @@ enum ha_sync_message_attribute_t { * Union to enumerate typed attributes in a message */ union ha_sync_message_value_t { - u_int8_t u8; u_int32_t u32; - u_int16_t u16; - chunk_t chnk; - host_t *host; - identification_t *id; - ike_sa_id_t *ike_sa_id; char *str; + chunk_t chunk; + ike_sa_id_t *ike_sa_id; + identification_t *id; + host_t *host; }; /** diff --git a/src/charon/plugins/ha_sync/ha_sync_plugin.c b/src/charon/plugins/ha_sync/ha_sync_plugin.c index d6d2fe3bac..8a73512c86 100644 --- a/src/charon/plugins/ha_sync/ha_sync_plugin.c +++ b/src/charon/plugins/ha_sync/ha_sync_plugin.c @@ -19,6 +19,7 @@ #include "ha_sync_ike.h" #include "ha_sync_child.h" #include "ha_sync_socket.h" +#include "ha_sync_dispatcher.h" #include #include @@ -49,6 +50,11 @@ struct private_ha_sync_plugin_t { * CHILD_SA synchronization */ ha_sync_child_t *child; + + /** + * Dispatcher to process incoming messages + */ + ha_sync_dispatcher_t *dispatcher; }; /** @@ -60,6 +66,7 @@ static void destroy(private_ha_sync_plugin_t *this) charon->bus->remove_listener(charon->bus, &this->child->listener); this->ike->destroy(this->ike); this->child->destroy(this->child); + this->dispatcher->destroy(this->dispatcher); this->socket->destroy(this->socket); free(this); } @@ -79,6 +86,7 @@ plugin_t *plugin_create() free(this); return NULL; } + this->dispatcher = ha_sync_dispatcher_create(this->socket); this->ike = ha_sync_ike_create(this->socket); this->child = ha_sync_child_create(this->socket); charon->bus->add_listener(charon->bus, &this->ike->listener); diff --git a/src/charon/plugins/ha_sync/ha_sync_socket.c b/src/charon/plugins/ha_sync/ha_sync_socket.c index 193d6cb9c1..2a3092932e 100644 --- a/src/charon/plugins/ha_sync/ha_sync_socket.c +++ b/src/charon/plugins/ha_sync/ha_sync_socket.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -66,9 +67,12 @@ static ha_sync_message_t *pull(private_ha_sync_socket_t *this) { ha_sync_message_t *message; char buf[1024]; + int oldstate; ssize_t len; + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); len = recv(this->fd, buf, sizeof(buf), 0); + pthread_setcancelstate(oldstate, NULL); if (len <= 0) { if (errno != EINTR)