- IED server: added callback to control access to data model directories (get-name-list requests)(LIB61850-396)

v1.6_develop_387
Michael Zillgith 2 years ago
parent a4a58e4250
commit aa863f35f0

@ -146,6 +146,28 @@ readAccessHandler(LogicalDevice* ld, LogicalNode* ln, DataObject* dataObject, Fu
return DATA_ACCESS_ERROR_SUCCESS; return DATA_ACCESS_ERROR_SUCCESS;
} }
static bool
directoryAccessHandler(void* parameter, ClientConnection connection, IedServer_DirectoryCategory category, LogicalDevice* logicalDevice)
{
switch(category) {
case DIRECTORY_CAT_LD_LIST:
printf("Get list of logical devices from %s\n", ClientConnection_getPeerAddress(connection));
break;
case DIRECTORY_CAT_DATASET_LIST:
printf("Get list of datasets for LD %s from %s\n", ModelNode_getName((ModelNode*)logicalDevice), ClientConnection_getPeerAddress(connection));
break;
case DIRECTORY_CAT_DATA_LIST:
printf("Get list of data for LD %s from %s\n", ModelNode_getName((ModelNode*)logicalDevice), ClientConnection_getPeerAddress(connection));
break;
case DIRECTORY_CAT_LOG_LIST:
printf("Get list of logs for LD %s from %s -> reject\n", ModelNode_getName((ModelNode*)logicalDevice), ClientConnection_getPeerAddress(connection));
return false;
break;
}
return true;
}
int int
main(int argc, char** argv) main(int argc, char** argv)
{ {
@ -234,6 +256,8 @@ main(int argc, char** argv)
*/ */
IedServer_setReadAccessHandler(iedServer, readAccessHandler, NULL); IedServer_setReadAccessHandler(iedServer, readAccessHandler, NULL);
IedServer_setDirectoryAccessHandler(iedServer, directoryAccessHandler, NULL);
/* MMS server will be instructed to start listening for client connections. */ /* MMS server will be instructed to start listening for client connections. */
IedServer_start(iedServer, tcpPort); IedServer_start(iedServer, tcpPort);

@ -1943,6 +1943,19 @@ typedef bool
LIB61850_API void LIB61850_API void
IedServer_setDataSetAccessHandler(IedServer self, IedServer_DataSetAccessHandler handler, void* parameter); IedServer_setDataSetAccessHandler(IedServer self, IedServer_DataSetAccessHandler handler, void* parameter);
typedef enum {
DIRECTORY_CAT_LD_LIST,
DIRECTORY_CAT_DATA_LIST,
DIRECTORY_CAT_DATASET_LIST,
DIRECTORY_CAT_LOG_LIST
} IedServer_DirectoryCategory;
typedef bool
(*IedServer_DirectoryAccessHandler) (void* parameter, ClientConnection connection, IedServer_DirectoryCategory category, LogicalDevice* logicalDevice);
LIB61850_API void
IedServer_setDirectoryAccessHandler(IedServer self, IedServer_DirectoryAccessHandler handler, void* parameter);
/**@}*/ /**@}*/
/**@}*/ /**@}*/

@ -346,6 +346,9 @@ struct sMmsMapping {
IedServer_DataSetAccessHandler dataSetAccessHandler; IedServer_DataSetAccessHandler dataSetAccessHandler;
void* dataSetAccessHandlerParameter; void* dataSetAccessHandlerParameter;
IedServer_DirectoryAccessHandler directoryAccessHandler;
void* directoryAccessHandlerParameter;
}; };
#endif /* MMS_MAPPING_INTERNAL_H_ */ #endif /* MMS_MAPPING_INTERNAL_H_ */

@ -1945,3 +1945,10 @@ IedServer_setDataSetAccessHandler(IedServer self, IedServer_DataSetAccessHandler
self->mmsMapping->dataSetAccessHandler = handler; self->mmsMapping->dataSetAccessHandler = handler;
self->mmsMapping->dataSetAccessHandlerParameter = parameter; self->mmsMapping->dataSetAccessHandlerParameter = parameter;
} }
void
IedServer_setDirectoryAccessHandler(IedServer self, IedServer_DirectoryAccessHandler handler, void* parameter)
{
self->mmsMapping->directoryAccessHandler = handler;
self->mmsMapping->directoryAccessHandlerParameter = parameter;
}

@ -3228,6 +3228,46 @@ unselectControlsForConnection(MmsMapping* self, MmsServerConnection connection)
} }
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */ #endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
static bool
mmsGetNameListHandler(void* parameter, MmsGetNameListType nameListType, MmsDomain* domain, MmsServerConnection connection)
{
MmsMapping* self = (MmsMapping*) parameter;
bool allowAccess = true;
if (self->directoryAccessHandler) {
LogicalDevice* ld = NULL;
IedServer_DirectoryCategory category = DIRECTORY_CAT_DATA_LIST;
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
if (domain) {
ld = IedModel_getDevice(self->model, MmsDomain_getName(domain));
if (ld == NULL) {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: mmsGetNameListHandler -> LD not found!\n");
}
}
/* convert type to category */
if (nameListType == MMS_GETNAMELIST_DATA)
category = DIRECTORY_CAT_DATA_LIST;
else if (nameListType == MMS_GETNAMELIST_DATASETS)
category = DIRECTORY_CAT_DATASET_LIST;
else if (nameListType == MMS_GETNAMELIST_DOMAINS)
category = DIRECTORY_CAT_LD_LIST;
else if (nameListType == MMS_GETNAMELIST_JOURNALS)
category = DIRECTORY_CAT_LOG_LIST;
allowAccess = self->directoryAccessHandler(self->directoryAccessHandlerParameter, clientConnection, category, ld);
}
return allowAccess;
}
static void /* is called by MMS server layer and runs in the connection handling thread */ static void /* is called by MMS server layer and runs in the connection handling thread */
mmsConnectionHandler(void* parameter, MmsServerConnection connection, MmsServerEvent event) mmsConnectionHandler(void* parameter, MmsServerConnection connection, MmsServerEvent event)
{ {
@ -3627,6 +3667,7 @@ MmsMapping_installHandlers(MmsMapping* self)
MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self); MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self);
MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self); MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self);
MmsServer_installVariableListAccessHandler(self->mmsServer, variableListAccessHandler, (void*) self); MmsServer_installVariableListAccessHandler(self->mmsServer, variableListAccessHandler, (void*) self);
MmsServer_installGetNameListHandler(self->mmsServer, mmsGetNameListHandler, (void*) self);
#if (CONFIG_IEC61850_LOG_SERVICE == 1) #if (CONFIG_IEC61850_LOG_SERVICE == 1)
MmsServer_installReadJournalHandler(self->mmsServer, mmsReadJournalHandler, (void*) self); MmsServer_installReadJournalHandler(self->mmsServer, mmsReadJournalHandler, (void*) self);

@ -110,6 +110,18 @@ typedef bool (*MmsReadJournalHandler)(void* parameter, MmsDomain* domain, const
LIB61850_INTERNAL void LIB61850_INTERNAL void
MmsServer_installReadJournalHandler(MmsServer self, MmsReadJournalHandler handler, void* parameter); MmsServer_installReadJournalHandler(MmsServer self, MmsReadJournalHandler handler, void* parameter);
typedef enum {
MMS_GETNAMELIST_DOMAINS,
MMS_GETNAMELIST_JOURNALS,
MMS_GETNAMELIST_DATASETS,
MMS_GETNAMELIST_DATA
} MmsGetNameListType;
typedef bool (*MmsGetNameListHandler)(void* parameter, MmsGetNameListType nameListType, MmsDomain* domain, MmsServerConnection connection);
LIB61850_INTERNAL void
MmsServer_installGetNameListHandler(MmsServer self, MmsGetNameListHandler handler, void* parameter);
/** /**
* \brief ObtainFile service callback handler * \brief ObtainFile service callback handler
* *

@ -129,6 +129,9 @@ struct sMmsServer {
MmsReadJournalHandler readJournalHandler; MmsReadJournalHandler readJournalHandler;
void* readJournalHandlerParameter; void* readJournalHandlerParameter;
MmsGetNameListHandler getNameListHandler;
void* getNameListHandlerParameter;
AcseAuthenticator authenticator; AcseAuthenticator authenticator;
void* authenticatorParameter; void* authenticatorParameter;

@ -1,7 +1,7 @@
/* /*
* mms_get_namelist_service.c * mms_get_namelist_service.c
* *
* Copyright 2013-2022 Michael Zillgith * Copyright 2013-2023 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -190,20 +190,29 @@ getJournalListDomainSpecific(MmsServerConnection connection, char* domainName)
MmsDomain* domain = MmsDevice_getDomain(device, domainName); MmsDomain* domain = MmsDevice_getDomain(device, domainName);
if (domain != NULL) { if (domain) {
nameList = LinkedList_create();
if (domain->journals != NULL) { bool allowAccess = true;
LinkedList journalList = domain->journals; if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_JOURNALS, domain, connection);
}
while ((journalList = LinkedList_getNext(journalList)) != NULL) { if (allowAccess) {
nameList = LinkedList_create();
MmsJournal journal = (MmsJournal) LinkedList_getData(journalList); if (domain->journals != NULL) {
LinkedList_add(nameList, (void*) journal->name); LinkedList journalList = domain->journals;
}
while ((journalList = LinkedList_getNext(journalList)) != NULL) {
MmsJournal journal = (MmsJournal) LinkedList_getData(journalList);
LinkedList_add(nameList, (void*) journal->name);
}
}
} }
} }
@ -219,46 +228,56 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
MmsDomain* domain = MmsDevice_getDomain(device, domainName); MmsDomain* domain = MmsDevice_getDomain(device, domainName);
if (domain != NULL) { if (domain) {
nameList = LinkedList_create();
MmsVariableSpecification** variables = domain->namedVariables;
int i; bool allowAccess = true;
LinkedList element = nameList; if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_DATASETS, domain, connection);
}
if (allowAccess) {
nameList = LinkedList_create();
MmsVariableSpecification** variables = domain->namedVariables;
int i;
LinkedList element = nameList;
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
int* index = (int*) GLOBAL_MALLOC(sizeof(int) * domain->namedVariablesCount); int* index = (int*) GLOBAL_MALLOC(sizeof(int) * domain->namedVariablesCount);
for (i = 0; i < domain->namedVariablesCount; i++) for (i = 0; i < domain->namedVariablesCount; i++)
index[i] = i; index[i] = i;
sortIndex(index, domain->namedVariablesCount, domain->namedVariables); sortIndex(index, domain->namedVariablesCount, domain->namedVariables);
#endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */ #endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */
for (i = 0; i < domain->namedVariablesCount; i++) { for (i = 0; i < domain->namedVariablesCount; i++) {
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
element = LinkedList_insertAfter(element, StringUtils_copyString(variables[index[i]]->name)); element = LinkedList_insertAfter(element, StringUtils_copyString(variables[index[i]]->name));
#else #else
element = LinkedList_insertAfter(element, StringUtils_copyString(variables[i]->name)); element = LinkedList_insertAfter(element, StringUtils_copyString(variables[i]->name));
#endif #endif
#if (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) #if (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1)
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
char* prefix = variables[index[i]]->name; char* prefix = variables[index[i]]->name;
element = addSubNamedVaribleNamesToList(element, prefix, variables[index[i]]); element = addSubNamedVaribleNamesToList(element, prefix, variables[index[i]]);
#else #else
char* prefix = variables[i]->name; char* prefix = variables[i]->name;
element = addSubNamedVaribleNamesToList(element, prefix, variables[i]); element = addSubNamedVaribleNamesToList(element, prefix, variables[i]);
#endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */ #endif /* (CONFIG_MMS_SORT_NAME_LIST == 1) */
#endif /* (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) */ #endif /* (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) */
} }
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
GLOBAL_FREEMEM(index); GLOBAL_FREEMEM(index);
#endif #endif
}
} }
return nameList; return nameList;
@ -293,10 +312,19 @@ getNamedVariableListsDomainSpecific(MmsServerConnection connection, char* domain
MmsDomain* domain = MmsDevice_getDomain(device, domainName); MmsDomain* domain = MmsDevice_getDomain(device, domainName);
if (domain != NULL) { if (domain) {
LinkedList variableLists = MmsDomain_getNamedVariableLists(domain);
bool allowAccess = true;
nameList = createStringsFromNamedVariableList(variableLists); if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_DATASETS, domain, connection);
}
if (allowAccess) {
LinkedList variableLists = MmsDomain_getNamedVariableLists(domain);
nameList = createStringsFromNamedVariableList(variableLists);
}
} }
return nameList; return nameList;
@ -613,38 +641,79 @@ mmsServer_handleGetNameListRequest(
if (objectClass == OBJECT_CLASS_DOMAIN) { if (objectClass == OBJECT_CLASS_DOMAIN) {
LinkedList nameList = getDomainNames(connection); bool allowAccess = true;
if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_DOMAINS, NULL, connection);
}
if (allowAccess) {
LinkedList nameList = getDomainNames(connection);
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
StringUtils_sortList(nameList); StringUtils_sortList(nameList);
#endif #endif
createNameListResponse(connection, invokeId, nameList, response, continueAfterId); createNameListResponse(connection, invokeId, nameList, response, continueAfterId);
LinkedList_destroyStatic(nameList); LinkedList_destroyStatic(nameList);
}
else {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
}
} }
#if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) #if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)
else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE) { else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE) {
LinkedList nameList = getNameListVMDSpecific(connection);
createNameListResponse(connection, invokeId, nameList, response, continueAfterId); bool allowAccess = true;
if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_DATA, NULL, connection);
}
if (allowAccess) {
LinkedList nameList = getNameListVMDSpecific(connection);
#if (CONFIG_MMS_SORT_NAME_LIST == 1)
StringUtils_sortList(nameList);
#endif
createNameListResponse(connection, invokeId, nameList, response, continueAfterId);
LinkedList_destroyStatic(nameList); LinkedList_destroyStatic(nameList);
}
else {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
}
} }
#endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */ #endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */
#if (MMS_DATA_SET_SERVICE == 1) #if (MMS_DATA_SET_SERVICE == 1)
else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE_LIST) { else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE_LIST) {
LinkedList nameList = getNamedVariableListsVMDSpecific(connection);
bool allowAccess = true;
if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_DATASETS, NULL, connection);
}
if (allowAccess) {
LinkedList nameList = getNamedVariableListsVMDSpecific(connection);
#if (CONFIG_MMS_SORT_NAME_LIST == 1) #if (CONFIG_MMS_SORT_NAME_LIST == 1)
StringUtils_sortList(nameList); StringUtils_sortList(nameList);
#endif #endif
createNameListResponse(connection, invokeId, nameList, response, continueAfterId); createNameListResponse(connection, invokeId, nameList, response, continueAfterId);
LinkedList_destroy(nameList); LinkedList_destroy(nameList);
}
else {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
}
} }
#endif /* (MMS_DATA_SET_SERVICE == 1) */ #endif /* (MMS_DATA_SET_SERVICE == 1) */

@ -372,6 +372,13 @@ MmsServer_installReadJournalHandler(MmsServer self, MmsReadJournalHandler handle
self->readJournalHandlerParameter = parameter; self->readJournalHandlerParameter = parameter;
} }
void
MmsServer_installGetNameListHandler(MmsServer self, MmsGetNameListHandler handler, void* parameter)
{
self->getNameListHandler = handler;
self->getNameListHandlerParameter = parameter;
}
void void
MmsServer_setClientAuthenticator(MmsServer self, AcseAuthenticator authenticator, void* authenticatorParameter) MmsServer_setClientAuthenticator(MmsServer self, AcseAuthenticator authenticator, void* authenticatorParameter)
{ {

Loading…
Cancel
Save