Skip to content

Commit

Permalink
- CS101_ASDU_addInformationObject now checks for correct object type
Browse files Browse the repository at this point in the history
  • Loading branch information
mzillgith committed Dec 9, 2019
1 parent b65015e commit 93928f5
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 11 deletions.
25 changes: 15 additions & 10 deletions lib60870-C/src/iec60870/cs101/cs101_asdu.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016, 2017 MZ Automation GmbH
* Copyright 2016-2019 MZ Automation GmbH
*
* This file is part of lib60870-C
*
Expand Down Expand Up @@ -233,16 +233,21 @@ CS101_ASDU_addInformationObject(CS101_ASDU self, InformationObject io)
}
else if (numberOfElements < 0x7f) {

if (CS101_ASDU_isSequence(self)) {
/* Check if type of information object is matching ASDU type */

/* check that new information object has correct IOA */
if (InformationObject_getObjectAddress(io) == (getFirstIOA(self) + CS101_ASDU_getNumberOfElements(self)))
encoded = InformationObject_encode(io, (Frame) &asduFrame, self->parameters, true);
else
encoded = false;
}
else {
encoded = InformationObject_encode(io, (Frame) &asduFrame, self->parameters, false);;
if (self->asdu[0] == (uint8_t) InformationObject_getType(io)) {

if (CS101_ASDU_isSequence(self)) {

/* check that new information object has correct IOA */
if (InformationObject_getObjectAddress(io) == (getFirstIOA(self) + CS101_ASDU_getNumberOfElements(self)))
encoded = InformationObject_encode(io, (Frame) &asduFrame, self->parameters, true);
else
encoded = false;
}
else {
encoded = InformationObject_encode(io, (Frame) &asduFrame, self->parameters, false);;
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion lib60870-C/src/inc/api/iec60870_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,12 @@ CS101_ASDU_destroy(CS101_ASDU self);
/**
* \brief add an information object to the ASDU
*
* NOTE: Only information objects of the exact same type can be added to a single ASDU!
*
* \param self ASDU object instance
* \param io information object to be added
*
* \return true when added, false when there not enough space left in the ASDU or IO cannot be added to the sequence because of wrong IOA.
* \return true when added, false when there not enough space left in the ASDU or IO cannot be added to the sequence because of wrong IOA, or wrong type.
*/
bool
CS101_ASDU_addInformationObject(CS101_ASDU self, InformationObject io);
Expand Down
124 changes: 124 additions & 0 deletions lib60870-C/tests/all_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -5016,6 +5016,125 @@ test_CS104_Connection_ConnectTimeout(void)
CS104_Connection_destroy(con);
}

void
test_CS104_Connection_UseAfterClose(void)
{
CS104_Slave slave = NULL;
CS104_Connection con = NULL;

slave = CS104_Slave_create(100, 100);

TEST_ASSERT_NOT_NULL(slave);

CS104_Slave_setLocalPort(slave, 20004);
CS104_Slave_start(slave);

con = CS104_Connection_create("127.0.0.1", 20004);

TEST_ASSERT_NOT_NULL(con);

bool result = CS104_Connection_connect(con);

TEST_ASSERT_TRUE(result);

CS104_Connection_close(con);

result = CS104_Connection_sendInterrogationCommand(con, CS101_COT_ACTIVATION, 1, IEC60870_QOI_STATION);

TEST_ASSERT_FALSE(result);

CS104_Slave_destroy(slave);

CS104_Connection_destroy(con);
}

void
test_CS104_Connection_UseAfterServerClosedConnection(void)
{
CS104_Slave slave = NULL;
CS104_Connection con = NULL;

slave = CS104_Slave_create(100, 100);

TEST_ASSERT_NOT_NULL(slave);

CS104_Slave_setLocalPort(slave, 20004);
CS104_Slave_start(slave);

con = CS104_Connection_create("127.0.0.1", 20004);

TEST_ASSERT_NOT_NULL(con);

bool result = CS104_Connection_connect(con);

TEST_ASSERT_TRUE(result);

CS104_Slave_destroy(slave);

/* wait to allow client side to detect connection loss */
Thread_sleep(500);

result = CS104_Connection_sendInterrogationCommand(con, CS101_COT_ACTIVATION, 1, IEC60870_QOI_STATION);

TEST_ASSERT_FALSE(result);

CS104_Connection_destroy(con);
}

void
test_CS101_ASDU_addObjectOfWrongType(void)
{
CS101_ASDU asdu = CS101_ASDU_create(&defaultAppLayerParameters, false, CS101_COT_PERIODIC, 0, 1, false, false);

InformationObject io1 = (InformationObject) SinglePointInformation_create(NULL, 101, true, IEC60870_QUALITY_GOOD);

bool added = CS101_ASDU_addInformationObject(asdu, io1);

TEST_ASSERT_TRUE(added);

InformationObject_destroy(io1);

InformationObject io2 = (InformationObject) DoublePointInformation_create(NULL, 102, IEC60870_DOUBLE_POINT_OFF, IEC60870_QUALITY_GOOD);

added = CS101_ASDU_addInformationObject(asdu, io2);

TEST_ASSERT_FALSE(added);

InformationObject_destroy(io2);

CS101_ASDU_destroy(asdu);
}

void
test_CS101_ASDU_addUntilOverflow(void)
{
CS101_ASDU asdu = CS101_ASDU_create(&defaultAppLayerParameters, false, CS101_COT_PERIODIC, 0, 1, false, false);

int i = 0;

for (i = 0; i < 60; i++) {
InformationObject io = (InformationObject) SinglePointInformation_create(NULL, 100 + i, true, IEC60870_QUALITY_GOOD);

bool added = CS101_ASDU_addInformationObject(asdu, io);

TEST_ASSERT_TRUE(added);

InformationObject_destroy(io);

TEST_ASSERT_EQUAL_INT(i + 1, CS101_ASDU_getNumberOfElements(asdu));
}

InformationObject io = (InformationObject) SinglePointInformation_create(NULL, 100 + i, true, IEC60870_QUALITY_GOOD);

bool added = CS101_ASDU_addInformationObject(asdu, io);

TEST_ASSERT_FALSE(added);

InformationObject_destroy(io);

CS101_ASDU_destroy(asdu);
}

int
main(int argc, char** argv)
{
Expand Down Expand Up @@ -5103,5 +5222,10 @@ main(int argc, char** argv)

RUN_TEST(test_CS104_Connection_ConnectTimeout);

RUN_TEST(test_CS104_Connection_UseAfterClose);
RUN_TEST(test_CS104_Connection_UseAfterServerClosedConnection);
RUN_TEST(test_CS101_ASDU_addObjectOfWrongType);
RUN_TEST(test_CS101_ASDU_addUntilOverflow);

return UNITY_END();
}

0 comments on commit 93928f5

Please sign in to comment.