diff --git a/CHANGELOG b/CHANGELOG index cf2264d0..6ee02d5a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,7 @@ Other changes: - Ethernet(Linux): Set to promisc mode by default - removed legacy defines for report reasons (#449) +- removed legacy compatibility functions for SV subscriner ("SVClientaSDU_") Fixed bugs and vulnerabilities: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7499c8c2..ba9aa90e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,8 @@ option(CONFIG_IEC61850_SERVICE_TRACKING "Build with support for IEC 61850 servic option(CONFIG_IEC61850_SETTING_GROUPS "Build with support for IEC 61850 setting group services" ON) option(CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL "Allow user provided callback to control read access" ON) option(CONFIG_IEC61850_RCB_ALLOW_ONLY_PRECONFIGURED_CLIENT "allow only configured clients (when pre-configured by ClientLN)" OFF) +option(CONFIG_IEC61850_L2_GOOSE "Build with support for L2 GOOSE (winpcap required on windows)" ON) +option(CONFIG_IEC61850_L2_SMV "Build with support for L2 SMV (winpcap required on windows)" ON) option(CONFIG_IEC61850_R_GOOSE "Build with support for R-GOOSE (mbedtls required)" ON) option(CONFIG_IEC61850_R_SMV "Build with support for R-SMV (mbedtls required)" ON) option(CONFIG_IEC61850_SNTP_CLIENT "Build with SNTP client code" ON) diff --git a/README.md b/README.md index d8024cff..c8086bfa 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,8 @@ The library support the following IEC 61850 protocol features: * Setting group handling * Support for service tracking * GOOSE and SV control block handling -* Support for R-session protocol/R-GOOSE/R-SMV -* Simple SNTP client code +* Support for R-session protocol/R-GOOSE/R-SMV (BETA) +* Simple SNTP client code (BETA) * TLS support * C and C#/.NET API diff --git a/config/stack_config.h b/config/stack_config.h index 37e663e3..00ac2bcc 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -68,36 +68,20 @@ /* maximum COTP (ISO 8073) TPDU size - valid range is 1024 - 8192 */ #define CONFIG_COTP_MAX_TPDU_SIZE 8192 -/* Ethernet interface ID for GOOSE and SV */ +/* Ethernet interface ID for L2 GOOSE and SV */ #define CONFIG_ETHERNET_INTERFACE_ID "eth0" /* #define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0" */ /* #define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names. */ -/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */ +/* Set to 1 to include generic GOOSE support in the build. Otherwise set to 0 */ #define CONFIG_INCLUDE_GOOSE_SUPPORT 1 -/* Set to 1 to include Sampled Values support in the build. Otherwise set to 0 */ +/* Set to 1 to include generic Sampled Values support in the build. Otherwise set to 0 */ #define CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT 1 /* Set to 1 to compile for edition 1 server - default is 0 to compile for edition 2 */ #define CONFIG_IEC61850_EDITION_1 0 -#ifdef _WIN32 - -/* GOOSE will be disabled for Windows if ethernet support (winpcap) is not available */ -#ifdef EXCLUDE_ETHERNET_WINDOWS -#ifdef CONFIG_INCLUDE_GOOSE_SUPPORT -#undef CONFIG_INCLUDE_GOOSE_SUPPORT -#endif -#define CONFIG_INCLUDE_GOOSE_SUPPORT 0 -#define CONFIG_INCUDE_ETHERNET_WINDOWS 0 -#else -#define CONFIG_INCLUDE_ETHERNET_WINDOWS 1 -#undef CONFIG_ETHERNET_INTERFACE_ID -#define CONFIG_ETHERNET_INTERFACE_ID "0" -#endif -#endif - /* The GOOSE retransmission interval in ms for the stable condition - i.e. no monitored value changed */ #define CONFIG_GOOSE_STABLE_STATE_TRANSMISSION_INTERVAL 5000 @@ -179,9 +163,36 @@ /* compile with support for R-SMV (mbedtls required) */ #define CONFIG_IEC61850_R_SMV 0 +/* compile with support for L2 GOOSE */ +#define CONFIG_IEC61850_L2_GOOSE 0 + +/* compile with support for L2 SMV */ +#define CONFIG_IEC61850_L2_SMV 0 + /* compile SNTP client code */ #define CONFIG_IEC61850_SNTP_CLIENT 0 + +#ifdef _WIN32 + +/* L2 GOOSE/SMV will be disabled for Windows if ethernet support (winpcap) is not available */ +#ifdef EXCLUDE_ETHERNET_WINDOWS +#ifdef CONFIG_IEC61850_L2_GOOSE +#undef CONFIG_IEC61850_L2_GOOSE +#endif +#ifdef CONFIG_IEC61850_L2_SMV +#undef CONFIG_IEC61850_L2_SMV +#endif +#define CONFIG_IEC61850_L2_GOOSE 0 +#define CONFIG_IEC61850_L2_SMV 0 +#define CONFIG_INCUDE_ETHERNET_WINDOWS 0 +#else +#define CONFIG_INCLUDE_ETHERNET_WINDOWS 1 +#undef CONFIG_ETHERNET_INTERFACE_ID +#define CONFIG_ETHERNET_INTERFACE_ID "0" +#endif +#endif + /* overwrite default results for MMS identify service */ /* #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" */ /* #define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" */ diff --git a/config/stack_config.h.cmake b/config/stack_config.h.cmake index 28521f25..271bcb9c 100644 --- a/config/stack_config.h.cmake +++ b/config/stack_config.h.cmake @@ -68,10 +68,10 @@ /* #define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0" */ /* #define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names. */ -/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */ +/* Set to 1 to include generic GOOSE support in the build. Otherwise set to 0 */ #cmakedefine01 CONFIG_INCLUDE_GOOSE_SUPPORT -/* Set to 1 to include Sampled Values support in the build. Otherwise set to 0 */ +/* Set to 1 to include generic Sampled Values support in the build. Otherwise set to 0 */ #define CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT 1 /* compile with support for R-GOOSE (mbedtls requried) */ @@ -80,6 +80,12 @@ /* compile with support for R-SMV (mbedtls required) */ #cmakedefine01 CONFIG_IEC61850_R_SMV +/* compile with support for L2 GOOSE */ +#cmakedefine01 CONFIG_IEC61850_L2_GOOSE + +/* compile with support for L2 SMV */ +#cmakedefine01 CONFIG_IEC61850_L2_SMV + /* compile SNTP client code */ #cmakedefine01 CONFIG_IEC61850_SNTP_CLIENT @@ -88,12 +94,16 @@ #ifdef _WIN32 -/* GOOSE will be disabled for Windows if ethernet support (winpcap) is not available */ +/* L2 GOOSE/SMV will be disabled for Windows if ethernet support (winpcap) is not available */ #ifdef EXCLUDE_ETHERNET_WINDOWS -#ifdef CONFIG_INCLUDE_GOOSE_SUPPORT -#undef CONFIG_INCLUDE_GOOSE_SUPPORT +#ifdef CONFIG_IEC61850_L2_GOOSE +#undef CONFIG_IEC61850_L2_GOOSE +#endif +#ifdef CONFIG_IEC61850_L2_SMV +#undef CONFIG_IEC61850_L2_SMV #endif -#define CONFIG_INCLUDE_GOOSE_SUPPORT 0 +#define CONFIG_IEC61850_L2_GOOSE 0 +#define CONFIG_IEC61850_L2_SMV 0 #define CONFIG_INCUDE_ETHERNET_WINDOWS 0 #else #define CONFIG_INCLUDE_ETHERNET_WINDOWS 1 diff --git a/hal/CMakeLists.txt b/hal/CMakeLists.txt index 9b421f6b..2ef87d31 100644 --- a/hal/CMakeLists.txt +++ b/hal/CMakeLists.txt @@ -28,7 +28,7 @@ message("Found winpcap -> compile ethernet HAL layer (required for GOOSE/SV supp set(WITH_WPCAP 1) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Include") else() -message("winpcap not found -> skip ethernet HAL layer (no GOOSE/SV support)") +message("winpcap not found -> skip ethernet HAL layer (no L2 GOOSE/SV support)") endif() endif(WIN32) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50e6d4c5..8c08bb6f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -220,7 +220,7 @@ set (lib_bsd_SRCS IF(WIN32) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib") -message("Found winpcap -> can compile with GOOSE support") +message("Found winpcap -> can compile with L2 GOOSE/SMV support") set(WITH_WPCAP 1) endif() @@ -232,16 +232,13 @@ set_source_files_properties(${lib_common_SRCS} ${lib_windows_SRCS} PROPERTIES LANGUAGE CXX) set_source_files_properties(${lib_rsession_SRCS} PROPERTIES LANGUAGE CXX) -ENDIF() - -IF(WITH_WPCAP) -IF(MSVC) set_source_files_properties(${lib_goose_SRCS} PROPERTIES LANGUAGE CXX) set_source_files_properties(${lib_sv_SRCS} PROPERTIES LANGUAGE CXX) - ENDIF() + +IF(WITH_WPCAP) ELSE() add_definitions(-DEXCLUDE_ETHERNET_WINDOWS) ENDIF() @@ -250,7 +247,7 @@ include_directories( ../third_party/winpcap/include ) -IF(WITH_WPCAP) +IF(WITH_WPCAP OR CONFIG_IEC61850_R_GOOSE OR CONFIG_IEC61850_R_SMV) set (library_SRCS ${lib_common_SRCS} ${lib_asn1c_SRCS} @@ -266,11 +263,10 @@ set (library_SRCS ${lib_common_SRCS} ${lib_asn1c_SRCS} ${lib_windows_SRCS} - ${lib_rsession_SRCS} ${lib_sntp_SRCS} ) -ENDIF(WITH_WPCAP) +ENDIF(WITH_WPCAP OR CONFIG_IEC61850_R_GOOSE OR CONFIG_IEC61850_R_SMV) ELSEIF(UNIX) IF(APPLE) diff --git a/src/goose/goose_publisher.c b/src/goose/goose_publisher.c index 094881a5..fa276ec1 100644 --- a/src/goose/goose_publisher.c +++ b/src/goose/goose_publisher.c @@ -40,7 +40,8 @@ static bool prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID, bool useVlanTags); -struct sGoosePublisher { +struct sGoosePublisher +{ uint8_t* buffer; #if (CONFIG_IEC61850_R_GOOSE == 1) @@ -49,8 +50,10 @@ struct sGoosePublisher { uint16_t appId; #endif /* (CONFIG_IEC61850_R_GOOSE == 1) */ +#if (CONFIG_IEC61850_L2_GOOSE == 1) /* only for Ethernet based GOOSE */ EthernetSocket ethernetSocket; +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ int lengthField; int payloadStart; @@ -99,6 +102,7 @@ GoosePublisher_createRemote(RSession session, uint16_t appId) } #endif /* (CONFIG_IEC61850_R_GOOSE == 1) */ +#if (CONFIG_IEC61850_L2_GOOSE == 1) GoosePublisher GoosePublisher_createEx(CommParameters* parameters, const char* interfaceID, bool useVlanTag) { @@ -127,15 +131,18 @@ GoosePublisher_create(CommParameters* parameters, const char* interfaceID) { return GoosePublisher_createEx(parameters, interfaceID, true); } +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ void GoosePublisher_destroy(GoosePublisher self) { if (self) { +#if (CONFIG_IEC61850_L2_GOOSE == 1) if (self->ethernetSocket) { Ethernet_destroySocket(self->ethernetSocket); } +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ MmsValue_delete(self->timestamp); @@ -242,6 +249,7 @@ GoosePublisher_setTimeAllowedToLive(GoosePublisher self, uint32_t timeAllowedToL self->timeAllowedToLive = timeAllowedToLive; } +#if (CONFIG_IEC61850_L2_GOOSE == 1) static bool prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID, bool useVlanTags) { @@ -342,6 +350,7 @@ prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* return false; } } +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ static int32_t createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffer, size_t maxPayloadSize) @@ -460,7 +469,8 @@ createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffe { MmsValue* dataSetEntry = (MmsValue*) element->data; - if (dataSetEntry) { + if (dataSetEntry) + { bufPos = MmsValue_encodeMmsData(dataSetEntry, buffer, bufPos, true); } else { @@ -490,7 +500,9 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet) if (self->sqNum == 0) self->sqNum = 1; - if (self->ethernetSocket) { +#if (CONFIG_IEC61850_L2_GOOSE == 1) + if (self->ethernetSocket) + { int lengthIndex = self->lengthField; size_t gooseLength = self->payloadLength + 8; @@ -503,9 +515,11 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet) if (DEBUG_GOOSE_PUBLISHER) printf("GOOSE_PUBLISHER: send GOOSE message\n"); } -#if (CONFIG_IEC61850_R_GOOSE == 1) - else if (self->remoteSession) { +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ +#if (CONFIG_IEC61850_R_GOOSE == 1) + if (self->remoteSession) + { RSession_sendMessage(self->remoteSession, RSESSION_SPDU_ID_GOOSE, self->simulation, self->appId, buffer, self->payloadLength); if (DEBUG_GOOSE_PUBLISHER) diff --git a/src/goose/goose_receiver.c b/src/goose/goose_receiver.c index eb4365cc..fd94d9c5 100644 --- a/src/goose/goose_receiver.c +++ b/src/goose/goose_receiver.c @@ -73,7 +73,7 @@ GooseReceiver_createEx(uint8_t* buffer) { GooseReceiver self = (GooseReceiver) GLOBAL_MALLOC(sizeof(struct sGooseReceiver)); - if (self != NULL) + if (self) { self->running = false; self->stop = false; @@ -94,7 +94,8 @@ GooseReceiver_create() { GooseReceiver self = GooseReceiver_createEx(NULL); - if (self) { + if (self) + { self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH); } @@ -107,7 +108,8 @@ GooseReceiver_createRemote(RSession session) { GooseReceiver self = GooseReceiver_create(); - if (self) { + if (self) + { self->session = session; } @@ -1116,7 +1118,8 @@ parseGooseMessage(GooseReceiver self, uint8_t* buffer, int numbytes) if (subscriberFound) parseGoosePayload(self, buffer + bufPos, apduLength); - else { + else + { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: GOOSE message ignored due to unknown DST-MAC or APPID value\n"); } @@ -1128,6 +1131,7 @@ gooseReceiverLoop(void *threadParameter) { GooseReceiver self = (GooseReceiver) threadParameter; +#if (CONFIG_IEC61850_L2_GOOSE == 1) if (self->ethSocket) { EthernetHandleSet handleSet = EthernetHandleSet_new(); @@ -1159,8 +1163,10 @@ gooseReceiverLoop(void *threadParameter) EthernetHandleSet_destroy(handleSet); } +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ + #if (CONFIG_IEC61850_R_GOOSE == 1) - else if (self->session) + if (self->session) { HandleSet handleSet = Handleset_new(); @@ -1207,29 +1213,38 @@ GooseReceiver_start(GooseReceiver self) { self->thread = Thread_create((ThreadExecutionFunction) gooseReceiverLoop, (void*) self, false); - if (self->thread != NULL) { - - if (self->ethSocket) { + if (self->thread) + { +#if (CONFIG_IEC61850_L2_GOOSE == 1) + if (self->ethSocket) + { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: GOOSE receiver started for interface %s\n", self->interfaceId); Thread_start(self->thread); + + return; } +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ + + #if (CONFIG_IEC61850_R_GOOSE == 1) - else if (self->session) { + if (self->session) + { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: R-GOOSE receiver started\n"); Thread_start(self->thread); + + return; } #endif /* (CONFIG_IEC61850_R_GOOSE == 1) */ - else { - if (DEBUG_GOOSE_SUBSCRIBER) - printf("GOOSE_SUBSCRIBER: ERROR - No link/transport layer specified -> cannot start!\n"); - Thread_destroy(self->thread); - self->thread = NULL; - } + if (DEBUG_GOOSE_SUBSCRIBER) + printf("GOOSE_SUBSCRIBER: ERROR - No link/transport layer specified -> cannot start!\n"); + + Thread_destroy(self->thread); + self->thread = NULL; } else { if (DEBUG_GOOSE_SUBSCRIBER) @@ -1287,7 +1302,8 @@ EthernetSocket GooseReceiver_startThreadless(GooseReceiver self) { #if (CONFIG_IEC61850_R_GOOSE == 1) - if (self->session) { + if (self->session) + { if (RSession_start(self->session) == R_SESSION_ERROR_OK) { self->running = true; @@ -1304,6 +1320,7 @@ GooseReceiver_startThreadless(GooseReceiver self) else { #endif /* (CONFIG_IEC61850_R_GOOSE == 1) */ +#if (CONFIG_IEC61850_L2_GOOSE == 1) if (self->interfaceId == NULL) self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL); else @@ -1340,6 +1357,7 @@ GooseReceiver_startThreadless(GooseReceiver self) else { self->running = false; } +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ #if (CONFIG_IEC61850_R_GOOSE == 1) } @@ -1351,8 +1369,10 @@ GooseReceiver_startThreadless(GooseReceiver self) void GooseReceiver_stopThreadless(GooseReceiver self) { +#if (CONFIG_IEC61850_L2_GOOSE == 1) if (self->ethSocket) Ethernet_destroySocket(self->ethSocket); +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ self->running = false; } @@ -1368,7 +1388,6 @@ handleSessionPayloadElement(void* parameter, uint16_t appId, uint8_t* payloadDat } #endif /* (CONFIG_IEC61850_R_GOOSE == 1) */ - /* call after reception of ethernet frame */ bool GooseReceiver_tick(GooseReceiver self) @@ -1384,6 +1403,8 @@ GooseReceiver_tick(GooseReceiver self) else { #endif /* (CONFIG_IEC61850_R_GOOSE == 1) */ + +#if (CONFIG_IEC61850_L2_GOOSE == 1) int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH); if (packetSize > 0) @@ -1393,6 +1414,7 @@ GooseReceiver_tick(GooseReceiver self) } else return false; +#endif /* (CONFIG_IEC61850_L2_GOOSE == 1) */ #if (CONFIG_IEC61850_R_GOOSE == 1) } diff --git a/src/sampled_values/sv_publisher.c b/src/sampled_values/sv_publisher.c index f69b90cd..90179cf6 100644 --- a/src/sampled_values/sv_publisher.c +++ b/src/sampled_values/sv_publisher.c @@ -1,7 +1,7 @@ /* * sv_publisher.c * - * Copyright 2016-2022 Michael Zillgith + * Copyright 2016-2024 Michael Zillgith * * This file is part of libIEC61850. * @@ -76,8 +76,10 @@ struct sSVPublisher { uint16_t appId; bool simulation; +#if (CONFIG_IEC61850_L2_SMV == 1) /* only for Ethernet based SV */ EthernetSocket ethernetSocket; +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ #if (CONFIG_IEC61850_R_SMV == 1) /* only for R-SV */ @@ -93,7 +95,7 @@ struct sSVPublisher { SVPublisher_ASDU asduList; }; - +#if (CONFIG_IEC61850_L2_SMV == 1) static bool preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* interfaceId, bool useVlanTags) { @@ -194,7 +196,7 @@ preparePacketBuffer(SVPublisher self, CommParameters* parameters, const char* in return true; } - +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ static int encodeUInt16FixedSize(uint16_t value, uint8_t* buffer, int bufPos) @@ -303,6 +305,7 @@ SVPublisher_createRemote(RSession session, uint16_t appId) } #endif /* (CONFIG_IEC61850_R_SMV == 1) */ +#if (CONFIG_IEC61850_L2_SMV == 1) SVPublisher SVPublisher_createEx(CommParameters* parameters, const char* interfaceId, bool useVlanTag) { @@ -329,6 +332,7 @@ SVPublisher_create(CommParameters* parameters, const char* interfaceId) { return SVPublisher_createEx(parameters, interfaceId, true); } +#endif /* (CONFIG_IEC61850_R_SMV == 1) */ SVPublisher_ASDU SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint32_t confRev) @@ -527,21 +531,25 @@ SVPublisher_setupComplete(SVPublisher self) void SVPublisher_publish(SVPublisher self) { - if (DEBUG_SV_PUBLISHER) - printf("SV_PUBLISHER: send SV message\n"); +#if (CONFIG_IEC61850_L2_SMV == 1) + if (self->ethernetSocket) + { + if (DEBUG_SV_PUBLISHER) + printf("SV_PUBLISHER: send L2 SV message\n"); - if (self->ethernetSocket) { Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + self->payloadLength); } +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ + #if (CONFIG_IEC61850_R_SMV == 1) - else if (self->remoteSession) { + if (self->remoteSession) + { + if (DEBUG_SV_PUBLISHER) + printf("SV_PUBLISHER: send R-SV message\n"); + RSession_sendMessage(self->remoteSession, RSESSION_SPDU_ID_SV, self->simulation, self->appId, self->buffer, self->payloadLength); } #endif /* (CONFIG_IEC61850_R_SMV == 1) */ - else { - if (DEBUG_SV_PUBLISHER) - printf("SV_PUBLISHER: no network layer!\n"); - } } void @@ -549,8 +557,10 @@ SVPublisher_destroy(SVPublisher self) { if (self) { +#if (CONFIG_IEC61850_L2_SMV == 1) if (self->ethernetSocket) Ethernet_destroySocket(self->ethernetSocket); +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ if (self->buffer) GLOBAL_FREEMEM(self->buffer); @@ -808,139 +818,3 @@ SVPublisher_ASDU_setSmpSynch(SVPublisher_ASDU self, uint16_t smpSynch) self->smpSynch = smpSynch; *(self->smpSynchBuf) = self->smpSynch; } - -/******************************************************************* - * Wrapper functions to support old API (remove in future versions) - *******************************************************************/ - -SVPublisher -SampledValuesPublisher_create(CommParameters* parameters, const char* interfaceId) -{ - return SVPublisher_create(parameters, interfaceId); -} - -SVPublisher_ASDU -SampledValuesPublisher_addASDU(SVPublisher self, char* svID, char* datset, uint32_t confRev) -{ - return SVPublisher_addASDU(self, svID, datset, confRev); -} - -void -SampledValuesPublisher_setupComplete(SVPublisher self) -{ - SVPublisher_setupComplete(self); -} - -void -SampledValuesPublisher_publish(SVPublisher self) -{ - SVPublisher_publish(self); -} - -void -SampledValuesPublisher_destroy(SVPublisher self) -{ - SVPublisher_destroy(self); -} - -void -SV_ASDU_resetBuffer(SVPublisher_ASDU self) -{ - SVPublisher_ASDU_resetBuffer(self); -} - -int -SV_ASDU_addINT8(SVPublisher_ASDU self) -{ - return SVPublisher_ASDU_addINT8(self); -} - -void -SV_ASDU_setINT8(SVPublisher_ASDU self, int index, int8_t value) -{ - SVPublisher_ASDU_setINT8(self, index, value); -} - -int -SV_ASDU_addINT32(SVPublisher_ASDU self) -{ - return SVPublisher_ASDU_addINT32(self); -} - -void -SV_ASDU_setINT32(SVPublisher_ASDU self, int index, int32_t value) -{ - SVPublisher_ASDU_setINT32(self, index, value); -} - -int -SV_ASDU_addINT64(SVPublisher_ASDU self) -{ - return SVPublisher_ASDU_addINT64(self); -} - -void -SV_ASDU_setINT64(SVPublisher_ASDU self, int index, int64_t value) -{ - SVPublisher_ASDU_setINT64(self, index, value); -} - -int -SV_ASDU_addFLOAT(SVPublisher_ASDU self) -{ - return SVPublisher_ASDU_addFLOAT(self); -} - -void -SV_ASDU_setFLOAT(SVPublisher_ASDU self, int index, float value) -{ - SVPublisher_ASDU_setFLOAT(self, index, value); -} - -int -SV_ASDU_addFLOAT64(SVPublisher_ASDU self) -{ - return SVPublisher_ASDU_addFLOAT64(self); -} - -void -SV_ASDU_setFLOAT64(SVPublisher_ASDU self, int index, double value) -{ - SVPublisher_ASDU_setFLOAT64(self, index, value); -} - -void -SV_ASDU_setSmpCnt(SVPublisher_ASDU self, uint16_t value) -{ - SVPublisher_ASDU_setSmpCnt(self, value); -} - -uint16_t -SV_ASDU_getSmpCnt(SVPublisher_ASDU self) -{ - return SVPublisher_ASDU_getSmpCnt(self); -} - -void -SV_ASDU_increaseSmpCnt(SVPublisher_ASDU self) -{ - SVPublisher_ASDU_increaseSmpCnt(self); -} - -void -SV_ASDU_setRefrTm(SVPublisher_ASDU self, uint64_t refrTm) -{ - SVPublisher_ASDU_setRefrTm(self, refrTm); -} - -void -SV_ASDU_setSmpMod(SVPublisher_ASDU self, uint8_t smpMod) -{ - SVPublisher_ASDU_setSmpMod(self, smpMod); -} - -void -SV_ASDU_setSmpRate(SVPublisher_ASDU self, uint16_t smpRate) -{ - SVPublisher_ASDU_setSmpRate(self, smpRate); -} diff --git a/src/sampled_values/sv_subscriber.c b/src/sampled_values/sv_subscriber.c index 9e465c0b..221eb1a8 100644 --- a/src/sampled_values/sv_subscriber.c +++ b/src/sampled_values/sv_subscriber.c @@ -1,7 +1,7 @@ /* * sv_receiver.c * - * Copyright 2015-2022 Michael Zillgith + * Copyright 2015-2024 Michael Zillgith * * This file is part of libIEC61850. * @@ -67,7 +67,6 @@ struct sSVReceiver Semaphore subscriberListLock; Thread thread; #endif - }; struct sSVSubscriber @@ -101,7 +100,8 @@ SVReceiver_create(void) { SVReceiver self = (SVReceiver) GLOBAL_CALLOC(1, sizeof(struct sSVReceiver)); - if (self != NULL) { + if (self) + { self->subscriberList = LinkedList_create(); self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH); @@ -122,7 +122,8 @@ SVReceiver_createRemote(RSession session) { SVReceiver self = (SVReceiver) GLOBAL_CALLOC(1, sizeof(struct sSVReceiver)); - if (self != NULL) { + if (self != NULL) + { self->subscriberList = LinkedList_create(); self->buffer = NULL; @@ -193,6 +194,7 @@ svReceiverLoop(void* threadParameter) { SVReceiver self = (SVReceiver) threadParameter; +#if (CONFIG_IEC61850_L2_SMV == 1) if (self->ethSocket) { EthernetHandleSet handleSet = EthernetHandleSet_new(); @@ -217,8 +219,10 @@ svReceiverLoop(void* threadParameter) EthernetHandleSet_destroy(handleSet); } +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ + #if (CONFIG_IEC61850_R_SMV == 1) - else if (self->session) + if (self->session) { self->stopped = false; @@ -349,14 +353,12 @@ SVReceiver_startThreadless(SVReceiver self) return true; } - else - { - return false; - } } else { #endif /* (CONFIG_IEC61850_R_SMV == 1) */ + +#if (CONFIG_IEC61850_L2_SMV == 1) if (self->interfaceId == NULL) self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL); else @@ -367,22 +369,25 @@ SVReceiver_startThreadless(SVReceiver self) Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV); self->running = true; - } - if (self->ethSocket) return true; - else - return false; + } +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ + #if (CONFIG_IEC61850_R_SMV == 1) } #endif /* (CONFIG_IEC61850_R_SMV == 1) */ + + return false; } void SVReceiver_stopThreadless(SVReceiver self) { +#if (CONFIG_IEC61850_L2_SMV == 1) if (self->ethSocket) Ethernet_destroySocket(self->ethSocket); +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ #if (CONFIG_IEC61850_R_SMV == 1) if (self->session) { @@ -611,35 +616,37 @@ handleSVApdu(SVReceiver self, uint16_t appId, uint8_t* apdu, int apduLength, uin bool subscriberFound = false; - while (element != NULL) { + while (element) + { subscriber = (SVSubscriber) LinkedList_getData(element); - if (subscriber->appId == appId) { - - - if (self->checkDestAddr) { - - if (self->ethSocket) { - if (memcmp(dstAddr, subscriber->ethAddr, 6) == 0) { + if (subscriber->appId == appId) + { + if (self->checkDestAddr) + { + if (self->ethSocket) + { + if (memcmp(dstAddr, subscriber->ethAddr, 6) == 0) + { subscriberFound = true; break; } else + { if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Checking ethernet dest address failed!\n"); + } } - else { + else + { //TODO check destination IP address for R-SV - } - } - else { + else + { subscriberFound = true; break; } - - } element = LinkedList_getNext(element); @@ -650,8 +657,11 @@ handleSVApdu(SVReceiver self, uint16_t appId, uint8_t* apdu, int apduLength, uin #endif if (subscriberFound) + { parseSVPayload(self, subscriber, apdu, apduLength); - else { + } + else + { if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: SV message ignored due to unknown APPID value or dest address mismatch\n"); } @@ -724,6 +734,7 @@ handleSessionPayloadElement(void* parameter, uint16_t appId, uint8_t* payloadDat bool SVReceiver_tick(SVReceiver self) { +#if (CONFIG_IEC61850_L2_SMV == 1) if (self->ethSocket) { int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH); @@ -734,8 +745,10 @@ SVReceiver_tick(SVReceiver self) return true; } } +#endif /* (CONFIG_IEC61850_L2_SMV == 1) */ + #if (CONFIG_IEC61850_R_SMV == 1) - else if (self->session) + if (self->session) { if (RSession_receiveMessage(self->session, handleSessionPayloadElement, (void*) self) == R_SESSION_ERROR_OK) return true; @@ -750,7 +763,7 @@ SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID) { SVSubscriber self = (SVSubscriber) GLOBAL_CALLOC(1, sizeof(struct sSVSubscriber)); - if (self != NULL) + if (self) { self->appId = appID; @@ -764,7 +777,7 @@ SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID) void SVSubscriber_destroy(SVSubscriber self) { - if (self != NULL) + if (self) GLOBAL_FREEMEM(self); } @@ -819,7 +832,7 @@ decodeUtcTimeToNsTime(uint8_t* buffer, uint8_t* timeQuality) nsVal = nsVal * 1000000000UL; nsVal = nsVal >> 24; - if (timeQuality != NULL) + if (timeQuality) *timeQuality = buffer[7]; uint64_t timeval64 = (uint64_t) timeval32 * 1000000000ULL + nsVal; @@ -832,7 +845,7 @@ SVSubscriber_ASDU_getRefrTmAsMs(SVSubscriber_ASDU self) { msSinceEpoch msTime = 0; - if (self->refrTm != NULL) + if (self->refrTm) msTime = decodeUtcTimeToNsTime(self->refrTm, NULL); return (msTime / 1000000ULL); @@ -843,7 +856,7 @@ SVSubscriber_ASDU_getRefrTmAsNs(SVSubscriber_ASDU self) { nsSinceEpoch nsTime = 0; - if (self->refrTm != NULL) + if (self->refrTm) nsTime = decodeUtcTimeToNsTime(self->refrTm, NULL); return nsTime; @@ -1086,99 +1099,3 @@ SVSubscriber_ASDU_getDataSize(SVSubscriber_ASDU self) { return self->dataBufferLength; } - -uint16_t -SVClientASDU_getSmpCnt(SVSubscriber_ASDU self) -{ - return SVSubscriber_ASDU_getSmpCnt(self); -} - -const char* -SVClientASDU_getSvId(SVSubscriber_ASDU self) -{ - return SVSubscriber_ASDU_getSvId(self); -} - -uint32_t -SVClientASDU_getConfRev(SVSubscriber_ASDU self) -{ - return SVSubscriber_ASDU_getConfRev(self); -} - -bool -SVClientASDU_hasRefrTm(SVSubscriber_ASDU self) -{ - return SVSubscriber_ASDU_hasRefrTm(self); -} - -uint64_t -SVClientASDU_getRefrTmAsMs(SVSubscriber_ASDU self) -{ - return SVSubscriber_ASDU_getRefrTmAsMs(self); -} - -int8_t -SVClientASDU_getINT8(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT8(self, index); -} - -int16_t -SVClientASDU_getINT16(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT16(self, index); -} - -int32_t -SVClientASDU_getINT32(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT32(self, index); -} - -int64_t -SVClientASDU_getINT64(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT64(self, index); -} - -uint8_t -SVClientASDU_getINT8U(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT8U(self, index); -} - -uint16_t -SVClientASDU_getINT16U(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT16U(self, index); -} - -uint32_t -SVClientASDU_getINT32U(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT32U(self, index); -} - -uint64_t -SVClientASDU_getINT64U(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getINT64U(self, index); -} - -float -SVClientASDU_getFLOAT32(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getFLOAT32(self, index); -} - -double -SVClientASDU_getFLOAT64(SVSubscriber_ASDU self, int index) -{ - return SVSubscriber_ASDU_getFLOAT64(self, index); -} - -int -SVClientASDU_getDataSize(SVSubscriber_ASDU self) -{ - return SVSubscriber_ASDU_getDataSize(self); -} diff --git a/src/sampled_values/sv_subscriber.h b/src/sampled_values/sv_subscriber.h index 0ec4d5ef..c33228a8 100644 --- a/src/sampled_values/sv_subscriber.h +++ b/src/sampled_values/sv_subscriber.h @@ -560,72 +560,7 @@ SVSubscriber_ASDU_getDataSize(SVSubscriber_ASDU self); uint8_t SVSubscriber_ASDU_getSmpSynch(SVSubscriber_ASDU self); -#ifndef DEPRECATED -#if defined(__GNUC__) || defined(__clang__) - #define DEPRECATED __attribute__((deprecated)) -#else - #define DEPRECATED -#endif -#endif - -/** - * \addtogroup sv_subscriber_deprecated_api_group Deprecated API - * \ingroup sv_subscriber_api_group IEC 61850 Sampled Values (SV) publisher API - * \deprecated - * @{ - */ - -typedef struct sSVSubscriberASDU* SVClientASDU; - -LIB61850_API DEPRECATED uint16_t -SVClientASDU_getSmpCnt(SVSubscriber_ASDU self); - -LIB61850_API DEPRECATED const char* -SVClientASDU_getSvId(SVSubscriber_ASDU self); - -LIB61850_API DEPRECATED uint32_t -SVClientASDU_getConfRev(SVSubscriber_ASDU self); - -LIB61850_API DEPRECATED bool -SVClientASDU_hasRefrTm(SVSubscriber_ASDU self); - -LIB61850_API DEPRECATED uint64_t -SVClientASDU_getRefrTmAsMs(SVSubscriber_ASDU self); - -LIB61850_API DEPRECATED int8_t -SVClientASDU_getINT8(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED int16_t -SVClientASDU_getINT16(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED int32_t -SVClientASDU_getINT32(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED int64_t -SVClientASDU_getINT64(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED uint8_t -SVClientASDU_getINT8U(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED uint16_t -SVClientASDU_getINT16U(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED uint32_t -SVClientASDU_getINT32U(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED uint64_t -SVClientASDU_getINT64U(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED float -SVClientASDU_getFLOAT32(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED double -SVClientASDU_getFLOAT64(SVSubscriber_ASDU self, int index); - -LIB61850_API DEPRECATED int -SVClientASDU_getDataSize(SVSubscriber_ASDU self); - -/**@} @}*/ +/** @}*/ #ifdef __cplusplus }