From 82e52881f9b74ed063114a7b339bed9d3c20888b Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 16 Jun 2022 09:11:47 +0200 Subject: [PATCH] - fixed problem with write access to data attribute of type array (LIB61850-336) --- src/iec61850/server/impl/ied_server.c | 23 +++++++------ src/iec61850/server/mms_mapping/mms_mapping.c | 17 ++++++++-- .../iso_mms/client/mms_client_connection.c | 1 - src/mms/iso_mms/client/mms_client_read.c | 32 ++++++++++--------- src/mms/iso_mms/common/mms_type_spec.c | 3 ++ src/mms/iso_mms/server/mms_value_cache.c | 5 ++- 6 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index 62fbd8d9..69179908 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -236,14 +236,16 @@ static void installDefaultValuesForDataAttribute(IedServer self, LogicalDevice* ld, DataAttribute* dataAttribute, char* objectReference, int position, int idx, char* componentId, int compIdPos) { - if (idx == -1) { - sprintf(objectReference + position, ".%s", dataAttribute->name); - } - else { - if (compIdPos == 0) - sprintf(componentId, "%s", dataAttribute->name); - else - sprintf(componentId + compIdPos, "$%s", dataAttribute->name); + if (dataAttribute->name) { + if (idx == -1) { + sprintf(objectReference + position, ".%s", dataAttribute->name); + } + else { + if (compIdPos == 0) + sprintf(componentId, "%s", dataAttribute->name); + else + sprintf(componentId + compIdPos, "$%s", dataAttribute->name); + } } char mmsVariableName[65]; /* maximum size is 64 according to 61850-8-1 */ @@ -384,10 +386,12 @@ installDefaultValuesInCache(IedServer self) { IedModel* model = self->model; - char objectReference[130]; char componentId[130]; componentId[0] = 0; + char objectReference[130]; + + LogicalDevice* logicalDevice = model->firstChild; while (logicalDevice != NULL) { @@ -409,6 +413,7 @@ installDefaultValuesInCache(IedServer self) int refPosition = strlen(objectReference); while (dataObject != NULL) { + componentId[0] = 0; installDefaultValuesForDataObject(self, logicalDevice, dataObject, objectReference, refPosition, -1, componentId, 0); dataObject = (DataObject*) dataObject->sibling; diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index bcb2f28a..248112b2 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -117,19 +117,30 @@ createNamedVariableFromDataAttribute(DataAttribute* attribute) { MmsVariableSpecification* origNamedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); - origNamedVariable->name = StringUtils_copyString(attribute->name); + + if (attribute->name) + origNamedVariable->name = StringUtils_copyString(attribute->name); + else + origNamedVariable->name = NULL; MmsVariableSpecification* namedVariable = origNamedVariable; - if (attribute->elementCount > 0) { + bool isBasicArray = false; + + if (attribute->elementCount > 0) + { namedVariable->type = MMS_ARRAY; namedVariable->typeSpec.array.elementCount = attribute->elementCount; namedVariable->typeSpec.array.elementTypeSpec = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification)); namedVariable = namedVariable->typeSpec.array.elementTypeSpec; + + if (attribute->firstChild && ((DataAttribute*)(attribute->firstChild))->type != IEC61850_CONSTRUCTED) { + isBasicArray = true; + } } - if (attribute->firstChild != NULL) { + if ((attribute->firstChild != NULL) && (isBasicArray == false)) { namedVariable->type = MMS_STRUCTURE; int componentCount = ModelNode_getChildCount((ModelNode*) attribute); diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index 5635fd78..e2dbb6a7 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -680,7 +680,6 @@ exit_error: static void handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, MmsOutstandingCall outstandingCall, MmsError err) { - if (outstandingCall->type == MMS_CALL_TYPE_READ_VARIABLE) { MmsConnection_ReadVariableHandler handler = diff --git a/src/mms/iso_mms/client/mms_client_read.c b/src/mms/iso_mms/client/mms_client_read.c index 8a4b5063..caba0a8b 100644 --- a/src/mms/iso_mms/client/mms_client_read.c +++ b/src/mms/iso_mms/client/mms_client_read.c @@ -111,28 +111,30 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi if (componentCount > 0) { value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue)); - value->type = MMS_STRUCTURE; - value->value.structure.size = componentCount; - value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); - if (value->value.structure.components) { - int j; - for (j = 0; j < componentCount; j++) { - value->value.structure.components[j] = mmsMsg_parseDataElement( - accessResultList[i]->choice.structure.list.array[j]); + if (value) { + value->type = MMS_STRUCTURE; + value->value.structure.size = componentCount; + value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*)); - if (value->value.structure.components[j] == NULL) { + if (value->value.structure.components) { + int j; + for (j = 0; j < componentCount; j++) { + value->value.structure.components[j] = mmsMsg_parseDataElement( + accessResultList[i]->choice.structure.list.array[j]); - if (DEBUG_MMS_CLIENT) - printf("MMS CLIENT: failed to parse struct element %i\n", j); + if (value->value.structure.components[j] == NULL) { - MmsValue_delete(value); - value = NULL; - break; + if (DEBUG_MMS_CLIENT) + printf("MMS CLIENT: failed to parse struct element %i\n", j); + + MmsValue_delete(value); + value = NULL; + break; + } } } } - } else { if (DEBUG_MMS_CLIENT) diff --git a/src/mms/iso_mms/common/mms_type_spec.c b/src/mms/iso_mms/common/mms_type_spec.c index 63306ab2..f83b804e 100644 --- a/src/mms/iso_mms/common/mms_type_spec.c +++ b/src/mms/iso_mms/common/mms_type_spec.c @@ -29,6 +29,9 @@ void MmsVariableSpecification_destroy(MmsVariableSpecification* typeSpec) { + if (typeSpec == NULL) + return; + if (typeSpec->name != NULL) GLOBAL_FREEMEM(typeSpec->name); diff --git a/src/mms/iso_mms/server/mms_value_cache.c b/src/mms/iso_mms/server/mms_value_cache.c index f4ade311..99075b1f 100644 --- a/src/mms/iso_mms/server/mms_value_cache.c +++ b/src/mms/iso_mms/server/mms_value_cache.c @@ -173,19 +173,18 @@ searchCacheForValueEx(MmsValueCache self, const char* itemId, char* parentId, in const char* childId = getChildSubString(itemId, parentId); if (childId) { - MmsVariableSpecification* typeSpec = MmsDomain_getNamedVariable(self->domain, parentId); value = MmsVariableSpecification_getChildValue(typeSpec, cacheEntry->value, childId); if (value) { + if (idx != -1) { if (MmsValue_getType(value) == MMS_ARRAY) { MmsValue* elementValue = MmsValue_getElement(value, idx); - if (elementValue) { - if (componentId) { + if ((componentId != NULL) && (componentId[0] != 0)) { MmsVariableSpecification* childSpec = MmsVariableSpecification_getNamedVariableRecursive(typeSpec, childId); if (childSpec) {