diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2010-12-10 14:56:40 +0100 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2010-12-10 14:56:40 +0100 |
commit | 5988fc0dfd30e3e1f61c236ba4eaa7be8eb6d3dc (patch) | |
tree | ca347eb6a79ed0c02c1c80ac7527eb8346cd75ff /src | |
parent | 755f2419a586f6f7b49ed761613260de4a806f6a (diff) | |
download | strongswan-5988fc0dfd30e3e1f61c236ba4eaa7be8eb6d3dc.tar.bz2 strongswan-5988fc0dfd30e3e1f61c236ba4eaa7be8eb6d3dc.tar.xz |
define pb_tnc_state_machine_t object
Diffstat (limited to 'src')
6 files changed, 401 insertions, 229 deletions
diff --git a/src/libcharon/plugins/tnccs_20/Makefile.am b/src/libcharon/plugins/tnccs_20/Makefile.am index f5dd6ba2a..4b335a0ac 100644 --- a/src/libcharon/plugins/tnccs_20/Makefile.am +++ b/src/libcharon/plugins/tnccs_20/Makefile.am @@ -21,6 +21,7 @@ libstrongswan_tnccs_20_la_SOURCES = \ messages/pb_access_recommendation_message.h messages/pb_access_recommendation_message.c \ messages/pb_error_message.h messages/pb_error_message.c \ messages/pb_language_preference_message.h messages/pb_language_preference_message.c \ - messages/pb_reason_string_message.h messages/pb_reason_string_message.c + messages/pb_reason_string_message.h messages/pb_reason_string_message.c \ + state_machine/pb_tnc_state_machine.h state_machine/pb_tnc_state_machine.c libstrongswan_tnccs_20_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c index edada34e3..8e4c54ef4 100644 --- a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c @@ -17,6 +17,7 @@ #include "tnccs_20_types.h" #include "pb_tnc_batch.h" #include "messages/pb_error_message.h" +#include "state_machine/pb_tnc_state_machine.h" #include <debug.h> #include <utils/linked_list.h> @@ -24,14 +25,6 @@ #include <tls_reader.h> #include <tnc/tnccs/tnccs.h> -ENUM(pb_tnc_state_names, PB_STATE_INIT, PB_STATE_END, - "Init", - "Server Working", - "Client Working", - "Decided", - "End" -); - ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE, "CDATA", "SDATA", @@ -206,95 +199,8 @@ METHOD(pb_tnc_batch_t, build, void, writer->destroy(writer); } -/* - * Implements the PB-TNC state machine in receive direction - */ -static bool state_transition_upon_receive(pb_tnc_state_t *state, - pb_tnc_batch_type_t batch_type, - bool is_server) -{ - switch (*state) - { - case PB_STATE_INIT: - if (is_server && batch_type == PB_BATCH_CDATA) - { - *state = PB_STATE_SERVER_WORKING; - break; - } - if (!is_server && batch_type == PB_BATCH_SDATA) - { - *state = PB_STATE_CLIENT_WORKING; - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_SERVER_WORKING: - if (!is_server && batch_type == PB_BATCH_SDATA) - { - *state = PB_STATE_CLIENT_WORKING; - break; - } - if (!is_server && batch_type == PB_BATCH_RESULT) - { - *state = PB_STATE_DECIDED; - break; - } - if ((is_server && batch_type == PB_BATCH_CRETRY) || - (!is_server && batch_type == PB_BATCH_SRETRY)) - { - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_CLIENT_WORKING: - if (is_server && batch_type == PB_BATCH_CDATA) - { - *state = PB_STATE_SERVER_WORKING; - break; - } - if (is_server && batch_type == PB_BATCH_CRETRY) - { - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_DECIDED: - if ((is_server && batch_type == PB_BATCH_CRETRY) || - (!is_server && batch_type == PB_BATCH_SRETRY)) - { - *state = PB_STATE_SERVER_WORKING; - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_END: - if (batch_type == PB_BATCH_CLOSE) - { - break; - } - return FALSE; - } - return TRUE; -} - static status_t process_batch_header(private_pb_tnc_batch_t *this, - pb_tnc_state_t *state) + pb_tnc_state_machine_t *state_machine) { tls_reader_t *reader; pb_tnc_message_t *msg; @@ -358,7 +264,7 @@ static status_t process_batch_header(private_pb_tnc_batch_t *this, goto fatal; } - if (!state_transition_upon_receive(state, this->type, this->is_server)) + if (!state_machine->receive_batch(state_machine, this->type)) { DBG1(DBG_TNC, "unexpected PB-TNC Batch Type: %N", pb_tnc_batch_type_names, this->type); @@ -514,11 +420,11 @@ fatal: } METHOD(pb_tnc_batch_t, process, status_t, - private_pb_tnc_batch_t *this, pb_tnc_state_t *state) + private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine) { status_t status; - status = process_batch_header(this, state); + status = process_batch_header(this, state_machine); if (status == FAILED) { return FAILED; diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h index 7bc4639d4..a437799d3 100644 --- a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.h @@ -21,30 +21,14 @@ #ifndef PB_TNC_BATCH_H_ #define PB_TNC_BATCH_H_ +typedef enum pb_tnc_batch_type_t pb_tnc_batch_type_t; +typedef struct pb_tnc_batch_t pb_tnc_batch_t; + #include "messages/pb_tnc_message.h" +#include "state_machine/pb_tnc_state_machine.h" #include <library.h> -typedef enum pb_tnc_state_t pb_tnc_state_t; - -/** - * PB-TNC States (State machine) as defined in section 3.2 of RFC 5793 - */ -enum pb_tnc_state_t { - PB_STATE_INIT, - PB_STATE_SERVER_WORKING, - PB_STATE_CLIENT_WORKING, - PB_STATE_DECIDED, - PB_STATE_END, -}; - -/** - * enum name for pb_tnc_state_t. - */ -extern enum_name_t *pb_tnc_state_names; - -typedef enum pb_tnc_batch_type_t pb_tnc_batch_type_t; - /** * PB-TNC Batch Types as defined in section 4.1 of RFC 5793 */ @@ -58,8 +42,6 @@ enum pb_tnc_batch_type_t { PB_BATCH_ROOF = 6 }; -typedef struct pb_tnc_batch_t pb_tnc_batch_t; - /** * enum name for pb_tnc_batch_type_t. */ @@ -99,10 +81,11 @@ struct pb_tnc_batch_t { /** * Process the PB-TNC Batch * - * @param in: current state, out: new state + * @param PB-TNC state machine * @return return processing status */ - status_t (*process)(pb_tnc_batch_t *this, pb_tnc_state_t *state); + status_t (*process)(pb_tnc_batch_t *this, + pb_tnc_state_machine_t *state_machine); /** * Enumerates over all PB-TNC Messages diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c new file mode 100644 index 000000000..4cca60f5e --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * HSR 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 "pb_tnc_state_machine.h" +#include "messages/pb_error_message.h" + +#include <debug.h> +#include <utils/linked_list.h> +#include <tls_writer.h> +#include <tls_reader.h> +#include <tnc/tnccs/tnccs.h> + +ENUM(pb_tnc_state_names, PB_STATE_INIT, PB_STATE_END, + "Init", + "Server Working", + "Client Working", + "Decided", + "End" +); + +/** + * PB-TNC State Machine (see section 3.2 of RFC 5793) + * + * Receive CRETRY SRETRY + * or SRETRY +----------------+ + * +--+ | | + * v | v | + * +---------+ CRETRY +---------+ + * CDATA | Server |<---------| Decided | CLOSE + * +----------->| Working |--------->| |-------+ + * | +---------+ RESULT +---------+ | + * | ^ | | v + * | | | +---------------------->======= + * ======== | | CLOSE " End " + * " Init " CDATA| |SDATA ======= + * ======== | | ^ ^ + * | | | v | | + * | | SDATA +---------+ CLOSE | | + * | +-------->| Client |----------------------+ | + * | | Working | | + * | +---------+ | + * | | ^ | + * | +--+ | + * | Receive CRETRY | + * | CLOSE | + * +--------------------------------------------------+ + */ + +typedef struct private_pb_tnc_state_machine_t private_pb_tnc_state_machine_t; + +/** + * Private data of a pb_tnc_state_machine_t object. + * + */ +struct private_pb_tnc_state_machine_t { + /** + * Public pb_pa_message_t interface. + */ + pb_tnc_state_machine_t public; + + /** + * PB-TNC Server if TRUE, PB-TNC Client if FALSE + */ + bool is_server; + + /** + * Current PB-TNC state + */ + pb_tnc_state_t state; +}; + +METHOD(pb_tnc_state_machine_t, get_state, pb_tnc_state_t, + private_pb_tnc_state_machine_t *this) +{ + return this->state; +} + +METHOD(pb_tnc_state_machine_t, receive_batch, bool, + private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type) +{ + pb_tnc_state_t old_state = this->state; + + switch (this->state) + { + case PB_STATE_INIT: + if (this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (!this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_SERVER_WORKING: + if (!this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (!this->is_server && type == PB_BATCH_RESULT) + { + this->state = PB_STATE_DECIDED; + break; + } + if ((this->is_server && type == PB_BATCH_CRETRY) || + (!this->is_server && type == PB_BATCH_SRETRY)) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_CLIENT_WORKING: + if (this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_CRETRY) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_DECIDED: + if ((this->is_server && type == PB_BATCH_CRETRY) || + (!this->is_server && type == PB_BATCH_SRETRY)) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_END: + if (type == PB_BATCH_CLOSE) + { + break; + } + return FALSE; + } + + if (this->state != old_state) + { + DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", + pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); + } + return TRUE; +} + +METHOD(pb_tnc_state_machine_t, send_batch, bool, + private_pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type) +{ + pb_tnc_state_t old_state = this->state; + + switch (this->state) + { + case PB_STATE_INIT: + if (!this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_SERVER_WORKING: + if (this->is_server && type == PB_BATCH_SDATA) + { + this->state = PB_STATE_CLIENT_WORKING; + break; + } + if (this->is_server && type == PB_BATCH_RESULT) + { + this->state = PB_STATE_DECIDED; + break; + } + if (this->is_server && type == PB_BATCH_SRETRY) + { + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_CLIENT_WORKING: + if (!this->is_server && type == PB_BATCH_CDATA) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_DECIDED: + if ((this->is_server && type == PB_BATCH_SRETRY) || + (!this->is_server && type == PB_BATCH_CRETRY)) + { + this->state = PB_STATE_SERVER_WORKING; + break; + } + if (type == PB_BATCH_CLOSE) + { + this->state = PB_STATE_END; + break; + } + return FALSE; + case PB_STATE_END: + if (type == PB_BATCH_CLOSE) + { + break; + } + return FALSE; + } + + if (this->state != old_state) + { + DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", + pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); + } + return TRUE; +} + +METHOD(pb_tnc_state_machine_t, destroy, void, + private_pb_tnc_state_machine_t *this) +{ + free(this); +} + +/** + * See header + */ +pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server) +{ + private_pb_tnc_state_machine_t *this; + + INIT(this, + .public = { + .get_state = _get_state, + .receive_batch = _receive_batch, + .send_batch = _send_batch, + .destroy = _destroy, + }, + .is_server = is_server, + .state = PB_STATE_INIT, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h new file mode 100644 index 000000000..8076b6ded --- /dev/null +++ b/src/libcharon/plugins/tnccs_20/state_machine/pb_tnc_state_machine.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 Andreas Steffen + * HSR 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. + */ + +/** + * @defgroup pb_tnc_state_machine pb_tnc_state_machine + * @{ @ingroup tnccs_20 + */ + +#ifndef PB_TNC_STATE_MACHINE_H_ +#define PB_TNC_STATE_MACHINE_H_ + +typedef struct pb_tnc_state_machine_t pb_tnc_state_machine_t; +typedef enum pb_tnc_state_t pb_tnc_state_t; + +#include "batch/pb_tnc_batch.h" + +#include <library.h> + +/** + * PB-TNC States (state machine) as defined in section 3.2 of RFC 5793 + */ +enum pb_tnc_state_t { + PB_STATE_INIT, + PB_STATE_SERVER_WORKING, + PB_STATE_CLIENT_WORKING, + PB_STATE_DECIDED, + PB_STATE_END, +}; + +/** + * enum name for pb_tnc_state_t. + */ +extern enum_name_t *pb_tnc_state_names; + +/** + * Interface for the PB-TNC state machine. + */ +struct pb_tnc_state_machine_t { + + /** + * Get the current PB-TNC STATE + * + * @return current state + */ + pb_tnc_state_t (*get_state)(pb_tnc_state_machine_t *this); + + /** + * Compute state transition due to received PB-TNC Batch + * + * @param type type of received batch + * @result TRUE if a valid transition was found, FALSE otherwise + */ + bool (*receive_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type); + + /** + * Compute state transition due to sent PB-TNC Batch + * + * @param type type of sent batch + * @result TRUE if a valid transition was found, FALSE otherwise + */ + bool (*send_batch)(pb_tnc_state_machine_t *this, pb_tnc_batch_type_t type); + + /** + * Destroys a pb_tnc_state_machine_t object. + */ + void (*destroy)(pb_tnc_state_machine_t *this); +}; + +/** + * Create and initialize a PB-TNC state machine + * + * @param is_server TRUE if PB-TNC server, FALSE if PB-TNC client + */ +pb_tnc_state_machine_t* pb_tnc_state_machine_create(bool is_server); + +#endif /** PB_TNC_STATE_MACHINE_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 8bf88a270..fcabc55c3 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -24,6 +24,7 @@ #include "messages/pb_access_recommendation_message.h" #include "messages/pb_reason_string_message.h" #include "messages/pb_language_preference_message.h" +#include "state_machine/pb_tnc_state_machine.h" #include <debug.h> #include <daemon.h> @@ -52,7 +53,7 @@ struct private_tnccs_20_t { /** * PB-TNC State Machine */ - pb_tnc_state_t state; + pb_tnc_state_machine_t *state_machine; /** * Connection ID assigned to this TNCCS connection @@ -272,7 +273,6 @@ METHOD(tls_t, process, status_t, chunk_t data; pb_tnc_batch_t *batch; pb_tnc_message_t *msg; - pb_tnc_state_t old_state = this->state; enumerator_t *enumerator; status_t status; @@ -294,13 +294,7 @@ METHOD(tls_t, process, status_t, data.len, this->connection_id); DBG3(DBG_TNC, "%B", &data); batch = pb_tnc_batch_create_from_data(this->is_server, data); - status = batch->process(batch, &this->state); - - if (this->state != old_state) - { - DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", - pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); - } + status = batch->process(batch, this->state_machine); switch (status) { @@ -343,92 +337,6 @@ METHOD(tls_t, process, status_t, return NEED_MORE; } -/* - * Implements the PB-TNC state machine in send direction - */ -static bool state_transition_upon_send(pb_tnc_state_t *state, - pb_tnc_batch_type_t batch_type) -{ - switch (*state) - { - case PB_STATE_INIT: - if (batch_type == PB_BATCH_CDATA) - { - *state = PB_STATE_SERVER_WORKING; - break; - } - if (batch_type == PB_BATCH_SDATA) - { - *state = PB_STATE_CLIENT_WORKING; - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_SERVER_WORKING: - if (batch_type == PB_BATCH_SDATA) - { - *state = PB_STATE_CLIENT_WORKING; - break; - } - if (batch_type == PB_BATCH_RESULT) - { - *state = PB_STATE_DECIDED; - break; - } - if (batch_type == PB_BATCH_CRETRY || - batch_type == PB_BATCH_SRETRY) - { - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_CLIENT_WORKING: - if (batch_type == PB_BATCH_CDATA) - { - *state = PB_STATE_SERVER_WORKING; - break; - } - if (batch_type == PB_BATCH_CRETRY) - { - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_DECIDED: - if (batch_type == PB_BATCH_CRETRY || - batch_type == PB_BATCH_SRETRY) - { - *state = PB_STATE_SERVER_WORKING; - break; - } - if (batch_type == PB_BATCH_CLOSE) - { - *state = PB_STATE_END; - break; - } - return FALSE; - case PB_STATE_END: - if (batch_type == PB_BATCH_CLOSE) - { - break; - } - return FALSE; - } - return TRUE; -} - METHOD(tls_t, build, status_t, private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen) { @@ -464,15 +372,13 @@ METHOD(tls_t, build, status_t, if (this->batch) { pb_tnc_batch_type_t batch_type; - pb_tnc_state_t old_state; status_t status; chunk_t data; - batch_type = this->batch->get_type(this->batch); - old_state = this->state; this->mutex->lock(this->mutex); + batch_type = this->batch->get_type(this->batch); - if (state_transition_upon_send(&this->state, batch_type)) + if (this->state_machine->send_batch(this->state_machine, batch_type)) { this->batch->build(this->batch); data = this->batch->get_encoding(this->batch); @@ -497,11 +403,6 @@ METHOD(tls_t, build, status_t, this->batch = NULL; this->mutex->unlock(this->mutex); - if (this->state != old_state) - { - DBG2(DBG_TNC, "PB-TNC state transition from '%N' to '%N'", - pb_tnc_state_names, old_state, pb_tnc_state_names, this->state); - } return status; } else @@ -552,6 +453,7 @@ METHOD(tls_t, destroy, void, private_tnccs_20_t *this) { charon->tnccs->remove_connection(charon->tnccs, this->connection_id); + this->state_machine->destroy(this->state_machine); this->mutex->destroy(this->mutex); DESTROY_IF(this->batch); free(this); @@ -575,7 +477,7 @@ tls_t *tnccs_20_create(bool is_server) .destroy = _destroy, }, .is_server = is_server, - .state = PB_STATE_INIT, + .state_machine = pb_tnc_state_machine_create(is_server), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); |