From 84fcfbbd22ac9312fb74e47f6fe08ea9de4fdf28 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 30 May 2019 17:37:42 +0200 Subject: [PATCH] - MMS client/server: handle missing invoke ID in reject/error PDUs --- src/mms/inc_private/mms_common_internal.h | 4 +- .../iso_mms/client/mms_client_connection.c | 70 +++++++++++++------ .../iso_mms/server/mms_server_connection.c | 26 ++++--- 3 files changed, 66 insertions(+), 34 deletions(-) diff --git a/src/mms/inc_private/mms_common_internal.h b/src/mms/inc_private/mms_common_internal.h index 53e6b678..8f8c92b6 100644 --- a/src/mms/inc_private/mms_common_internal.h +++ b/src/mms/inc_private/mms_common_internal.h @@ -92,10 +92,10 @@ LIB61850_INTERNAL void mmsMsg_createMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response); LIB61850_INTERNAL int -mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, MmsServiceError* serviceError); +mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, bool* hasInvokeId, MmsServiceError* serviceError); LIB61850_INTERNAL int -mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, int* rejectType, int* rejectReason); +mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, bool* hasInvokeId, int* rejectType, int* rejectReason); LIB61850_INTERNAL MmsValue* mmsMsg_parseDataElement(Data_t* dataElement); diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index 51d25044..6ae1f383 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -533,10 +533,13 @@ parseServiceError(uint8_t* buffer, int bufPos, int maxLength, MmsServiceError* e } int -mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, MmsServiceError* serviceError) +mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, bool* hasInvokeId, MmsServiceError* serviceError) { int length; + if (hasInvokeId) + *hasInvokeId = false; + uint8_t tag = buffer[bufPos++]; if (tag != 0xa2) goto exit_error; @@ -561,6 +564,8 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32 switch (tag) { case 0x80: /* invoke Id */ + if (hasInvokeId) + *hasInvokeId = true; if (invokeId != NULL) *invokeId = BerDecoder_decodeUint32(buffer, length, bufPos); bufPos += length; @@ -589,10 +594,13 @@ exit_error: } int -mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, int* rejectType, int* rejectReason) +mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, bool* hasInvokeId, int* rejectType, int* rejectReason) { int length; + if (hasInvokeId) + *hasInvokeId = false; + uint8_t tag = buffer[bufPos++]; if (tag != 0xa4) @@ -619,6 +627,8 @@ mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invo goto exit_error; if (tag == 0x80) { /* invoke id */ + if (hasInvokeId) + *hasInvokeId = true; if (invokeId != NULL) *invokeId = BerDecoder_decodeUint32(buffer, length, bufPos); } @@ -1080,9 +1090,11 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload) printf("MMS_CLIENT: Confirmed error PDU!\n"); uint32_t invokeId; + bool hasInvokeId = false; + MmsServiceError serviceError = { 0, 0 }; - if (mmsMsg_parseConfirmedErrorPDU(payload->buffer, 0, payload->size, &invokeId, &serviceError) < 0) { + if (mmsMsg_parseConfirmedErrorPDU(payload->buffer, 0, payload->size, &invokeId, &hasInvokeId, &serviceError) < 0) { if (DEBUG_MMS_CLIENT) printf("MMS_CLIENT: Error parsing confirmedErrorPDU!\n"); @@ -1090,26 +1102,35 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload) } else { - MmsOutstandingCall call = checkForOutstandingCall(self, invokeId); + if (hasInvokeId) { + MmsOutstandingCall call = checkForOutstandingCall(self, invokeId); - if (call) { + if (call) { - MmsError err = convertServiceErrorToMmsError(serviceError); + MmsError err = convertServiceErrorToMmsError(serviceError); - if (call->type != MMS_CALL_TYPE_NONE) { - handleAsyncResponse(self, NULL, 0, call, err); + if (call->type != MMS_CALL_TYPE_NONE) { + handleAsyncResponse(self, NULL, 0, call, err); + } + else { + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: internal problem (unexpected call type - error PDU)\n"); + } } else { if (DEBUG_MMS_CLIENT) - printf("MMS_CLIENT: internal problem (unexpected call type - error PDU)\n"); + printf("MMS_CLIENT: server sent unexpected confirmed error PDU!\n"); + + return; } } else { if (DEBUG_MMS_CLIENT) - printf("MMS_CLIENT: unexpected message from server!\n"); + printf("MMS_CLIENT: server sent confirmed error PDU without invoke ID!\n"); return; } + } } else if (tag == 0xa4) { /* reject PDU */ @@ -1117,33 +1138,40 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload) if (DEBUG_MMS_CLIENT) printf("MMS_CLIENT: reject PDU!\n"); - uint32_t invokeId; + bool hasInvokeId = false; + uint32_t invokeId = 0; int rejectType; int rejectReason; - if (mmsMsg_parseRejectPDU(payload->buffer, 0, payload->size, &invokeId, &rejectType, &rejectReason) >= 0) { + if (mmsMsg_parseRejectPDU(payload->buffer, 0, payload->size, &invokeId, &hasInvokeId, &rejectType, &rejectReason) >= 0) { if (DEBUG_MMS_CLIENT) - printf("MMS_CLIENT: reject PDU invokeID: %i type: %i reason: %i\n", (int) invokeId, rejectType, rejectReason); + printf("MMS_CLIENT: reject PDU invokeID: %u type: %i reason: %i\n", invokeId, rejectType, rejectReason); - MmsOutstandingCall call = checkForOutstandingCall(self, invokeId); + if (hasInvokeId) { + MmsOutstandingCall call = checkForOutstandingCall(self, invokeId); - if (call) { + if (call) { - MmsError err = convertRejectCodesToMmsError(rejectType, rejectReason); + MmsError err = convertRejectCodesToMmsError(rejectType, rejectReason); - if (call->type != MMS_CALL_TYPE_NONE) { - handleAsyncResponse(self, NULL, 0, call, err); + if (call->type != MMS_CALL_TYPE_NONE) { + handleAsyncResponse(self, NULL, 0, call, err); + } + else { + + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: internal problem (unexpected call type - reject PDU)\n"); + } } else { - - if (DEBUG_MMS_CLIENT) - printf("MMS_CLIENT: internal problem (unexpected call type - reject PDU)\n"); + return; } } else { return; } + } else goto exit_with_error; diff --git a/src/mms/iso_mms/server/mms_server_connection.c b/src/mms/iso_mms/server/mms_server_connection.c index d00ce842..1a1f5088 100644 --- a/src/mms/iso_mms/server/mms_server_connection.c +++ b/src/mms/iso_mms/server/mms_server_connection.c @@ -411,28 +411,32 @@ handleConfirmedErrorPdu( uint8_t* buffer, int bufPos, int maxBufPos, ByteBuffer* response) { - uint32_t invokeId; + uint32_t invokeId = 0; + bool hasInvokeId = false; MmsServiceError serviceError; - if (mmsMsg_parseConfirmedErrorPDU(buffer, bufPos, maxBufPos, &invokeId, &serviceError)) { + if (mmsMsg_parseConfirmedErrorPDU(buffer, bufPos, maxBufPos, &invokeId, &hasInvokeId, &serviceError)) { if (DEBUG_MMS_SERVER) - printf("MMS_SERVER: Handle confirmed error PDU: invokeID: %i\n", invokeId); + printf("MMS_SERVER: Handle confirmed error PDU: invokeID: %u\n", invokeId); - /* check if message is related to an existing file upload task */ - int i; - for (i = 0; i < CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS; i++) { + if (hasInvokeId) { + /* check if message is related to an existing file upload task */ + int i; + for (i = 0; i < CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS; i++) { - if (self->server->fileUploadTasks[i].state != MMS_FILE_UPLOAD_STATE_NOT_USED) { + if (self->server->fileUploadTasks[i].state != MMS_FILE_UPLOAD_STATE_NOT_USED) { - if (self->server->fileUploadTasks[i].lastRequestInvokeId == invokeId) { + if (self->server->fileUploadTasks[i].lastRequestInvokeId == invokeId) { - self->server->fileUploadTasks[i].state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE; - return; - } + self->server->fileUploadTasks[i].state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE; + return; + } + } } } + } else { if (DEBUG_MMS_SERVER)