From 532298c378637f6faf08eb9fcac782582bc77556 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Wed, 13 Apr 2022 17:50:17 +0200 Subject: [PATCH 1/7] - RCBEventHandler: replaced GI event by purgeBuf event when client disables RCB instance (LIB61850-316) --- src/iec61850/server/mms_mapping/reporting.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index 8efc160c..998fda06 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -170,7 +170,7 @@ ReportControl_unlockNotify(ReportControl* self) static void purgeBuf(ReportControl* rc) { - if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: run purgeBuf\n"); + if (DEBUG_IED_SERVER) printf("IED_SERVER: RCB %s purgeBuf\n", rc->name); /* reset trigger */ rc->triggered = false; @@ -1978,7 +1978,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme purgeBuf(rc); if (self->rcbEventHandler) { - self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_GI, NULL, DATA_ACCESS_ERROR_SUCCESS); + self->rcbEventHandler(self->rcbEventHandlerParameter, rc->rcb, clientConnection, RCB_EVENT_PURGEBUF, NULL, DATA_ACCESS_ERROR_SUCCESS); } } From 1954da2b78c9428400f6ef242203211de9a2aeb3 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 15 Apr 2022 11:39:00 +0200 Subject: [PATCH 2/7] - .NET API: added IedServer.GetFunctionalConstrainedData method (LIB61850-317) --- dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs | 19 +++++++++++++++++++ src/iec61850/inc/iec61850_server.h | 3 +-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index 3cd8b548..ebb61dbd 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -2136,6 +2136,9 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr IedServer_getAttributeValue(IntPtr self, IntPtr dataAttribute); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr IedServer_getFunctionalConstrainedData(IntPtr self, IntPtr dataObject, int fc); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate int InternalControlPerformCheckHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool interlockCheck); @@ -2757,6 +2760,22 @@ namespace IEC61850 return null; } + /// + /// Get the MmsValue object related to a functional constrained data object (FCD) + /// + /// the data object to specify the FCD + /// the FC to specify the FCD + /// FCDO corresponding MmsValue object cached by the server + public MmsValue GetFunctionalConstrainedData(DataObject dataObject, FunctionalConstraint fc) + { + IntPtr mmsValuePtr = IedServer_getFunctionalConstrainedData(self, dataObject.self, (int)fc); + + if (mmsValuePtr != IntPtr.Zero) + return new MmsValue(mmsValuePtr); + else + return null; + } + /// /// Enable all GOOSE control blocks. /// diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 902e4de3..5a3dd29d 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -911,9 +911,8 @@ IedServer_getBitStringAttributeValue(IedServer self, const DataAttribute* dataAt LIB61850_API const char* IedServer_getStringAttributeValue(IedServer self, const DataAttribute* dataAttribute); - /** - * \brief Get the MmsValue object related to a FunctionalConstrainedData object + * \brief Get the MmsValue object related to a functional constrained data object (FCD) * * Get the MmsValue from the server cache that is associated with the Functional Constrained Data (FCD) * object that is specified by the DataObject and the given Function Constraint (FC). From 5fe49d4618cfbb092e7abea6b26f13e0a91219a1 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 15 Apr 2022 19:12:40 +0200 Subject: [PATCH 3/7] - fixed wrong MMS protocol version check (#379) --- src/mms/iso_mms/server/mms_association_service.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mms/iso_mms/server/mms_association_service.c b/src/mms/iso_mms/server/mms_association_service.c index a3075e27..83a32f3e 100644 --- a/src/mms/iso_mms/server/mms_association_service.c +++ b/src/mms/iso_mms/server/mms_association_service.c @@ -284,12 +284,15 @@ parseInitRequestDetail(MmsServerConnection self, uint8_t* buffer, int bufPos, in { uint32_t protocolVersion = BerDecoder_decodeUint32(buffer, length, bufPos); - if (protocolVersion != 1) { + if (protocolVersion < 1) { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: invalid protocol version %u\n", protocolVersion); return false; } + + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: proposed version number %u\n", protocolVersion); } break; From b62060b67fde25d9710c795206ded5b7aedb7f8f Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 15 Apr 2022 19:15:50 +0200 Subject: [PATCH 4/7] - fixed bug creating "Cancel" in CDC_APC_create --- examples/server_example_dynamic/server_example_dynamic.c | 3 +++ src/iec61850/server/model/cdc.c | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/server_example_dynamic/server_example_dynamic.c b/examples/server_example_dynamic/server_example_dynamic.c index 43cd9fa9..956a32e7 100644 --- a/examples/server_example_dynamic/server_example_dynamic.c +++ b/examples/server_example_dynamic/server_example_dynamic.c @@ -49,6 +49,9 @@ int main(int argc, char** argv) { DataAttribute* temperatureValue = (DataAttribute*) ModelNode_getChild((ModelNode*) ttmp1_tmpsv, "instMag.f"); DataAttribute* temperatureTimestamp = (DataAttribute*) ModelNode_getChild((ModelNode*) ttmp1_tmpsv, "t"); + LogicalNode* ggio1 = LogicalNode_create("GGIO1", lDevice1); + DataObject* ggio1_anIn1 = CDC_APC_create("AnOut1", (ModelNode*)ggio1, 0, CDC_CTL_MODEL_HAS_CANCEL | CDC_CTL_MODEL_SBO_ENHANCED, false); + DataSet* dataSet = DataSet_create("events", lln0); DataSetEntry_create(dataSet, "TTMP1$MX$TmpSv$instMag$f", -1, NULL); diff --git a/src/iec61850/server/model/cdc.c b/src/iec61850/server/model/cdc.c index e8ac05cf..13967de6 100644 --- a/src/iec61850/server/model/cdc.c +++ b/src/iec61850/server/model/cdc.c @@ -190,8 +190,6 @@ CDA_Cancel(ModelNode* parent, DataAttributeType type, bool isTImeActivated) return oper; } - - /************************************************ * Common Data Classes - helper functions ***********************************************/ @@ -674,7 +672,7 @@ addAnalogControls(DataObject* parent, uint32_t controlOptions, bool isIntegerNot addCommonOperateElements(oper, isTimeActivated, true); if (controlOptions & CDC_CTL_MODEL_HAS_CANCEL) { - DataAttribute* cancel = DataAttribute_create("SBOw", (ModelNode*) parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0); + DataAttribute* cancel = DataAttribute_create("Cancel", (ModelNode*) parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0); CAC_AnalogueValue_create("ctlVal", (ModelNode*) cancel, IEC61850_FC_CO, 0, isIntegerNotFloat); From 584a733b2ab086b04b37eb979e78963f3da33639 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 15 Apr 2022 20:14:25 +0200 Subject: [PATCH 5/7] - mms_utility: added option to read data set directory --- examples/mms_utility/mms_utility.c | 47 ++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/examples/mms_utility/mms_utility.c b/examples/mms_utility/mms_utility.c index ee658622..8b43d9d7 100644 --- a/examples/mms_utility/mms_utility.c +++ b/examples/mms_utility/mms_utility.c @@ -24,6 +24,7 @@ print_help() printf("-x delete file\n"); printf("-j read journal\n"); printf("-v read domain variable list\n"); + printf("-z get domain variable list directory\n"); printf("-y array index for read access\n"); printf("-m print raw MMS messages\n"); } @@ -123,10 +124,11 @@ int main(int argc, char** argv) int printRawMmsMessages = 0; int deleteFile = 0; int readVariableList = 0; + int readDataSetDirectory = 0; int c; - while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:v:c:y:")) != -1) + while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:v:c:y:z:")) != -1) { switch (c) { case 'm': printRawMmsMessages = 1; @@ -167,6 +169,11 @@ int main(int argc, char** argv) readVariableList = 1; variableName = StringUtils_copyString(optarg); break; + case 'z': + readDataSetDirectory = 1; + variableName = StringUtils_copyString(optarg); + break; + case 'f': showFileList = 1; break; @@ -192,12 +199,13 @@ int main(int argc, char** argv) print_help(); return 0; } + } MmsConnection con = MmsConnection_create(); MmsError error; - /* Set maximum MMS PDU size (local detail) to 2000 byte */ + /* Set maximum MMS PDU size (local detail) */ MmsConnection_setLocalDetail(con, maxPduSize); if (printRawMmsMessages) @@ -404,6 +412,41 @@ int main(int argc, char** argv) printf("Reading VMD scope variable list not yet supported!\n"); } + if (readDataSetDirectory) { + if (readWriteHasDomain) { + + bool deletable = false; + + LinkedList varListDir = MmsConnection_readNamedVariableListDirectory(con, &error, domainName, variableName, &deletable); + + if (error != MMS_ERROR_NONE) { + printf("Reading variable list directory failed: (ERROR %i)\n", error); + } + else { + LinkedList varListElem = LinkedList_getNext(varListDir); + + int listIdx = 0; + + while (varListElem) { + MmsVariableAccessSpecification* varAccessSpec = (MmsVariableAccessSpecification*)LinkedList_getData(varListElem); + + if (varAccessSpec->arrayIndex) + printf("[%i] %s/%s(%i)%s\n", listIdx, varAccessSpec->domainId, varAccessSpec->itemId, varAccessSpec->arrayIndex, varAccessSpec->componentName == NULL ? "" : varAccessSpec->componentName); + else + printf("[%i] %s/%s\n", listIdx, varAccessSpec->domainId, varAccessSpec->itemId); + + listIdx++; + + varListElem = LinkedList_getNext(varListElem); + } + + printf("Read SUCCESS\n"); + } + } + else + printf("Reading VMD scope variable list not yet supported!\n"); + } + if (showFileList) { char lastName[300]; lastName[0] = 0; From 3288bc0fc506a38dfaa45699e016c945d5a28cdf Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 15 Apr 2022 20:16:26 +0200 Subject: [PATCH 6/7] - MmsConnection_readNamedVariableListDirectory: added code to parse array index and array component of data set entries (LIB61850-317) --- src/mms/inc_private/mms_common_internal.h | 3 + .../client/mms_client_named_variable_list.c | 54 +++++++++++++- src/mms/iso_mms/common/mms_common_msg.c | 71 ++++++++++++++++++- .../server/mms_named_variable_list_service.c | 71 +------------------ 4 files changed, 125 insertions(+), 74 deletions(-) diff --git a/src/mms/inc_private/mms_common_internal.h b/src/mms/inc_private/mms_common_internal.h index f5431a87..62d07b17 100644 --- a/src/mms/inc_private/mms_common_internal.h +++ b/src/mms/inc_private/mms_common_internal.h @@ -118,6 +118,9 @@ mmsMsg_createStringFromAsnIdentifier(Identifier_t identifier); LIB61850_INTERNAL void mmsMsg_copyAsn1IdentifierToStringBuffer(Identifier_t identifier, char* buffer, int bufSize); +LIB61850_INTERNAL char* +mmsMsg_getComponentNameFromAlternateAccess(AlternateAccess_t* alternateAccess, char* componentNameBuf, int nameBufPos); + LIB61850_INTERNAL void mmsMsg_deleteAccessResultList(AccessResult_t** accessResult, int variableCount); diff --git a/src/mms/iso_mms/client/mms_client_named_variable_list.c b/src/mms/iso_mms/client/mms_client_named_variable_list.c index 98c30ab0..0af73479 100644 --- a/src/mms/iso_mms/client/mms_client_named_variable_list.c +++ b/src/mms/iso_mms/client/mms_client_named_variable_list.c @@ -222,8 +222,11 @@ parseNamedVariableAttributes(GetNamedVariableListAttributesResponse_t* response, for (i = 0; i < attributesCount; i++) { - char* domainId; - char* itemId; + char* domainId = NULL; + char* itemId = NULL; + int arrayIdx = -1; + char componentNameBuffer[129]; + char* componentName = NULL; if (response->listOfVariable.list.array[i]->variableSpecification.choice.name.present == ObjectName_PR_vmdspecific) { @@ -240,7 +243,52 @@ parseNamedVariableAttributes(GetNamedVariableListAttributesResponse_t* response, variableSpecification.choice.name.choice.domainspecific.itemId); } - MmsVariableAccessSpecification* listEntry = MmsVariableAccessSpecification_create(domainId, itemId); + if (response->listOfVariable.list.array[i]->alternateAccess) { + AlternateAccess_t* alternateAccess = response->listOfVariable.list.array[i]->alternateAccess; + + if (alternateAccess->list.count > 0) { + if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAlternateAccess) { + + if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present + == alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present) + { + INTEGER_t* asnIndex = + &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index); + + if (asnIndex) { + long indexValue; + + if (asn_INTEGER2long(asnIndex, &indexValue) != -1) { + arrayIdx = (int)indexValue; + } + } + + AlternateAccess_t* nestedAltAccess = alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess; + + if (nestedAltAccess) { + componentName = mmsMsg_getComponentNameFromAlternateAccess(nestedAltAccess, componentNameBuffer, 0); + } + } + } + else if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAccess) { + INTEGER_t* asnIndex = + &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index); + + if (asnIndex) { + long indexValue; + + if (asn_INTEGER2long(asnIndex, &indexValue) != -1) { + arrayIdx = (int)indexValue; + } + } + } + } + } + + if (componentName) + componentName = StringUtils_copyString(componentName); + + MmsVariableAccessSpecification* listEntry = MmsVariableAccessSpecification_createAlternateAccess(domainId, itemId, arrayIdx, componentName); LinkedList_add(attributes, listEntry); } diff --git a/src/mms/iso_mms/common/mms_common_msg.c b/src/mms/iso_mms/common/mms_common_msg.c index eefd408f..fb7d7548 100644 --- a/src/mms/iso_mms/common/mms_common_msg.c +++ b/src/mms/iso_mms/common/mms_common_msg.c @@ -1,7 +1,7 @@ /* * mms_common_msg.c * - * Copyright 2013-2019 Michael Zillgith + * Copyright 2013-2022 Michael Zillgith * * This file is part of libIEC61850. * @@ -489,6 +489,75 @@ mmsMsg_copyAsn1IdentifierToStringBuffer(Identifier_t identifier, char* buffer, i } } +char* +mmsMsg_getComponentNameFromAlternateAccess(AlternateAccess_t* alternateAccess, char* componentNameBuf, int nameBufPos) +{ + if (alternateAccess->list.count == 1) { + + if (alternateAccess->list.array[0]->present == AlternateAccess__Member_PR_unnamed) { + + if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAlternateAccess) { + + if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present == + AlternateAccessSelection__selectAlternateAccess__accessSelection_PR_component) + { + Identifier_t componentIdentifier = alternateAccess->list.array[0]->choice.unnamed-> + choice.selectAlternateAccess.accessSelection.choice.component; + + AlternateAccess_t* nextAlternateAccess = alternateAccess->list.array[0]->choice.unnamed-> + choice.selectAlternateAccess.alternateAccess; + + if (nextAlternateAccess) { + if (nameBufPos + componentIdentifier.size + 1 < 65) { + memcpy(componentNameBuf + nameBufPos, componentIdentifier.buf, componentIdentifier.size); + nameBufPos += componentIdentifier.size; + componentNameBuf[nameBufPos++] = '$'; + return mmsMsg_getComponentNameFromAlternateAccess(nextAlternateAccess, componentNameBuf, nameBufPos); + } + else { + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: component identifier name too long!\n"); + } + } + else { + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: next alternate access specification is missing!\n"); + } + } + } + else if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAccess) { + + /* final component part */ + + if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present == + AlternateAccessSelection__selectAccess_PR_component) + { + Identifier_t componentIdentifier = alternateAccess->list.array[0]->choice.unnamed-> + choice.selectAccess.choice.component; + + if (nameBufPos + componentIdentifier.size + 1 < 65) { + memcpy(componentNameBuf + nameBufPos, componentIdentifier.buf, componentIdentifier.size); + nameBufPos += componentIdentifier.size; + componentNameBuf[nameBufPos++] = 0; + return componentNameBuf; + } + else { + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: component identifier name too long!\n"); + } + } + } + + } + + } + + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: invalid component access specification\n"); + + return NULL; +} + #if (MMS_FILE_SERVICE == 1) void diff --git a/src/mms/iso_mms/server/mms_named_variable_list_service.c b/src/mms/iso_mms/server/mms_named_variable_list_service.c index e7d152c2..dbe35ffb 100644 --- a/src/mms/iso_mms/server/mms_named_variable_list_service.c +++ b/src/mms/iso_mms/server/mms_named_variable_list_service.c @@ -296,75 +296,6 @@ checkIfVariableExists(MmsDevice* device, MmsAccessSpecifier* accessSpecifier) return true; } -static char* -getComponentNameFromAlternateAccess(AlternateAccess_t* alternateAccess, char* componentNameBuf, int nameBufPos) -{ - if (alternateAccess->list.count == 1) { - - if (alternateAccess->list.array[0]->present == AlternateAccess__Member_PR_unnamed) { - - if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAlternateAccess) { - - if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present == - AlternateAccessSelection__selectAlternateAccess__accessSelection_PR_component) - { - Identifier_t componentIdentifier = alternateAccess->list.array[0]->choice.unnamed-> - choice.selectAlternateAccess.accessSelection.choice.component; - - AlternateAccess_t* nextAlternateAccess = alternateAccess->list.array[0]->choice.unnamed-> - choice.selectAlternateAccess.alternateAccess; - - if (nextAlternateAccess) { - if (nameBufPos + componentIdentifier.size + 1 < 65) { - memcpy(componentNameBuf + nameBufPos, componentIdentifier.buf, componentIdentifier.size); - nameBufPos += componentIdentifier.size; - componentNameBuf[nameBufPos++] = '$'; - return getComponentNameFromAlternateAccess(nextAlternateAccess, componentNameBuf, nameBufPos); - } - else { - if (DEBUG_MMS_SERVER) - printf("MMS_SERVER: component identifier name too long!\n"); - } - } - else { - if (DEBUG_MMS_SERVER) - printf("MMS_SERVER: next alternate access specification is missing!\n"); - } - } - } - else if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAccess) { - - /* final component part */ - - if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present == - AlternateAccessSelection__selectAccess_PR_component) - { - Identifier_t componentIdentifier = alternateAccess->list.array[0]->choice.unnamed-> - choice.selectAccess.choice.component; - - if (nameBufPos + componentIdentifier.size + 1 < 65) { - memcpy(componentNameBuf + nameBufPos, componentIdentifier.buf, componentIdentifier.size); - nameBufPos += componentIdentifier.size; - componentNameBuf[nameBufPos++] = 0; - return componentNameBuf; - } - else { - if (DEBUG_MMS_SERVER) - printf("MMS_SERVER: component identifier name too long!\n"); - } - } - } - - } - - } - - if (DEBUG_MMS_SERVER) - printf("MMS_SERVER: invalid component access specification\n"); - - return NULL; -} - static MmsNamedVariableList createNamedVariableList(MmsServer server, MmsDomain* domain, MmsDevice* device, DefineNamedVariableListRequest_t* request, @@ -426,7 +357,7 @@ createNamedVariableList(MmsServer server, MmsDomain* domain, MmsDevice* device, if (alternateAccess->choice.unnamed->choice.selectAlternateAccess.alternateAccess) { componentNameBuf[0] = 0; - componentName = getComponentNameFromAlternateAccess( + componentName = mmsMsg_getComponentNameFromAlternateAccess( alternateAccess->choice.unnamed->choice.selectAlternateAccess.alternateAccess, componentNameBuf, 0); } From e44a44c9e759fc6e51c859b51f532b6bda152435 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 15 Apr 2022 20:26:44 +0200 Subject: [PATCH 7/7] - parseNamedVariableAttributes: fixed new code --- src/mms/iso_mms/client/mms_client_named_variable_list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mms/iso_mms/client/mms_client_named_variable_list.c b/src/mms/iso_mms/client/mms_client_named_variable_list.c index 0af73479..8b960a2f 100644 --- a/src/mms/iso_mms/client/mms_client_named_variable_list.c +++ b/src/mms/iso_mms/client/mms_client_named_variable_list.c @@ -250,7 +250,7 @@ parseNamedVariableAttributes(GetNamedVariableListAttributesResponse_t* response, if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAlternateAccess) { if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present - == alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present) + == AlternateAccessSelection__selectAlternateAccess__accessSelection_PR_index) { INTEGER_t* asnIndex = &(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.index);