Skip to content

Commit 2650583

Browse files
committed
Merged in v2.3_develop_126 (pull request #1)
LIB8705-126
2 parents a5d99b2 + 8e0196a commit 2650583

6 files changed

Lines changed: 167 additions & 3 deletions

File tree

lib60870-C/src/iec60870/cs101/cs101_slave.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ struct sCS101_Slave
6868
CS101_ResetCUHandler resetCUHandler;
6969
void* resetCUHandlerParameter;
7070

71+
CS101_IsCAAllowedHandler isCAAllowedHandler;
72+
void* isCAAllowedHandlerParameter;
73+
7174
SerialTransceiverFT12 transceiver;
7275

7376
LinkLayerSecondaryUnbalanced unbalancedLinkLayer;
@@ -560,6 +563,13 @@ CS101_Slave_getLinkLayerParameters(CS101_Slave self)
560563
return &(self->linkLayerParameters);
561564
}
562565

566+
void
567+
CS101_Slave_setAllowedCAHandler(CS101_Slave self, CS101_IsCAAllowedHandler handler, void* parameter)
568+
{
569+
self->isCAAllowedHandler = handler;
570+
self->isCAAllowedHandlerParameter = parameter;
571+
}
572+
563573
void
564574
CS101_Slave_setResetCUHandler(CS101_Slave self, CS101_ResetCUHandler handler, void* parameter)
565575
{
@@ -660,6 +670,19 @@ handleASDU(CS101_Slave self, CS101_ASDU asdu)
660670

661671
int ca = CS101_ASDU_getCA(asdu);
662672

673+
/* check with user callback if CA address is known/used by application */
674+
if (self->isCAAllowedHandler && (isBroadcastCA(self, ca) == false))
675+
{
676+
if (self->isCAAllowedHandler(self->isCAAllowedHandlerParameter, ca) == false)
677+
{
678+
DEBUG_PRINT("CS101_SLAVE: Rcvd ASDU with unknown CA\n");
679+
680+
responseNegative(asdu, &(self->iMasterConnection), CS101_COT_UNKNOWN_CA);
681+
682+
return;
683+
}
684+
}
685+
663686
/* call plugins */
664687
if (self->plugins)
665688
{

lib60870-C/src/iec60870/cs104/cs104_slave.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,9 @@ struct sCS104_Slave
11751175
CS104_SlaveRawMessageHandler rawMessageHandler;
11761176
void* rawMessageHandlerParameter;
11771177

1178+
CS101_IsCAAllowedHandler isCAAllowedHandler;
1179+
void* isCAAllowedHandlerParameter;
1180+
11781181
#if (CONFIG_CS104_SUPPORT_TLS == 1)
11791182
TLSConfiguration tlsConfig;
11801183
#endif
@@ -1637,6 +1640,13 @@ CS104_Slave_setConnectionEventHandler(CS104_Slave self, CS104_ConnectionEventHan
16371640
self->connectionEventHandlerParameter = parameter;
16381641
}
16391642

1643+
void
1644+
CS104_Slave_setAllowedCAHandler(CS104_Slave self, CS101_IsCAAllowedHandler handler, void* parameter)
1645+
{
1646+
self->isCAAllowedHandler = handler;
1647+
self->isCAAllowedHandlerParameter = parameter;
1648+
}
1649+
16401650
/**
16411651
* Activate connection and deactivate existing active connections if required
16421652
*/
@@ -2068,6 +2078,19 @@ handleASDU(MasterConnection self, CS101_ASDU asdu)
20682078

20692079
int ca = CS101_ASDU_getCA(asdu);
20702080

2081+
/* check with user callback if CA address is known/used by application */
2082+
if (slave->isCAAllowedHandler && (isBroadcastCA(slave, ca) == false))
2083+
{
2084+
if (slave->isCAAllowedHandler(slave->isCAAllowedHandlerParameter, ca) == false)
2085+
{
2086+
DEBUG_PRINT("CS104 SLAVE: Rcvd ASDU with unknown CA\n");
2087+
2088+
responseNegative(asdu, self, CS101_COT_UNKNOWN_CA);
2089+
2090+
return true;
2091+
}
2092+
}
2093+
20712094
/* call plugins */
20722095
if (slave->plugins)
20732096
{

lib60870-C/src/inc/api/cs101_slave.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* cs101_slave.h
33
*
4-
* Copyright 2017-2022 Michael Zillgith
4+
* Copyright 2017-2025 Michael Zillgith
55
*
66
* This file is part of lib60870-C
77
*
@@ -252,6 +252,16 @@ CS101_Slave_getAppLayerParameters(CS101_Slave self);
252252
LinkLayerParameters
253253
CS101_Slave_getLinkLayerParameters(CS101_Slave self);
254254

255+
/**
256+
* \brief Set a callback handler for the library to check if a specific CA is known by the application
257+
*
258+
* \param self the slave instance
259+
* \param handler the callback function to be used
260+
* \param parameter user provided context parameter that will be passed to the callback function (or NULL if not required).
261+
*/
262+
void
263+
CS101_Slave_setAllowedCAHandler(CS101_Slave self, CS101_IsCAAllowedHandler handler, void* parameter);
264+
255265
/**
256266
* \brief Set the handler for the reset CU (communication unit) message
257267
*

lib60870-C/src/inc/api/cs104_slave.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* cs104_slave.h
33
*
4-
* Copyright 2017-2022 Michael Zillgith
4+
* Copyright 2017-2025 Michael Zillgith
55
*
66
* This file is part of lib60870-C
77
*
@@ -179,6 +179,16 @@ CS104_Slave_setMaxOpenConnections(CS104_Slave self, int maxOpenConnections);
179179
void
180180
CS104_Slave_setServerMode(CS104_Slave self, CS104_ServerMode serverMode);
181181

182+
/**
183+
* \brief Set a callback handler for the library to check if a specific CA is known by the application
184+
*
185+
* \param self the slave instance
186+
* \param handler the callback function to be used
187+
* \param parameter user provided context parameter that will be passed to the callback function (or NULL if not required).
188+
*/
189+
void
190+
CS104_Slave_setAllowedCAHandler(CS104_Slave self, CS101_IsCAAllowedHandler handler, void* parameter);
191+
182192
/**
183193
* \brief Set the connection request handler
184194
*

lib60870-C/src/inc/api/iec60870_slave.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2018 MZ Automation GmbH
2+
* Copyright 2016-2025 MZ Automation GmbH
33
*
44
* This file is part of lib60870-C
55
*
@@ -247,6 +247,18 @@ typedef bool (*CS101_DelayAcquisitionHandler) (void* parameter, IMasterConnectio
247247
*/
248248
typedef bool (*CS101_ASDUHandler) (void* parameter, IMasterConnection connection, CS101_ASDU asdu);
249249

250+
/**
251+
* \brief Handler that allows the application to inform the slave library if a specific CA is allowed/available
252+
*
253+
* \note this handler is called whenever such a check is required by the library (e.g. when a ASDU is received)
254+
*
255+
* \param[in] parameter user provided parameter
256+
* \param[in] ca the CA(ASDU) to be checked
257+
*
258+
* \return true, when the CA is known and accepted, false, otherwise
259+
*/
260+
typedef bool (*CS101_IsCAAllowedHandler) (void* parameter, int ca);
261+
250262
/**
251263
* @}
252264
*/

lib60870-C/tests/all_tests.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7076,6 +7076,90 @@ test_CS104Slave_rejectCommandsWithBroadcastCA()
70767076
CS104_Slave_destroy(slave);
70777077
}
70787078

7079+
static bool
7080+
test_IsCAAllowedHandler(void* parameter, int ca)
7081+
{
7082+
int expectedCa = *((int*)parameter);
7083+
7084+
return (expectedCa == ca);
7085+
}
7086+
7087+
void
7088+
test_CS104Slave_rejectCommandWithUnknownCA()
7089+
{
7090+
int expectedCa = 100;
7091+
CS101_ASDU receivedASDU = NULL;
7092+
7093+
CS104_Slave slave = CS104_Slave_create(10, 10);
7094+
7095+
CS104_Slave_setServerMode(slave, CS104_MODE_SINGLE_REDUNDANCY_GROUP);
7096+
CS104_Slave_setLocalPort(slave, 20004);
7097+
7098+
CS104_Slave_setAllowedCAHandler(slave, test_IsCAAllowedHandler, &expectedCa);
7099+
7100+
CS104_Slave_start(slave);
7101+
7102+
CS101_AppLayerParameters alParams = CS104_Slave_getAppLayerParameters(slave);
7103+
7104+
CS104_Connection con = CS104_Connection_create("127.0.0.1", 20004);
7105+
7106+
bool result = CS104_Connection_connect(con);
7107+
TEST_ASSERT_TRUE(result);
7108+
7109+
CS104_Connection_setASDUReceivedHandler(con, test_CS104Slave_handleTestCommand_asduReceivedHandler, &receivedASDU);
7110+
7111+
CS104_Connection_sendStartDT(con);
7112+
7113+
TestCommandWithCP56Time2a tc;
7114+
7115+
uint64_t time1 = Hal_getTimeInMs();
7116+
struct sCP56Time2a cpTime1;
7117+
CP56Time2a_createFromMsTimestamp(&cpTime1, time1);
7118+
7119+
/* send test command with unknown CA */
7120+
tc = TestCommandWithCP56Time2a_create(NULL, 0xaa55, &cpTime1);
7121+
7122+
CS101_ASDU asdu = CS101_ASDU_create(&defaultAppLayerParameters, false, CS101_COT_ACTIVATION, 0, 1, false, false);
7123+
7124+
CS101_ASDU_addInformationObject(asdu, (InformationObject) tc);
7125+
TestCommandWithCP56Time2a_destroy(tc);
7126+
TEST_ASSERT_TRUE(CS104_Connection_sendASDU(con, asdu));
7127+
CS101_ASDU_destroy(asdu);
7128+
7129+
Thread_sleep(500);
7130+
7131+
TEST_ASSERT_NOT_NULL(receivedASDU);
7132+
TEST_ASSERT_EQUAL_INT(C_TS_TA_1, CS101_ASDU_getTypeID(receivedASDU));
7133+
TEST_ASSERT_EQUAL_INT(CS101_COT_UNKNOWN_CA, CS101_ASDU_getCOT(receivedASDU));
7134+
TEST_ASSERT_TRUE(CS101_ASDU_isNegative(receivedASDU));
7135+
7136+
/* send test command with known CA */
7137+
tc = TestCommandWithCP56Time2a_create(NULL, 0xaa55, &cpTime1);
7138+
7139+
asdu = CS101_ASDU_create(&defaultAppLayerParameters, false, CS101_COT_ACTIVATION, 0, expectedCa, false, false);
7140+
7141+
CS101_ASDU_addInformationObject(asdu, (InformationObject) tc);
7142+
TestCommandWithCP56Time2a_destroy(tc);
7143+
TEST_ASSERT_TRUE(CS104_Connection_sendASDU(con, asdu));
7144+
CS101_ASDU_destroy(asdu);
7145+
7146+
Thread_sleep(500);
7147+
7148+
TEST_ASSERT_NOT_NULL(receivedASDU);
7149+
TEST_ASSERT_EQUAL_INT(C_TS_TA_1, CS101_ASDU_getTypeID(receivedASDU));
7150+
TEST_ASSERT_EQUAL_INT(CS101_COT_ACTIVATION_CON, CS101_ASDU_getCOT(receivedASDU));
7151+
TEST_ASSERT_FALSE(CS101_ASDU_isNegative(receivedASDU));
7152+
7153+
CS104_Connection_close(con);
7154+
7155+
CS104_Connection_destroy(con);
7156+
7157+
if (receivedASDU)
7158+
CS101_ASDU_destroy(receivedASDU);
7159+
7160+
CS104_Slave_destroy(slave);
7161+
}
7162+
70797163
int
70807164
main(int argc, char** argv)
70817165
{
@@ -7213,5 +7297,7 @@ main(int argc, char** argv)
72137297

72147298
RUN_TEST(test_CS104Slave_rejectCommandsWithBroadcastCA);
72157299

7300+
RUN_TEST(test_CS104Slave_rejectCommandWithUnknownCA);
7301+
72167302
return UNITY_END();
72177303
}

0 commit comments

Comments
 (0)