From b81279e44240c87742df065a008b0d407fa48722 Mon Sep 17 00:00:00 2001 From: Maxson Ramon dos Anjos Medeiros Date: Fri, 4 Jul 2025 14:41:51 +0200 Subject: [PATCH] API DataSet access handler added --- dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs | 57 ++++++++++++++++++- .../server_example_access_control/Program.cs | 18 ++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index 4113cee3..1980b23b 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -2160,6 +2160,15 @@ namespace IEC61850 IEC61850_CB_ACCESS_TYPE_WRITE } + public enum DataSetOperation + { + DATASET_CREATE, + DATASET_DELETE, + DATASET_READ, + DATASET_WRITE, + DATASET_GET_DIRECTORY + } + public delegate CheckHandlerResult CheckHandler (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool interlockCheck); public static class SqliteLogStorage @@ -2360,6 +2369,12 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] public static extern void IedServer_setControlBlockAccessHandler(IntPtr self, IedServer_ControlBlockAccessHandler handler, IntPtr parameter); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + public static extern void IedServer_setDataSetAccessHandler(IntPtr self, IedServer_DataSetAccessHandler handler, IntPtr parameter); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool IedServer_DataSetAccessHandler(IntPtr parameter, IntPtr connection, int operation, string datasetRef); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate bool IedServer_ControlBlockAccessHandler(IntPtr parameter, IntPtr connection, int acsiClass, IntPtr ld, IntPtr ln, string objectName, string subObjectName, int accessType); @@ -2619,7 +2634,6 @@ namespace IEC61850 } - /// /// Set a handler to control read and write access to control blocks and logs /// @@ -2638,6 +2652,47 @@ namespace IEC61850 } } + public delegate bool DataSetAccessHandler(object parameter, ClientConnection connection, DataSetOperation operation, string datasetRef); + + private DataSetAccessHandler dataSetAccessHandler = null; + + private object dataSetAccessHandlerParameter = null; + + private IedServer_DataSetAccessHandler internalDataSetAccessHandler = null; + + /// + /// Callback that is called when the client is calling a dataset operation (create, delete, read, write, list directory) + /// note This callback is called before the IedServer_RCBEventHandler and only in case of operations(RCB_EVENT_GET_PARAMETER, RCB_EVENT_SET_PARAMETER, RCB_EVENT_ENABLE + /// + /// the callback handler to be used + /// a user provided parameter that is passed to the handler + public void SetDataSetAccessHandler(DataSetAccessHandler handler, object parameter) + { + dataSetAccessHandler = handler; + dataSetAccessHandlerParameter = parameter; + + if (internalDataSetAccessHandler == null) + { + internalDataSetAccessHandler = new IedServer_DataSetAccessHandler(InternalDataSetlHandlerImplementation); + + IedServer_setDataSetAccessHandler(self, internalDataSetAccessHandler, IntPtr.Zero); + } + } + + private bool InternalDataSetlHandlerImplementation (IntPtr parameter, IntPtr connection, int operation, string datasetRef) + { + if (dataSetAccessHandler != null && connection != IntPtr.Zero) + { + ClientConnection con = null; + + this.clientConnections.TryGetValue(connection, out con); + + return dataSetAccessHandler(dataSetAccessHandlerParameter, con, (DataSetOperation)operation, datasetRef); + } + + return false; + } + private Dictionary writeAccessHandlers = new Dictionary (); private void ConnectionIndicationHandlerImpl (IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter) diff --git a/dotnet/server_example_access_control/Program.cs b/dotnet/server_example_access_control/Program.cs index b77c0cb2..c6f069d8 100644 --- a/dotnet/server_example_access_control/Program.cs +++ b/dotnet/server_example_access_control/Program.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Net; using static IEC61850.Server.IedServer; using System.Collections.Generic; +using System.Reflection.Metadata; namespace server_access_control { @@ -143,6 +144,23 @@ namespace server_access_control iedServer.SetControlBlockAccessHandler(ControlBlockAccessCallBack, iedServer); + /* By default access to variables with FC=DC and FC=CF is not allowed. + * This allow to write to simpleIOGenericIO/GGIO1.NamPlt.vendor variable used + * by iec61850_client_example1. + */ + iedServer.SetWriteAccessPolicy(FunctionalConstraint.DC, AccessPolicy.ACCESS_POLICY_ALLOW); + + /* Install handler to perform access control on datasets */ + bool dataSetAccessHandler(object parameter, ClientConnection connection, DataSetOperation operation, string datasetRef) + { + Console.WriteLine("Data set access: "+ datasetRef+" operation: "+ operation.ToString() + "\n"); + + return true; + } + + iedServer.SetDataSetAccessHandler(dataSetAccessHandler, iedServer); + + iedServer.Start(102); if (iedServer.IsRunning())