- 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;
}
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
main(int argc, char** argv)
{
@ -234,6 +256,8 @@ main(int argc, char** argv)
*/
IedServer_setReadAccessHandler(iedServer, readAccessHandler, NULL);
IedServer_setDirectoryAccessHandler(iedServer, directoryAccessHandler, NULL);
/* MMS server will be instructed to start listening for client connections. */
IedServer_start(iedServer, tcpPort);

@ -1943,6 +1943,19 @@ typedef bool
LIB61850_API void
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;
void* dataSetAccessHandlerParameter;
IedServer_DirectoryAccessHandler directoryAccessHandler;
void* directoryAccessHandlerParameter;
};
#endif /* MMS_MAPPING_INTERNAL_H_ */

@ -1945,3 +1945,10 @@ IedServer_setDataSetAccessHandler(IedServer self, IedServer_DataSetAccessHandler
self->mmsMapping->dataSetAccessHandler = handler;
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) */
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 */
mmsConnectionHandler(void* parameter, MmsServerConnection connection, MmsServerEvent event)
{
@ -3627,6 +3667,7 @@ MmsMapping_installHandlers(MmsMapping* self)
MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self);
MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self);
MmsServer_installVariableListAccessHandler(self->mmsServer, variableListAccessHandler, (void*) self);
MmsServer_installGetNameListHandler(self->mmsServer, mmsGetNameListHandler, (void*) self);
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
MmsServer_installReadJournalHandler(self->mmsServer, mmsReadJournalHandler, (void*) self);

@ -110,6 +110,18 @@ typedef bool (*MmsReadJournalHandler)(void* parameter, MmsDomain* domain, const
LIB61850_INTERNAL void
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
*

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

@ -1,7 +1,7 @@
/*
* mms_get_namelist_service.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2023 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -190,7 +190,15 @@ getJournalListDomainSpecific(MmsServerConnection connection, char* domainName)
MmsDomain* domain = MmsDevice_getDomain(device, domainName);
if (domain != NULL) {
if (domain) {
bool allowAccess = true;
if (connection->server->getNameListHandler) {
allowAccess = connection->server->getNameListHandler(connection->server->getNameListHandlerParameter, MMS_GETNAMELIST_JOURNALS, domain, connection);
}
if (allowAccess) {
nameList = LinkedList_create();
if (domain->journals != NULL) {
@ -206,6 +214,7 @@ getJournalListDomainSpecific(MmsServerConnection connection, char* domainName)
}
}
}
return nameList;
}
@ -219,7 +228,15 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
MmsDomain* domain = MmsDevice_getDomain(device, domainName);
if (domain != NULL) {
if (domain) {
bool allowAccess = true;
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;
@ -259,6 +276,8 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName)
#if (CONFIG_MMS_SORT_NAME_LIST == 1)
GLOBAL_FREEMEM(index);
#endif
}
}
return nameList;
@ -293,11 +312,20 @@ getNamedVariableListsDomainSpecific(MmsServerConnection connection, char* domain
MmsDomain* domain = MmsDevice_getDomain(device, domainName);
if (domain != NULL) {
if (domain) {
bool allowAccess = true;
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;
}
@ -613,6 +641,13 @@ mmsServer_handleGetNameListRequest(
if (objectClass == OBJECT_CLASS_DOMAIN) {
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)
@ -623,19 +658,48 @@ mmsServer_handleGetNameListRequest(
LinkedList_destroyStatic(nameList);
}
else {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
}
}
#if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)
else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE) {
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);
}
else {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
}
}
#endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */
#if (MMS_DATA_SET_SERVICE == 1)
else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE_LIST) {
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)
@ -645,6 +709,11 @@ mmsServer_handleGetNameListRequest(
createNameListResponse(connection, invokeId, nameList, response, continueAfterId);
LinkedList_destroy(nameList);
}
else {
mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
}
}
#endif /* (MMS_DATA_SET_SERVICE == 1) */

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

Loading…
Cancel
Save