upgraded Test IMC/IMV pair to fully support multple IMC IDs
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 11 Dec 2011 21:01:49 +0000 (22:01 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 11 Dec 2011 21:01:49 +0000 (22:01 +0100)
man/strongswan.conf.5.in
src/libimcv/plugins/imc_test/imc_test.c
src/libimcv/plugins/imv_test/imv_test.c
src/libimcv/plugins/imv_test/imv_test_state.c
src/libimcv/plugins/imv_test/imv_test_state.h
testing/tests/tnc/tnccs-20/hosts/carol/etc/strongswan.conf
testing/tests/tnc/tnccs-20/hosts/dave/etc/strongswan.conf

index fdc13c1..885da52 100644 (file)
@@ -607,6 +607,9 @@ List of TCP ports that can be open or must be closed
 .BR libimcv.plugins.imv-scanner.udp_ports
 List of UDP ports that can be open or must be closed
 .TP
+.BR libimcv.plugins.imc-test.additional_ids " [0]"
+Number of additional IMC IDs
+.TP
 .BR libimcv.plugins.imc-test.command " [none]"
 Command to be sent to the Test IMV
 .TP
index b7858c5..9ca73fa 100644 (file)
@@ -83,6 +83,7 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
                DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
+
        switch (new_state)
        {
                case TNC_CONNECTION_STATE_CREATE:
@@ -91,6 +92,7 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
                        retry = lib->settings->get_bool(lib->settings,
                                                                "libimcv.plugins.imc-test.retry", FALSE);
                        state = imc_test_state_create(connection_id, command, retry);
+                       test_state = (imc_test_state_t*)state;
 
                        result = imc_test->create_state(imc_test, state);
                        if (result != TNC_RESULT_SUCCESS)
@@ -112,7 +114,6 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
                                                           "multiple IMC IDs", imc_id, imc_name);
                                return TNC_RESULT_SUCCESS;
                        }
-                       test_state = (imc_test_state_t*)state;
 
                        while (additional_ids-- > 0)
                        {
@@ -178,52 +179,28 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
        }
 }
 
-static TNC_Result send_message(TNC_ConnectionID connection_id)
+static TNC_Result send_message(imc_state_t *state, TNC_UInt32 src_imc_id,
+                                                                                                  TNC_UInt32 dst_imv_id)
 {
+       imc_test_state_t *test_state;
        pa_tnc_msg_t *msg;
        pa_tnc_attr_t *attr;
-       imc_state_t *state;
-       imc_test_state_t *test_state;
-       enumerator_t *enumerator;
-       void *pointer;
-       TNC_UInt32 imc_id;
+       bool excl;
+       TNC_ConnectionID connection_id;
        TNC_Result result;
 
-       if (!imc_test->get_state(imc_test, connection_id, &state))
-       {
-               return TNC_RESULT_FATAL;
-       }
+       connection_id = state->get_connection_id(state);
        test_state = (imc_test_state_t*)state;
-
-       /* send PA message for primary IMC ID */
        attr = ita_attr_command_create(test_state->get_command(test_state));
        attr->set_noskip_flag(attr, TRUE);
        msg = pa_tnc_msg_create();
        msg->add_attribute(msg, attr);
        msg->build(msg);
-       result = imc_test->send_message(imc_test, connection_id, FALSE, 0,
-                                                                       TNC_IMVID_ANY, msg->get_encoding(msg)); 
+       excl = dst_imv_id != TNC_IMVID_ANY;
+       result = imc_test->send_message(imc_test, connection_id, excl, src_imc_id,
+                                                                       dst_imv_id, msg->get_encoding(msg));    
        msg->destroy(msg);
 
-       /* send PA messages for additional IMC IDs */
-       enumerator = test_state->create_id_enumerator(test_state);
-       while (result == TNC_RESULT_SUCCESS &&
-                  enumerator->enumerate(enumerator, &pointer))
-       {
-               /* interpret pointer as scalar value */
-               imc_id = (TNC_UInt32)pointer;
-
-               attr = ita_attr_command_create(test_state->get_command(test_state));
-               attr->set_noskip_flag(attr, TRUE);
-               msg = pa_tnc_msg_create();
-               msg->add_attribute(msg, attr);
-               msg->build(msg);
-               result = imc_test->send_message(imc_test, connection_id, FALSE, imc_id,
-                                                                               TNC_IMVID_ANY, msg->get_encoding(msg)); 
-               msg->destroy(msg);
-       }
-       enumerator->destroy(enumerator);
-
        return result;
 }
 
@@ -233,12 +210,41 @@ static TNC_Result send_message(TNC_ConnectionID connection_id)
 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
                                                                  TNC_ConnectionID connection_id)
 {
+       imc_state_t *state;
+       imc_test_state_t *test_state;
+       enumerator_t *enumerator;
+       void *pointer;
+       TNC_UInt32 additional_id;
+       TNC_Result result;
+
        if (!imc_test)
        {
                DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
                return TNC_RESULT_NOT_INITIALIZED;
        }
-       return send_message(connection_id);
+
+       /* get current IMC state */
+       if (!imc_test->get_state(imc_test, connection_id, &state))
+       {
+               return TNC_RESULT_FATAL;
+       }
+       test_state = (imc_test_state_t*)state;
+
+       /* send PA message for primary IMC ID */
+       result = send_message(state, imc_id, TNC_IMVID_ANY);
+       
+       /* send PA messages for additional IMC IDs */
+       enumerator = test_state->create_id_enumerator(test_state);
+       while (result == TNC_RESULT_SUCCESS &&
+                  enumerator->enumerate(enumerator, &pointer))
+       {
+               /* interpret pointer as scalar value */
+               additional_id = (TNC_UInt32)pointer;
+               result = send_message(state, additional_id, TNC_IMVID_ANY);     
+       }
+       enumerator->destroy(enumerator);
+
+       return result;
 }
 
 static TNC_Result receive_message(TNC_IMCID imc_id,
@@ -300,7 +306,8 @@ static TNC_Result receive_message(TNC_IMCID imc_id,
        pa_tnc_msg->destroy(pa_tnc_msg);
 
        /* if no error occurred then always return the same response */
-       return fatal_error ? TNC_RESULT_FATAL : send_message(connection_id);
+       return fatal_error ? TNC_RESULT_FATAL :
+                                                send_message(state, dst_imc_id, src_imv_id);
 }
 
 /**
index be5aa98..0afd81a 100644 (file)
@@ -71,9 +71,6 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
                                                                                  TNC_ConnectionState new_state)
 {
        imv_state_t *state;
-       imv_test_state_t *test_state;
-       TNC_Result result;
-       int rounds;
 
        if (!imv_test)
        {
@@ -87,44 +84,12 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
                        return imv_test->create_state(imv_test, state);
                case TNC_CONNECTION_STATE_DELETE:
                        return imv_test->delete_state(imv_test, connection_id);
-               case TNC_CONNECTION_STATE_HANDSHAKE:
-                       /* get updated IMV state */
-                       result = imv_test->change_state(imv_test, connection_id,
-                                                                                       new_state, &state);
-                       if (result != TNC_RESULT_SUCCESS)
-                       {
-                               return result;
-                       }
-                       test_state = (imv_test_state_t*)state;
-
-                       /* set the number of measurement rounds */
-                       rounds = lib->settings->get_int(lib->settings,
-                                                               "libimcv.plugins.imv-test.rounds", 0);
-                       test_state->set_rounds(test_state, rounds);
-                       return TNC_RESULT_SUCCESS;
                default:
                        return imv_test->change_state(imv_test, connection_id,
                                                                                  new_state, NULL);
        }
 }
 
-static TNC_Result send_message(TNC_ConnectionID connection_id)
-{
-       pa_tnc_msg_t *msg;
-       pa_tnc_attr_t *attr;
-       TNC_Result result;
-
-       attr = ita_attr_command_create("repeat");
-       msg = pa_tnc_msg_create();
-       msg->add_attribute(msg, attr);
-       msg->build(msg);
-       result = imv_test->send_message(imv_test, connection_id, FALSE, 0,
-                                                                       TNC_IMCID_ANY, msg->get_encoding(msg)); 
-       msg->destroy(msg);
-
-       return result;
-}
-
 static TNC_Result receive_message(TNC_IMVID imv_id,
                                                                  TNC_ConnectionID connection_id,
                                                                  TNC_UInt32 msg_flags,
@@ -137,9 +102,10 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
        pa_tnc_msg_t *pa_tnc_msg;
        pa_tnc_attr_t *attr;
        imv_state_t *state;
-       imv_test_state_t *imv_test_state;
+       imv_test_state_t *test_state;
        enumerator_t *enumerator;
        TNC_Result result;
+       int rounds;
        bool fatal_error, retry = FALSE;
 
        if (!imv_test)
@@ -153,6 +119,7 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
        {
                return TNC_RESULT_FATAL;
        }
+       test_state = (imv_test_state_t*)state;
 
        /* parse received PA-TNC message and automatically handle any errors */ 
        result = imv_test->receive_message(imv_test, state, msg, msg_vid,
@@ -167,6 +134,11 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
        /* preprocess any IETF standard error attributes */
        fatal_error = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg);
 
+       /* add any new IMC and set its number of rounds */
+       rounds = lib->settings->get_int(lib->settings,
+                                                               "libimcv.plugins.imv-test.rounds", 0);
+       test_state->add_imc(test_state, src_imc_id, rounds);
+
        /* analyze PA-TNC attributes */
        enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
        while (enumerator->enumerate(enumerator, &attr))
@@ -225,15 +197,23 @@ static TNC_Result receive_message(TNC_IMVID imv_id,
        /* request a handshake retry ? */
        if (retry)
        {
+               test_state->set_rounds(test_state, rounds);
                return imv_test->request_handshake_retry(imv_id, connection_id,
                                                                TNC_RETRY_REASON_IMV_SERIOUS_EVENT);
        }
        
        /* repeat the measurement ? */
-       imv_test_state = (imv_test_state_t*)state;
-       if (imv_test_state->another_round(imv_test_state))
+       if (test_state->another_round(test_state, src_imc_id))
        {
-               return send_message(connection_id);
+               attr = ita_attr_command_create("repeat");
+               pa_tnc_msg = pa_tnc_msg_create();
+               pa_tnc_msg->add_attribute(pa_tnc_msg, attr);
+               pa_tnc_msg->build(pa_tnc_msg);
+               result = imv_test->send_message(imv_test, connection_id, TRUE, imv_id,
+                                                       src_imc_id, pa_tnc_msg->get_encoding(pa_tnc_msg));      
+               pa_tnc_msg->destroy(pa_tnc_msg);
+
+               return result;
        }
 
        return imv_test->provide_recommendation(imv_test, connection_id);
index 9df117a..530090a 100644 (file)
@@ -15,6 +15,7 @@
 #include "imv_test_state.h"
 
 #include <utils/lexparser.h>
+#include <utils/linked_list.h>
 #include <debug.h>
 
 typedef struct private_imv_test_state_t private_imv_test_state_t;
@@ -60,10 +61,20 @@ struct private_imv_test_state_t {
        TNC_IMV_Evaluation_Result eval;
 
        /**
-        * IMC-IMV round-trip count
+        * List of IMCs
         */
-       int rounds;
+       linked_list_t *imcs;
+
+};
+
+typedef struct imc_entry_t imc_entry_t;
 
+/**
+ * Define an internal IMC entry
+ */
+struct imc_entry_t {
+       TNC_UInt32 imc_id;
+       int rounds;
 };
 
 typedef struct entry_t entry_t;
@@ -180,19 +191,73 @@ METHOD(imv_state_t, get_reason_string, bool,
 METHOD(imv_state_t, destroy, void,
        private_imv_test_state_t *this)
 {
+       this->imcs->destroy_function(this->imcs, free);
        free(this);
 }
 
+METHOD(imv_test_state_t, add_imc, void,
+       private_imv_test_state_t *this, TNC_UInt32 imc_id, int rounds)
+{
+       enumerator_t *enumerator;
+       imc_entry_t *imc_entry;
+       bool found = FALSE;
+
+       enumerator = this->imcs->create_enumerator(this->imcs);
+       while (enumerator->enumerate(enumerator, &imc_entry))
+       {
+               if (imc_entry->imc_id == imc_id)
+               {
+                       found = TRUE;
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       if (!found)
+       {
+               imc_entry = malloc_thing(imc_entry_t);
+               imc_entry->imc_id = imc_id;
+               imc_entry->rounds = rounds;
+               this->imcs->insert_last(this->imcs, imc_entry);
+       }
+}
+
 METHOD(imv_test_state_t, set_rounds, void,
        private_imv_test_state_t *this, int rounds)
 {
-       this->rounds = rounds;
+       enumerator_t *enumerator;
+       imc_entry_t *imc_entry;
+
+       enumerator = this->imcs->create_enumerator(this->imcs);
+       while (enumerator->enumerate(enumerator, &imc_entry))
+       {
+               imc_entry->rounds = rounds;
+       }
+       enumerator->destroy(enumerator);
 }
 
 METHOD(imv_test_state_t, another_round, bool,
-       private_imv_test_state_t *this)
+       private_imv_test_state_t *this, TNC_UInt32 imc_id)
 {
-       return (this->rounds-- > 0);
+       enumerator_t *enumerator;
+       imc_entry_t *imc_entry;
+       bool not_finished = FALSE;
+
+       enumerator = this->imcs->create_enumerator(this->imcs);
+       while (enumerator->enumerate(enumerator, &imc_entry))
+       {
+               if (imc_entry->rounds > 0)
+               {
+                       not_finished = TRUE;
+               }
+               if (imc_entry->imc_id == imc_id)
+               {
+                       imc_entry->rounds--;
+               }
+       }
+       enumerator->destroy(enumerator);
+       
+       return not_finished;    
 }
 
 /**
@@ -215,6 +280,7 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
                                .get_reason_string = _get_reason_string,
                                .destroy = _destroy,
                        },
+                       .add_imc = _add_imc,
                        .set_rounds = _set_rounds,
                        .another_round = _another_round,
                },
@@ -222,6 +288,7 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
                .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
                .connection_id = connection_id,
+               .imcs = linked_list_create(),
        );
        
        return &this->public.interface;
index 7e7b3a8..af78d14 100644 (file)
@@ -37,6 +37,14 @@ struct imv_test_state_t {
        imv_state_t interface;
 
        /**
+        * Add an IMC
+        *
+        * @param imc_id        ID of the IMC to be added
+        * @param rounds        number of re-measurement rounds
+        */
+       void (*add_imc)(imv_test_state_t *this, TNC_UInt32 imc_id, int rounds);
+
+       /**
         * Set the IMC-IMV round-trip count
         *
         * @param rounds        number of re-measurement rounds
@@ -46,9 +54,10 @@ struct imv_test_state_t {
        /**
         * Check and decrease IMC-IMV round-trip count
         *
+        * @param imc_id        ID of the IMC to be checked
         * @return                      new connection state
         */
-       bool (*another_round)(imv_test_state_t *this);
+       bool (*another_round)(imv_test_state_t *this, TNC_UInt32 imc_id);
 };
 
 /**
index 78eaf0e..50d7af6 100644 (file)
@@ -14,6 +14,7 @@ libimcv {
   plugins {
     imc-test {
       command = allow
+      additional_ids = 2
     }
   }
 }
index 2e56fb1..b67541c 100644 (file)
@@ -17,6 +17,7 @@ libimcv {
   plugins {
     imc-test {
       command = isolate
+      additional_ids = 1
     }
   }
 }