From 6cd2eab06622c7d3cc062c9903babb67e85bae59 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Tue, 16 May 2023 19:12:51 +0100 Subject: [PATCH] - make write access to RCB elements configurable according to ReportSettings (LIB61850-404) --- src/iec61850/inc/iec61850_server.h | 33 +++++++++++++++- src/iec61850/inc_private/ied_server_private.h | 3 +- src/iec61850/server/impl/ied_server.c | 7 ++++ src/iec61850/server/impl/ied_server_config.c | 39 ++++++++++++++++++- src/iec61850/server/mms_mapping/reporting.c | 38 ++++++++++++++++++ 5 files changed, 117 insertions(+), 3 deletions(-) diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 2a9665a1..b3f99d57 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -3,7 +3,7 @@ * * IEC 61850 server API for libiec61850. * - * Copyright 2013-2022 Michael Zillgith + * Copyright 2013-2023 Michael Zillgith * * This file is part of libIEC61850. * @@ -42,6 +42,13 @@ extern "C" { #include "iso_connection_parameters.h" #include "iec61850_config_file_parser.h" +#define IEC61850_REPORTSETTINGS_RPT_ID 1 +#define IEC61850_REPORTSETTINGS_BUF_TIME 2 +#define IEC61850_REPORTSETTINGS_DATSET 4 +#define IEC61850_REPORTSETTINGS_TRG_OPS 8 +#define IEC61850_REPORTSETTINGS_OPT_FIELDS 16 +#define IEC61850_REPORTSETTINGS_INTG_PD 32 + /** * \brief Configuration object to configure IEC 61850 stack features */ @@ -99,6 +106,9 @@ struct sIedServerConfig /** integrity report start times will by synchronized with straight numbers (default: false) */ bool syncIntegrityReportTimes; + + /** for each configurable ReportSetting there is a separate flag (default: Dyn = enable write for all) */ + uint8_t reportSettingsWritable; }; /** @@ -388,6 +398,27 @@ IedServerConfig_useIntegratedGoosePublisher(IedServerConfig self, bool enable); LIB61850_API bool IedServerConfig_isLogServiceEnabled(IedServerConfig self); +/** + * \brief Make a configurable report setting writeable or read-only + * + * \note Can be used to implement some of Services\ReportSettings options + * + * \param[in] setting one IEC61850_REPORTSETTINGS_RPT_ID, _BUF_TIME, _DATSET, _TRG_OPS, _OPT_FIELDS, _INTG_PD + * \param[in] isDyn true, when setting is writable ("Dyn") or false, when read-only + */ +LIB61850_API void +IedServerConfig_setReportSetting(IedServerConfig self, uint8_t setting, bool isDyn); + +/** + * \brief Check if a configurable report setting is writable or read-only + * + * \param[in] setting one IEC61850_REPORTSETTINGS_RPT_ID, _BUF_TIME, _DATSET, _TRG_OPS, _OPT_FIELDS, _INTG_PD + * + * \return isDyn true, when setting is writable ("Dyn") or false, when read-only + */ +LIB61850_API bool +IedServerConfig_getReportSetting(IedServerConfig self, uint8_t setting); + /** * An opaque handle for an IED server instance */ diff --git a/src/iec61850/inc_private/ied_server_private.h b/src/iec61850/inc_private/ied_server_private.h index e6f6e412..d5555659 100644 --- a/src/iec61850/inc_private/ied_server_private.h +++ b/src/iec61850/inc_private/ied_server_private.h @@ -3,7 +3,7 @@ * * Library private function definitions for IedServer. * - * Copyright 2013-2018 Michael Zillgith + * Copyright 2013-2023 Michael Zillgith * * This file is part of libIEC61850. * @@ -50,6 +50,7 @@ struct sIedServer bool enableBRCBResvTms; bool enableOwnerForRCB; bool syncIntegrityReportTimes; + uint8_t rcbSettingsWritable; #endif #if (CONFIG_MMS_THREADLESS_STACK != 1) diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index 0253bcf1..2350984e 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -483,12 +483,19 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio self->enableBRCBResvTms = serverConfiguration->enableResvTmsForBRCB; self->enableOwnerForRCB = serverConfiguration->enableOwnerForRCB; self->syncIntegrityReportTimes = serverConfiguration->syncIntegrityReportTimes; + self->rcbSettingsWritable = serverConfiguration->reportSettingsWritable; } else { self->reportBufferSizeBRCBs = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE; self->reportBufferSizeURCBs = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE; self->enableOwnerForRCB = false; self->syncIntegrityReportTimes = false; + self->rcbSettingsWritable = IEC61850_REPORTSETTINGS_RPT_ID + + IEC61850_REPORTSETTINGS_BUF_TIME + + IEC61850_REPORTSETTINGS_DATSET + + IEC61850_REPORTSETTINGS_TRG_OPS + + IEC61850_REPORTSETTINGS_OPT_FIELDS + + IEC61850_REPORTSETTINGS_INTG_PD; #if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) self->enableBRCBResvTms = true; #else diff --git a/src/iec61850/server/impl/ied_server_config.c b/src/iec61850/server/impl/ied_server_config.c index fdc38f8e..673f58b1 100644 --- a/src/iec61850/server/impl/ied_server_config.c +++ b/src/iec61850/server/impl/ied_server_config.c @@ -1,7 +1,7 @@ /* * ied_server_config.c * - * Copyright 2018-2022 Michael Zillgith + * Copyright 2018-2023 Michael Zillgith * * This file is part of libIEC61850. * @@ -59,6 +59,12 @@ IedServerConfig_create() self->enableResvTmsForBRCB = true; self->enableOwnerForRCB = false; self->syncIntegrityReportTimes = false; + self->reportSettingsWritable = IEC61850_REPORTSETTINGS_RPT_ID + + IEC61850_REPORTSETTINGS_BUF_TIME + + IEC61850_REPORTSETTINGS_DATSET + + IEC61850_REPORTSETTINGS_TRG_OPS + + IEC61850_REPORTSETTINGS_OPT_FIELDS + + IEC61850_REPORTSETTINGS_INTG_PD; } return self; @@ -264,3 +270,34 @@ IedServerConfig_getSyncIntegrityReportTimes(IedServerConfig self) { return self->syncIntegrityReportTimes; } + +static void +configureSetting(IedServerConfig self, uint8_t flags, uint8_t setting, bool value) +{ + if (flags & setting) + { + if (value) { + self->reportSettingsWritable |= setting; + } + else { + self->reportSettingsWritable &= ~setting; + } + } +} + +void +IedServerConfig_setReportSetting(IedServerConfig self, uint8_t setting, bool isDyn) +{ + configureSetting(self, setting, IEC61850_REPORTSETTINGS_RPT_ID, isDyn); + configureSetting(self, setting, IEC61850_REPORTSETTINGS_BUF_TIME, isDyn); + configureSetting(self, setting, IEC61850_REPORTSETTINGS_DATSET, isDyn); + configureSetting(self, setting, IEC61850_REPORTSETTINGS_TRG_OPS, isDyn); + configureSetting(self, setting, IEC61850_REPORTSETTINGS_OPT_FIELDS, isDyn); + configureSetting(self, setting, IEC61850_REPORTSETTINGS_INTG_PD, isDyn); +} + +bool +IedServerConfig_getReportSetting(IedServerConfig self, uint8_t setting) +{ + return (self->reportSettingsWritable & setting); +} diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index f8e8ef97..cba98b86 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -2091,6 +2091,12 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme } else if (strcmp(elementName, "DatSet") == 0) { + if (!(self->iedServer->rcbSettingsWritable & IEC61850_REPORTSETTINGS_DATSET)) + { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } + #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore_wait(rc->rcbValuesLock); #endif @@ -2138,6 +2144,12 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme } else if (strcmp(elementName, "IntgPd") == 0) { + if (!(self->iedServer->rcbSettingsWritable & IEC61850_REPORTSETTINGS_INTG_PD)) + { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } + #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore_wait(rc->rcbValuesLock); #endif @@ -2185,6 +2197,12 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme } else if (strcmp(elementName, "TrgOps") == 0) { + if (!(self->iedServer->rcbSettingsWritable & IEC61850_REPORTSETTINGS_TRG_OPS)) + { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } + #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore_wait(rc->rcbValuesLock); #endif @@ -2258,6 +2276,12 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme else if (strcmp(elementName, "BufTm") == 0) { + if (!(self->iedServer->rcbSettingsWritable & IEC61850_REPORTSETTINGS_BUF_TIME)) + { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } + #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore_wait(rc->rcbValuesLock); #endif @@ -2291,6 +2315,12 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme } else if (strcmp(elementName, "RptID") == 0) { + if (!(self->iedServer->rcbSettingsWritable & IEC61850_REPORTSETTINGS_RPT_ID)) + { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } + #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore_wait(rc->rcbValuesLock); #endif @@ -2398,6 +2428,14 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme goto exit_function; } + else if (strcmp(elementName, "OptFlds") == 0) { + + if (!(self->iedServer->rcbSettingsWritable & IEC61850_REPORTSETTINGS_OPT_FIELDS)) + { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } + } #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore_wait(rc->rcbValuesLock);