diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index a21e406..9271131 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -1048,7 +1048,7 @@ createDataSets(MmsDevice* mmsDevice, IedModel* iedModel) MmsDomain* dataSetDomain = MmsDevice_getDomain(mmsDevice, domainName); - MmsNamedVariableList varList = MmsNamedVariableList_create(dataset->name, false); + MmsNamedVariableList varList = MmsNamedVariableList_create(dataSetDomain, dataset->name, false); DataSetEntry* dataSetEntry = dataset->fcdas; @@ -2052,6 +2052,73 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS return DATA_ACCESS_ERROR_SUCCESS; } +static bool +variableListChangedHandler (void* parameter, bool create, MmsVariableListType listType, MmsDomain* domain, + char* listName, MmsServerConnection* connection) +{ + bool allow = true; + +#if (DEBUG_IED_SERVER == 1) + if (create) + printf("create data set "); + else + printf("delete data set "); + + switch (listType) { + case MMS_VMD_SPECIFIC: + printf("VMD "); + break; + case MMS_ASSOCIATION_SPECIFIC: + printf("association "); + break; + case MMS_DOMAIN_SPECIFIC: + printf("domain "); + break; + } + + printf("specific (name=%s)\n", listName); +#endif /* (DEBUG_IED_SERVER == 1) */ + + MmsMapping* self = (MmsMapping*) parameter; + + if (create == false) { + /* Check if data set is referenced in a report */ + + LinkedList element = self->reportControls; + + while ((element = LinkedList_getNext(element)) != NULL) { + ReportControl* rc = (ReportControl*) element->data; + + if (rc->isDynamicDataSet) { + if (rc->dataSet != NULL) { + + if (listType == MMS_DOMAIN_SPECIFIC) { + if (rc->dataSet->logicalDeviceName != NULL) { + if (strcmp(rc->dataSet->name, listName) == 0) { + if (strcmp(rc->dataSet->logicalDeviceName, MmsDomain_getName(domain)) == 0) { + allow = false; + break; + } + } + } + } + else if (listType == MMS_ASSOCIATION_SPECIFIC) { + if (rc->dataSet->logicalDeviceName == NULL) { + if (strcmp(rc->dataSet->name, listName) == 0) { + allow = false; + break; + } + } + } + + } + } + } + } + + return allow; +} + void MmsMapping_installHandlers(MmsMapping* self) { @@ -2059,6 +2126,7 @@ MmsMapping_installHandlers(MmsMapping* self) MmsServer_installWriteHandler(self->mmsServer, mmsWriteHandler, (void*) self); MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self); MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self); + MmsServer_installVariableListChangedHandler(self->mmsServer, variableListChangedHandler, (void*) self); } void @@ -2446,7 +2514,10 @@ MmsMapping_createDataSetByNamedVariableList(MmsMapping* self, MmsNamedVariableLi { DataSet* dataSet = (DataSet*) GLOBAL_MALLOC(sizeof(DataSet)); - dataSet->logicalDeviceName = NULL; /* name is not relevant for dynamically created data set */ + if (variableList->domain != NULL) + dataSet->logicalDeviceName = MmsDomain_getName(variableList->domain); + else + dataSet->logicalDeviceName = NULL; /* name is not relevant for association specific data sets */ dataSet->name = variableList->name; dataSet->elementCount = LinkedList_size(variableList->listOfVariables); diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index ce50808..baa1fdc 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -468,13 +468,17 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet, MmsValue* dataSetValue; - if (newDatSet != NULL) - dataSetValue = newDatSet; + if (newDatSet != NULL) { + if (strcmp(MmsValue_toString(newDatSet), "") == 0) { + success = true; + dataSetValue = NULL; + } + else + dataSetValue = newDatSet; + } else dataSetValue = ReportControl_getRCBValue(rc, "DatSet"); - char* dataSetName = MmsValue_toString(dataSetValue); - if (rc->isDynamicDataSet) { if (rc->dataSet != NULL) { deleteDataSetValuesShadowBuffer(rc); @@ -485,6 +489,8 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet, } if (dataSetValue != NULL) { + char* dataSetName = MmsValue_toString(dataSetValue); + DataSet* dataSet = IedModel_lookupDataSet(mapping->model, dataSetName); if (dataSet == NULL) { @@ -1084,10 +1090,10 @@ updateOwner(ReportControl* rc, MmsServerConnection* connection) if (connection != NULL) { char* clientAddressString = MmsServerConnection_getClientAddress(connection); - if (DEBUG_IED_SERVER) printf("reporting.c: set owner to %s\n", clientAddressString); + if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: set owner to %s\n", clientAddressString); if (strchr(clientAddressString, '.') != NULL) { - if (DEBUG_IED_SERVER) printf("reporting.c: client address is IPv4 address\n"); + if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: client address is IPv4 address\n"); { uint8_t ipV4Addr[4]; @@ -1114,7 +1120,7 @@ updateOwner(ReportControl* rc, MmsServerConnection* connection) else { uint8_t ipV6Addr[16]; MmsValue_setOctetString(owner, ipV6Addr, 0); - if (DEBUG_IED_SERVER) printf("reporting.c: client address is IPv6 address or unknown\n"); + if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: client address is IPv6 address or unknown\n"); } } else { @@ -1219,6 +1225,9 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme } } else { + if (rc->enabled == false) + goto exit_function; + if (((rc->enabled) || (rc->reserved)) && (rc->clientConnection != connection)) { retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; goto exit_function; @@ -1247,7 +1256,10 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme if (strcmp(elementName, "GI") == 0) { if ((rc->enabled) && (rc->clientConnection == connection)) { - rc->gi = true; + + if (MmsValue_getBoolean(value)) + rc->gi = true; + retVal = DATA_ACCESS_ERROR_SUCCESS; goto exit_function; } @@ -1299,7 +1311,6 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; goto exit_function; } - } retVal = DATA_ACCESS_ERROR_SUCCESS; @@ -1381,6 +1392,14 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme goto exit_function; } + else if (strcmp(elementName, "SqNum") == 0) { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } + else if (strcmp(elementName, "Owner") == 0) { + retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + goto exit_function; + } MmsValue* rcbValue = ReportControl_getRCBValue(rc, elementName); diff --git a/src/mms/inc/mms_named_variable_list.h b/src/mms/inc/mms_named_variable_list.h index f2f57e3..15e7d16 100644 --- a/src/mms/inc/mms_named_variable_list.h +++ b/src/mms/inc/mms_named_variable_list.h @@ -38,6 +38,7 @@ extern "C" { struct sMmsNamedVariableList { bool deletable; + MmsDomain* domain; char* name; LinkedList listOfVariables; }; @@ -55,11 +56,14 @@ char* MmsNamedVariableListEntry_getVariableName(MmsNamedVariableListEntry self); MmsNamedVariableList -MmsNamedVariableList_create(char* name, bool deletable); +MmsNamedVariableList_create(MmsDomain* domain, char* name, bool deletable); char* MmsNamedVariableList_getName(MmsNamedVariableList self); +MmsDomain* +MmsNamedVariableList_getDomain(MmsNamedVariableList self); + bool MmsNamedVariableList_isDeletable(MmsNamedVariableList self); diff --git a/src/mms/iso_mms/server/mms_named_variable_list.c b/src/mms/iso_mms/server/mms_named_variable_list.c index 9fe16a9..6489428 100644 --- a/src/mms/iso_mms/server/mms_named_variable_list.c +++ b/src/mms/iso_mms/server/mms_named_variable_list.c @@ -62,17 +62,24 @@ MmsNamedVariableListEntry_getVariableName(MmsNamedVariableListEntry self) { } MmsNamedVariableList -MmsNamedVariableList_create(char* name, bool deletable) +MmsNamedVariableList_create(MmsDomain* domain, char* name, bool deletable) { MmsNamedVariableList self = (MmsNamedVariableList) GLOBAL_MALLOC(sizeof(struct sMmsNamedVariableList)); self->deletable = deletable; self->name = copyString(name); self->listOfVariables = LinkedList_create(); + self->domain = domain; return self; } +MmsDomain* +MmsNamedVariableList_getDomain(MmsNamedVariableList self) +{ + return self->domain; +} + char* MmsNamedVariableList_getName(MmsNamedVariableList self) { diff --git a/src/mms/iso_mms/server/mms_named_variable_list_service.c b/src/mms/iso_mms/server/mms_named_variable_list_service.c index 9714d89..d4ebe5f 100644 --- a/src/mms/iso_mms/server/mms_named_variable_list_service.c +++ b/src/mms/iso_mms/server/mms_named_variable_list_service.c @@ -236,7 +236,7 @@ checkIfVariableExists(MmsDevice* device, MmsAccessSpecifier* accessSpecifier) static MmsNamedVariableList -createNamedVariableList(MmsDevice* device, +createNamedVariableList(MmsDomain* domain, MmsDevice* device, DefineNamedVariableListRequest_t* request, char* variableListName, MmsError* mmsError) { @@ -249,7 +249,7 @@ createNamedVariableList(MmsDevice* device, goto exit_function; } - namedVariableList = MmsNamedVariableList_create(variableListName, true); + namedVariableList = MmsNamedVariableList_create(domain, variableListName, true); int i; for (i = 0; i < variableCount; i++) { @@ -315,11 +315,11 @@ createNamedVariableList(MmsDevice* device, varSpec->choice.name.choice.domainspecific.domainId.buf, varSpec->choice.name.choice.domainspecific.domainId.size); - MmsDomain* domain = MmsDevice_getDomain(device, domainId); + MmsDomain* elementDomain = MmsDevice_getDomain(device, domainId); MmsAccessSpecifier accessSpecifier; - accessSpecifier.domain = domain; + accessSpecifier.domain = elementDomain; accessSpecifier.variableName = variableName; accessSpecifier.arrayIndex = arrayIndex; accessSpecifier.componentName = componentName; @@ -412,7 +412,7 @@ mmsServer_handleDefineNamedVariableListRequest( else { MmsError mmsError; - MmsNamedVariableList namedVariableList = createNamedVariableList(device, + MmsNamedVariableList namedVariableList = createNamedVariableList(domain, device, request, variableListName, &mmsError); if (namedVariableList != NULL) { @@ -456,7 +456,7 @@ mmsServer_handleDefineNamedVariableListRequest( else { MmsError mmsError; - MmsNamedVariableList namedVariableList = createNamedVariableList(device, + MmsNamedVariableList namedVariableList = createNamedVariableList(NULL, device, request, variableListName, &mmsError); if (namedVariableList != NULL) {