pull/266/head
Michael Zillgith 5 years ago
commit 00a821e67e

@ -44,7 +44,7 @@ typedef enum
ISO_IND_TICK ISO_IND_TICK
} IsoIndication; } IsoIndication;
typedef void typedef bool
(*IsoIndicationCallback)(IsoIndication indication, void* param, ByteBuffer* payload); (*IsoIndicationCallback)(IsoIndication indication, void* param, ByteBuffer* payload);
/** /**

@ -191,6 +191,7 @@ struct sMmsServerConnection {
int maxServOutstandingCalling; int maxServOutstandingCalling;
int maxServOutstandingCalled; int maxServOutstandingCalled;
int dataStructureNestingLevel; int dataStructureNestingLevel;
uint8_t negotiatedParameterCBC[2];
uint32_t maxPduSize; /* local detail */ uint32_t maxPduSize; /* local detail */
IsoConnection isoConnection; IsoConnection isoConnection;
MmsServer server; MmsServer server;
@ -259,6 +260,9 @@ mmsServer_createConfirmedResponse(uint32_t invokeId);
LIB61850_INTERNAL void LIB61850_INTERNAL void
mmsMsg_createServiceErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError errorType); mmsMsg_createServiceErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError errorType);
LIB61850_INTERNAL void
mmsMsg_createInitiateErrorPdu(ByteBuffer* response, uint8_t initiateErrorCode);
LIB61850_INTERNAL void LIB61850_INTERNAL void
mmsServer_createServiceErrorPduWithServiceSpecificInfo(uint32_t invokeId, ByteBuffer* response, mmsServer_createServiceErrorPduWithServiceSpecificInfo(uint32_t invokeId, ByteBuffer* response,
MmsError errorType, uint8_t* serviceSpecificInfo, int serviceSpecficInfoLength); MmsError errorType, uint8_t* serviceSpecificInfo, int serviceSpecficInfoLength);

@ -499,7 +499,9 @@ IsoClientConnection_handleConnection(IsoClientConnection self)
setState(self, STATE_CONNECTED); setState(self, STATE_CONNECTED);
nextState = INT_STATE_WAIT_FOR_DATA_MSG; nextState = INT_STATE_WAIT_FOR_DATA_MSG;
self->callback(ISO_IND_ASSOCIATION_SUCCESS, self->callbackParameter, self->receivePayloadBuffer); if (self->callback(ISO_IND_ASSOCIATION_SUCCESS, self->callbackParameter, self->receivePayloadBuffer) == false) {
nextState = INT_STATE_CLOSE_ON_ERROR;
}
CotpConnection_resetPayload(self->cotpConnection); CotpConnection_resetPayload(self->cotpConnection);
} }

@ -981,7 +981,7 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
removeFromOutstandingCalls(self, outstandingCall->invokeId); removeFromOutstandingCalls(self, outstandingCall->invokeId);
} }
static void static bool
mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload) mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
{ {
MmsConnection self = (MmsConnection) parameter; MmsConnection self = (MmsConnection) parameter;
@ -1022,7 +1022,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
} }
} }
return; return true;
} }
if (indication == ISO_IND_CLOSED) { if (indication == ISO_IND_CLOSED) {
@ -1035,7 +1035,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (self->connectionLostHandler != NULL) if (self->connectionLostHandler != NULL)
self->connectionLostHandler(self, self->connectionLostHandlerParameter); self->connectionLostHandler(self, self->connectionLostHandlerParameter);
return; return true;
} }
if (indication == ISO_IND_ASSOCIATION_FAILED) { if (indication == ISO_IND_ASSOCIATION_FAILED) {
@ -1043,12 +1043,12 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
printf("MMS_CLIENT: mmsIsoCallback: association failed!\n"); printf("MMS_CLIENT: mmsIsoCallback: association failed!\n");
setConnectionState(self, MMS_CONNECTION_STATE_CLOSING); setConnectionState(self, MMS_CONNECTION_STATE_CLOSING);
return; return false;
} }
if (payload != NULL) { if (payload != NULL) {
if (ByteBuffer_getSize(payload) < 1) { if (ByteBuffer_getSize(payload) < 1) {
return; return false;
} }
} }
@ -1075,7 +1075,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
} }
else { else {
setConnectionState(self, MMS_CONNECTION_STATE_CLOSING); setConnectionState(self, MMS_CONNECTION_STATE_CLOSING);
IsoClientConnection_close(self->isoClient);
goto exit_with_error;
} }
} }
else { else {
@ -1083,7 +1084,18 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (DEBUG_MMS_CLIENT) if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: Failed to parse initiate response!\n"); printf("MMS_CLIENT: Failed to parse initiate response!\n");
return false;
}
} }
else if (tag == 0xaa) { /* initiate error PDU */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received initiate error PDU\n");
setConnectionState(self, MMS_CONNECTION_STATE_CLOSING);
return false;
} }
else if (tag == 0xa3) { /* unconfirmed PDU */ else if (tag == 0xa3) { /* unconfirmed PDU */
handleUnconfirmedMmsPdu(self, payload); handleUnconfirmedMmsPdu(self, payload);
@ -1096,7 +1108,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
} }
else if (tag == 0x8c) { /* conclude response PDU */ else if (tag == 0x8c) { /* conclude response PDU */
if (DEBUG_MMS_CLIENT) if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received conclude.reponse+\n"); printf("MMS_CLIENT: received conclude.response+\n");
if (self->concludeHandler) { if (self->concludeHandler) {
self->concludeHandler(self->concludeHandlerParameter, MMS_ERROR_NONE, true); self->concludeHandler(self->concludeHandlerParameter, MMS_ERROR_NONE, true);
@ -1151,14 +1163,14 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (DEBUG_MMS_CLIENT) if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: server sent unexpected confirmed error PDU!\n"); printf("MMS_CLIENT: server sent unexpected confirmed error PDU!\n");
return; return false;
} }
} }
else { else {
if (DEBUG_MMS_CLIENT) if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: server sent confirmed error PDU without invoke ID!\n"); printf("MMS_CLIENT: server sent confirmed error PDU without invoke ID!\n");
return; return false;
} }
} }
@ -1195,11 +1207,11 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
} }
} }
else { else {
return; return false;
} }
} }
else { else {
return; return false;
} }
} }
@ -1247,7 +1259,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (DEBUG_MMS_CLIENT) if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: unexpected message from server!\n"); printf("MMS_CLIENT: unexpected message from server!\n");
return; return false;
} }
} }
else else
@ -1385,14 +1397,14 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
if (DEBUG_MMS_CLIENT) if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: LEAVE mmsIsoCallback - OK\n"); printf("MMS_CLIENT: LEAVE mmsIsoCallback - OK\n");
return; return true;
exit_with_error: exit_with_error:
if (DEBUG_MMS_CLIENT) if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: received malformed message from server!\n"); printf("MMS_CLIENT: received malformed message from server!\n");
return; return false;
} }
#if (CONFIG_MMS_THREADLESS_STACK == 0) #if (CONFIG_MMS_THREADLESS_STACK == 0)

@ -1,7 +1,7 @@
/* /*
* mms_client_initiate.c * mms_client_initiate.c
* *
* Copyright 2013-2017 Michael Zillgith * Copyright 2013-2020 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -94,11 +94,11 @@ mmsClient_createInitiateRequest(MmsConnection self, ByteBuffer* message)
buffer[bufPos++] = 0x01; buffer[bufPos++] = 0x01;
buffer[bufPos++] = 0x01; buffer[bufPos++] = 0x01;
/* proposedParameterCBC */ /* proposedParameterCBC: fixed */
buffer[bufPos++] = 0x81; buffer[bufPos++] = 0x81;
buffer[bufPos++] = 0x03; buffer[bufPos++] = 0x03;
buffer[bufPos++] = 0x05; /* padding */ buffer[bufPos++] = 0x05; /* padding */
buffer[bufPos++] = 0xf1; buffer[bufPos++] = 0xf1; /* str1, str2, vnam, vlis, valt */
buffer[bufPos++] = 0x00; buffer[bufPos++] = 0x00;
/* servicesSupportedCalling */ /* servicesSupportedCalling */

@ -62,14 +62,13 @@
#define MMS_SERVICE_CONCLUDE 0x10 #define MMS_SERVICE_CONCLUDE 0x10
#define MMS_SERVICE_CANCEL 0x08 #define MMS_SERVICE_CANCEL 0x08
/* negotiated parameter CBB */ /* our supported parameter CBB: str1, str2, vnam, vlis, valt */
static uint8_t parameterCBB[] = static uint8_t parameterCBB[] =
{ {
0xf1, 0xf1,
0x00 0x00
}; };
/********************************************************************************************** /**********************************************************************************************
* MMS Initiate Service * MMS Initiate Service
*********************************************************************************************/ *********************************************************************************************/
@ -86,7 +85,10 @@ encodeInitResponseDetail(MmsServerConnection self, uint8_t* buffer, int bufPos,
bufPos = BerEncoder_encodeUInt32WithTL(0x80, 1, buffer, bufPos); /* negotiated protocol version */ bufPos = BerEncoder_encodeUInt32WithTL(0x80, 1, buffer, bufPos); /* negotiated protocol version */
bufPos = BerEncoder_encodeBitString(0x81, 11, parameterCBB, buffer, bufPos); self->negotiatedParameterCBC[0] = self->negotiatedParameterCBC[0] & parameterCBB[0];
self->negotiatedParameterCBC[1] = self->negotiatedParameterCBC[1] & parameterCBB[1];
bufPos = BerEncoder_encodeBitString(0x81, 11, self->negotiatedParameterCBC, buffer, bufPos);
#if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1)
@ -157,7 +159,6 @@ encodeInitResponseDetail(MmsServerConnection self, uint8_t* buffer, int bufPos,
#endif #endif
} }
#else #else
uint8_t servicesSupported[] = uint8_t servicesSupported[] =
{ {
@ -253,6 +254,67 @@ createInitiateResponse(MmsServerConnection self, ByteBuffer* writeBuffer)
return bufPos; return bufPos;
} }
static bool
parseInitRequestDetail(MmsServerConnection self, uint8_t* buffer, int bufPos, int maxBufPos)
{
while (bufPos < maxBufPos) {
uint8_t tag = buffer[bufPos++];
int length;
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
/* TODO write initiate error PDU! */
return false;
}
if (bufPos + length > maxBufPos) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: length field too long\n");
return false;
}
switch(tag) {
case 0x80: /* proposed-version-number */
{
uint32_t protocolVersion = BerDecoder_decodeUint32(buffer, length, bufPos);
if (protocolVersion != 1) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: invalid protocol version %u\n", protocolVersion);
return false;
}
}
break;
case 0x81: /* proposed-parameter-CBC */
if (length == 3) {
self->negotiatedParameterCBC[0] = buffer[bufPos + 1];
self->negotiatedParameterCBC[1] = buffer[bufPos + 2];
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: requested parameter CBC: %02x %02x\n",
self->negotiatedParameterCBC[0],
self->negotiatedParameterCBC[1]);
}
else {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: unexpected parameter CBC length\n");
}
break;
}
bufPos += length;
}
return true;
}
static bool static bool
parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, int maxBufPos) parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, int maxBufPos)
{ {
@ -265,6 +327,9 @@ parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, i
self->maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING; self->maxServOutstandingCalling = DEFAULT_MAX_SERV_OUTSTANDING_CALLING;
self->negotiatedParameterCBC[0] = 0;
self->negotiatedParameterCBC[1] = 0;
while (bufPos < maxBufPos) { while (bufPos < maxBufPos) {
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
int length; int length;
@ -276,6 +341,13 @@ parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, i
return false; return false;
} }
if (bufPos + length > maxBufPos) {
if (DEBUG_MMS_SERVER)
printf("MMS_SERVER: length field too long\n");
return false;
}
switch (tag) { switch (tag) {
case 0x80: /* local-detail-calling */ case 0x80: /* local-detail-calling */
self->maxPduSize = BerDecoder_decodeUint32(buffer, length, bufPos); self->maxPduSize = BerDecoder_decodeUint32(buffer, length, bufPos);
@ -305,7 +377,10 @@ parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, i
break; break;
case 0xa4: /* mms-init-request-detail */ case 0xa4: /* mms-init-request-detail */
/* we ignore this */
if (parseInitRequestDetail(self, buffer, bufPos, bufPos + length) == false)
return false;
break; break;
case 0x00: /* indefinite length end tag -> ignore */ case 0x00: /* indefinite length end tag -> ignore */
@ -328,10 +403,12 @@ mmsServer_handleInitiateRequest (
ByteBuffer* response) ByteBuffer* response)
{ {
if (parseInitiateRequestPdu(self, buffer, bufPos, maxBufPos)) if (parseInitiateRequestPdu(self, buffer, bufPos, maxBufPos)) {
createInitiateResponse(self, response); createInitiateResponse(self, response);
}
else { else {
/* TODO send initiate error PDU */ /* send initiate error PDU */
mmsMsg_createInitiateErrorPdu(response, 0);
} }
} }

@ -216,6 +216,27 @@ mmsMsg_createServiceErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError e
mmsServer_createServiceErrorPduWithServiceSpecificInfo(invokeId, response, errorType, NULL, 0); mmsServer_createServiceErrorPduWithServiceSpecificInfo(invokeId, response, errorType, NULL, 0);
} }
void
mmsMsg_createInitiateErrorPdu(ByteBuffer* response, uint8_t initiateErrorCode)
{
/* determine encoded size */
uint32_t serviceErrorContentSize = 5; /* errorClass */
/* encode */
uint8_t* buffer = response->buffer;
int bufPos = response->size;
bufPos = BerEncoder_encodeTL(0xaa, serviceErrorContentSize, buffer, bufPos); /* serviceError */
bufPos = BerEncoder_encodeTL(0xa0, 3, buffer, bufPos); /* serviceError */
buffer[bufPos++] = 8; /* initiate */
buffer[bufPos++] = 1;
buffer[bufPos++] = initiateErrorCode;
response->size = bufPos;
}
bool bool
mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess) mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess)
{ {

Loading…
Cancel
Save