From 0ce4838ca284fadc3ee14f031e657b46f60d9888 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 21 Aug 2025 19:24:11 +0100 Subject: [PATCH] - IedServer: added global write access handler (LIB61850-528) --- src/iec61850/inc/iec61850_server.h | 3 + src/iec61850/inc_private/mms_mapping.h | 3 + .../inc_private/mms_mapping_internal.h | 5 +- src/iec61850/server/mms_mapping/mms_mapping.c | 94 +++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index cacbc524..29b615a1 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -1955,6 +1955,9 @@ IedServer_handleWriteAccessForComplexAttribute(IedServer self, DataAttribute* da LIB61850_API void IedServer_handleWriteAccessForDataObject(IedServer self, DataObject* dataObject, FunctionalConstraint fc, WriteAccessHandler handler, void* parameter); +LIB61850_API void +IedServer_handleWriteAccessGlobally(IedServer self, WriteAccessHandler handler, void* parameter); + typedef enum { ACCESS_POLICY_ALLOW, ACCESS_POLICY_DENY diff --git a/src/iec61850/inc_private/mms_mapping.h b/src/iec61850/inc_private/mms_mapping.h index 340a2d81..d2d2d831 100644 --- a/src/iec61850/inc_private/mms_mapping.h +++ b/src/iec61850/inc_private/mms_mapping.h @@ -142,6 +142,9 @@ MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicat LIB61850_INTERNAL void MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logStorage); +LIB61850_INTERNAL void +MmsMapping_installGlobalWriteAccessHandler(MmsMapping* self, WriteAccessHandler handler, void* parameter); + LIB61850_INTERNAL void MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter); diff --git a/src/iec61850/inc_private/mms_mapping_internal.h b/src/iec61850/inc_private/mms_mapping_internal.h index 1830b87c..6c3aa355 100644 --- a/src/iec61850/inc_private/mms_mapping_internal.h +++ b/src/iec61850/inc_private/mms_mapping_internal.h @@ -287,7 +287,10 @@ struct sMmsMapping { LinkedList controlObjects; uint64_t nextControlTimeout; /* next timeout in one of the control state machines */ - LinkedList attributeAccessHandlers; + LinkedList attributeAccessHandlers; /* write access handlers for individual data attribtues */ + + WriteAccessHandler writeAccessHandler; /* global write access handler */ + void* writeAccessHandlerParam; #if (CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL == 1) ReadAccessHandler readAccessHandler; diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index cca93cb7..896f47e2 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -3273,6 +3273,93 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, const char* variableId, int writeHandlerListElement = LinkedList_getNext(writeHandlerListElement); } + /* Call global write access handler */ + if (self->writeAccessHandler) + { + /* lookup data attribute */ + IedModel* model = self->iedServer->model; + + ModelNode* ld = IedModel_getModelNodeByObjectReference(model, domain->domainName); + + if (ld) + { + *separator = 0; + + ModelNode* ln = ModelNode_getChild(ld, variableId); + + if (ln) + { + char* daRef = separator + 4; + + /* replace "$" with "."*/ + + StringUtils_replace(daRef, '$', '.'); + + ModelNode* da = ModelNode_getChild(ln, daRef); + + if (da) + { + if (arrayIdx != -1) + { + da = ModelNode_getChildWithIdx(da, arrayIdx); + + if (da == NULL) + { + printf("array idx not found\n"); + } + + if (componentId) + { + StringUtils_replace(componentId, '$', '.'); + + da = ModelNode_getChild(da, componentId); + + if (da == NULL) + { + printf("component %s not found\n", componentId); + } + } + } + + if (da) + { + if (da->modelType != DataAttributeModelType) + { + printf("model node not a data attribute!\n"); + } + else + { + ClientConnection clientConnection = + private_IedServer_getClientConnectionByHandle(self->iedServer, connection); + + MmsDataAccessError handlerResult = + self->writeAccessHandler((DataAttribute*)da, value, clientConnection, self->writeAccessHandlerParam); + + if ((handlerResult == DATA_ACCESS_ERROR_SUCCESS) || + (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)) + { + handlerFound = true; + + if (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE) + updateValue = false; + } + else + return handlerResult; + } + } + } + else + { + printf("da %s no found\n", daRef); + } + } + else + { + printf("ln %s not found\n", variableId); + } + } + } + /* DENY access if no handler is found and default policy is DENY */ if (!handlerFound) { @@ -3317,6 +3404,13 @@ getAccessHandlerForAttribute(MmsMapping* self, DataAttribute* dataAttribute) return NULL; } +void +MmsMapping_installGlobalWriteAccessHandler(MmsMapping* self, WriteAccessHandler handler, void* parameter) +{ + self->writeAccessHandler = handler; + self->writeAccessHandlerParam = parameter; +} + void MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)