From 23e695dae89a471d49cc82981621ce6263ef6283 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Sun, 5 Jun 2016 12:40:58 +0200 Subject: [PATCH] - removed asn1c dependable code from ServiceError PDU creation - added ServiceError creation function that support serviceSpecific info - server: delete dataset service now returns ServiceError with object-constraint-conflict when data set cannot be deleted because it is used in a control block --- src/iec61850/server/mms_mapping/mms_mapping.c | 10 +- src/mms/inc/mms_common.h | 1 + src/mms/inc_private/mms_server_internal.h | 6 +- src/mms/iso_mms/server/mms_file_service.c | 14 +- .../iso_mms/server/mms_get_namelist_service.c | 16 +- .../server/mms_get_var_access_service.c | 6 +- .../server/mms_named_variable_list_service.c | 88 +++++--- src/mms/iso_mms/server/mms_read_service.c | 14 +- src/mms/iso_mms/server/mms_server_common.c | 208 +++++++++++------- 9 files changed, 221 insertions(+), 142 deletions(-) diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index a5367335..bed90c8b 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -2483,10 +2483,10 @@ variableListChangedHandler (void* parameter, bool create, MmsVariableListType li else { /* Check if data set is referenced in a report */ - LinkedList element = self->reportControls; + LinkedList rcElement = self->reportControls; - while ((element = LinkedList_getNext(element)) != NULL) { - ReportControl* rc = (ReportControl*) element->data; + while ((rcElement = LinkedList_getNext(rcElement)) != NULL) { + ReportControl* rc = (ReportControl*) rcElement->data; if (rc->isDynamicDataSet) { if (rc->dataSet != NULL) { @@ -2495,7 +2495,7 @@ variableListChangedHandler (void* parameter, bool create, MmsVariableListType li if (rc->dataSet->logicalDeviceName != NULL) { if (strcmp(rc->dataSet->name, listName) == 0) { if (strcmp(rc->dataSet->logicalDeviceName, MmsDomain_getName(domain)) == 0) { - allow = MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED; + allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT; break; } } @@ -2504,7 +2504,7 @@ variableListChangedHandler (void* parameter, bool create, MmsVariableListType li else if (listType == MMS_ASSOCIATION_SPECIFIC) { if (rc->dataSet->logicalDeviceName == NULL) { if (strcmp(rc->dataSet->name, listName) == 0) { - allow = MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED; + allow = MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT; break; } } diff --git a/src/mms/inc/mms_common.h b/src/mms/inc/mms_common.h index b8bf9444..c1a8169e 100644 --- a/src/mms/inc/mms_common.h +++ b/src/mms/inc/mms_common.h @@ -66,6 +66,7 @@ typedef enum MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE = 41, MMS_ERROR_SERVICE_OTHER = 50, + MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT = 55, MMS_ERROR_SERVICE_PREEMPT_OTHER = 60, diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h index 2ec666de..0ddbbbd9 100644 --- a/src/mms/inc_private/mms_server_internal.h +++ b/src/mms/inc_private/mms_server_internal.h @@ -168,7 +168,11 @@ MmsPdu_t* mmsServer_createConfirmedResponse(uint32_t invokeId); void -mmsServer_createConfirmedErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError errorType); +mmsServer_createServiceErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError errorType); + +void +mmsServer_createServiceErrorPduWithServiceSpecificInfo(uint32_t invokeId, ByteBuffer* response, + MmsError errorType, uint8_t* serviceSpecificInfo, int serviceSpecficInfoLength); void mmsServer_writeConcludeResponsePdu(ByteBuffer* response); diff --git a/src/mms/iso_mms/server/mms_file_service.c b/src/mms/iso_mms/server/mms_file_service.c index 582fb7cf..2e7a2820 100644 --- a/src/mms/iso_mms/server/mms_file_service.c +++ b/src/mms/iso_mms/server/mms_file_service.c @@ -220,7 +220,7 @@ mmsServer_handleFileDeleteRequest( if (DEBUG_MMS_SERVER) printf("MMS_SERVER: mms_file_service.c: File (%s) not found\n", filename); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); return; } @@ -228,7 +228,7 @@ mmsServer_handleFileDeleteRequest( if (DEBUG_MMS_SERVER) printf("MMS_SERVER: mms_file_service.c: Delete file (%s) failed\n", filename); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_ACCESS_DENIED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_ACCESS_DENIED); return; } @@ -294,12 +294,12 @@ mmsServer_handleFileOpenRequest( createFileOpenResponse(invokeId, response, filename, frsm); } else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); } else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER); } else goto exit_invalid_parameter; @@ -388,7 +388,7 @@ mmsServer_handleFileReadRequest( if (frsm != NULL) createFileReadResponse(connection, invokeId, response, frsm); else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER); } static void @@ -547,7 +547,7 @@ createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, int maxPduS if (DEBUG_MMS_SERVER) printf("MMS_SERVER: Error opening directory!\n"); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); return; } @@ -651,7 +651,7 @@ mmsServer_handleFileRenameRequest( if (DEBUG_MMS_SERVER) printf("MMS_SERVER: rename file failed!\n"); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER); } } else diff --git a/src/mms/iso_mms/server/mms_get_namelist_service.c b/src/mms/iso_mms/server/mms_get_namelist_service.c index 7ce55afe..e90c4f1c 100644 --- a/src/mms/iso_mms/server/mms_get_namelist_service.c +++ b/src/mms/iso_mms/server/mms_get_namelist_service.c @@ -345,7 +345,7 @@ createNameListResponse( } if (startElement == NULL) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); return; } } @@ -526,7 +526,7 @@ mmsServer_handleGetNameListRequest( LinkedList nameList = getNameListDomainSpecific(connection, domainSpecificName); if (nameList == NULL) - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { createNameListResponse(connection, invokeId, nameList, response, continueAfterId); LinkedList_destroy(nameList); @@ -536,7 +536,7 @@ mmsServer_handleGetNameListRequest( LinkedList nameList = getJournalListDomainSpecific(connection, domainSpecificName); if (nameList == NULL) - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { createNameListResponse(connection, invokeId, nameList, response, continueAfterId); LinkedList_destroyStatic(nameList); @@ -547,7 +547,7 @@ mmsServer_handleGetNameListRequest( LinkedList nameList = getNamedVariableListsDomainSpecific(connection, domainSpecificName); if (nameList == NULL) - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { #if (CONFIG_MMS_SORT_NAME_LIST == 1) @@ -563,7 +563,7 @@ mmsServer_handleGetNameListRequest( else { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: getNameList domain specific objectClass %i not supported!\n", objectClass); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } } @@ -621,7 +621,7 @@ mmsServer_handleGetNameListRequest( else { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: getNameList VMD specific objectClass %i not supported!\n", objectClass); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } } @@ -641,14 +641,14 @@ mmsServer_handleGetNameListRequest( LinkedList_destroy(nameList); } else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } #endif /* (MMS_DYNAMIC_DATA_SETS == 1) */ #endif /* (MMS_DATA_SET_SERVICE == 1) */ else { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: getNameList(%i) not supported!\n", objectScope); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } } diff --git a/src/mms/iso_mms/server/mms_get_var_access_service.c b/src/mms/iso_mms/server/mms_get_var_access_service.c index d47ecb0e..b1c813ea 100644 --- a/src/mms/iso_mms/server/mms_get_var_access_service.c +++ b/src/mms/iso_mms/server/mms_get_var_access_service.c @@ -221,7 +221,7 @@ createVariableAccessAttributesResponse( if (domain == NULL) { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: domain %s not known\n", domainId); - mmsServer_createConfirmedErrorPdu(invokeId, response, + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); goto exit_function; } @@ -237,7 +237,7 @@ createVariableAccessAttributesResponse( if (namedVariable == NULL) { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: named variable %s not known\n", nameId); - mmsServer_createConfirmedErrorPdu(invokeId, response, + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); goto exit_function; @@ -266,7 +266,7 @@ createVariableAccessAttributesResponse( if (DEBUG_MMS_SERVER) printf("MMS getVariableAccessAttributes: message to large! send error PDU!\n"); - mmsServer_createConfirmedErrorPdu(invokeId, response, + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_SERVICE_OTHER); goto exit_function; 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 71ce3a5e..1c730454 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 @@ -99,6 +99,18 @@ createDeleteNamedVariableListResponse(uint32_t invokeId, ByteBuffer* response, response->size = bufPos; } +static void /* Confirmed service error (ServiceError) */ +createServiceErrorDeleteVariableLists(uint32_t invokeId, ByteBuffer* response, + MmsError errorType, uint32_t numberDeleted) +{ + uint8_t buffer[8]; + + int size = BerEncoder_encodeUInt32WithTL(0x86, numberDeleted, buffer, 0); + + mmsServer_createServiceErrorPduWithServiceSpecificInfo(invokeId, response, errorType, + buffer, size); +} + void mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection, uint8_t* buffer, int bufPos, int maxBufPos, @@ -125,6 +137,8 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection, MmsDevice* device = MmsServer_getDevice(connection->server); if (scopeOfDelete == DeleteNamedVariableListRequest__scopeOfDelete_specific) { + MmsError serviceError = MMS_ERROR_NONE; + int numberMatched = 0; int numberDeleted = 0; @@ -154,10 +168,14 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection, if (MmsNamedVariableList_isDeletable(variableList)) { - if (mmsServer_callVariableListChangedHandler(false, MMS_DOMAIN_SPECIFIC, domain, listName, connection) == MMS_ERROR_NONE) { + MmsError deleteError = mmsServer_callVariableListChangedHandler(false, MMS_DOMAIN_SPECIFIC, domain, listName, connection); + + if (deleteError == MMS_ERROR_NONE) { MmsDomain_deleteNamedVariableList(domain, listName); numberDeleted++; } + else + serviceError = deleteError; } } } @@ -173,10 +191,14 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection, if (variableList != NULL) { numberMatched++; - if (mmsServer_callVariableListChangedHandler(false, MMS_ASSOCIATION_SPECIFIC, NULL, listName, connection) == MMS_ERROR_NONE) { + MmsError deleteError = mmsServer_callVariableListChangedHandler(false, MMS_ASSOCIATION_SPECIFIC, NULL, listName, connection); + + if (deleteError == MMS_ERROR_NONE) { numberDeleted++; MmsServerConnection_deleteNamedVariableList(connection, listName); } + else + serviceError = deleteError; } } else if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_vmdspecific) { @@ -190,19 +212,25 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection, if (variableList != NULL) { numberMatched++; - if (mmsServer_callVariableListChangedHandler(false, MMS_VMD_SPECIFIC, NULL, listName, connection) - == MMS_ERROR_NONE) { + MmsError deleteError = mmsServer_callVariableListChangedHandler(false, MMS_VMD_SPECIFIC, NULL, listName, connection); + + if (deleteError == MMS_ERROR_NONE) { numberDeleted++; mmsServer_deleteVariableList(device->namedVariableLists, listName); } + else + serviceError = deleteError; } } } - createDeleteNamedVariableListResponse(invokeId, response, numberMatched, numberDeleted); + if (serviceError == MMS_ERROR_NONE) + createDeleteNamedVariableListResponse(invokeId, response, numberMatched, numberDeleted); + else + createServiceErrorDeleteVariableLists(invokeId, response, serviceError, numberDeleted); } else { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); @@ -404,7 +432,7 @@ mmsServer_handleDefineNamedVariableListRequest( char domainName[65]; if (request->variableListName.choice.domainspecific.domainId.size > 64) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); goto exit_free_struct; } @@ -415,7 +443,7 @@ mmsServer_handleDefineNamedVariableListRequest( MmsDomain* domain = MmsDevice_getDomain(device, domainName); if (domain == NULL) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); goto exit_free_struct; } @@ -423,7 +451,7 @@ mmsServer_handleDefineNamedVariableListRequest( char variableListName[65]; if (request->variableListName.choice.domainspecific.itemId.size > 64) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); goto exit_free_struct; } @@ -432,7 +460,7 @@ mmsServer_handleDefineNamedVariableListRequest( request->variableListName.choice.domainspecific.itemId.size); if (MmsDomain_getNamedVariableList(domain, variableListName) != NULL) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS); } else { MmsError mmsError; @@ -450,15 +478,15 @@ mmsServer_handleDefineNamedVariableListRequest( } else { MmsNamedVariableList_destroy(namedVariableList); - mmsServer_createConfirmedErrorPdu(invokeId, response, mmsError); + mmsServer_createServiceErrorPdu(invokeId, response, mmsError); } } else - mmsServer_createConfirmedErrorPdu(invokeId, response, mmsError); + mmsServer_createServiceErrorPdu(invokeId, response, mmsError); } } else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE); } @@ -470,7 +498,7 @@ mmsServer_handleDefineNamedVariableListRequest( if (request->variableListName.choice.aaspecific.size > 64) { //TODO send reject PDU instead? - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); goto exit_free_struct; } @@ -479,7 +507,7 @@ mmsServer_handleDefineNamedVariableListRequest( request->variableListName.choice.aaspecific.size); if (MmsServerConnection_getNamedVariableList(connection, variableListName) != NULL) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS); } else { MmsError mmsError; @@ -495,16 +523,16 @@ mmsServer_handleDefineNamedVariableListRequest( } else { MmsNamedVariableList_destroy(namedVariableList); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED); } } else - mmsServer_createConfirmedErrorPdu(invokeId, response, mmsError); + mmsServer_createServiceErrorPdu(invokeId, response, mmsError); } } else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE); } else if (request->variableListName.present == ObjectName_PR_vmdspecific) { LinkedList vmdScopeNVLs = MmsDevice_getNamedVariableLists(connection->server->device); @@ -515,7 +543,7 @@ mmsServer_handleDefineNamedVariableListRequest( if (request->variableListName.choice.vmdspecific.size > 64) { //TODO send reject PDU instead? - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); goto exit_free_struct; } @@ -524,7 +552,7 @@ mmsServer_handleDefineNamedVariableListRequest( request->variableListName.choice.vmdspecific.size); if (mmsServer_getNamedVariableListWithName(MmsDevice_getNamedVariableLists(connection->server->device), variableListName) != NULL) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS); } else { MmsError mmsError; @@ -541,7 +569,7 @@ mmsServer_handleDefineNamedVariableListRequest( } else { MmsNamedVariableList_destroy(namedVariableList); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED); } } @@ -549,7 +577,7 @@ mmsServer_handleDefineNamedVariableListRequest( } } else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_TYPE_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_TYPE_UNSUPPORTED); exit_free_struct: asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); @@ -648,7 +676,7 @@ mmsServer_handleGetNamedVariableListAttributesRequest( if ((request->choice.domainspecific.domainId.size > 64) || (request->choice.domainspecific.itemId.size > 64)) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER); goto exit_function; } @@ -669,10 +697,10 @@ mmsServer_handleGetNamedVariableListAttributesRequest( if (variableList != NULL) createGetNamedVariableListAttributesResponse(invokeId, response, variableList); else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); } else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); } #if (MMS_DYNAMIC_DATA_SETS == 1) @@ -681,7 +709,7 @@ mmsServer_handleGetNamedVariableListAttributesRequest( char listName[65]; if (request->choice.aaspecific.size > 64) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER); goto exit_function; } @@ -693,14 +721,14 @@ mmsServer_handleGetNamedVariableListAttributesRequest( if (varList != NULL) createGetNamedVariableListAttributesResponse(invokeId, response, varList); else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); } #endif /* (MMS_DYNAMIC_DATA_SETS == 1) */ else if (request->present == ObjectName_PR_vmdspecific) { char listName[65]; if (request->choice.vmdspecific.size > 64) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER); goto exit_function; } @@ -714,10 +742,10 @@ mmsServer_handleGetNamedVariableListAttributesRequest( if (varList != NULL) createGetNamedVariableListAttributesResponse(invokeId, response, varList); else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); } else { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } exit_function: diff --git a/src/mms/iso_mms/server/mms_read_service.c b/src/mms/iso_mms/server/mms_read_service.c index cfe2af9c..3ad46abb 100644 --- a/src/mms/iso_mms/server/mms_read_service.c +++ b/src/mms/iso_mms/server/mms_read_service.c @@ -431,7 +431,7 @@ encodeReadResponse(MmsServerConnection connection, if (DEBUG_MMS_SERVER) printf("MMS read: message to large! send error PDU!\n"); - mmsServer_createConfirmedErrorPdu(invokeId, response, + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_SERVICE_OTHER); goto exit_function; @@ -647,7 +647,7 @@ handleReadNamedVariableListRequest( if (domain == NULL) { if (DEBUG_MMS_SERVER) printf("MMS read: domain %s not found!\n", domainIdStr); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); } else { MmsNamedVariableList namedList = MmsDomain_getNamedVariableList(domain, nameIdStr); @@ -658,7 +658,7 @@ handleReadNamedVariableListRequest( } else { if (DEBUG_MMS_SERVER) printf("MMS read: named variable list %s not found!\n", nameIdStr); - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); } } } @@ -672,7 +672,7 @@ handleReadNamedVariableListRequest( MmsNamedVariableList namedList = mmsServer_getNamedVariableListWithName(connection->server->device->namedVariableLists, listName); if (namedList == NULL) - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { VarAccessSpec accessSpec; @@ -697,7 +697,7 @@ handleReadNamedVariableListRequest( MmsNamedVariableList namedList = MmsServerConnection_getNamedVariableList(connection, listName); if (namedList == NULL) - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { VarAccessSpec accessSpec; @@ -711,7 +711,7 @@ handleReadNamedVariableListRequest( } #endif /* (MMS_DYNAMIC_DATA_SETS == 1) */ else - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } #endif /* MMS_DATA_SET_SERVICE == 1 */ @@ -745,7 +745,7 @@ mmsServer_handleReadRequest( } #endif else { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); + mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); } asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); diff --git a/src/mms/iso_mms/server/mms_server_common.c b/src/mms/iso_mms/server/mms_server_common.c index 46d87bed..ba277499 100644 --- a/src/mms/iso_mms/server/mms_server_common.c +++ b/src/mms/iso_mms/server/mms_server_common.c @@ -1,7 +1,7 @@ /* * mms_server_common.c * - * Copyright 2013 Michael Zillgith + * Copyright 2013-2016 Michael Zillgith * * This file is part of libIEC61850. * @@ -45,96 +45,142 @@ mmsServer_createConfirmedResponse(uint32_t invokeId) return mmsPdu; } +static void +mapErrorTypeToErrorClass(MmsError errorType, uint8_t* tag, uint8_t* value) +{ + switch (errorType) { + + case MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED: + *tag = 0x87; /* access */ + *value = 1; + break; + + case MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT: + *tag = 0x87; /* access */ + *value = 2; + break; + + case MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED: + *tag = 0x87; /* access */ + *value = 3; + break; + + case MMS_ERROR_SERVICE_OTHER: + *tag = 0x84; /* service */ + *value = 0; + break; + + case MMS_ERROR_SERVICE_OBJECT_CONSTRAINT_CONFLICT: + *tag = 0x84; /* service */ + *value = 5; + break; + + case MMS_ERROR_DEFINITION_OTHER: + *tag = 0x82; /* definition */ + *value = 0; + break; + + case MMS_ERROR_DEFINITION_OBJECT_UNDEFINED: + *tag = 0x82; /* definition */ + *value = 1; + break; + + case MMS_ERROR_DEFINITION_TYPE_UNSUPPORTED: + *tag = 0x82; /* definition */ + *value = 3; + break; + + case MMS_ERROR_DEFINITION_OBJECT_EXISTS: + *tag = 0x82; /* definition */ + *value = 5; + break; + + case MMS_ERROR_FILE_OTHER: + *tag = 0x8b; /* file */ + *value = 0; + break; + + case MMS_ERROR_FILE_FILE_NON_EXISTENT: + *tag = 0x8b; /* file */ + *value = 7; + break; + + case MMS_ERROR_RESOURCE_OTHER: + *tag = 0x83; /* resource */ + *value = 0; + break; + + case MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE: + *tag = 0x83; /* resource */ + *value = 4; + break; + + default: + + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: unknown errorType!\n"); + + *tag = 0x8c; /* others */ + *value = 0; + break; + + } + +} void -mmsServer_createConfirmedErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError errorType) +mmsServer_createServiceErrorPduWithServiceSpecificInfo(uint32_t invokeId, ByteBuffer* response, + MmsError errorType, uint8_t* serviceSpecificInfo, int serviceSpecficInfoLength) { - MmsPdu_t* mmsPdu = (MmsPdu_t*) GLOBAL_CALLOC(1, sizeof(MmsPdu_t)); - mmsPdu->present = MmsPdu_PR_confirmedErrorPDU; + /* determine encoded size */ - asn_long2INTEGER(&(mmsPdu->choice.confirmedErrorPDU.invokeID), - invokeId); + uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId) + 2; - if (errorType == MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_access; + uint32_t specificInfoSize = 0; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__access_objectnonexistent); - } - else if (errorType == MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_access; + if (serviceSpecificInfo != NULL) + specificInfoSize = 1 + BerEncoder_determineLengthSize(serviceSpecficInfoLength) + + serviceSpecficInfoLength; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__access_objectaccessdenied); - } - else if (errorType == MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_access; + uint32_t serviceErrorContentSize = 5 /* errorClass */ + specificInfoSize; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__access_objectaccessunsupported); - } - else if (errorType == MMS_ERROR_SERVICE_OTHER) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_service; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__service_other); - } - else if (errorType == MMS_ERROR_DEFINITION_OTHER) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_definition; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__definition_other); - } - else if (errorType == MMS_ERROR_DEFINITION_OBJECT_EXISTS) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_definition; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__definition_objectexists); - } - else if (errorType == MMS_ERROR_DEFINITION_OBJECT_UNDEFINED) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_definition; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__definition_objectundefined); - } - else if (errorType == MMS_ERROR_DEFINITION_TYPE_UNSUPPORTED) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_definition; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__definition_typeunsupported); - } - else if (errorType == MMS_ERROR_FILE_FILE_NON_EXISTENT) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_file; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__file_filenonexistent); - } - else if (errorType == MMS_ERROR_FILE_OTHER) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_file; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__file_other); - } - else if (errorType == MMS_ERROR_RESOURCE_OTHER) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_resource; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__resource_other); - } - else if (errorType == MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE) { - mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.present = - ServiceError__errorClass_PR_resource; - asn_long2INTEGER(&mmsPdu->choice.confirmedErrorPDU.serviceError.errorClass.choice.access, - ServiceError__errorClass__resource_capabilityunavailable); - } + uint32_t serviceErrorSize = 1 + BerEncoder_determineLengthSize(serviceErrorContentSize) + + serviceErrorContentSize; + + uint32_t confirmedErrorContentSize = serviceErrorSize + invokeIdSize; + + /* encode */ + uint8_t* buffer = response->buffer; + int bufPos = response->size; + + bufPos = BerEncoder_encodeTL(0xa2, confirmedErrorContentSize, buffer, bufPos); + + bufPos = BerEncoder_encodeTL(0x80, invokeIdSize - 2, buffer, bufPos); /* invokeID */ + bufPos = BerEncoder_encodeUInt32((uint32_t) invokeId, buffer, bufPos); - der_encode(&asn_DEF_MmsPdu, mmsPdu, - mmsServer_write_out, (void*) response); + bufPos = BerEncoder_encodeTL(0xa2, serviceErrorContentSize, buffer, bufPos); /* serviceError */ + bufPos = BerEncoder_encodeTL(0xa0, 3, buffer, bufPos); /* serviceError */ - asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); + uint8_t errorCodeTag; + uint8_t errorCodeValue; + + mapErrorTypeToErrorClass(errorType, &errorCodeTag, &errorCodeValue); + + buffer[bufPos++] = errorCodeTag; + buffer[bufPos++] = 1; + buffer[bufPos++] = errorCodeValue; + + if (serviceSpecificInfo != NULL) + bufPos = BerEncoder_encodeOctetString(0xa3, serviceSpecificInfo, serviceSpecficInfoLength, + buffer, bufPos); + + response->size = bufPos; +} + +void /* Confirmed service error (ServiceError) */ +mmsServer_createServiceErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError errorType) +{ + mmsServer_createServiceErrorPduWithServiceSpecificInfo(invokeId, response, errorType, NULL, 0); } int