From: Mike Stepanek (mstepane) Date: Thu, 25 Feb 2021 15:03:21 +0000 (+0000) Subject: Merge pull request #2764 in SNORT/snort3 from ~JRITTLE/snort3:iec104_trace_fix to... X-Git-Tag: 3.1.2.0~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=50debe1258b70a122e564e463c27d3e92bb0ef3a;p=thirdparty%2Fsnort3.git Merge pull request #2764 in SNORT/snort3 from ~JRITTLE/snort3:iec104_trace_fix to master Squashed commit of the following: commit 888682bccf55b3b6f93c6d2a023fc295e34b99d6 Author: jrittle Date: Wed Feb 24 09:40:49 2021 -0500 iec104: additional input sanitization, syntax, and style changes --- diff --git a/src/service_inspectors/iec104/iec104_module.h b/src/service_inspectors/iec104/iec104_module.h index 37ef3245c..bf25f598b 100644 --- a/src/service_inspectors/iec104/iec104_module.h +++ b/src/service_inspectors/iec104/iec104_module.h @@ -66,11 +66,6 @@ public: const snort::TraceOption* get_trace_options() const override; }; -#endif - -#ifndef IEC104_RULES -#define IEC104_RULES - #define IEC104_BAD_LENGTH 1 #define IEC104_BAD_START 2 #define IEC104_RESERVED_ASDU_TYPE 3 diff --git a/src/service_inspectors/iec104/iec104_parse_apdu.cc b/src/service_inspectors/iec104/iec104_parse_apdu.cc index f7a852122..187cf1379 100644 --- a/src/service_inspectors/iec104/iec104_parse_apdu.cc +++ b/src/service_inspectors/iec104/iec104_parse_apdu.cc @@ -1330,7 +1330,7 @@ static void parseIec104GenericIOGroup(const GenericIec104AsduIOGroup* genericIOG static void parseIec104GenericAsdu(uint32_t asduType, const Iec104ApciI* apci) { - uint8_t verifiedNumberOfElements = parseIec104Vsq(apci); + uint32_t verifiedNumberOfElements = parseIec104Vsq(apci); parseIec104CauseOfTx(apci); parseIec104TwoOctetCommonAddress(apci); @@ -1339,1187 +1339,1190 @@ static void parseIec104GenericAsdu(uint32_t asduType, const Iec104ApciI* apci) genericIOGroup.asduType = asduType; genericIOGroup.apduSize = apci->header.length; - // iterate over the reported number of elements overlaying the structures - for (uint32_t i = 0; i < verifiedNumberOfElements; i++) - { - - // - // Handle Structure Qualifier == 1 - // - if (apci->asdu.variableStructureQualifier.sq) - { - // IOA should only be printed on the first iteration in SQ1 - if (i == 0) - { - genericIOGroup.includeIOA = true; - } - else - { - genericIOGroup.includeIOA = false; - } - - // fill genericIOGroup with the appropriate asdu depending on the type - switch (asduType) - { - case IEC104_ASDU_M_SP_NA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_sp_na_1IOGroup = &apci->asdu.m_sp_na_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_SP_NA_1_IO_Subgroup* curIo = &apci->asdu.m_sp_na_1.subgroup + i; - genericIOGroup.m_sp_na_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_SP_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_DP_NA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_dp_na_1IOGroup = &apci->asdu.m_dp_na_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_DP_NA_1_IO_Subgroup* curIo = &apci->asdu.m_dp_na_1.subgroup + i; - genericIOGroup.m_dp_na_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_DP_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_ST_NA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_st_na_1IOGroup = &apci->asdu.m_st_na_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_ST_NA_1_IO_Subgroup* curIo = &apci->asdu.m_st_na_1.subgroup + i; - genericIOGroup.m_st_na_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_ST_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_BO_NA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_bo_na_1IOGroup = &apci->asdu.m_bo_na_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_BO_NA_1_IO_Subgroup* curIo = &apci->asdu.m_bo_na_1.subgroup + i; - genericIOGroup.m_bo_na_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_BO_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_ME_NA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_me_na_1IOGroup = &apci->asdu.m_me_na_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_ME_NA_1_IO_Subgroup* curIo = &apci->asdu.m_me_na_1.subgroup + i; - genericIOGroup.m_me_na_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_ME_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_ME_NB_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_me_nb_1IOGroup = &apci->asdu.m_me_nb_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_ME_NB_1_IO_Subgroup* curIo = &apci->asdu.m_me_nb_1.subgroup + i; - genericIOGroup.m_me_nb_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_ME_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_ME_NC_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_me_nc_1IOGroup = &apci->asdu.m_me_nc_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_ME_NC_1_IO_Subgroup* curIo = &apci->asdu.m_me_nc_1.subgroup + i; - genericIOGroup.m_me_nc_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_ME_TC_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_IT_NA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_it_na_1IOGroup = &apci->asdu.m_it_na_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_IT_NA_1_IO_Subgroup* curIo = &apci->asdu.m_it_na_1.subgroup + i; - genericIOGroup.m_it_na_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_IT_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_EP_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_EP_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_EP_TC_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_M_PS_NA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_ps_na_1IOGroup = &apci->asdu.m_ps_na_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_PS_NA_1_IO_Subgroup* curIo = &apci->asdu.m_ps_na_1.subgroup + i; - genericIOGroup.m_ps_na_1IOSubgroup = curIo; - - break; - } - - case IEC104_ASDU_M_ME_ND_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.m_me_nd_1IOGroup = &apci->asdu.m_me_nd_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104M_ME_ND_1_IO_Subgroup* curIo = &apci->asdu.m_me_nd_1.subgroup + i; - genericIOGroup.m_me_nd_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_M_SP_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_DP_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_ST_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_BO_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_ME_TD_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_ME_TE_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_ME_TF_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_IT_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_EP_TD_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_EP_TE_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_EP_TF_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SC_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_DC_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_RC_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SE_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SE_NB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SE_NC_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_BO_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SC_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_DC_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_RC_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SE_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SE_TB_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_SE_TC_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_BO_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_M_EI_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_IC_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_CI_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_RD_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_CS_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_TS_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_RP_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_CD_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_C_TS_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - //case IEC104_ASDU_P_ME_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - //case IEC104_ASDU_P_ME_NB_1 - // path doesn't happen as it gets caught during the ASDU check - - //case IEC104_ASDU_P_ME_NC_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_P_AC_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_F_FR_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_F_SR_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_F_SC_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_F_LS_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_F_AF_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - // case IEC104_ASDU_F_SG_NA_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_F_DR_TA_1: - { - // Since there is only one full IOGroup structure in SQ1 this can stay for all cases - genericIOGroup.f_dr_ta_1IOGroup = &apci->asdu.f_dr_ta_1; - - // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer - // since `i` will be 0 on the first go round this works for all iterations - // since C adds based on the pointer type we only need to cast and increment - const Iec104F_DR_TA_1_IO_Subgroup* curIo = &apci->asdu.f_dr_ta_1.subgroup + i; - genericIOGroup.f_dr_ta_1IOSubgroup = curIo; - - break; - } - - // case IEC104_ASDU_F_SC_NB_1 - // path doesn't happen as it gets caught during the ASDU check - - default: - { - // SQ1 ASDU parsing not implemented for this type - } - } - - // parse the new subgroup - parseIec104GenericIOGroup(&genericIOGroup); - - } - // - // Handle Structure Qualifier == 0 - // - else - { - // the IOA should always be included for SQ0 - genericIOGroup.includeIOA = true; - - // fill genericIOGroup with the appropriate asdu depending on the type - switch (asduType) - { - case IEC104_ASDU_M_SP_NA_1: - { - // increment the information object block pointer by the size of the M_SP_NA_1_IO_Group struct - const Iec104M_SP_NA_1_IO_Group* curIo = - (const Iec104M_SP_NA_1_IO_Group*) &apci->asdu.m_sp_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_sp_na_1IOGroup = curIo; - genericIOGroup.m_sp_na_1IOSubgroup = &curIo->subgroup; - - break; - } - - case IEC104_ASDU_M_SP_TA_1: - { - // increment the information object block pointer by the size of the M_SP_TA_1_IO_Group struct - const Iec104M_SP_TA_1_IO_Group* curIo = - (const Iec104M_SP_TA_1_IO_Group*) &apci->asdu.m_sp_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_sp_ta_1IOGroup = curIo; - genericIOGroup.m_sp_ta_1IOSubgroup = &curIo->subgroup; - - break; - } - - case IEC104_ASDU_M_DP_NA_1: - { - // increment the information object block pointer by the size of the M_DP_NA_1_IO_Group struct - const Iec104M_DP_NA_1_IO_Group* curIo = - (const Iec104M_DP_NA_1_IO_Group*) &apci->asdu.m_dp_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_dp_na_1IOGroup = curIo; - genericIOGroup.m_dp_na_1IOSubgroup = &curIo->subgroup; - - break; - } + // make sure the number of elements value is acceptable + if (verifiedNumberOfElements > 0 && verifiedNumberOfElements <= 255) { + // iterate over the reported number of elements overlaying the structures + for (uint32_t i = 0; i < verifiedNumberOfElements; i++) + { + + // + // Handle Structure Qualifier == 1 + // + if (apci->asdu.variableStructureQualifier.sq) + { + // IOA should only be printed on the first iteration in SQ1 + if (i == 0) + { + genericIOGroup.includeIOA = true; + } + else + { + genericIOGroup.includeIOA = false; + } + + // fill genericIOGroup with the appropriate asdu depending on the type + switch (asduType) + { + case IEC104_ASDU_M_SP_NA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_sp_na_1IOGroup = &apci->asdu.m_sp_na_1; + + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_SP_NA_1_IO_Subgroup* curIo = &apci->asdu.m_sp_na_1.subgroup + i; + genericIOGroup.m_sp_na_1IOSubgroup = curIo; + + break; + } + + // case IEC104_ASDU_M_SP_TA_1 + // path doesn't happen as it gets caught during the ASDU check + + case IEC104_ASDU_M_DP_NA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_dp_na_1IOGroup = &apci->asdu.m_dp_na_1; + + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_DP_NA_1_IO_Subgroup* curIo = &apci->asdu.m_dp_na_1.subgroup + i; + genericIOGroup.m_dp_na_1IOSubgroup = curIo; + + break; + } + + // case IEC104_ASDU_M_DP_TA_1 + // path doesn't happen as it gets caught during the ASDU check + + case IEC104_ASDU_M_ST_NA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_st_na_1IOGroup = &apci->asdu.m_st_na_1; + + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_ST_NA_1_IO_Subgroup* curIo = &apci->asdu.m_st_na_1.subgroup + i; + genericIOGroup.m_st_na_1IOSubgroup = curIo; + + break; + } + + // case IEC104_ASDU_M_ST_TA_1 + // path doesn't happen as it gets caught during the ASDU check + + case IEC104_ASDU_M_BO_NA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_bo_na_1IOGroup = &apci->asdu.m_bo_na_1; + + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_BO_NA_1_IO_Subgroup* curIo = &apci->asdu.m_bo_na_1.subgroup + i; + genericIOGroup.m_bo_na_1IOSubgroup = curIo; + + break; + } + + // case IEC104_ASDU_M_BO_TA_1 + // path doesn't happen as it gets caught during the ASDU check + + case IEC104_ASDU_M_ME_NA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_me_na_1IOGroup = &apci->asdu.m_me_na_1; + + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_ME_NA_1_IO_Subgroup* curIo = &apci->asdu.m_me_na_1.subgroup + i; + genericIOGroup.m_me_na_1IOSubgroup = curIo; + + break; + } + + // case IEC104_ASDU_M_ME_TA_1 + // path doesn't happen as it gets caught during the ASDU check + + case IEC104_ASDU_M_ME_NB_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_me_nb_1IOGroup = &apci->asdu.m_me_nb_1; + + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_ME_NB_1_IO_Subgroup* curIo = &apci->asdu.m_me_nb_1.subgroup + i; + genericIOGroup.m_me_nb_1IOSubgroup = curIo; + + break; + } + + // case IEC104_ASDU_M_ME_TB_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_DP_TA_1: - { - // increment the information object block pointer by the size of the M_DP_TA_1_IO_Group struct - const Iec104M_DP_TA_1_IO_Group* curIo = - (const Iec104M_DP_TA_1_IO_Group*) &apci->asdu.m_dp_ta_1 + i; + case IEC104_ASDU_M_ME_NC_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_me_nc_1IOGroup = &apci->asdu.m_me_nc_1; - // print the SQ0 IO block - genericIOGroup.m_dp_ta_1IOGroup = curIo; - genericIOGroup.m_dp_ta_1IOSubgroup = &curIo->subgroup; + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_ME_NC_1_IO_Subgroup* curIo = &apci->asdu.m_me_nc_1.subgroup + i; + genericIOGroup.m_me_nc_1IOSubgroup = curIo; - break; - } + break; + } - case IEC104_ASDU_M_ST_NA_1: - { - // increment the information object block pointer by the size of the M_ST_NA_1_IO_Group struct - const Iec104M_ST_NA_1_IO_Group* curIo = - (const Iec104M_ST_NA_1_IO_Group*) &apci->asdu.m_st_na_1 + i; + // case IEC104_ASDU_M_ME_TC_1 + // path doesn't happen as it gets caught during the ASDU check - // print the SQ0 IO block - genericIOGroup.m_st_na_1IOGroup = curIo; - genericIOGroup.m_st_na_1IOSubgroup = &curIo->subgroup; + case IEC104_ASDU_M_IT_NA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_it_na_1IOGroup = &apci->asdu.m_it_na_1; - break; - } + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_IT_NA_1_IO_Subgroup* curIo = &apci->asdu.m_it_na_1.subgroup + i; + genericIOGroup.m_it_na_1IOSubgroup = curIo; - case IEC104_ASDU_M_ST_TA_1: - { - // increment the information object block pointer by the size of the M_ST_TA_1_IO_Group struct - const Iec104M_ST_TA_1_IO_Group* curIo = - (const Iec104M_ST_TA_1_IO_Group*) &apci->asdu.m_st_ta_1 + i; + break; + } - // print the SQ0 IO block - genericIOGroup.m_st_ta_1IOGroup = curIo; - genericIOGroup.m_st_ta_1IOSubgroup = &curIo->subgroup; + // case IEC104_ASDU_M_IT_TA_1 + // path doesn't happen as it gets caught during the ASDU check - break; - } + // case IEC104_ASDU_M_EP_TA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_BO_NA_1: - { - // increment the information object block pointer by the size of the M_BO_NA_1_IO_Group struct - const Iec104M_BO_NA_1_IO_Group* curIo = - (const Iec104M_BO_NA_1_IO_Group*) &apci->asdu.m_bo_na_1 + i; + // case IEC104_ASDU_M_EP_TB_1 + // path doesn't happen as it gets caught during the ASDU check - // print the SQ0 IO block - genericIOGroup.m_bo_na_1IOGroup = curIo; - genericIOGroup.m_bo_na_1IOSubgroup = &curIo->subgroup; + // case IEC104_ASDU_M_EP_TC_1 + // path doesn't happen as it gets caught during the ASDU check - break; - } + case IEC104_ASDU_M_PS_NA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_ps_na_1IOGroup = &apci->asdu.m_ps_na_1; - case IEC104_ASDU_M_BO_TA_1: - { - // increment the information object block pointer by the size of the M_BO_TA_1_IO_Group struct - const Iec104M_BO_TA_1_IO_Group* curIo = - (const Iec104M_BO_TA_1_IO_Group*) &apci->asdu.m_bo_ta_1 + i; + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_PS_NA_1_IO_Subgroup* curIo = &apci->asdu.m_ps_na_1.subgroup + i; + genericIOGroup.m_ps_na_1IOSubgroup = curIo; - // print the SQ0 IO block - genericIOGroup.m_bo_ta_1IOGroup = curIo; - genericIOGroup.m_bo_ta_1IOSubgroup = &curIo->subgroup; + break; + } - break; - } + case IEC104_ASDU_M_ME_ND_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.m_me_nd_1IOGroup = &apci->asdu.m_me_nd_1; - case IEC104_ASDU_M_ME_NA_1: - { - // increment the information object block pointer by the size of the M_ME_NA_1_IO_Group struct - const Iec104M_ME_NA_1_IO_Group* curIo = - (const Iec104M_ME_NA_1_IO_Group*) &apci->asdu.m_me_na_1 + i; + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104M_ME_ND_1_IO_Subgroup* curIo = &apci->asdu.m_me_nd_1.subgroup + i; + genericIOGroup.m_me_nd_1IOSubgroup = curIo; - // print the SQ0 IO block - genericIOGroup.m_me_na_1IOGroup = curIo; - genericIOGroup.m_me_na_1IOSubgroup = &curIo->subgroup; + break; + } - break; - } + // case IEC104_ASDU_M_SP_TB_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_TA_1: - { - // increment the information object block pointer by the size of the M_ME_TA_1_IO_Group struct - const Iec104M_ME_TA_1_IO_Group* curIo = - (const Iec104M_ME_TA_1_IO_Group*) &apci->asdu.m_me_ta_1 + i; + // case IEC104_ASDU_M_DP_TB_1 + // path doesn't happen as it gets caught during the ASDU check - // print the SQ0 IO block - genericIOGroup.m_me_ta_1IOGroup = curIo; - genericIOGroup.m_me_ta_1IOSubgroup = &curIo->subgroup; + // case IEC104_ASDU_M_ST_TB_1 + // path doesn't happen as it gets caught during the ASDU check - break; - } + // case IEC104_ASDU_M_BO_TB_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_NB_1: - { - // increment the information object block pointer by the size of the M_ME_NB_1_IO_Group struct - const Iec104M_ME_NB_1_IO_Group* curIo = - (const Iec104M_ME_NB_1_IO_Group*) &apci->asdu.m_me_nb_1 + i; + // case IEC104_ASDU_M_ME_TD_1 + // path doesn't happen as it gets caught during the ASDU check - // print the SQ0 IO block - genericIOGroup.m_me_nb_1IOGroup = curIo; - genericIOGroup.m_me_nb_1IOSubgroup = &curIo->subgroup; + // case IEC104_ASDU_M_ME_TE_1 + // path doesn't happen as it gets caught during the ASDU check - break; - } + // case IEC104_ASDU_M_ME_TF_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_TB_1: - { - // increment the information object block pointer by the size of the M_ME_TB_1_IO_Group struct - const Iec104M_ME_TB_1_IO_Group* curIo = - (const Iec104M_ME_TB_1_IO_Group*) &apci->asdu.m_me_tb_1 + i; + // case IEC104_ASDU_M_IT_TB_1 + // path doesn't happen as it gets caught during the ASDU check - // print the SQ0 IO block - genericIOGroup.m_me_tb_1IOGroup = curIo; - genericIOGroup.m_me_tb_1IOSubgroup = &curIo->subgroup; + // case IEC104_ASDU_M_EP_TD_1 + // path doesn't happen as it gets caught during the ASDU check - break; - } + // case IEC104_ASDU_M_EP_TE_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_NC_1: - { - // increment the information object block pointer by the size of the M_ME_NC_1_IO_Group struct - const Iec104M_ME_NC_1_IO_Group* curIo = - (const Iec104M_ME_NC_1_IO_Group*) &apci->asdu.m_me_nc_1 + i; + // case IEC104_ASDU_M_EP_TF_1 + // path doesn't happen as it gets caught during the ASDU check - // print the SQ0 IO block - genericIOGroup.m_me_nc_1IOGroup = curIo; - genericIOGroup.m_me_nc_1IOSubgroup = &curIo->subgroup; + // case IEC104_ASDU_C_SC_NA_1 + // path doesn't happen as it gets caught during the ASDU check - break; - } + // case IEC104_ASDU_C_DC_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_TC_1: - { - // increment the information object block pointer by the size of the M_ME_TC_1_IO_Group struct - const Iec104M_ME_TC_1_IO_Group* curIo = - (const Iec104M_ME_TC_1_IO_Group*) &apci->asdu.m_me_tc_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_me_tc_1IOGroup = curIo; - genericIOGroup.m_me_tc_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_RC_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_IT_NA_1: - { - // increment the information object block pointer by the size of the M_IT_NA_1_IO_Group struct - const Iec104M_IT_NA_1_IO_Group* curIo = - (const Iec104M_IT_NA_1_IO_Group*) &apci->asdu.m_it_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_it_na_1IOGroup = curIo; - genericIOGroup.m_it_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_SE_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_IT_TA_1: - { - // increment the information object block pointer by the size of the M_IT_TA_1_IO_Group struct - const Iec104M_IT_TA_1_IO_Group* curIo = - (const Iec104M_IT_TA_1_IO_Group*) &apci->asdu.m_it_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_it_ta_1IOGroup = curIo; - genericIOGroup.m_it_ta_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_SE_NB_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_EP_TA_1: - { - // increment the information object block pointer by the size of the M_EP_TA_1_IO_Group struct - const Iec104M_EP_TA_1_IO_Group* curIo = - (const Iec104M_EP_TA_1_IO_Group*) &apci->asdu.m_ep_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ep_ta_1IOGroup = curIo; - genericIOGroup.m_ep_ta_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_SE_NC_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_EP_TB_1: - { - // increment the information object block pointer by the size of the M_EP_TB_1_IO_Group struct - const Iec104M_EP_TB_1_IO_Group* curIo = - (const Iec104M_EP_TB_1_IO_Group*) &apci->asdu.m_ep_tb_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ep_tb_1IOGroup = curIo; - genericIOGroup.m_ep_tb_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_BO_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_EP_TC_1: - { - // increment the information object block pointer by the size of the M_EP_TC_1_IO_Group struct - const Iec104M_EP_TC_1_IO_Group* curIo = - (const Iec104M_EP_TC_1_IO_Group*) &apci->asdu.m_ep_tc_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ep_tc_1IOGroup = curIo; - genericIOGroup.m_ep_tc_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_SC_TA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_PS_NA_1: - { - // increment the information object block pointer by the size of the M_PS_NA_1_IO_Group struct - const Iec104M_PS_NA_1_IO_Group* curIo = - (const Iec104M_PS_NA_1_IO_Group*) &apci->asdu.m_ps_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ps_na_1IOGroup = curIo; - genericIOGroup.m_ps_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_DC_TA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_ND_1: - { - // increment the information object block pointer by the size of the M_ME_ND_1_IO_Group struct - const Iec104M_ME_ND_1_IO_Group* curIo = - (const Iec104M_ME_ND_1_IO_Group*) &apci->asdu.m_me_nd_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_me_nd_1IOGroup = curIo; - genericIOGroup.m_me_nd_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_RC_TA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_SP_TB_1: - { - // increment the information object block pointer by the size of the M_SP_TB_1_IO_Group struct - const Iec104M_SP_TB_1_IO_Group* curIo = - (const Iec104M_SP_TB_1_IO_Group*) &apci->asdu.m_sp_tb_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_sp_tb_1IOGroup = curIo; - genericIOGroup.m_sp_tb_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_SE_TA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_DP_TB_1: - { - // increment the information object block pointer by the size of the M_DP_TB_1_IO_Group struct - const Iec104M_DP_TB_1_IO_Group* curIo = - (const Iec104M_DP_TB_1_IO_Group*) &apci->asdu.m_dp_tb_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_dp_tb_1IOGroup = curIo; - genericIOGroup.m_dp_tb_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_SE_TB_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ST_TB_1: - { - // increment the information object block pointer by the size of the M_ST_TB_1_IO_Group struct - const Iec104M_ST_TB_1_IO_Group* curIo = - (const Iec104M_ST_TB_1_IO_Group*) &apci->asdu.m_st_tb_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_st_tb_1IOGroup = curIo; - genericIOGroup.m_st_tb_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_SE_TC_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_BO_TB_1: - { - // increment the information object block pointer by the size of the M_BO_TB_1_IO_Group struct - const Iec104M_BO_TB_1_IO_Group* curIo = - (const Iec104M_BO_TB_1_IO_Group*) &apci->asdu.m_bo_tb_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_bo_tb_1IOGroup = curIo; - genericIOGroup.m_bo_tb_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_BO_TA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_TD_1: - { - // increment the information object block pointer by the size of the M_ME_TD_1_IO_Group struct - const Iec104M_ME_TD_1_IO_Group* curIo = - (const Iec104M_ME_TD_1_IO_Group*) &apci->asdu.m_me_td_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_me_td_1IOGroup = curIo; - genericIOGroup.m_me_td_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_M_EI_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_TE_1: - { - // increment the information object block pointer by the size of the M_ME_TE_1_IO_Group struct - const Iec104M_ME_TE_1_IO_Group* curIo = - (const Iec104M_ME_TE_1_IO_Group*) &apci->asdu.m_me_te_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_me_te_1IOGroup = curIo; - genericIOGroup.m_me_te_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_IC_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_ME_TF_1: - { - // increment the information object block pointer by the size of the M_ME_TF_1_IO_Group struct - const Iec104M_ME_TF_1_IO_Group* curIo = - (const Iec104M_ME_TF_1_IO_Group*) &apci->asdu.m_me_tf_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_me_tf_1IOGroup = curIo; - genericIOGroup.m_me_tf_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_CI_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_IT_TB_1: - { - // increment the information object block pointer by the size of the M_IT_TB_1_IO_Group struct - const Iec104M_IT_TB_1_IO_Group* curIo = - (const Iec104M_IT_TB_1_IO_Group*) &apci->asdu.m_it_tb_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_it_tb_1IOGroup = curIo; - genericIOGroup.m_it_tb_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_RD_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_EP_TD_1: - { - // increment the information object block pointer by the size of the M_EP_TD_1_IO_Group struct - const Iec104M_EP_TD_1_IO_Group* curIo = - (const Iec104M_EP_TD_1_IO_Group*) &apci->asdu.m_ep_td_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ep_td_1IOGroup = curIo; - genericIOGroup.m_ep_td_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_CS_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_EP_TE_1: - { - // increment the information object block pointer by the size of the M_EP_TE_1_IO_Group struct - const Iec104M_EP_TE_1_IO_Group* curIo = - (const Iec104M_EP_TE_1_IO_Group*) &apci->asdu.m_ep_te_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ep_te_1IOGroup = curIo; - genericIOGroup.m_ep_te_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_TS_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_M_EP_TF_1: - { - // increment the information object block pointer by the size of the M_EP_TF_1_IO_Group struct - const Iec104M_EP_TF_1_IO_Group* curIo = - (const Iec104M_EP_TF_1_IO_Group*) &apci->asdu.m_ep_tf_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ep_tf_1IOGroup = curIo; - genericIOGroup.m_ep_tf_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_RP_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_SC_NA_1: - { - // increment the information object block pointer by the size of the C_SC_NA_1_IO_Group struct - const Iec104C_SC_NA_1_IO_Group* curIo = - (const Iec104C_SC_NA_1_IO_Group*) &apci->asdu.c_sc_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_sc_na_1IOGroup = curIo; - genericIOGroup.c_sc_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_CD_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_DC_NA_1: - { - // increment the information object block pointer by the size of the C_DC_NA_1_IO_Group struct - const Iec104C_DC_NA_1_IO_Group* curIo = - (const Iec104C_DC_NA_1_IO_Group*) &apci->asdu.c_dc_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_dc_na_1IOGroup = curIo; - genericIOGroup.c_dc_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_C_TS_TA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_RC_NA_1: - { - // increment the information object block pointer by the size of the C_RC_NA_1_IO_Group struct - const Iec104C_RC_NA_1_IO_Group* curIo = - (const Iec104C_RC_NA_1_IO_Group*) &apci->asdu.c_rc_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_rc_na_1IOGroup = curIo; - genericIOGroup.c_rc_na_1IOSubgroup = &curIo->subgroup; - break; - } + //case IEC104_ASDU_P_ME_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_SE_NA_1: - { - // increment the information object block pointer by the size of the C_SE_NA_1_IO_Group struct - const Iec104C_SE_NA_1_IO_Group* curIo = - (const Iec104C_SE_NA_1_IO_Group*) &apci->asdu.c_se_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_se_na_1IOGroup = curIo; - genericIOGroup.c_se_na_1IOSubgroup = &curIo->subgroup; - break; - } + //case IEC104_ASDU_P_ME_NB_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_SE_NB_1: - { - // increment the information object block pointer by the size of the C_SE_NB_1_IO_Group struct - const Iec104C_SE_NB_1_IO_Group* curIo = - (const Iec104C_SE_NB_1_IO_Group*) &apci->asdu.c_se_nb_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_se_nb_1IOGroup = curIo; - genericIOGroup.c_se_nb_1IOSubgroup = &curIo->subgroup; - break; - } + //case IEC104_ASDU_P_ME_NC_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_SE_NC_1: - { - // increment the information object block pointer by the size of the C_SE_NC_1_IO_Group struct - const Iec104C_SE_NC_1_IO_Group* curIo = - (const Iec104C_SE_NC_1_IO_Group*) &apci->asdu.c_se_nc_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_se_nc_1IOGroup = curIo; - genericIOGroup.c_se_nc_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_P_AC_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_BO_NA_1: - { - // increment the information object block pointer by the size of the C_BO_NA_1_IO_Group struct - const Iec104C_BO_NA_1_IO_Group* curIo = - (const Iec104C_BO_NA_1_IO_Group*) &apci->asdu.c_bo_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_bo_na_1IOGroup = curIo; - genericIOGroup.c_bo_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_F_FR_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_SC_TA_1: - { - // increment the information object block pointer by the size of the C_SC_TA_1_IO_Group struct - const Iec104C_SC_TA_1_IO_Group* curIo = - (const Iec104C_SC_TA_1_IO_Group*) &apci->asdu.c_sc_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_sc_ta_1IOGroup = curIo; - genericIOGroup.c_sc_ta_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_DC_TA_1: - { - // increment the information object block pointer by the size of the C_DC_TA_1_IO_Group struct - const Iec104C_DC_TA_1_IO_Group* curIo = - (const Iec104C_DC_TA_1_IO_Group*) &apci->asdu.c_dc_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_dc_ta_1IOGroup = curIo; - genericIOGroup.c_dc_ta_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_RC_TA_1: - { - // increment the information object block pointer by the size of the C_RC_TA_1_IO_Group struct - const Iec104C_RC_TA_1_IO_Group* curIo = - (const Iec104C_RC_TA_1_IO_Group*) &apci->asdu.c_rc_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_rc_ta_1IOGroup = curIo; - genericIOGroup.c_rc_ta_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_SE_TA_1: - { - // increment the information object block pointer by the size of the C_SE_TA_1_IO_Group struct - const Iec104C_SE_TA_1_IO_Group* curIo = - (const Iec104C_SE_TA_1_IO_Group*) &apci->asdu.c_se_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_se_ta_1IOGroup = curIo; - genericIOGroup.c_se_ta_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_SE_TB_1: - { - // increment the information object block pointer by the size of the C_SE_TB_1_IO_Group struct - const Iec104C_SE_TB_1_IO_Group* curIo = - (const Iec104C_SE_TB_1_IO_Group*) &apci->asdu.c_se_tb_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_se_tb_1IOGroup = curIo; - genericIOGroup.c_se_tb_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_SE_TC_1: - { - // increment the information object block pointer by the size of the C_SE_TC_1_IO_Group struct - const Iec104C_SE_TC_1_IO_Group* curIo = - (const Iec104C_SE_TC_1_IO_Group*) &apci->asdu.c_se_tc_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_se_tc_1IOGroup = curIo; - genericIOGroup.c_se_tc_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_BO_TA_1: - { - // increment the information object block pointer by the size of the C_BO_TA_1_IO_Group struct - const Iec104C_BO_TA_1_IO_Group* curIo = - (const Iec104C_BO_TA_1_IO_Group*) &apci->asdu.c_bo_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_bo_ta_1IOGroup = curIo; - genericIOGroup.c_bo_ta_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_M_EI_NA_1: - { - // increment the information object block pointer by the size of the M_EI_NA_1_IO_Group struct - const Iec104M_EI_NA_1_IO_Group* curIo = - (const Iec104M_EI_NA_1_IO_Group*) &apci->asdu.m_ei_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.m_ei_na_1IOGroup = curIo; - genericIOGroup.m_ei_na_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_IC_NA_1: - { - // increment the information object block pointer by the size of the C_IC_NA_1_IO_Group struct - const Iec104C_IC_NA_1_IO_Group* curIo = - (const Iec104C_IC_NA_1_IO_Group*) &apci->asdu.c_ic_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_ic_na_1IOGroup = curIo; - genericIOGroup.c_ic_na_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_CI_NA_1: - { - // increment the information object block pointer by the size of the C_CI_NA_1_IO_Group struct - const Iec104C_CI_NA_1_IO_Group* curIo = - (const Iec104C_CI_NA_1_IO_Group*) &apci->asdu.c_ci_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_ci_na_1IOGroup = curIo; - genericIOGroup.c_ci_na_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_RD_NA_1: - { - // increment the information object block pointer by the size of the C_RD_NA_1_IO_Group struct - const Iec104C_RD_NA_1_IO_Group* curIo = - (const Iec104C_RD_NA_1_IO_Group*) &apci->asdu.c_rd_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_rd_na_1IOGroup = curIo; - genericIOGroup.c_rd_na_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_CS_NA_1: - { - // increment the information object block pointer by the size of the C_CS_NA_1_IO_Group struct - const Iec104C_CS_NA_1_IO_Group* curIo = - (const Iec104C_CS_NA_1_IO_Group*) &apci->asdu.c_cs_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_cs_na_1IOGroup = curIo; - genericIOGroup.c_cs_na_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_TS_NA_1: - { - // increment the information object block pointer by the size of the C_TS_NA_1_IO_Group struct - const Iec104C_TS_NA_1_IO_Group* curIo = - (const Iec104C_TS_NA_1_IO_Group*) &apci->asdu.c_ts_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_ts_na_1IOGroup = curIo; - genericIOGroup.c_ts_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_F_SR_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_C_RP_NA_1: - { - // increment the information object block pointer by the size of the C_RP_NA_1_IO_Group struct - const Iec104C_RP_NA_1_IO_Group* curIo = - (const Iec104C_RP_NA_1_IO_Group*) &apci->asdu.c_rp_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_rp_na_1IOGroup = curIo; - genericIOGroup.c_rp_na_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_CD_NA_1: - { - // increment the information object block pointer by the size of the C_CD_NA_1_IO_Group struct - const Iec104C_CD_NA_1_IO_Group* curIo = - (const Iec104C_CD_NA_1_IO_Group*) &apci->asdu.c_cd_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_cd_na_1IOGroup = curIo; - genericIOGroup.c_cd_na_1IOSubgroup = &curIo->subgroup; - break; - } - - case IEC104_ASDU_C_TS_TA_1: - { - // increment the information object block pointer by the size of the C_TS_TA_1_IO_Group struct - const Iec104C_TS_TA_1_IO_Group* curIo = - (const Iec104C_TS_TA_1_IO_Group*) &apci->asdu.c_ts_ta_1 + i; - - // print the SQ0 IO block - genericIOGroup.c_ts_ta_1IOGroup = curIo; - genericIOGroup.c_ts_ta_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_F_SC_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_P_ME_NA_1: - { - // increment the information object block pointer by the size of the P_ME_NA_1_IO_Group struct - const Iec104P_ME_NA_1_IO_Group* curIo = - (const Iec104P_ME_NA_1_IO_Group*) &apci->asdu.p_me_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.p_me_na_1IOGroup = curIo; - genericIOGroup.p_me_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_F_LS_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_P_ME_NB_1: - { - // increment the information object block pointer by the size of the P_ME_NB_1_IO_Group struct - const Iec104P_ME_NB_1_IO_Group* curIo = - (const Iec104P_ME_NB_1_IO_Group*) &apci->asdu.p_me_nb_1 + i; - - // print the SQ0 IO block - genericIOGroup.p_me_nb_1IOGroup = curIo; - genericIOGroup.p_me_nb_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_F_AF_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_P_ME_NC_1: - { - // increment the information object block pointer by the size of the P_ME_NC_1_IO_Group struct - const Iec104P_ME_NC_1_IO_Group* curIo = - (const Iec104P_ME_NC_1_IO_Group*) &apci->asdu.p_me_nc_1 + i; - - // print the SQ0 IO block - genericIOGroup.p_me_nc_1IOGroup = curIo; - genericIOGroup.p_me_nc_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_F_SG_NA_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_P_AC_NA_1: - { - // increment the information object block pointer by the size of the P_AC_NA_1_IO_Group struct - const Iec104P_AC_NA_1_IO_Group* curIo = - (const Iec104P_AC_NA_1_IO_Group*) &apci->asdu.p_ac_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.p_ac_na_1IOGroup = curIo; - genericIOGroup.p_ac_na_1IOSubgroup = &curIo->subgroup; - break; - } + case IEC104_ASDU_F_DR_TA_1: + { + // Since there is only one full IOGroup structure in SQ1 this can stay for all cases + genericIOGroup.f_dr_ta_1IOGroup = &apci->asdu.f_dr_ta_1; - case IEC104_ASDU_F_FR_NA_1: - { - // increment the information object block pointer by the size of the F_FR_NA_1_IO_Group struct - const Iec104F_FR_NA_1_IO_Group* curIo = - (const Iec104F_FR_NA_1_IO_Group*) &apci->asdu.f_fr_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.f_fr_na_1IOGroup = curIo; - genericIOGroup.f_fr_na_1IOSubgroup = &curIo->subgroup; - break; - } + // the subgroup pointer can be calculated by incrementing the first subgroup pointer by the iteration times the size of the subgroup pointer + // since `i` will be 0 on the first go round this works for all iterations + // since C adds based on the pointer type we only need to cast and increment + const Iec104F_DR_TA_1_IO_Subgroup* curIo = &apci->asdu.f_dr_ta_1.subgroup + i; + genericIOGroup.f_dr_ta_1IOSubgroup = curIo; - case IEC104_ASDU_F_SR_NA_1: - { - // increment the information object block pointer by the size of the F_SR_NA_1_IO_Group struct - const Iec104F_SR_NA_1_IO_Group* curIo = - (const Iec104F_SR_NA_1_IO_Group*) &apci->asdu.f_sr_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.f_sr_na_1IOGroup = curIo; - genericIOGroup.f_sr_na_1IOSubgroup = &curIo->subgroup; - break; - } + break; + } - case IEC104_ASDU_F_SC_NA_1: - { - // increment the information object block pointer by the size of the F_SC_NA_1_IO_Group struct - const Iec104F_SC_NA_1_IO_Group* curIo = - (const Iec104F_SC_NA_1_IO_Group*) &apci->asdu.f_sc_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.f_sc_na_1IOGroup = curIo; - genericIOGroup.f_sc_na_1IOSubgroup = &curIo->subgroup; - break; - } + // case IEC104_ASDU_F_SC_NB_1 + // path doesn't happen as it gets caught during the ASDU check - case IEC104_ASDU_F_LS_NA_1: - { - // increment the information object block pointer by the size of the F_LS_NA_1_IO_Group struct - const Iec104F_LS_NA_1_IO_Group* curIo = - (const Iec104F_LS_NA_1_IO_Group*) &apci->asdu.f_ls_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.f_ls_na_1IOGroup = curIo; - genericIOGroup.f_ls_na_1IOSubgroup = &curIo->subgroup; - break; - } + default: + { + // SQ1 ASDU parsing not implemented for this type + } + } - case IEC104_ASDU_F_AF_NA_1: - { - // increment the information object block pointer by the size of the F_AF_NA_1_IO_Group struct - const Iec104F_AF_NA_1_IO_Group* curIo = - (const Iec104F_AF_NA_1_IO_Group*) &apci->asdu.f_af_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.f_af_na_1IOGroup = curIo; - genericIOGroup.f_af_na_1IOSubgroup = &curIo->subgroup; - break; - } + // parse the new subgroup + parseIec104GenericIOGroup(&genericIOGroup); - case IEC104_ASDU_F_SG_NA_1: - { - // increment the information object block pointer by the size of the F_SG_NA_1_IO_Group struct - const Iec104F_SG_NA_1_IO_Group* curIo = - (const Iec104F_SG_NA_1_IO_Group*) &apci->asdu.f_sg_na_1 + i; - - // print the SQ0 IO block - genericIOGroup.f_sg_na_1IOGroup = curIo; - genericIOGroup.f_sg_na_1IOSubgroup = &curIo->subgroup; - break; } - - // case IEC104_ASDU_F_DR_TA_1 - // path doesn't happen as it gets caught during the ASDU check - - case IEC104_ASDU_F_SC_NB_1: + // + // Handle Structure Qualifier == 0 + // + else { - // increment the information object block pointer by the size of the F_SC_NB_1_IO_Group struct - const Iec104F_SC_NB_1_IO_Group* curIo = - (const Iec104F_SC_NB_1_IO_Group*) &apci->asdu.f_sc_nb_1 + i; - - // print the SQ0 IO block - genericIOGroup.f_sc_nb_1IOGroup = curIo; - genericIOGroup.f_sc_nb_1IOSubgroup = &curIo->subgroup; - break; - } + // the IOA should always be included for SQ0 + genericIOGroup.includeIOA = true; - default: - { - // SQ0 ASDU parsing not implemented for this type + // fill genericIOGroup with the appropriate asdu depending on the type + switch (asduType) + { + case IEC104_ASDU_M_SP_NA_1: + { + // increment the information object block pointer by the size of the M_SP_NA_1_IO_Group struct + const Iec104M_SP_NA_1_IO_Group* curIo = + (const Iec104M_SP_NA_1_IO_Group*) &apci->asdu.m_sp_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_sp_na_1IOGroup = curIo; + genericIOGroup.m_sp_na_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_SP_TA_1: + { + // increment the information object block pointer by the size of the M_SP_TA_1_IO_Group struct + const Iec104M_SP_TA_1_IO_Group* curIo = + (const Iec104M_SP_TA_1_IO_Group*) &apci->asdu.m_sp_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_sp_ta_1IOGroup = curIo; + genericIOGroup.m_sp_ta_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_DP_NA_1: + { + // increment the information object block pointer by the size of the M_DP_NA_1_IO_Group struct + const Iec104M_DP_NA_1_IO_Group* curIo = + (const Iec104M_DP_NA_1_IO_Group*) &apci->asdu.m_dp_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_dp_na_1IOGroup = curIo; + genericIOGroup.m_dp_na_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_DP_TA_1: + { + // increment the information object block pointer by the size of the M_DP_TA_1_IO_Group struct + const Iec104M_DP_TA_1_IO_Group* curIo = + (const Iec104M_DP_TA_1_IO_Group*) &apci->asdu.m_dp_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_dp_ta_1IOGroup = curIo; + genericIOGroup.m_dp_ta_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ST_NA_1: + { + // increment the information object block pointer by the size of the M_ST_NA_1_IO_Group struct + const Iec104M_ST_NA_1_IO_Group* curIo = + (const Iec104M_ST_NA_1_IO_Group*) &apci->asdu.m_st_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_st_na_1IOGroup = curIo; + genericIOGroup.m_st_na_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ST_TA_1: + { + // increment the information object block pointer by the size of the M_ST_TA_1_IO_Group struct + const Iec104M_ST_TA_1_IO_Group* curIo = + (const Iec104M_ST_TA_1_IO_Group*) &apci->asdu.m_st_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_st_ta_1IOGroup = curIo; + genericIOGroup.m_st_ta_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_BO_NA_1: + { + // increment the information object block pointer by the size of the M_BO_NA_1_IO_Group struct + const Iec104M_BO_NA_1_IO_Group* curIo = + (const Iec104M_BO_NA_1_IO_Group*) &apci->asdu.m_bo_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_bo_na_1IOGroup = curIo; + genericIOGroup.m_bo_na_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_BO_TA_1: + { + // increment the information object block pointer by the size of the M_BO_TA_1_IO_Group struct + const Iec104M_BO_TA_1_IO_Group* curIo = + (const Iec104M_BO_TA_1_IO_Group*) &apci->asdu.m_bo_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_bo_ta_1IOGroup = curIo; + genericIOGroup.m_bo_ta_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ME_NA_1: + { + // increment the information object block pointer by the size of the M_ME_NA_1_IO_Group struct + const Iec104M_ME_NA_1_IO_Group* curIo = + (const Iec104M_ME_NA_1_IO_Group*) &apci->asdu.m_me_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_na_1IOGroup = curIo; + genericIOGroup.m_me_na_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ME_TA_1: + { + // increment the information object block pointer by the size of the M_ME_TA_1_IO_Group struct + const Iec104M_ME_TA_1_IO_Group* curIo = + (const Iec104M_ME_TA_1_IO_Group*) &apci->asdu.m_me_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_ta_1IOGroup = curIo; + genericIOGroup.m_me_ta_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ME_NB_1: + { + // increment the information object block pointer by the size of the M_ME_NB_1_IO_Group struct + const Iec104M_ME_NB_1_IO_Group* curIo = + (const Iec104M_ME_NB_1_IO_Group*) &apci->asdu.m_me_nb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_nb_1IOGroup = curIo; + genericIOGroup.m_me_nb_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ME_TB_1: + { + // increment the information object block pointer by the size of the M_ME_TB_1_IO_Group struct + const Iec104M_ME_TB_1_IO_Group* curIo = + (const Iec104M_ME_TB_1_IO_Group*) &apci->asdu.m_me_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_tb_1IOGroup = curIo; + genericIOGroup.m_me_tb_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ME_NC_1: + { + // increment the information object block pointer by the size of the M_ME_NC_1_IO_Group struct + const Iec104M_ME_NC_1_IO_Group* curIo = + (const Iec104M_ME_NC_1_IO_Group*) &apci->asdu.m_me_nc_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_nc_1IOGroup = curIo; + genericIOGroup.m_me_nc_1IOSubgroup = &curIo->subgroup; + + break; + } + + case IEC104_ASDU_M_ME_TC_1: + { + // increment the information object block pointer by the size of the M_ME_TC_1_IO_Group struct + const Iec104M_ME_TC_1_IO_Group* curIo = + (const Iec104M_ME_TC_1_IO_Group*) &apci->asdu.m_me_tc_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_tc_1IOGroup = curIo; + genericIOGroup.m_me_tc_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_IT_NA_1: + { + // increment the information object block pointer by the size of the M_IT_NA_1_IO_Group struct + const Iec104M_IT_NA_1_IO_Group* curIo = + (const Iec104M_IT_NA_1_IO_Group*) &apci->asdu.m_it_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_it_na_1IOGroup = curIo; + genericIOGroup.m_it_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_IT_TA_1: + { + // increment the information object block pointer by the size of the M_IT_TA_1_IO_Group struct + const Iec104M_IT_TA_1_IO_Group* curIo = + (const Iec104M_IT_TA_1_IO_Group*) &apci->asdu.m_it_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_it_ta_1IOGroup = curIo; + genericIOGroup.m_it_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_EP_TA_1: + { + // increment the information object block pointer by the size of the M_EP_TA_1_IO_Group struct + const Iec104M_EP_TA_1_IO_Group* curIo = + (const Iec104M_EP_TA_1_IO_Group*) &apci->asdu.m_ep_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ep_ta_1IOGroup = curIo; + genericIOGroup.m_ep_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_EP_TB_1: + { + // increment the information object block pointer by the size of the M_EP_TB_1_IO_Group struct + const Iec104M_EP_TB_1_IO_Group* curIo = + (const Iec104M_EP_TB_1_IO_Group*) &apci->asdu.m_ep_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ep_tb_1IOGroup = curIo; + genericIOGroup.m_ep_tb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_EP_TC_1: + { + // increment the information object block pointer by the size of the M_EP_TC_1_IO_Group struct + const Iec104M_EP_TC_1_IO_Group* curIo = + (const Iec104M_EP_TC_1_IO_Group*) &apci->asdu.m_ep_tc_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ep_tc_1IOGroup = curIo; + genericIOGroup.m_ep_tc_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_PS_NA_1: + { + // increment the information object block pointer by the size of the M_PS_NA_1_IO_Group struct + const Iec104M_PS_NA_1_IO_Group* curIo = + (const Iec104M_PS_NA_1_IO_Group*) &apci->asdu.m_ps_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ps_na_1IOGroup = curIo; + genericIOGroup.m_ps_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_ME_ND_1: + { + // increment the information object block pointer by the size of the M_ME_ND_1_IO_Group struct + const Iec104M_ME_ND_1_IO_Group* curIo = + (const Iec104M_ME_ND_1_IO_Group*) &apci->asdu.m_me_nd_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_nd_1IOGroup = curIo; + genericIOGroup.m_me_nd_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_SP_TB_1: + { + // increment the information object block pointer by the size of the M_SP_TB_1_IO_Group struct + const Iec104M_SP_TB_1_IO_Group* curIo = + (const Iec104M_SP_TB_1_IO_Group*) &apci->asdu.m_sp_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_sp_tb_1IOGroup = curIo; + genericIOGroup.m_sp_tb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_DP_TB_1: + { + // increment the information object block pointer by the size of the M_DP_TB_1_IO_Group struct + const Iec104M_DP_TB_1_IO_Group* curIo = + (const Iec104M_DP_TB_1_IO_Group*) &apci->asdu.m_dp_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_dp_tb_1IOGroup = curIo; + genericIOGroup.m_dp_tb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_ST_TB_1: + { + // increment the information object block pointer by the size of the M_ST_TB_1_IO_Group struct + const Iec104M_ST_TB_1_IO_Group* curIo = + (const Iec104M_ST_TB_1_IO_Group*) &apci->asdu.m_st_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_st_tb_1IOGroup = curIo; + genericIOGroup.m_st_tb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_BO_TB_1: + { + // increment the information object block pointer by the size of the M_BO_TB_1_IO_Group struct + const Iec104M_BO_TB_1_IO_Group* curIo = + (const Iec104M_BO_TB_1_IO_Group*) &apci->asdu.m_bo_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_bo_tb_1IOGroup = curIo; + genericIOGroup.m_bo_tb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_ME_TD_1: + { + // increment the information object block pointer by the size of the M_ME_TD_1_IO_Group struct + const Iec104M_ME_TD_1_IO_Group* curIo = + (const Iec104M_ME_TD_1_IO_Group*) &apci->asdu.m_me_td_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_td_1IOGroup = curIo; + genericIOGroup.m_me_td_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_ME_TE_1: + { + // increment the information object block pointer by the size of the M_ME_TE_1_IO_Group struct + const Iec104M_ME_TE_1_IO_Group* curIo = + (const Iec104M_ME_TE_1_IO_Group*) &apci->asdu.m_me_te_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_te_1IOGroup = curIo; + genericIOGroup.m_me_te_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_ME_TF_1: + { + // increment the information object block pointer by the size of the M_ME_TF_1_IO_Group struct + const Iec104M_ME_TF_1_IO_Group* curIo = + (const Iec104M_ME_TF_1_IO_Group*) &apci->asdu.m_me_tf_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_me_tf_1IOGroup = curIo; + genericIOGroup.m_me_tf_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_IT_TB_1: + { + // increment the information object block pointer by the size of the M_IT_TB_1_IO_Group struct + const Iec104M_IT_TB_1_IO_Group* curIo = + (const Iec104M_IT_TB_1_IO_Group*) &apci->asdu.m_it_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_it_tb_1IOGroup = curIo; + genericIOGroup.m_it_tb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_EP_TD_1: + { + // increment the information object block pointer by the size of the M_EP_TD_1_IO_Group struct + const Iec104M_EP_TD_1_IO_Group* curIo = + (const Iec104M_EP_TD_1_IO_Group*) &apci->asdu.m_ep_td_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ep_td_1IOGroup = curIo; + genericIOGroup.m_ep_td_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_EP_TE_1: + { + // increment the information object block pointer by the size of the M_EP_TE_1_IO_Group struct + const Iec104M_EP_TE_1_IO_Group* curIo = + (const Iec104M_EP_TE_1_IO_Group*) &apci->asdu.m_ep_te_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ep_te_1IOGroup = curIo; + genericIOGroup.m_ep_te_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_EP_TF_1: + { + // increment the information object block pointer by the size of the M_EP_TF_1_IO_Group struct + const Iec104M_EP_TF_1_IO_Group* curIo = + (const Iec104M_EP_TF_1_IO_Group*) &apci->asdu.m_ep_tf_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ep_tf_1IOGroup = curIo; + genericIOGroup.m_ep_tf_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SC_NA_1: + { + // increment the information object block pointer by the size of the C_SC_NA_1_IO_Group struct + const Iec104C_SC_NA_1_IO_Group* curIo = + (const Iec104C_SC_NA_1_IO_Group*) &apci->asdu.c_sc_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_sc_na_1IOGroup = curIo; + genericIOGroup.c_sc_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_DC_NA_1: + { + // increment the information object block pointer by the size of the C_DC_NA_1_IO_Group struct + const Iec104C_DC_NA_1_IO_Group* curIo = + (const Iec104C_DC_NA_1_IO_Group*) &apci->asdu.c_dc_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_dc_na_1IOGroup = curIo; + genericIOGroup.c_dc_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_RC_NA_1: + { + // increment the information object block pointer by the size of the C_RC_NA_1_IO_Group struct + const Iec104C_RC_NA_1_IO_Group* curIo = + (const Iec104C_RC_NA_1_IO_Group*) &apci->asdu.c_rc_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_rc_na_1IOGroup = curIo; + genericIOGroup.c_rc_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SE_NA_1: + { + // increment the information object block pointer by the size of the C_SE_NA_1_IO_Group struct + const Iec104C_SE_NA_1_IO_Group* curIo = + (const Iec104C_SE_NA_1_IO_Group*) &apci->asdu.c_se_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_se_na_1IOGroup = curIo; + genericIOGroup.c_se_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SE_NB_1: + { + // increment the information object block pointer by the size of the C_SE_NB_1_IO_Group struct + const Iec104C_SE_NB_1_IO_Group* curIo = + (const Iec104C_SE_NB_1_IO_Group*) &apci->asdu.c_se_nb_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_se_nb_1IOGroup = curIo; + genericIOGroup.c_se_nb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SE_NC_1: + { + // increment the information object block pointer by the size of the C_SE_NC_1_IO_Group struct + const Iec104C_SE_NC_1_IO_Group* curIo = + (const Iec104C_SE_NC_1_IO_Group*) &apci->asdu.c_se_nc_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_se_nc_1IOGroup = curIo; + genericIOGroup.c_se_nc_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_BO_NA_1: + { + // increment the information object block pointer by the size of the C_BO_NA_1_IO_Group struct + const Iec104C_BO_NA_1_IO_Group* curIo = + (const Iec104C_BO_NA_1_IO_Group*) &apci->asdu.c_bo_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_bo_na_1IOGroup = curIo; + genericIOGroup.c_bo_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SC_TA_1: + { + // increment the information object block pointer by the size of the C_SC_TA_1_IO_Group struct + const Iec104C_SC_TA_1_IO_Group* curIo = + (const Iec104C_SC_TA_1_IO_Group*) &apci->asdu.c_sc_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_sc_ta_1IOGroup = curIo; + genericIOGroup.c_sc_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_DC_TA_1: + { + // increment the information object block pointer by the size of the C_DC_TA_1_IO_Group struct + const Iec104C_DC_TA_1_IO_Group* curIo = + (const Iec104C_DC_TA_1_IO_Group*) &apci->asdu.c_dc_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_dc_ta_1IOGroup = curIo; + genericIOGroup.c_dc_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_RC_TA_1: + { + // increment the information object block pointer by the size of the C_RC_TA_1_IO_Group struct + const Iec104C_RC_TA_1_IO_Group* curIo = + (const Iec104C_RC_TA_1_IO_Group*) &apci->asdu.c_rc_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_rc_ta_1IOGroup = curIo; + genericIOGroup.c_rc_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SE_TA_1: + { + // increment the information object block pointer by the size of the C_SE_TA_1_IO_Group struct + const Iec104C_SE_TA_1_IO_Group* curIo = + (const Iec104C_SE_TA_1_IO_Group*) &apci->asdu.c_se_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_se_ta_1IOGroup = curIo; + genericIOGroup.c_se_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SE_TB_1: + { + // increment the information object block pointer by the size of the C_SE_TB_1_IO_Group struct + const Iec104C_SE_TB_1_IO_Group* curIo = + (const Iec104C_SE_TB_1_IO_Group*) &apci->asdu.c_se_tb_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_se_tb_1IOGroup = curIo; + genericIOGroup.c_se_tb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_SE_TC_1: + { + // increment the information object block pointer by the size of the C_SE_TC_1_IO_Group struct + const Iec104C_SE_TC_1_IO_Group* curIo = + (const Iec104C_SE_TC_1_IO_Group*) &apci->asdu.c_se_tc_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_se_tc_1IOGroup = curIo; + genericIOGroup.c_se_tc_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_BO_TA_1: + { + // increment the information object block pointer by the size of the C_BO_TA_1_IO_Group struct + const Iec104C_BO_TA_1_IO_Group* curIo = + (const Iec104C_BO_TA_1_IO_Group*) &apci->asdu.c_bo_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_bo_ta_1IOGroup = curIo; + genericIOGroup.c_bo_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_M_EI_NA_1: + { + // increment the information object block pointer by the size of the M_EI_NA_1_IO_Group struct + const Iec104M_EI_NA_1_IO_Group* curIo = + (const Iec104M_EI_NA_1_IO_Group*) &apci->asdu.m_ei_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.m_ei_na_1IOGroup = curIo; + genericIOGroup.m_ei_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_IC_NA_1: + { + // increment the information object block pointer by the size of the C_IC_NA_1_IO_Group struct + const Iec104C_IC_NA_1_IO_Group* curIo = + (const Iec104C_IC_NA_1_IO_Group*) &apci->asdu.c_ic_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_ic_na_1IOGroup = curIo; + genericIOGroup.c_ic_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_CI_NA_1: + { + // increment the information object block pointer by the size of the C_CI_NA_1_IO_Group struct + const Iec104C_CI_NA_1_IO_Group* curIo = + (const Iec104C_CI_NA_1_IO_Group*) &apci->asdu.c_ci_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_ci_na_1IOGroup = curIo; + genericIOGroup.c_ci_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_RD_NA_1: + { + // increment the information object block pointer by the size of the C_RD_NA_1_IO_Group struct + const Iec104C_RD_NA_1_IO_Group* curIo = + (const Iec104C_RD_NA_1_IO_Group*) &apci->asdu.c_rd_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_rd_na_1IOGroup = curIo; + genericIOGroup.c_rd_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_CS_NA_1: + { + // increment the information object block pointer by the size of the C_CS_NA_1_IO_Group struct + const Iec104C_CS_NA_1_IO_Group* curIo = + (const Iec104C_CS_NA_1_IO_Group*) &apci->asdu.c_cs_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_cs_na_1IOGroup = curIo; + genericIOGroup.c_cs_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_TS_NA_1: + { + // increment the information object block pointer by the size of the C_TS_NA_1_IO_Group struct + const Iec104C_TS_NA_1_IO_Group* curIo = + (const Iec104C_TS_NA_1_IO_Group*) &apci->asdu.c_ts_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_ts_na_1IOGroup = curIo; + genericIOGroup.c_ts_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_RP_NA_1: + { + // increment the information object block pointer by the size of the C_RP_NA_1_IO_Group struct + const Iec104C_RP_NA_1_IO_Group* curIo = + (const Iec104C_RP_NA_1_IO_Group*) &apci->asdu.c_rp_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_rp_na_1IOGroup = curIo; + genericIOGroup.c_rp_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_CD_NA_1: + { + // increment the information object block pointer by the size of the C_CD_NA_1_IO_Group struct + const Iec104C_CD_NA_1_IO_Group* curIo = + (const Iec104C_CD_NA_1_IO_Group*) &apci->asdu.c_cd_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_cd_na_1IOGroup = curIo; + genericIOGroup.c_cd_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_C_TS_TA_1: + { + // increment the information object block pointer by the size of the C_TS_TA_1_IO_Group struct + const Iec104C_TS_TA_1_IO_Group* curIo = + (const Iec104C_TS_TA_1_IO_Group*) &apci->asdu.c_ts_ta_1 + i; + + // print the SQ0 IO block + genericIOGroup.c_ts_ta_1IOGroup = curIo; + genericIOGroup.c_ts_ta_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_P_ME_NA_1: + { + // increment the information object block pointer by the size of the P_ME_NA_1_IO_Group struct + const Iec104P_ME_NA_1_IO_Group* curIo = + (const Iec104P_ME_NA_1_IO_Group*) &apci->asdu.p_me_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.p_me_na_1IOGroup = curIo; + genericIOGroup.p_me_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_P_ME_NB_1: + { + // increment the information object block pointer by the size of the P_ME_NB_1_IO_Group struct + const Iec104P_ME_NB_1_IO_Group* curIo = + (const Iec104P_ME_NB_1_IO_Group*) &apci->asdu.p_me_nb_1 + i; + + // print the SQ0 IO block + genericIOGroup.p_me_nb_1IOGroup = curIo; + genericIOGroup.p_me_nb_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_P_ME_NC_1: + { + // increment the information object block pointer by the size of the P_ME_NC_1_IO_Group struct + const Iec104P_ME_NC_1_IO_Group* curIo = + (const Iec104P_ME_NC_1_IO_Group*) &apci->asdu.p_me_nc_1 + i; + + // print the SQ0 IO block + genericIOGroup.p_me_nc_1IOGroup = curIo; + genericIOGroup.p_me_nc_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_P_AC_NA_1: + { + // increment the information object block pointer by the size of the P_AC_NA_1_IO_Group struct + const Iec104P_AC_NA_1_IO_Group* curIo = + (const Iec104P_AC_NA_1_IO_Group*) &apci->asdu.p_ac_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.p_ac_na_1IOGroup = curIo; + genericIOGroup.p_ac_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_F_FR_NA_1: + { + // increment the information object block pointer by the size of the F_FR_NA_1_IO_Group struct + const Iec104F_FR_NA_1_IO_Group* curIo = + (const Iec104F_FR_NA_1_IO_Group*) &apci->asdu.f_fr_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.f_fr_na_1IOGroup = curIo; + genericIOGroup.f_fr_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_F_SR_NA_1: + { + // increment the information object block pointer by the size of the F_SR_NA_1_IO_Group struct + const Iec104F_SR_NA_1_IO_Group* curIo = + (const Iec104F_SR_NA_1_IO_Group*) &apci->asdu.f_sr_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.f_sr_na_1IOGroup = curIo; + genericIOGroup.f_sr_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_F_SC_NA_1: + { + // increment the information object block pointer by the size of the F_SC_NA_1_IO_Group struct + const Iec104F_SC_NA_1_IO_Group* curIo = + (const Iec104F_SC_NA_1_IO_Group*) &apci->asdu.f_sc_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.f_sc_na_1IOGroup = curIo; + genericIOGroup.f_sc_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_F_LS_NA_1: + { + // increment the information object block pointer by the size of the F_LS_NA_1_IO_Group struct + const Iec104F_LS_NA_1_IO_Group* curIo = + (const Iec104F_LS_NA_1_IO_Group*) &apci->asdu.f_ls_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.f_ls_na_1IOGroup = curIo; + genericIOGroup.f_ls_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_F_AF_NA_1: + { + // increment the information object block pointer by the size of the F_AF_NA_1_IO_Group struct + const Iec104F_AF_NA_1_IO_Group* curIo = + (const Iec104F_AF_NA_1_IO_Group*) &apci->asdu.f_af_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.f_af_na_1IOGroup = curIo; + genericIOGroup.f_af_na_1IOSubgroup = &curIo->subgroup; + break; + } + + case IEC104_ASDU_F_SG_NA_1: + { + // increment the information object block pointer by the size of the F_SG_NA_1_IO_Group struct + const Iec104F_SG_NA_1_IO_Group* curIo = + (const Iec104F_SG_NA_1_IO_Group*) &apci->asdu.f_sg_na_1 + i; + + // print the SQ0 IO block + genericIOGroup.f_sg_na_1IOGroup = curIo; + genericIOGroup.f_sg_na_1IOSubgroup = &curIo->subgroup; + break; + } + + // case IEC104_ASDU_F_DR_TA_1 + // path doesn't happen as it gets caught during the ASDU check + + case IEC104_ASDU_F_SC_NB_1: + { + // increment the information object block pointer by the size of the F_SC_NB_1_IO_Group struct + const Iec104F_SC_NB_1_IO_Group* curIo = + (const Iec104F_SC_NB_1_IO_Group*) &apci->asdu.f_sc_nb_1 + i; + + // print the SQ0 IO block + genericIOGroup.f_sc_nb_1IOGroup = curIo; + genericIOGroup.f_sc_nb_1IOSubgroup = &curIo->subgroup; + break; + } + + default: + { + // SQ0 ASDU parsing not implemented for this type + } + } + + // parse the group + parseIec104GenericIOGroup(&genericIOGroup); } - } - - // parse the group - parseIec104GenericIOGroup(&genericIOGroup); } } } @@ -2607,9 +2610,7 @@ void parseIec104ApciI(const Iec104ApciI* apci) curAsduCheck.sq0Allowed = true; curAsduCheck.sq1Allowed = false; curAsduCheck.multipleIOAllowed = false; - curAsduCheck.checkCauseOfTx = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 }; + curAsduCheck.checkCauseOfTx = { }; // select the appropriate asdu based on typeId value switch (apci->asdu.typeId) diff --git a/src/service_inspectors/iec104/iec104_parse_information_object_elements.cc b/src/service_inspectors/iec104/iec104_parse_information_object_elements.cc index f956ed4b1..a8b2356a0 100644 --- a/src/service_inspectors/iec104/iec104_parse_information_object_elements.cc +++ b/src/service_inspectors/iec104/iec104_parse_information_object_elements.cc @@ -24,7 +24,7 @@ #include "iec104_parse_information_object_elements.h" -#include +#include #include "detection/detection_engine.h" #include "events/event_queue.h" @@ -191,18 +191,10 @@ void parseIec104Afq(const Iec104AfqType* afq) } } -uint8_t parseIec104Vsq(const Iec104ApciI* apci) +uint32_t parseIec104Vsq(const Iec104ApciI* apci) { // number of elements == 0 is caught in check apdu - - // make sure the reported number of elements would not exceed the packet size - // * take the apci->header.length value - // * subtract off type id, vsq, cause of tx, and 2-byte common address sizes - // * if the sq bit is set, subtract off the IOA - // * use a switch statement with cases of each message type to get the size of one group - // * divide the result of the earlier calculation by this group size to get the maximum allowable groups without overflowing - - uint8_t maxNumberOfElements = 0; + uint32_t informationObjectSubgroupSize = 0; // determine the size of the current message type group @@ -545,31 +537,42 @@ uint8_t parseIec104Vsq(const Iec104ApciI* apci) } } + // make sure the reported number of elements would not exceed the packet size + // * take the apci->header.length value + // * subtract off type id, vsq, cause of tx, and 2-byte common address sizes + // * if the sq bit is set, subtract off the IOA + // * use a switch statement with cases of each message type to get the size of one group + // * divide the result of the earlier calculation by this group size to get the maximum allowable groups without overflowing + uint8_t maxNumberOfElements = 0; + if (informationObjectSubgroupSize) { - if (apci->asdu.variableStructureQualifier.sq == 0) - { - uint32_t informationObjectGroupSize = informationObjectSubgroupSize + sizeof(const Iec104InformationObjectAddressThreeOctetType); - maxNumberOfElements = (apci->header.length - - sizeof(uint8_t) // type id - - sizeof(const Iec104VariableStructureQualifierType) - - sizeof(const Iec104CauseOfTransmissionType) - - sizeof(const Iec104CommonAddressOfAsduType) - ) / informationObjectGroupSize; - } - else - { - maxNumberOfElements = (apci->header.length - - sizeof(uint8_t) // type id - - sizeof(const Iec104VariableStructureQualifierType) - - sizeof(const Iec104CauseOfTransmissionType) - - sizeof(const Iec104CommonAddressOfAsduType) - - sizeof(const Iec104InformationObjectAddressThreeOctetType) - ) / informationObjectSubgroupSize; + uint32_t reported_msg_len = apci->header.length; + if (reported_msg_len >= IEC104_APCI_TYPE_I_MIN_LEN) { + if (apci->asdu.variableStructureQualifier.sq == 0) + { + uint32_t informationObjectGroupSize = informationObjectSubgroupSize + sizeof(const Iec104InformationObjectAddressThreeOctetType); + maxNumberOfElements = (reported_msg_len + - sizeof(uint8_t) // type id + - sizeof(const Iec104VariableStructureQualifierType) + - sizeof(const Iec104CauseOfTransmissionType) + - sizeof(const Iec104CommonAddressOfAsduType) + ) / informationObjectGroupSize; + } + else + { + maxNumberOfElements = (reported_msg_len + - sizeof(uint8_t) // type id + - sizeof(const Iec104VariableStructureQualifierType) + - sizeof(const Iec104CauseOfTransmissionType) + - sizeof(const Iec104CommonAddressOfAsduType) + - sizeof(const Iec104InformationObjectAddressThreeOctetType) + ) / informationObjectSubgroupSize; + } } } - uint8_t verifiedNumberOfElements = apci->asdu.variableStructureQualifier.numberOfElements; + uint32_t verifiedNumberOfElements = apci->asdu.variableStructureQualifier.numberOfElements; if (verifiedNumberOfElements > 0 and verifiedNumberOfElements <= maxNumberOfElements) { // do nothing diff --git a/src/service_inspectors/iec104/iec104_parse_information_object_elements.h b/src/service_inspectors/iec104/iec104_parse_information_object_elements.h index 2857b6da3..c73315d4f 100644 --- a/src/service_inspectors/iec104/iec104_parse_information_object_elements.h +++ b/src/service_inspectors/iec104/iec104_parse_information_object_elements.h @@ -46,7 +46,7 @@ void parseIec104Srq(const Iec104SrqType* srq); void parseIec104Scq(const Iec104ScqType* scq); void parseIec104Lsq(const Iec104LsqType* lsq); void parseIec104Afq(const Iec104AfqType* afq); -uint8_t parseIec104Vsq(const Iec104ApciI* apci); +uint32_t parseIec104Vsq(const Iec104ApciI* apci); void parseIec104CauseOfTx(const Iec104ApciI* apci); void parseIec104TwoOctetCommonAddress(const Iec104ApciI* apci); void parseIec104InformationObjectAddressWithThreeOctets( diff --git a/src/service_inspectors/iec104/iec104_trace.h b/src/service_inspectors/iec104/iec104_trace.h index 5bd7acade..b38054f7b 100644 --- a/src/service_inspectors/iec104/iec104_trace.h +++ b/src/service_inspectors/iec104/iec104_trace.h @@ -24,7 +24,6 @@ // Detection trace utility -#include "framework/cursor.h" #include "main/snort_types.h" #include "main/thread.h" @@ -42,7 +41,7 @@ enum }; #ifdef DEBUG_MSGS -#define print_debug_information(p, msg) debug_log(iec104_trace, TRACE_IEC104_IDENTIFICATION, p, msg); +#define print_debug_information(p, msg) debug_log(iec104_trace, TRACE_IEC104_IDENTIFICATION, p, msg) #else #define print_debug_information(...) #endif diff --git a/src/service_inspectors/iec104/ips_iec104_apci_type.cc b/src/service_inspectors/iec104/ips_iec104_apci_type.cc index 27b42d4b1..168d9dfc4 100644 --- a/src/service_inspectors/iec104/ips_iec104_apci_type.cc +++ b/src/service_inspectors/iec104/ips_iec104_apci_type.cc @@ -60,7 +60,7 @@ static Iec104ApciTypeMap iec104_apci_type_map[] = { "information_transfer_format", IEC104_APCI_TYPE_I }, // information transfer format }; -static bool get_apci_type(const char* s, long &n) +static bool get_apci_type(const char* s, long& n) { constexpr size_t max = (sizeof(iec104_apci_type_map) / sizeof(Iec104ApciTypeMap)); @@ -109,14 +109,14 @@ uint32_t Iec104ApciTypeOption::hash() const return c; } -bool Iec104ApciTypeOption::operator==(const IpsOption &ips) const +bool Iec104ApciTypeOption::operator==(const IpsOption& ips) const { if (!IpsOption::operator==(ips)) { return false; } - const Iec104ApciTypeOption &rhs = (const Iec104ApciTypeOption&) ips; + const Iec104ApciTypeOption& rhs = (const Iec104ApciTypeOption&) ips; return (apci_type == rhs.apci_type); } @@ -183,7 +183,7 @@ public: uint8_t apci_type = IEC104_NO_APCI; }; -bool Iec104ApciTypeModule::set(const char*, Value &v, SnortConfig*) +bool Iec104ApciTypeModule::set(const char*, Value& v, SnortConfig*) { if (!v.is("~")) { diff --git a/src/service_inspectors/iec104/ips_iec104_asdu_func.cc b/src/service_inspectors/iec104/ips_iec104_asdu_func.cc index 7489e9afc..2e2fd3962 100644 --- a/src/service_inspectors/iec104/ips_iec104_asdu_func.cc +++ b/src/service_inspectors/iec104/ips_iec104_asdu_func.cc @@ -127,7 +127,7 @@ static Iec104AsduFuncMap iec104_asdu_func_map[] = // 128-256 reserved }; -static bool get_func(const char* s, long &n) +static bool get_func(const char* s, long& n) { constexpr size_t max = (sizeof(iec104_asdu_func_map) / sizeof(Iec104AsduFuncMap)); @@ -176,14 +176,14 @@ uint32_t Iec104AsduFuncOption::hash() const return c; } -bool Iec104AsduFuncOption::operator==(const IpsOption &ips) const +bool Iec104AsduFuncOption::operator==(const IpsOption& ips) const { if (!IpsOption::operator==(ips)) { return false; } - const Iec104AsduFuncOption &rhs = (const Iec104AsduFuncOption&) ips; + const Iec104AsduFuncOption& rhs = (const Iec104AsduFuncOption&) ips; return (func == rhs.func); } @@ -256,7 +256,7 @@ public: uint8_t func = IEC104_NO_ASDU; }; -bool Iec104AsduFuncModule::set(const char*, Value &v, SnortConfig*) +bool Iec104AsduFuncModule::set(const char*, Value& v, SnortConfig*) { if (!v.is("~")) {