summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-atn-ulcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-atn-ulcs.c')
-rw-r--r--epan/dissectors/packet-atn-ulcs.c2619
1 files changed, 2619 insertions, 0 deletions
diff --git a/epan/dissectors/packet-atn-ulcs.c b/epan/dissectors/packet-atn-ulcs.c
new file mode 100644
index 00000000..00983b07
--- /dev/null
+++ b/epan/dissectors/packet-atn-ulcs.c
@@ -0,0 +1,2619 @@
+/* Do not modify this file. Changes will be overwritten. */
+/* Generated automatically by the ASN.1 to Wireshark dissector compiler */
+/* packet-atn-ulcs.c */
+/* asn2wrs.py -u -L -p atn-ulcs -c ./atn-ulcs.cnf -s ./packet-atn-ulcs-template -D . -O ../.. atn-ulcs.asn */
+
+/* packet-atn-ulcs.c
+ * By Mathias Guettler <guettler@web.de>
+ * Copyright 2013
+ *
+ * Routines for ATN upper layer
+ * protocol packet disassembly
+
+ * ATN upper layers are embedded within OSI Layer 4 (COTP).
+ *
+ * ATN upper layers contain:
+ * Session Layer (NUL protocol option)
+ * Presentation Layer (NUL protocol option)
+ * ATN upper Layer/Application (ACSE PDU or PDV-list PDU)
+
+ * ATN applications protocols (i.e. CM or CPDLC) are contained within
+ * ACSE user-information or PDV presentation data.
+
+ * details see:
+ * http://en.wikipedia.org/wiki/CPDLC
+ * http://members.optusnet.com.au/~cjr/introduction.htm
+
+ * standards:
+ * http://legacy.icao.int/anb/panels/acp/repository.cfm
+
+ * note:
+ * We are dealing with ATN/ULCS aka ICAO Doc 9705 Ed2 here
+ * (don't think there is an ULCS equivalent for "FANS-1/A ").
+
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+ developer comments:
+why not using existing ses, pres and acse dissectors ?
+ ATN upper layers are derived from OSI standards for session,
+ presentation and application but the encoding differs
+ (it's PER instead of BER encoding to save bandwith).
+ Session and presentation use the "null" encoding option,
+ meaning that they are only present at connection establishment
+ and ommitted otherwise.
+ Instead of adapting existing dissectors it seemed simpler and cleaner
+ to implement everything the new atn-ulcs dissector.
+
+why using conversations ?
+ PER encoded user data is ambigous; the same encoding may apply to a CM or
+ CPDLC PDU. The workaround is to decode on a transport connection basis.
+ I use my own version of conversations to identify
+ the transport connection the PDU belongs to for the standard functions
+ from "conversation.h" didn't work out.
+
+what is the use of AARQ/AARE data ?
+ Converstions should be maintained on the COTP layer in a standard way
+ for there are usually more packets available than in the layers above.
+ In the worst case my dissector is called from a DT packet which
+ has destination references but no source reference.
+ I have to guess the reference used the other way round
+ (curently I am using ACSE PDU'S used during OSI connection establishment for that).
+ The idea is that each ACSE AARQ is answered by ACSE AARE and having this sequence
+ I have all the source/destination references for this transport connection.
+ I use AARQ/AARE data to store the source/destination reference of AARQ as well
+ as the optional ae-qualifier which tells me the application and
+ the dissector I have to use.
+ This approach donesn't work well when there are interleaving AARQ/AARE sequences for
+ the same aircraft.
+
+which ATN standard is supported ?
+ The dissector has been tested with ICAO doc9705 Edition2 compliant traffic.
+ No ATN Secutity is supported.
+ note:
+ The ATN upper layers are derived from OSI standards (ICAO DOC 9705)
+ while ATN/IPS (ICAO DOC 9896) which is entirely based on IPV6.
+
+*/
+
+/*
+ known defects/deficiencies:
+
+- user-information within AARE is sometines not decoded due to an unset flag
+ (the field is optional). As far as I can tell asn2wrs is right here,
+ but on the other hand I know that in all of this cases user-information
+ is present and is processed by the ATN end system.
+ Maybe a true ATN expert may help me out here.
+
+ - The conversation handling is based on src/dst addresses as well as
+ source or destination references depending on the TP4 packet type.
+ This means that after some time these references get reused for
+ new conversations. This almost certain happens for traces longer
+ than one day rendering this dissector unsuitable for captures exceeding
+ this one day.
+
+*/
+
+#include "config.h"
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+
+
+#include <epan/packet.h>
+#include <epan/address.h>
+#include <epan/conversation.h>
+#include <epan/osi-utils.h>
+#include "packet-ber.h"
+#include "packet-per.h"
+#include "packet-atn-ulcs.h"
+
+#define ATN_ACSE_PROTO "ICAO Doc9705 ULCS ACSE (ISO 8649/8650-1:1996)"
+#define ATN_ULCS_PROTO "ICAO Doc9705 ULCS"
+
+void proto_register_atn_ulcs(void);
+void proto_reg_handoff_atn_ulcs(void);
+
+static heur_dissector_list_t atn_ulcs_heur_subdissector_list;
+
+/* presentation subdissectors i.e. CM, CPDLC */
+static dissector_handle_t atn_cm_handle = NULL;
+static dissector_handle_t atn_cpdlc_handle = NULL;
+
+static int proto_atn_ulcs = -1;
+static guint32 ulcs_context_value = 0;
+static const char *object_identifier_id;
+
+static wmem_tree_t *aarq_data_tree = NULL;
+static wmem_tree_t *atn_conversation_tree = NULL;
+
+
+static proto_tree *root_tree = NULL;
+
+/* forward declarations for functions generated from asn1 */
+static int dissect_atn_ulcs_T_externalt_encoding_single_asn1_type(
+ tvbuff_t *tvb _U_,
+ int offset _U_,
+ asn1_ctx_t *actx _U_,
+ proto_tree *tree _U_,
+ int hf_index
+ _U_);
+
+static int dissect_atn_ulcs_T_externalt_encoding_octet_aligned(
+ tvbuff_t *tvb _U_,
+ int offset _U_,
+ asn1_ctx_t *actx _U_,
+ proto_tree *tree _U_,
+ int hf_index _U_);
+
+static int dissect_atn_ulcs_T_externalt_encoding_arbitrary(
+ tvbuff_t *tvb _U_,
+ int offset _U_,
+ asn1_ctx_t *actx _U_,
+ proto_tree *tree _U_,
+ int hf_index _U_);
+
+static int dissect_ACSE_apdu_PDU(
+ tvbuff_t *tvb _U_,
+ packet_info *pinfo _U_,
+ proto_tree *tree _U_,
+ void *data _U_);
+
+guint32 dissect_per_object_descriptor_t(
+ tvbuff_t *tvb,
+ guint32 offset,
+ asn1_ctx_t *actx,
+ proto_tree *tree,
+ int hf_index,
+ tvbuff_t **value_tvb);
+
+static gint dissect_atn_ulcs(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ void *data _U_);
+
+static int hf_atn_ulcs_Fully_encoded_data_PDU = -1; /* Fully_encoded_data */
+static int hf_atn_ulcs_ACSE_apdu_PDU = -1; /* ACSE_apdu */
+static int hf_atn_ulcs_Fully_encoded_data_item = -1; /* PDV_list */
+static int hf_atn_ulcs_transfer_syntax_name = -1; /* Transfer_syntax_name */
+static int hf_atn_ulcs_presentation_context_identifier = -1; /* Presentation_context_identifier */
+static int hf_atn_ulcs_presentation_data_values = -1; /* T_presentation_data_values */
+static int hf_atn_ulcs_pdv_list_presentation_data_values_single_asn1_type = -1; /* T_pdv_list_presentation_data_values_single_asn1_type */
+static int hf_atn_ulcs_octet_aligned = -1; /* OCTET_STRING */
+static int hf_atn_ulcs_pdv_list_presentation_data_values_arbitrary = -1; /* T_pdv_list_presentation_data_values_arbitrary */
+static int hf_atn_ulcs_direct_reference = -1; /* OBJECT_IDENTIFIER */
+static int hf_atn_ulcs_indirect_reference = -1; /* INTEGER */
+static int hf_atn_ulcs_data_value_descriptor = -1; /* T_data_value_descriptor */
+static int hf_atn_ulcs_encoding = -1; /* T_encoding */
+static int hf_atn_ulcs_externalt_encoding_single_asn1_type = -1; /* T_externalt_encoding_single_asn1_type */
+static int hf_atn_ulcs_externalt_encoding_octet_aligned = -1; /* T_externalt_encoding_octet_aligned */
+static int hf_atn_ulcs_externalt_encoding_arbitrary = -1; /* T_externalt_encoding_arbitrary */
+static int hf_atn_ulcs_aarq = -1; /* AARQ_apdu */
+static int hf_atn_ulcs_aare = -1; /* AARE_apdu */
+static int hf_atn_ulcs_rlrq = -1; /* RLRQ_apdu */
+static int hf_atn_ulcs_rlre = -1; /* RLRE_apdu */
+static int hf_atn_ulcs_abrt = -1; /* ABRT_apdu */
+static int hf_atn_ulcs_aarq_apdu_protocol_version = -1; /* T_aarq_apdu_protocol_version */
+static int hf_atn_ulcs_application_context_name = -1; /* Application_context_name */
+static int hf_atn_ulcs_called_AP_title = -1; /* AP_title */
+static int hf_atn_ulcs_called_AE_qualifier = -1; /* AE_qualifier */
+static int hf_atn_ulcs_called_AP_invocation_identifier = -1; /* AP_invocation_identifier */
+static int hf_atn_ulcs_called_AE_invocation_identifier = -1; /* AE_invocation_identifier */
+static int hf_atn_ulcs_calling_AP_title = -1; /* AP_title */
+static int hf_atn_ulcs_calling_AE_qualifier = -1; /* AE_qualifier */
+static int hf_atn_ulcs_calling_AP_invocation_identifier = -1; /* AP_invocation_identifier */
+static int hf_atn_ulcs_calling_AE_invocation_identifier = -1; /* AE_invocation_identifier */
+static int hf_atn_ulcs_sender_acse_requirements = -1; /* ACSE_requirements */
+static int hf_atn_ulcs_mechanism_name = -1; /* Mechanism_name */
+static int hf_atn_ulcs_calling_authentication_value = -1; /* Authentication_value */
+static int hf_atn_ulcs_application_context_name_list = -1; /* Application_context_name_list */
+static int hf_atn_ulcs_implementation_information = -1; /* Implementation_data */
+static int hf_atn_ulcs_user_information = -1; /* Association_information */
+static int hf_atn_ulcs_aare_apdu_protocol_version = -1; /* T_aare_apdu_protocol_version */
+static int hf_atn_ulcs_result = -1; /* Associate_result */
+static int hf_atn_ulcs_result_source_diagnostic = -1; /* Associate_source_diagnostic */
+static int hf_atn_ulcs_responding_AP_title = -1; /* AP_title */
+static int hf_atn_ulcs_responding_AE_qualifier = -1; /* AE_qualifier */
+static int hf_atn_ulcs_responding_AP_invocation_identifier = -1; /* AP_invocation_identifier */
+static int hf_atn_ulcs_responding_AE_invocation_identifier = -1; /* AE_invocation_identifier */
+static int hf_atn_ulcs_responder_acse_requirements = -1; /* ACSE_requirements */
+static int hf_atn_ulcs_responding_authentication_value = -1; /* Authentication_value */
+static int hf_atn_ulcs_rlrq_apdu_request_reason = -1; /* Release_request_reason */
+static int hf_atn_ulcs_rlre_apdu_response_reason = -1; /* Release_response_reason */
+static int hf_atn_ulcs_abort_source = -1; /* ABRT_source */
+static int hf_atn_ulcs_abort_diagnostic = -1; /* ABRT_diagnostic */
+static int hf_atn_ulcs_Application_context_name_list_item = -1; /* Application_context_name */
+static int hf_atn_ulcs_ap_title_form2 = -1; /* AP_title_form2 */
+static int hf_atn_ulcs_ap_title_form1 = -1; /* AP_title_form1 */
+static int hf_atn_ulcs_ae_qualifier_form2 = -1; /* AE_qualifier_form2 */
+static int hf_atn_ulcs_ae_qualifier_form1 = -1; /* AE_qualifier_form1 */
+static int hf_atn_ulcs_acse_service_user = -1; /* T_acse_service_user */
+static int hf_atn_ulcs_acse_service_provider = -1; /* T_acse_service_provider */
+static int hf_atn_ulcs_Association_information_item = -1; /* EXTERNALt */
+static int hf_atn_ulcs_charstring = -1; /* OCTET_STRING */
+static int hf_atn_ulcs_bitstring = -1; /* BIT_STRING */
+static int hf_atn_ulcs_external = -1; /* EXTERNAL */
+static int hf_atn_ulcs_other = -1; /* T_other */
+static int hf_atn_ulcs_other_mechanism_name = -1; /* OBJECT_IDENTIFIER */
+static int hf_atn_ulcs_other_mechanism_value = -1; /* T_other_mechanism_value */
+static int hf_atn_ulcs_rdnSequence = -1; /* RDNSequence */
+static int hf_atn_ulcs_RDNSequence_item = -1; /* RelativeDistinguishedName */
+static int hf_atn_ulcs_RelativeDistinguishedName_item = -1; /* AttributeTypeAndValue */
+static int hf_atn_ulcs_null = -1; /* NULL */
+/* named bits */
+static int hf_atn_ulcs_T_aarq_apdu_protocol_version_version1 = -1;
+static int hf_atn_ulcs_T_aare_apdu_protocol_version_version1 = -1;
+static int hf_atn_ulcs_ACSE_requirements_authentication = -1;
+static int hf_atn_ulcs_ACSE_requirements_application_context_negotiation = -1;
+
+static gint ett_atn_ulcs_Fully_encoded_data = -1;
+static gint ett_atn_ulcs_PDV_list = -1;
+static gint ett_atn_ulcs_T_presentation_data_values = -1;
+static gint ett_atn_ulcs_EXTERNALt = -1;
+static gint ett_atn_ulcs_T_encoding = -1;
+static gint ett_atn_ulcs_ACSE_apdu = -1;
+static gint ett_atn_ulcs_AARQ_apdu = -1;
+static gint ett_atn_ulcs_T_aarq_apdu_protocol_version = -1;
+static gint ett_atn_ulcs_AARE_apdu = -1;
+static gint ett_atn_ulcs_T_aare_apdu_protocol_version = -1;
+static gint ett_atn_ulcs_RLRQ_apdu = -1;
+static gint ett_atn_ulcs_RLRE_apdu = -1;
+static gint ett_atn_ulcs_ABRT_apdu = -1;
+static gint ett_atn_ulcs_ACSE_requirements = -1;
+static gint ett_atn_ulcs_Application_context_name_list = -1;
+static gint ett_atn_ulcs_AP_title = -1;
+static gint ett_atn_ulcs_AE_qualifier = -1;
+static gint ett_atn_ulcs_Associate_source_diagnostic = -1;
+static gint ett_atn_ulcs_Association_information = -1;
+static gint ett_atn_ulcs_Authentication_value = -1;
+static gint ett_atn_ulcs_T_other = -1;
+static gint ett_atn_ulcs_Name = -1;
+static gint ett_atn_ulcs_RDNSequence = -1;
+static gint ett_atn_ulcs_RelativeDistinguishedName = -1;
+static gint ett_atn_ulcs_AttributeTypeAndValue = -1;
+static gint ett_atn_ulcs = -1;
+static gint ett_atn_acse = -1;
+
+
+
+static int
+dissect_atn_ulcs_Transfer_syntax_name(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_object_identifier(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_Presentation_context_identifier_vals[] = {
+ { 1, "acse-apdu" },
+ { 2, "reserved" },
+ { 3, "user-ase-apdu" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_atn_ulcs_Presentation_context_identifier(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ offset = dissect_per_constrained_integer(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ 1U,
+ 127U,
+ &ulcs_context_value,
+ TRUE);
+
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_T_pdv_list_presentation_data_values_single_asn1_type(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_open_type(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_OCTET_STRING(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_octet_string(tvb, offset, actx, tree, hf_index,
+ NO_BOUND, NO_BOUND, FALSE, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_T_pdv_list_presentation_data_values_arbitrary(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ packet_info * pinfo = actx->pinfo;
+ tvbuff_t *tvb_usr = NULL;
+ proto_tree *atn_ulcs_tree = NULL;
+ atn_conversation_t *atn_cv = NULL;
+ heur_dtbl_entry_t *hdtbl_entry;
+
+ /* extract bitstring into new tvb buffer */
+ offset = dissect_per_bit_string(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ NO_BOUND,
+ NO_BOUND,
+ FALSE,
+ NULL,
+ 0,
+ &tvb_usr,
+ NULL);
+
+ if (tvb_usr) {
+ /* call appropiate dissector for bitstring data */
+ switch(ulcs_context_value){
+ case 1: /* ACSE PDU*/
+ atn_ulcs_tree = proto_tree_add_subtree(
+ root_tree, tvb, offset, 0,
+ ett_atn_acse, NULL, ATN_ACSE_PROTO );
+
+ dissect_ACSE_apdu_PDU(
+ tvb_new_subset_remaining(tvb_usr, 0),
+ pinfo,
+ atn_ulcs_tree, NULL);
+ break;
+ case 3: /* USER data; call subdissector for CM, CPDLC ... */
+
+ /* using dstref for PDV-list only occurrs in DT */
+ atn_cv = find_atn_conversation(
+ &pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src);
+
+ if(atn_cv) {
+ switch(atn_cv->ae_qualifier){
+ case cma: /* contact management */
+ call_dissector_with_data(
+ atn_cm_handle,
+ tvb_new_subset_remaining(tvb_usr, 0),
+ pinfo,
+ root_tree,
+ NULL);
+ break;
+ case cpdlc: /* plain old cpdlc */
+ case pmcpdlc: /* protected mode cpdlc */
+ call_dissector_with_data(
+ atn_cpdlc_handle,
+ tvb_new_subset_remaining(tvb_usr, 0),
+ pinfo,
+ root_tree,
+ NULL);
+ break;
+ default: /* unknown or unhandled datalink application */
+ dissector_try_heuristic(
+ atn_ulcs_heur_subdissector_list,
+ tvb_new_subset_remaining(tvb_usr,0),
+ actx->pinfo,
+ root_tree,
+ &hdtbl_entry,
+ NULL);
+ break;
+ }
+ }
+ else{
+ dissector_try_heuristic(
+ atn_ulcs_heur_subdissector_list,
+ tvb_new_subset_remaining(tvb_usr,0),
+ actx->pinfo,
+ root_tree,
+ &hdtbl_entry,
+ NULL);
+ }
+ break;
+ default:
+ break;
+ } /* switch(ulcs_context_value) */
+ }
+
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_T_presentation_data_values_vals[] = {
+ { 0, "single-ASN1-type" },
+ { 1, "octet-aligned" },
+ { 2, "arbitrary" },
+ { 0, NULL }
+};
+
+static const per_choice_t T_presentation_data_values_choice[] = {
+ { 0, &hf_atn_ulcs_pdv_list_presentation_data_values_single_asn1_type, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_pdv_list_presentation_data_values_single_asn1_type },
+ { 1, &hf_atn_ulcs_octet_aligned, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_OCTET_STRING },
+ { 2, &hf_atn_ulcs_pdv_list_presentation_data_values_arbitrary, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_pdv_list_presentation_data_values_arbitrary },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_T_presentation_data_values(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_T_presentation_data_values, T_presentation_data_values_choice,
+ NULL);
+
+ return offset;
+}
+
+
+static const per_sequence_t PDV_list_sequence[] = {
+ { &hf_atn_ulcs_transfer_syntax_name, ASN1_NO_EXTENSIONS , ASN1_OPTIONAL , dissect_atn_ulcs_Transfer_syntax_name },
+ { &hf_atn_ulcs_presentation_context_identifier, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_Presentation_context_identifier },
+ { &hf_atn_ulcs_presentation_data_values, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_T_presentation_data_values },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_PDV_list(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_PDV_list, PDV_list_sequence);
+
+ return offset;
+}
+
+
+static const per_sequence_t Fully_encoded_data_sequence_of[1] = {
+ { &hf_atn_ulcs_Fully_encoded_data_item, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_PDV_list },
+};
+
+static int
+dissect_atn_ulcs_Fully_encoded_data(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_constrained_sequence_of(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_Fully_encoded_data, Fully_encoded_data_sequence_of,
+ 1, 1, TRUE);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_OBJECT_IDENTIFIER(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_object_identifier(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_INTEGER(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_integer(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_T_data_value_descriptor(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ offset = dissect_per_octet_string(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ -1,
+ -1,
+ FALSE,
+ &actx->external.data_value_descriptor);
+ actx->external.data_value_descr_present = TRUE;
+
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_T_externalt_encoding_single_asn1_type(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ offset = dissect_per_open_type(tvb, offset, actx, tree, hf_index, NULL);
+
+
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_T_externalt_encoding_octet_aligned(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ offset = dissect_per_octet_string(tvb, offset, actx, tree, hf_index,
+ NO_BOUND, NO_BOUND, FALSE, NULL);
+
+
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_T_externalt_encoding_arbitrary(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ tvbuff_t *tvb_usr = NULL;
+ packet_info * pinfo = actx->pinfo;
+ atn_conversation_t *atn_cv = NULL;
+ heur_dtbl_entry_t *hdtbl_entry;
+
+ /* decode bit-string user data within ACSE */
+ offset = dissect_per_bit_string(
+ tvb,
+ offset,
+ actx,
+ tree, hf_index,
+ NO_BOUND,
+ NO_BOUND,
+ FALSE,
+ NULL,
+ 0,
+ &tvb_usr,
+ NULL);
+
+ if (tvb_usr) {
+ /* DT: dstref present, srcref is always zero */
+ if((pinfo->clnp_dstref) && (!pinfo->clnp_srcref)){
+
+ atn_cv = find_atn_conversation(
+ &pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src);
+ }
+ /* CR: srcref present, dstref always zero */
+ if((pinfo->clnp_srcref) && (!pinfo->clnp_dstref)){
+
+ atn_cv = find_atn_conversation(
+ &pinfo->src,
+ pinfo->clnp_srcref,
+ &pinfo->dst);
+ }
+ /* CC: srcref and dstref present */
+ if((pinfo->clnp_srcref) && (pinfo->clnp_dstref)){
+
+ atn_cv = find_atn_conversation(
+ &pinfo->src,
+ pinfo->clnp_srcref,
+ &pinfo->dst);
+ }
+
+ if(atn_cv) {
+ switch(atn_cv->ae_qualifier){
+ case cma: /* contact management */
+
+ call_dissector_with_data(
+ atn_cm_handle,
+ tvb_new_subset_remaining(tvb_usr, 0),
+ pinfo,
+ root_tree,
+ NULL);
+ break;
+ case cpdlc: /* plain old cpdlc */
+ case pmcpdlc: /* protected mode cpdlc */
+
+ call_dissector_with_data(
+ atn_cpdlc_handle,
+ tvb_new_subset_remaining(tvb_usr, 0),
+ pinfo,
+ root_tree,
+ NULL);
+ break;
+ default: /* unknown or unhandled datalink application */
+
+ dissector_try_heuristic(
+ atn_ulcs_heur_subdissector_list,
+ tvb_new_subset_remaining(tvb_usr,0),
+ actx->pinfo,
+ root_tree,
+ &hdtbl_entry,
+ NULL);
+ break;
+ }
+ }else {
+
+ dissector_try_heuristic(
+ atn_ulcs_heur_subdissector_list,
+ tvb_new_subset_remaining(tvb_usr,0),
+ actx->pinfo,
+ root_tree,
+ &hdtbl_entry,
+ NULL);
+ }
+ }
+
+ offset += tvb_reported_length_remaining(tvb, offset);
+
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_T_encoding_vals[] = {
+ { 0, "single-ASN1-type" },
+ { 1, "octet-aligned" },
+ { 2, "arbitrary" },
+ { 0, NULL }
+};
+
+static const per_choice_t T_encoding_choice[] = {
+ { 0, &hf_atn_ulcs_externalt_encoding_single_asn1_type, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_externalt_encoding_single_asn1_type },
+ { 1, &hf_atn_ulcs_externalt_encoding_octet_aligned, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_externalt_encoding_octet_aligned },
+ { 2, &hf_atn_ulcs_externalt_encoding_arbitrary, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_externalt_encoding_arbitrary },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_T_encoding(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_T_encoding, T_encoding_choice,
+ NULL);
+
+ return offset;
+}
+
+
+static const per_sequence_t EXTERNALt_sequence[] = {
+ { &hf_atn_ulcs_direct_reference, ASN1_NO_EXTENSIONS , ASN1_OPTIONAL , dissect_atn_ulcs_OBJECT_IDENTIFIER },
+ { &hf_atn_ulcs_indirect_reference, ASN1_NO_EXTENSIONS , ASN1_OPTIONAL , dissect_atn_ulcs_INTEGER },
+ { &hf_atn_ulcs_data_value_descriptor, ASN1_NO_EXTENSIONS , ASN1_OPTIONAL , dissect_atn_ulcs_T_data_value_descriptor },
+ { &hf_atn_ulcs_encoding , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_T_encoding },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_EXTERNALt(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_EXTERNALt, EXTERNALt_sequence);
+
+ return offset;
+}
+
+
+static int * const T_aarq_apdu_protocol_version_bits[] = {
+ &hf_atn_ulcs_T_aarq_apdu_protocol_version_version1,
+ NULL
+};
+
+static int
+dissect_atn_ulcs_T_aarq_apdu_protocol_version(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
+ NO_BOUND, NO_BOUND, FALSE, T_aarq_apdu_protocol_version_bits, 1, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_Application_context_name(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_object_identifier(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_AP_title_form2(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_object_identifier(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_NULL(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_null(tvb, offset, actx, tree, hf_index);
+
+ return offset;
+}
+
+
+static const per_sequence_t AttributeTypeAndValue_sequence[] = {
+ { &hf_atn_ulcs_null , ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_NULL },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_AttributeTypeAndValue(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_AttributeTypeAndValue, AttributeTypeAndValue_sequence);
+
+ return offset;
+}
+
+
+static const per_sequence_t RelativeDistinguishedName_set_of[1] = {
+ { &hf_atn_ulcs_RelativeDistinguishedName_item, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_AttributeTypeAndValue },
+};
+
+static int
+dissect_atn_ulcs_RelativeDistinguishedName(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ /*
+ * Dissect the first null item only, similar to RDNSequence.
+ */
+ offset = dissect_per_constrained_set_of(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_RelativeDistinguishedName, RelativeDistinguishedName_set_of,
+ 1, 1, FALSE);
+
+
+ return offset;
+}
+
+
+static const per_sequence_t RDNSequence_sequence_of[1] = {
+ { &hf_atn_ulcs_RDNSequence_item, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_RelativeDistinguishedName },
+};
+
+static int
+dissect_atn_ulcs_RDNSequence(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ /*
+ * atn-ulcs.asn currently defines
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ * RelativeDistinguishedName ::= SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+ * AttributeTypeAndValue ::= SEQUENCE { null NULL}
+ *
+ * which makes it easy to spam the dissection tree with null items. Dissect
+ * the first item only.
+ */
+ offset = dissect_per_constrained_sequence_of(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_RDNSequence, RDNSequence_sequence_of,
+ 1, 1, FALSE);
+
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_Name_vals[] = {
+ { 0, "rdnSequence" },
+ { 0, NULL }
+};
+
+static const per_choice_t Name_choice[] = {
+ { 0, &hf_atn_ulcs_rdnSequence, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_RDNSequence },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_Name(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_Name, Name_choice,
+ NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_AP_title_form1(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_atn_ulcs_Name(tvb, offset, actx, tree, hf_index);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_AP_title_vals[] = {
+ { 0, "ap-title-form2" },
+ { 1, "ap-title-form1" },
+ { 0, NULL }
+};
+
+static const per_choice_t AP_title_choice[] = {
+ { 0, &hf_atn_ulcs_ap_title_form2, ASN1_EXTENSION_ROOT , dissect_atn_ulcs_AP_title_form2 },
+ { 1, &hf_atn_ulcs_ap_title_form1, ASN1_EXTENSION_ROOT , dissect_atn_ulcs_AP_title_form1 },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_AP_title(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_AP_title, AP_title_choice,
+ NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_AE_qualifier_form2(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ packet_info * pinfo = actx->pinfo;
+ atn_conversation_t *atn_cv = NULL;
+ guint32 ae_qualifier = 0;
+
+ /* dissect ae-qualifier */
+ offset = dissect_per_integer(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ &ae_qualifier);
+
+
+ /*note: */
+ /* the field "calling-AE-qualifier" is optional, */
+ /* which means that we can exploit it only if it is present. */
+ /* We still depend on heuristical decoding of CM, CPDLC PDU's otherwise. */
+
+ /* AARQ/DT: dstref present, srcref is always zero */
+ if((pinfo->clnp_dstref) && (!pinfo->clnp_srcref)){
+ atn_cv = find_atn_conversation(&pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src );
+ }
+
+ /* AARQ/CR: srcref present, dstref is always zero */
+ if((!pinfo->clnp_dstref) && (pinfo->clnp_srcref)){
+ atn_cv = find_atn_conversation(&pinfo->src,
+ pinfo->clnp_srcref,
+ &pinfo->dst );
+ }
+
+ if(atn_cv){
+ atn_cv->ae_qualifier = ae_qualifier;
+ }
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_AE_qualifier_form1(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_atn_ulcs_RelativeDistinguishedName(tvb, offset, actx, tree, hf_index);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_AE_qualifier_vals[] = {
+ { 0, "ae-qualifier-form2" },
+ { 1, "ae-qualifier-form1" },
+ { 0, NULL }
+};
+
+static const per_choice_t AE_qualifier_choice[] = {
+ { 0, &hf_atn_ulcs_ae_qualifier_form2, ASN1_EXTENSION_ROOT , dissect_atn_ulcs_AE_qualifier_form2 },
+ { 1, &hf_atn_ulcs_ae_qualifier_form1, ASN1_EXTENSION_ROOT , dissect_atn_ulcs_AE_qualifier_form1 },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_AE_qualifier(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_AE_qualifier, AE_qualifier_choice,
+ NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_AP_invocation_identifier(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_integer(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_AE_invocation_identifier(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_integer(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+static int * const ACSE_requirements_bits[] = {
+ &hf_atn_ulcs_ACSE_requirements_authentication,
+ &hf_atn_ulcs_ACSE_requirements_application_context_negotiation,
+ NULL
+};
+
+static int
+dissect_atn_ulcs_ACSE_requirements(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
+ NO_BOUND, NO_BOUND, FALSE, ACSE_requirements_bits, 2, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_Mechanism_name(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ offset = dissect_per_object_identifier(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ NULL);
+
+
+ offset = dissect_per_object_identifier(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ NULL);
+
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_BIT_STRING(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
+ NO_BOUND, NO_BOUND, FALSE, NULL, 0, NULL, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_EXTERNAL(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_external_type(tvb, offset, actx, tree, hf_index, NULL);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_T_other_mechanism_value(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ offset=call_ber_oid_callback(
+ object_identifier_id,
+ tvb,
+ offset,
+ actx->pinfo,
+ tree, NULL);
+
+
+ offset=call_ber_oid_callback(
+ object_identifier_id,
+ tvb,
+ offset,
+ actx->pinfo,
+ tree, NULL);
+
+
+ return offset;
+}
+
+
+static const per_sequence_t T_other_sequence[] = {
+ { &hf_atn_ulcs_other_mechanism_name, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_OBJECT_IDENTIFIER },
+ { &hf_atn_ulcs_other_mechanism_value, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_T_other_mechanism_value },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_T_other(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_T_other, T_other_sequence);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_Authentication_value_vals[] = {
+ { 0, "charstring" },
+ { 1, "bitstring" },
+ { 2, "external" },
+ { 3, "other" },
+ { 0, NULL }
+};
+
+static const per_choice_t Authentication_value_choice[] = {
+ { 0, &hf_atn_ulcs_charstring , ASN1_NO_EXTENSIONS , dissect_atn_ulcs_OCTET_STRING },
+ { 1, &hf_atn_ulcs_bitstring , ASN1_NO_EXTENSIONS , dissect_atn_ulcs_BIT_STRING },
+ { 2, &hf_atn_ulcs_external , ASN1_NO_EXTENSIONS , dissect_atn_ulcs_EXTERNAL },
+ { 3, &hf_atn_ulcs_other , ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_other },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_Authentication_value(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_Authentication_value, Authentication_value_choice,
+ NULL);
+
+ return offset;
+}
+
+
+static const per_sequence_t Application_context_name_list_sequence_of[1] = {
+ { &hf_atn_ulcs_Application_context_name_list_item, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_Application_context_name },
+};
+
+static int
+dissect_atn_ulcs_Application_context_name_list(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence_of(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_Application_context_name_list, Application_context_name_list_sequence_of);
+
+ return offset;
+}
+
+
+
+static int
+dissect_atn_ulcs_Implementation_data(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_octet_string(tvb, offset, actx, tree, hf_index,
+ NO_BOUND, NO_BOUND, FALSE, NULL);
+
+ return offset;
+}
+
+
+static const per_sequence_t Association_information_sequence_of[1] = {
+ { &hf_atn_ulcs_Association_information_item, ASN1_NO_EXTENSIONS , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_EXTERNALt },
+};
+
+static int
+dissect_atn_ulcs_Association_information(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_constrained_sequence_of(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_Association_information, Association_information_sequence_of,
+ 1, 1, TRUE);
+
+ return offset;
+}
+
+
+static const per_sequence_t AARQ_apdu_sequence[] = {
+ { &hf_atn_ulcs_aarq_apdu_protocol_version, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_T_aarq_apdu_protocol_version },
+ { &hf_atn_ulcs_application_context_name, ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_Application_context_name },
+ { &hf_atn_ulcs_called_AP_title, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AP_title },
+ { &hf_atn_ulcs_called_AE_qualifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AE_qualifier },
+ { &hf_atn_ulcs_called_AP_invocation_identifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AP_invocation_identifier },
+ { &hf_atn_ulcs_called_AE_invocation_identifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AE_invocation_identifier },
+ { &hf_atn_ulcs_calling_AP_title, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AP_title },
+ { &hf_atn_ulcs_calling_AE_qualifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AE_qualifier },
+ { &hf_atn_ulcs_calling_AP_invocation_identifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AP_invocation_identifier },
+ { &hf_atn_ulcs_calling_AE_invocation_identifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AE_invocation_identifier },
+ { &hf_atn_ulcs_sender_acse_requirements, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_ACSE_requirements },
+ { &hf_atn_ulcs_mechanism_name, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Mechanism_name },
+ { &hf_atn_ulcs_calling_authentication_value, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Authentication_value },
+ { &hf_atn_ulcs_application_context_name_list, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Application_context_name_list },
+ { &hf_atn_ulcs_implementation_information, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Implementation_data },
+ { &hf_atn_ulcs_user_information, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Association_information },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_AARQ_apdu(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ packet_info * pinfo = actx->pinfo;
+ aarq_data_t *aarq_data = NULL;
+ atn_conversation_t *atn_cv = NULL;
+ guint32 aircraft_24_bit_address = 0;
+
+ /* AARQ/DT: dstref present, srcref is always zero */
+ if((pinfo->clnp_dstref) && (!pinfo->clnp_srcref)){
+
+ atn_cv = find_atn_conversation(
+ &pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src );
+ if(!atn_cv){
+ atn_cv = wmem_new(wmem_file_scope(), atn_conversation_t);
+ atn_cv->ae_qualifier = unknown;
+ create_atn_conversation(&pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src ,
+ atn_cv);
+ }
+ }
+
+ /* AARQ/CR: srcref present, dstref is always zero */
+ if((!pinfo->clnp_dstref) && (pinfo->clnp_srcref)){
+ atn_cv = find_atn_conversation(&pinfo->src,
+ pinfo->clnp_srcref,
+ &pinfo->dst );
+ if(!atn_cv){
+ atn_cv = wmem_new(wmem_file_scope(), atn_conversation_t);
+ atn_cv->ae_qualifier = unknown;
+ create_atn_conversation(&pinfo->src,
+ pinfo->clnp_srcref,
+ &pinfo->dst ,
+ atn_cv);
+ }
+ }
+
+ /* conversation is to be created prior to decoding */
+ /* of "AE-qualifier-form2" which takes place here: */
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_AARQ_apdu, AARQ_apdu_sequence);
+
+
+
+ /* save AARQ packet data to create a conversation */
+ /* when decoding the following AARE PDU */
+ /* ATN applications CM and CPDLC are air/ground applications */
+ /* so there is always an aircraft (with its 24-bit address) */
+ /* and a ground facility. */
+ /* the assumption is that there is only one open AARQ/AARE */
+ /* dialog per aircraft at a time. */
+ /* the aircraft's 24-bit address is used as a key to each AARQ */
+ /* data. AARQ data is used to create a conversation with */
+ /* air and ground endpoints (based on NSAP's and transport references) */
+ /* when decoding AARE.*/
+ /* note: */
+ /* it may be more robust to create the conversation */
+ /* in the "ositp" dissector an to merely use the conversation here */
+ aircraft_24_bit_address =
+ get_aircraft_24_bit_address_from_nsap(pinfo);
+
+ /* search for aarq entry */
+ aarq_data = (aarq_data_t *) wmem_tree_lookup32(
+ aarq_data_tree,
+ aircraft_24_bit_address);
+
+ if(!aarq_data){ /* aarq data not found, create new record */
+
+ /* alloc aarq data */
+ aarq_data = wmem_new(wmem_file_scope(), aarq_data_t);
+ aarq_data-> aarq_pending = FALSE;
+
+ /* insert aarq data */
+ wmem_tree_insert32(aarq_data_tree ,aircraft_24_bit_address,(void*)aarq_data);
+ }
+
+ /* check for pending AARQ/AARE sequences */
+ /* if "aarq_data-> aarq_pending" is set this means that there is already one */
+ /* AARQ/AARE sequence pending (is unwise to overwrite AARE/AARQ) */
+ if (aarq_data-> aarq_pending == FALSE ) {
+
+ /* init aarq data */
+ memset(aarq_data,0,sizeof(aarq_data_t));
+
+ aarq_data->cv = atn_cv;
+ aarq_data-> aarq_pending = TRUE;
+ }
+
+
+ return offset;
+}
+
+
+static int * const T_aare_apdu_protocol_version_bits[] = {
+ &hf_atn_ulcs_T_aare_apdu_protocol_version_version1,
+ NULL
+};
+
+static int
+dissect_atn_ulcs_T_aare_apdu_protocol_version(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_bit_string(tvb, offset, actx, tree, hf_index,
+ NO_BOUND, NO_BOUND, FALSE, T_aare_apdu_protocol_version_bits, 1, NULL, NULL);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_Associate_result_vals[] = {
+ { 0, "accepted" },
+ { 1, "rejected-permanent" },
+ { 2, "rejected-transient" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_atn_ulcs_Associate_result(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ /* extension present: last param set to true. asn2wrs didn't take notice of that */
+ offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index,
+ 0U, 2U, NULL, TRUE);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_T_acse_service_user_vals[] = {
+ { 0, "null" },
+ { 1, "no-reason-given" },
+ { 2, "application-context-name-not-supported" },
+ { 3, "calling-AP-title-not-recognized" },
+ { 4, "calling-AP-invocation-identifier-not-recognized" },
+ { 5, "calling-AE-qualifier-not-recognized" },
+ { 6, "calling-AE-invocation-identifier-not-recognized" },
+ { 7, "called-AP-title-not-recognized" },
+ { 8, "called-AP-invocation-identifier-not-recognized" },
+ { 9, "called-AE-qualifier-not-recognized" },
+ { 10, "called-AE-invocation-identifier-not-recognized" },
+ { 11, "authentication-mechanism-name-not-recognized" },
+ { 12, "authentication-mechanism-name-required" },
+ { 13, "authentication-failure" },
+ { 14, "authentication-required" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_atn_ulcs_T_acse_service_user(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index,
+ 0U, 14U, NULL, TRUE);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_T_acse_service_provider_vals[] = {
+ { 0, "null" },
+ { 1, "no-reason-given" },
+ { 2, "no-common-acse-version" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_atn_ulcs_T_acse_service_provider(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index,
+ 0U, 2U, NULL, TRUE);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_Associate_source_diagnostic_vals[] = {
+ { 1, "acse-service-user" },
+ { 2, "acse-service-provider" },
+ { 0, NULL }
+};
+
+static const per_choice_t Associate_source_diagnostic_choice[] = {
+ { 1, &hf_atn_ulcs_acse_service_user, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_acse_service_user },
+ { 2, &hf_atn_ulcs_acse_service_provider, ASN1_NO_EXTENSIONS , dissect_atn_ulcs_T_acse_service_provider },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_Associate_source_diagnostic(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_Associate_source_diagnostic, Associate_source_diagnostic_choice,
+ NULL);
+
+ return offset;
+}
+
+
+static const per_sequence_t AARE_apdu_sequence[] = {
+ { &hf_atn_ulcs_aare_apdu_protocol_version, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_T_aare_apdu_protocol_version },
+ { &hf_atn_ulcs_application_context_name, ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_Application_context_name },
+ { &hf_atn_ulcs_result , ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_Associate_result },
+ { &hf_atn_ulcs_result_source_diagnostic, ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_Associate_source_diagnostic },
+ { &hf_atn_ulcs_responding_AP_title, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AP_title },
+ { &hf_atn_ulcs_responding_AE_qualifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AE_qualifier },
+ { &hf_atn_ulcs_responding_AP_invocation_identifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AP_invocation_identifier },
+ { &hf_atn_ulcs_responding_AE_invocation_identifier, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_AE_invocation_identifier },
+ { &hf_atn_ulcs_responder_acse_requirements, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_ACSE_requirements },
+ { &hf_atn_ulcs_mechanism_name, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Mechanism_name },
+ { &hf_atn_ulcs_responding_authentication_value, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Authentication_value },
+ { &hf_atn_ulcs_application_context_name_list, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Application_context_name_list },
+ { &hf_atn_ulcs_implementation_information, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Implementation_data },
+ { &hf_atn_ulcs_user_information, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Association_information },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_AARE_apdu(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ packet_info * pinfo = actx->pinfo;
+ guint32 aircraft_24_bit_address = 0 ;
+ atn_conversation_t *atn_cv = NULL;
+ aarq_data_t *aarq_data = NULL;
+
+ /* get AARQ data and use it to create a new conversation, */
+ /* the conversation is used along with */
+ /* AARQ's "calling ae qualifier" to determine the */
+ /* type of air/ground application of each subsequent frame.*/
+ /* we use this information to invoke the correct application dissector. */
+ /* note: */
+ /* heuristical decoding of ASN1 will not work for all cases, */
+ /* for there may be CM PDU's which will exactly look like CPDLC PDU'S */
+
+ /* get 24-bit icao address */
+ aircraft_24_bit_address = get_aircraft_24_bit_address_from_nsap(pinfo);
+
+ /* search for aarq entry */
+ aarq_data = (aarq_data_t *) wmem_tree_lookup32(
+ aarq_data_tree,
+ aircraft_24_bit_address);
+
+ /* no aarq data present, do nothing */
+ /* without both ends of the conversation and without */
+ /* the "calling ae-qualifier there is no point in setting up "*/
+ /* a conversation */
+ if(!aarq_data) {
+
+ return offset;
+ }
+
+ /* AARE/DT: dstref present, srcref is always zero */
+ if((pinfo->clnp_dstref) && (!pinfo->clnp_srcref)){
+
+ atn_cv = find_atn_conversation(&pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src );
+
+ if(!atn_cv){ /* conversation not fond */
+
+ /* DT has only dstref - create new conversation */
+ create_atn_conversation(&pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src ,
+ aarq_data->cv);
+ }
+ }
+
+ /* AARE/CC: srcref and dstref present */
+ if((pinfo->clnp_dstref) && (pinfo->clnp_srcref)){
+
+ atn_cv = find_atn_conversation(
+ &pinfo->src,
+ pinfo->clnp_srcref,
+ &pinfo->dst);
+
+ if(atn_cv){ /* conversation found. */
+
+ /* create new conversation for dstref */
+ create_atn_conversation(&pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src ,
+ aarq_data->cv);
+
+ }else { /* no conversation found */
+ /* as CC contains srcref *and* dstref we use both to create new records */
+ create_atn_conversation(&pinfo->src,
+ pinfo->clnp_srcref,
+ &pinfo->dst ,
+ aarq_data->cv);
+ create_atn_conversation(&pinfo->dst,
+ pinfo->clnp_dstref,
+ &pinfo->src ,
+ aarq_data->cv);
+ }
+ }
+
+ /* clear aarq data */
+ memset(aarq_data,0,sizeof(aarq_data_t));
+ aarq_data-> aarq_pending = FALSE;
+
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_AARE_apdu, AARE_apdu_sequence);
+
+
+
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_Release_request_reason_vals[] = {
+ { 0, "normal" },
+ { 1, "urgent" },
+ { 30, "user-defined" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_atn_ulcs_Release_request_reason(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ /* extension present: last param set to true. asn2wrs didn't take notice of that */
+ offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index,
+ 0U, 30U, NULL, TRUE);
+
+ return offset;
+}
+
+
+static const per_sequence_t RLRQ_apdu_sequence[] = {
+ { &hf_atn_ulcs_rlrq_apdu_request_reason, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Release_request_reason },
+ { &hf_atn_ulcs_user_information, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Association_information },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_RLRQ_apdu(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_RLRQ_apdu, RLRQ_apdu_sequence);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_Release_response_reason_vals[] = {
+ { 0, "normal" },
+ { 1, "not-finished" },
+ { 30, "user-defined" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_atn_ulcs_Release_response_reason(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+
+ /* extension present: last param set to true. asn2wrs didn't take notice of that */
+ offset = dissect_per_constrained_integer(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ 0U,
+ 30U,
+ NULL,
+ TRUE);
+
+
+ return offset;
+}
+
+
+static const per_sequence_t RLRE_apdu_sequence[] = {
+ { &hf_atn_ulcs_rlre_apdu_response_reason, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Release_response_reason },
+ { &hf_atn_ulcs_user_information, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Association_information },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_RLRE_apdu(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_RLRE_apdu, RLRE_apdu_sequence);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_ABRT_source_vals[] = {
+ { 0, "acse-service-user" },
+ { 1, "acse-service-provider" },
+ { 0, NULL }
+};
+
+
+static int
+dissect_atn_ulcs_ABRT_source(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index,
+ 0U, 1U, NULL, TRUE);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_ABRT_diagnostic_vals[] = {
+ { 1, "no-reason-given" },
+ { 2, "protocol-error" },
+ { 3, "authentication-mechanism-name-not-recognized" },
+ { 4, "authentication-mechanism-name-required" },
+ { 5, "authentication-failure" },
+ { 6, "authentication-required" },
+ { 0, NULL }
+};
+
+static uint32_t ABRT_diagnostic_value_map[6+0] = {1, 2, 3, 4, 5, 6};
+
+static int
+dissect_atn_ulcs_ABRT_diagnostic(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_enumerated(tvb, offset, actx, tree, hf_index,
+ 6, NULL, TRUE, 0, ABRT_diagnostic_value_map);
+
+ return offset;
+}
+
+
+static const per_sequence_t ABRT_apdu_sequence[] = {
+ { &hf_atn_ulcs_abort_source, ASN1_EXTENSION_ROOT , ASN1_NOT_OPTIONAL, dissect_atn_ulcs_ABRT_source },
+ { &hf_atn_ulcs_abort_diagnostic, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_ABRT_diagnostic },
+ { &hf_atn_ulcs_user_information, ASN1_EXTENSION_ROOT , ASN1_OPTIONAL , dissect_atn_ulcs_Association_information },
+ { NULL, 0, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_ABRT_apdu(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_ABRT_apdu, ABRT_apdu_sequence);
+
+ return offset;
+}
+
+
+static const value_string atn_ulcs_ACSE_apdu_vals[] = {
+ { 0, "aarq" },
+ { 1, "aare" },
+ { 2, "rlrq" },
+ { 3, "rlre" },
+ { 4, "abrt" },
+ { 0, NULL }
+};
+
+static const per_choice_t ACSE_apdu_choice[] = {
+ { 0, &hf_atn_ulcs_aarq , ASN1_EXTENSION_ROOT , dissect_atn_ulcs_AARQ_apdu },
+ { 1, &hf_atn_ulcs_aare , ASN1_EXTENSION_ROOT , dissect_atn_ulcs_AARE_apdu },
+ { 2, &hf_atn_ulcs_rlrq , ASN1_EXTENSION_ROOT , dissect_atn_ulcs_RLRQ_apdu },
+ { 3, &hf_atn_ulcs_rlre , ASN1_EXTENSION_ROOT , dissect_atn_ulcs_RLRE_apdu },
+ { 4, &hf_atn_ulcs_abrt , ASN1_EXTENSION_ROOT , dissect_atn_ulcs_ABRT_apdu },
+ { 0, NULL, 0, NULL }
+};
+
+static int
+dissect_atn_ulcs_ACSE_apdu(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+ offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
+ ett_atn_ulcs_ACSE_apdu, ACSE_apdu_choice,
+ NULL);
+
+ return offset;
+}
+
+/*--- PDUs ---*/
+
+static int dissect_Fully_encoded_data_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_) {
+ int offset = 0;
+ asn1_ctx_t asn1_ctx;
+ asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, FALSE, pinfo);
+ offset = dissect_atn_ulcs_Fully_encoded_data(tvb, offset, &asn1_ctx, tree, hf_atn_ulcs_Fully_encoded_data_PDU);
+ offset += 7; offset >>= 3;
+ return offset;
+}
+static int dissect_ACSE_apdu_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_) {
+ int offset = 0;
+ asn1_ctx_t asn1_ctx;
+ asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, FALSE, pinfo);
+ offset = dissect_atn_ulcs_ACSE_apdu(tvb, offset, &asn1_ctx, tree, hf_atn_ulcs_ACSE_apdu_PDU);
+ offset += 7; offset >>= 3;
+ return offset;
+}
+
+
+#if 0
+/* re-implementing external data: packet-per.c */
+static const value_string per_External_encoding_vals[] = {
+{ 0, "single-ASN1-type" },
+{ 1, "octet-aligned" },
+{ 2, "arbitrary" },
+{ 0, NULL }
+};
+
+/* re-implementing external data: packet-per.c */
+static const per_choice_t External_encoding_choice[] =
+{
+ { 0,
+ &hf_atn_ulcs_externalt_encoding_single_asn1_type,
+ ASN1_NO_EXTENSIONS,
+ dissect_atn_ulcs_T_externalt_encoding_single_asn1_type
+ },
+ { 1,
+ &hf_atn_ulcs_externalt_encoding_octet_aligned,
+ ASN1_NO_EXTENSIONS,
+ dissect_atn_ulcs_T_externalt_encoding_octet_aligned
+ },
+ { 2,
+ &hf_atn_ulcs_externalt_encoding_arbitrary,
+ ASN1_NO_EXTENSIONS,
+ dissect_atn_ulcs_T_externalt_encoding_arbitrary
+ },
+ { 0,
+ NULL,
+ 0,
+ NULL
+ }
+};
+#endif
+
+/* ATN Session layer */
+#define SES_PDU_TYPE_MASK 0xf8
+#define SES_PARAM_IND_MASK 0x04
+#define SES_PARAM_B2_MASK 0x02
+#define SES_PARAM_B1_MASK 0x01
+
+static int hf_atn_ses_type = -1;
+static int hf_atn_ses_param_ind = -1;
+static int hf_atn_ses_param_b1 = -1;
+static int hf_atn_ses_param_b2 = -1;
+
+static gint ett_atn_ses = -1;
+
+#define ATN_SES_PROTO "ICAO Doc9705 ULCS Session (ISO 8326/8327-1:1994)"
+
+const value_string atn_ses_param_ind[] =
+{
+ {0, "No Parameter Indication "},
+ {1, "Parameter Indication "},
+ {0, NULL }
+};
+
+const value_string srf_b2[] =
+{
+ {0, "Transport Connection is kept"},
+ {1, "Transport Connection is released" },
+ {0, NULL }
+};
+
+const value_string srf_b1[] =
+{
+ {0, "Transport Connection is transient"},
+ {1, "Transport Connection is persistent"},
+ {0, NULL }
+};
+
+#define SES_ATN_SCN 0xe8
+#define SES_ATN_SCNC 0xf8
+#define SES_ATN_SAC 0xf0
+#define SES_ATN_SACC 0xd8
+#define SES_ATN_SRF 0xe0
+#define SES_ATN_SRFC 0xa0
+
+const value_string atn_ses_type[] =
+{
+ { 0x1d, "Short Connect (SCN) SPDU" },
+ { 0x1f, "Short Connect Accept (SAC) SPDU" },
+ { 0x1e, "Short Connect Accept Continue (SACC) SPDU" },
+ { 0x1c, "Short Refuse (SRF) SPDU" },
+ { 0x14, "Short Refuse Continue (SRFC) SPDU" },
+ {0, NULL }
+};
+
+/* ATN Presentation layer */
+#define ATN_PRES_PROTO "ICAO Doc9705 ULCS Presentation (ISO 8822/8823-1:1994)"
+
+static int hf_atn_pres_err = -1;
+static int hf_atn_pres_pdu_type = -1;
+static gint ett_atn_pres = -1;
+
+#define ATN_SES_PRES_MASK 0xf803
+#define PRES_CPR_ER_MASK 0x70
+
+/* type determined by SPDU and PPDU */
+const value_string atn_pres_vals[] =
+{
+ { 0xe802, "Short Presentation Connect PPDU (CP) " },
+ { 0xf802, "Short Presentation Connect PPDU (CP) " },
+ { 0xf002, "Short Presentation Connect Accept PPDU (CPA)" },
+ { 0xd802, "Short Presentation Connect Accept PPDU (CPA)" },
+ { 0xe002, "Short Presentation Connect Reject PPDU (CPR)" },
+ { 0xa002, "Short Presentation Connect Reject PPDU (CPR)" },
+ {0, NULL }
+};
+
+/* Short Presentation Connect Reject PPDU's 0yyy 00zz */
+const value_string atn_pres_err[] =
+{
+ { 0x00, "Presentation-user" },
+ { 0x01, "Reason not specified (transient)"},
+ { 0x02, "Temporary congestion (transient)"},
+ { 0x03, "Local limit exceeded (transient)"},
+ { 0x04, "Called presentation-address unknown (permanent)"},
+ { 0x05, "Protocol version not supported (permanent)"},
+ { 0x06, "Default context not supported (permanent)"},
+ { 0x07, "User data not readable (permanent)"},
+ { 0, NULL }
+};
+
+#if 0
+/* re-implementing external data: packet-per.c */
+static int atn_ulcs_Externalt_encoding(
+ tvbuff_t *tvb _U_,
+ int offset _U_,
+ asn1_ctx_t *actx _U_,
+ proto_tree *tree _U_,
+ int hf_index _U_)
+{
+ offset = dissect_per_choice(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index,
+ ett_atn_ulcs_EXTERNALt,
+ External_encoding_choice,
+ &actx->external.encoding);
+
+ return offset;
+}
+
+/* re-implementing external data: packet-per.c */
+static guint32 atn_per_external_type(
+ tvbuff_t *tvb _U_,
+ guint32 offset,
+ asn1_ctx_t *actx,
+ proto_tree *tree _U_,
+ int hf_index _U_,
+ per_type_fn type_cb)
+{
+ memset(&actx->external, '\0', sizeof(actx->external));
+ actx->external.hf_index = -1;
+ actx->external.encoding = -1;
+
+ actx->external.u.per.type_cb = type_cb;
+ offset = atn_ulcs_Externalt_encoding(
+ tvb,
+ offset,
+ actx,
+ tree,
+ hf_index);
+
+ memset(
+ &actx->external,
+ '\0',
+ sizeof(actx->external));
+
+ actx->external.hf_index = -1;
+ actx->external.encoding = -1;
+
+ return offset;
+}
+#endif
+
+/* determine 24-bit aircraft address(ARS) */
+/* from 20-byte ATN NSAP. */
+guint32 get_aircraft_24_bit_address_from_nsap(
+ packet_info *pinfo)
+{
+ const guint8* addr = NULL;
+ guint32 ars =0;
+ guint32 adr_prefix =0;
+
+ /* check NSAP address type*/
+ if( (pinfo->src.type != get_osi_address_type()) ||
+ (pinfo->dst.type != get_osi_address_type())) {
+ return ars; }
+
+ /* 20 octets address length required */
+ /* for ATN */
+ if( (pinfo->src.len != 20) ||
+ (pinfo->dst.len != 20)) {
+ return ars; }
+
+ /* first try source address */
+ /* if the src address originates */
+ /* from an aircraft it's downlink */
+
+ /* convert addr into 32-bit integer */
+ addr = (const guint8 *)pinfo->src.data;
+ adr_prefix =
+ ((addr[0]<<24) |
+ (addr[1]<<16) |
+ (addr[2]<<8) |
+ addr[3] );
+
+ /* according to ICAO doc9507 Ed2 SV5 */
+ /* clause 5.4.3.8.1.5 and 5.4.3.8.1.3 */
+ /* mobile addresses contain "c1" of "41" */
+ /* in the VER subfield of the NSAP */
+ if((adr_prefix == 0x470027c1) ||
+ (adr_prefix == 0x47002741)) {
+ /* ICAO doc9507 Ed2 SV5 5.4.3.8.4.4 */
+ /* states that the ARS subfield containes */
+ /* the 24-bitaddress of the aircraft */
+ ars = ((addr[8])<<16) |
+ ((addr[9])<<8) |
+ (addr[10]);
+ }
+
+ /* try destination address */
+ /* if the src address originates */
+ /* from an aircraft it's downlink */
+
+ /* convert addr into 32-bit integer */
+ addr = (const guint8 *)pinfo->dst.data;
+ adr_prefix = ((addr[0]<<24) |
+ (addr[1]<<16) |
+ (addr[2]<<8) |
+ addr[3] );
+
+ /* according to ICAO doc9507 Ed2 SV5 */
+ /* clause 5.4.3.8.1.5 and 5.4.3.8.1.3 */
+ /* mobile addresses contain "c1" of "41" */
+ /* in the VER subfield of the NSAP */
+ if((adr_prefix == 0x470027c1) ||
+ (adr_prefix == 0x47002741)) {
+ /* ICAO doc9507 Ed2 SV5 5.4.3.8.4.4 */
+ /* states that the ARS subfield containes */
+ /* the 24-bitaddress of the aircraft */
+ ars = ((addr[8])<<16) |
+ ((addr[9])<<8) |
+ (addr[10]);
+ }
+ return ars;
+}
+
+/* determine whether a PDU is uplink or downlink */
+/* by checking for known aircraft address prefices*/
+int check_heur_msg_type(packet_info *pinfo _U_)
+{
+ int t = no_msg;
+ const guint8* addr = NULL;
+ guint32 adr_prefix =0;
+
+ /* check NSAP address type*/
+ if( (pinfo->src.type != get_osi_address_type()) || (pinfo->dst.type != get_osi_address_type())) {
+ return t; }
+
+ /* check NSAP address length; 20 octets address length required */
+ if( (pinfo->src.len != 20) || (pinfo->dst.len != 20)) {
+ return t; }
+
+ addr = (const guint8 *)pinfo->src.data;
+
+ /* convert address to 32-bit integer */
+ adr_prefix = ((addr[0]<<24) | (addr[1]<<16) | (addr[2]<<8) | addr[3] );
+
+ /* According to the published ATN NSAP adddressing scheme */
+ /* in ICAO doc9705 Ed2 SV5 5.4.3.8.1.3 and 5.4.3.8.1.5 */
+ /* the "VER" field shall be 0x41 ("all Mobile AINSC") or */
+ /* 0xc1 ("all Mobile ATSC") for mobile stations (aka aircraft).*/
+ if((adr_prefix == 0x470027c1) || (adr_prefix == 0x47002741)) {
+ t = dm; /* source is an aircraft: it's a downlink PDU */
+ }
+
+ addr = (const guint8 *)pinfo->dst.data;
+
+ /* convert address to 32-bit integer */
+ adr_prefix = ((addr[0]<<24) | (addr[1]<<16) | (addr[2]<<8) | addr[3] );
+
+ /* According to the published ATN NSAP adddressing scheme */
+ /* in ICAO doc9705 Ed2 SV5 5.4.3.8.1.3 and 5.4.3.8.1.5 */
+ /* the "VER" field shall be 0x41 ("all Mobile AINSC") or */
+ /* 0xc1 ("all Mobile ATSC") for mobile stations (aka aircraft).*/
+ if((adr_prefix == 0x470027c1) || (adr_prefix == 0x47002741)) {
+ t = um; /* destination is aircraft: uplink PDU */
+ }
+
+ return t;
+}
+
+/* conversation may be used by other dissectors */
+wmem_tree_t *get_atn_conversation_tree(void){
+ return atn_conversation_tree;
+}
+
+
+/* find a atn conversation tree node by an endpoint */
+/* an endpoint is identified by atn src and dst addresses */
+/* and srcref or dstref (depends on the transport packet type) */
+/* IMHO it's a hack - conversations should be maintained */
+/* at transport layer (cotp) but this isn't working yet. */
+atn_conversation_t * find_atn_conversation(
+ address *address1,
+ guint16 clnp_ref1,
+ address *address2 )
+{
+ atn_conversation_t *cv = NULL;
+ guint32 key = 0;
+ guint32 tmp = 0;
+
+ tmp = add_address_to_hash( tmp, address1);
+ key = (tmp << 16) | clnp_ref1 ;
+
+ tmp = add_address_to_hash( tmp, address2);
+ key = (tmp << 24) | key ;
+
+ /* search for atn conversation */
+ cv = (atn_conversation_t *)
+ wmem_tree_lookup32(get_atn_conversation_tree(),key);
+
+ return cv;
+}
+
+/* create a atn conversation tree node */
+/* conversation data is to be allocated externally */
+/* a conversation may be referenced from both endpoints */
+atn_conversation_t * create_atn_conversation(
+ address *address1,
+ guint16 clnp_ref1,
+ address *address2,
+ atn_conversation_t *conversation)
+{
+ atn_conversation_t *cv = NULL;
+ guint32 key = 0;
+ guint32 tmp = 0;
+
+ tmp = add_address_to_hash( tmp, address1);
+ key = (tmp << 16) | clnp_ref1 ;
+
+ tmp = add_address_to_hash( tmp, address2);
+ key = (tmp << 24) | key ;
+
+ /* search for aircraft entry */
+ cv = (atn_conversation_t *)
+ wmem_tree_lookup32(
+ get_atn_conversation_tree(),
+ key);
+
+ /* tree node already present */
+ if(cv) {
+ return NULL; }
+
+ /* insert conversation data in tree*/
+ wmem_tree_insert32(
+ get_atn_conversation_tree(),
+ key,
+ (void*)conversation);
+
+ return conversation;
+}
+
+static int
+dissect_atn_ulcs(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ void *data _U_)
+{
+ int offset = 0;
+ proto_item *ti = NULL;
+ proto_tree *atn_ulcs_tree = NULL;
+ guint8 value_pres = 0;
+ guint8 value_ses = 0;
+ guint16 value_ses_pres = 0;
+
+ root_tree = tree;
+
+ /* data pointer */
+ /* decode as PDV-list */
+ if ( (int)(intptr_t) data == FALSE )
+ {
+ ti = proto_tree_add_item(
+ tree,
+ proto_atn_ulcs,
+ tvb,
+ 0,
+ 0 ,
+ ENC_NA);
+
+ atn_ulcs_tree = proto_item_add_subtree(
+ ti,
+ ett_atn_ulcs);
+
+ dissect_Fully_encoded_data_PDU(
+ tvb,
+ pinfo,
+ atn_ulcs_tree, NULL);
+
+ return offset +
+ tvb_reported_length_remaining(tvb, offset ) ;
+ }
+
+ /* decode as SPDU, PPDU and ACSE PDU */
+ if ( (int)(intptr_t) data == TRUE )
+ {
+ /* get session and presentation PDU's */
+ value_ses_pres = tvb_get_ntohs(tvb, offset);
+
+ /* SPDU: dissect session layer */
+ atn_ulcs_tree = proto_tree_add_subtree(
+ tree, tvb, offset, 0,
+ ett_atn_ses, NULL, ATN_SES_PROTO );
+
+ /* get SPDU (1 octet) */
+ value_ses = tvb_get_guint8(tvb, offset);
+
+ /* SPDU type/identifier */
+ proto_tree_add_item(atn_ulcs_tree,
+ hf_atn_ses_type,
+ tvb,
+ offset,
+ 1,
+ ENC_BIG_ENDIAN );
+
+ /* SPDU parameters may be present in Short Refuse */
+ /* or Short Refuse Continue SPDU's */
+ switch(value_ses & SES_PDU_TYPE_MASK){
+ case SES_ATN_SRF:
+ case SES_ATN_SRFC:
+
+ /* SPDU parameter presence */
+ proto_tree_add_item(atn_ulcs_tree,
+ hf_atn_ses_param_ind,
+ tvb,
+ offset,
+ 1,
+ ENC_BIG_ENDIAN );
+
+ /* parameter B2 */
+ proto_tree_add_item(atn_ulcs_tree,
+ hf_atn_ses_param_b2,
+ tvb,
+ offset,
+ 1,
+ ENC_BIG_ENDIAN );
+
+ /* parameter B1 */
+ proto_tree_add_item(atn_ulcs_tree,
+ hf_atn_ses_param_b1,
+ tvb,
+ offset,
+ 1,
+ ENC_BIG_ENDIAN );
+
+ break;
+ default:
+ break;
+ }
+ offset++;
+
+ /* PPDU: dissect presentation layer */
+ atn_ulcs_tree = proto_tree_add_subtree(
+ tree, tvb, offset, 0,
+ ett_atn_pres, NULL, ATN_PRES_PROTO );
+
+ value_pres = tvb_get_guint8(tvb, offset);
+
+ /* need session context to identify PPDU type */
+ /* note: */
+ proto_tree_add_uint_format(atn_ulcs_tree, hf_atn_pres_pdu_type,
+ tvb,
+ offset,
+ 1,
+ value_ses_pres,
+ "%s (0x%02x)",
+ val_to_str_const( value_ses_pres & ATN_SES_PRES_MASK, atn_pres_vals, "?"),
+ value_pres);
+
+ /* PPDU errorcode in case of SRF/CPR */
+ switch(value_ses & SES_PDU_TYPE_MASK){
+ case SES_ATN_SRF:
+ case SES_ATN_SRFC:
+ proto_tree_add_item(
+ atn_ulcs_tree,
+ hf_atn_pres_err,
+ tvb,
+ offset,
+ 1,
+ ENC_BIG_ENDIAN );
+ break;
+ default:
+ break;
+ }
+
+ offset++;
+
+ /* ACSE PDU: dissect application layer */
+ atn_ulcs_tree = proto_tree_add_subtree(
+ tree, tvb, offset, 0,
+ ett_atn_acse, NULL, ATN_ACSE_PROTO );
+
+ dissect_ACSE_apdu_PDU(
+ tvb_new_subset_remaining(tvb, offset),
+ pinfo,
+ atn_ulcs_tree, NULL);
+
+ return offset +
+ tvb_reported_length_remaining(tvb, offset );
+ }
+ return offset;
+}
+
+static gboolean dissect_atn_ulcs_heur(
+ tvbuff_t *tvb,
+ packet_info *pinfo,
+ proto_tree *tree,
+ void *data _U_)
+{
+ /* do we have enough data*/
+ /* at least session + presentation data or pdv-list */
+ if (tvb_captured_length(tvb) < 2){
+ return FALSE; }
+
+ /* check for session/presentation/ACSE PDU's */
+ /* SPDU and PPDU are one octet each */
+ switch( tvb_get_ntohs(tvb, 0) & 0xf8ff ){
+ case 0xe802: /* SCN + CP*/
+ case 0xf802: /* SCNC + CP */
+ case 0xf002: /* SAC + CPA */
+ case 0xd802: /* SACC + CPA */
+ case 0xe002: /* SRF + CPR + R0 */
+ case 0xe012: /* SRF + CPR + R1 */
+ case 0xe022: /* SRF + CPR + R2 */
+ case 0xe032: /* SRF + CPR + R3 */
+ case 0xe042: /* SRF + CPR + R4 */
+ case 0xe052: /* SRF + CPR + R5 */
+ case 0xe062: /* SRF + CPR + R6 */
+ case 0xe072: /* SRF + CPR + R7 */
+ case 0xa002: /* SRFC + CPR + R0*/
+ case 0xa012: /* SRFC + CPR + R1*/
+ case 0xa022: /* SRFC + CPR + R2*/
+ case 0xa032: /* SRFC + CPR + R3*/
+ case 0xa042: /* SRFC + CPR + R4*/
+ case 0xa052: /* SRFC + CPR + R5*/
+ case 0xa062: /* SRFC + CPR + R6*/
+ case 0xa072: /* SRFC + CPR + R7*/
+ /* indicate to dissector routine */
+ /* that a least SPDU, PPDU and */
+ /* ACSE PDU is present */
+ dissect_atn_ulcs(
+ tvb,
+ pinfo,
+ tree,
+ (void*) TRUE);
+ return TRUE;
+ default: /* no SPDU */
+ break;
+ }
+
+ /* try to detect "Fully-encoded-data" heuristically */
+ /* the constants listed match the ASN.1 PER encoding */
+ /* of PDV-List */
+ switch( tvb_get_ntohs(tvb, 0) & 0xfff0 ){
+ case 0x0020: /* acse-apdu */
+ case 0x00a0: /* user-ase-apdu */
+ /* indicate to dissector routine */
+ /* that a PDV-list PDU is present */
+ /* */
+ /* PDV-list PDU may contain */
+ /* application protocol data (CM, CPDLC) */
+ /* or an ACSE PDU */
+ dissect_atn_ulcs(tvb, pinfo, tree, (void*) FALSE);
+ return TRUE;
+ break;
+ default: /* no or unsupported PDU */
+ break;
+ }
+ return FALSE;
+}
+
+void proto_register_atn_ulcs (void)
+{
+ static hf_register_info hf_atn_ulcs[] = {
+ { &hf_atn_ulcs_Fully_encoded_data_PDU,
+ { "Fully-encoded-data", "atn-ulcs.Fully_encoded_data",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_ACSE_apdu_PDU,
+ { "ACSE-apdu", "atn-ulcs.ACSE_apdu",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_ACSE_apdu_vals), 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_Fully_encoded_data_item,
+ { "PDV-list", "atn-ulcs.PDV_list_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_transfer_syntax_name,
+ { "transfer-syntax-name", "atn-ulcs.transfer_syntax_name",
+ FT_OID, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_presentation_context_identifier,
+ { "presentation-context-identifier", "atn-ulcs.presentation_context_identifier",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Presentation_context_identifier_vals), 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_presentation_data_values,
+ { "presentation-data-values", "atn-ulcs.presentation_data_values",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_T_presentation_data_values_vals), 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_pdv_list_presentation_data_values_single_asn1_type,
+ { "single-ASN1-type", "atn-ulcs.single_ASN1_type_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "T_pdv_list_presentation_data_values_single_asn1_type", HFILL }},
+ { &hf_atn_ulcs_octet_aligned,
+ { "octet-aligned", "atn-ulcs.octet_aligned",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "OCTET_STRING", HFILL }},
+ { &hf_atn_ulcs_pdv_list_presentation_data_values_arbitrary,
+ { "arbitrary", "atn-ulcs.arbitrary",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "T_pdv_list_presentation_data_values_arbitrary", HFILL }},
+ { &hf_atn_ulcs_direct_reference,
+ { "direct-reference", "atn-ulcs.direct_reference",
+ FT_OID, BASE_NONE, NULL, 0,
+ "OBJECT_IDENTIFIER", HFILL }},
+ { &hf_atn_ulcs_indirect_reference,
+ { "indirect-reference", "atn-ulcs.indirect_reference",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "INTEGER", HFILL }},
+ { &hf_atn_ulcs_data_value_descriptor,
+ { "data-value-descriptor", "atn-ulcs.data_value_descriptor",
+ FT_STRING, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_encoding,
+ { "encoding", "atn-ulcs.encoding",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_T_encoding_vals), 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_externalt_encoding_single_asn1_type,
+ { "single-ASN1-type", "atn-ulcs.single_ASN1_type_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "T_externalt_encoding_single_asn1_type", HFILL }},
+ { &hf_atn_ulcs_externalt_encoding_octet_aligned,
+ { "octet-aligned", "atn-ulcs.octet_aligned",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "T_externalt_encoding_octet_aligned", HFILL }},
+ { &hf_atn_ulcs_externalt_encoding_arbitrary,
+ { "arbitrary", "atn-ulcs.arbitrary",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "T_externalt_encoding_arbitrary", HFILL }},
+ { &hf_atn_ulcs_aarq,
+ { "aarq", "atn-ulcs.aarq_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AARQ_apdu", HFILL }},
+ { &hf_atn_ulcs_aare,
+ { "aare", "atn-ulcs.aare_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "AARE_apdu", HFILL }},
+ { &hf_atn_ulcs_rlrq,
+ { "rlrq", "atn-ulcs.rlrq_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "RLRQ_apdu", HFILL }},
+ { &hf_atn_ulcs_rlre,
+ { "rlre", "atn-ulcs.rlre_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "RLRE_apdu", HFILL }},
+ { &hf_atn_ulcs_abrt,
+ { "abrt", "atn-ulcs.abrt_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ "ABRT_apdu", HFILL }},
+ { &hf_atn_ulcs_aarq_apdu_protocol_version,
+ { "protocol-version", "atn-ulcs.protocol_version",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "T_aarq_apdu_protocol_version", HFILL }},
+ { &hf_atn_ulcs_application_context_name,
+ { "application-context-name", "atn-ulcs.application_context_name",
+ FT_OID, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_called_AP_title,
+ { "called-AP-title", "atn-ulcs.called_AP_title",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_AP_title_vals), 0,
+ "AP_title", HFILL }},
+ { &hf_atn_ulcs_called_AE_qualifier,
+ { "called-AE-qualifier", "atn-ulcs.called_AE_qualifier",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_AE_qualifier_vals), 0,
+ "AE_qualifier", HFILL }},
+ { &hf_atn_ulcs_called_AP_invocation_identifier,
+ { "called-AP-invocation-identifier", "atn-ulcs.called_AP_invocation_identifier",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "AP_invocation_identifier", HFILL }},
+ { &hf_atn_ulcs_called_AE_invocation_identifier,
+ { "called-AE-invocation-identifier", "atn-ulcs.called_AE_invocation_identifier",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "AE_invocation_identifier", HFILL }},
+ { &hf_atn_ulcs_calling_AP_title,
+ { "calling-AP-title", "atn-ulcs.calling_AP_title",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_AP_title_vals), 0,
+ "AP_title", HFILL }},
+ { &hf_atn_ulcs_calling_AE_qualifier,
+ { "calling-AE-qualifier", "atn-ulcs.calling_AE_qualifier",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_AE_qualifier_vals), 0,
+ "AE_qualifier", HFILL }},
+ { &hf_atn_ulcs_calling_AP_invocation_identifier,
+ { "calling-AP-invocation-identifier", "atn-ulcs.calling_AP_invocation_identifier",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "AP_invocation_identifier", HFILL }},
+ { &hf_atn_ulcs_calling_AE_invocation_identifier,
+ { "calling-AE-invocation-identifier", "atn-ulcs.calling_AE_invocation_identifier",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "AE_invocation_identifier", HFILL }},
+ { &hf_atn_ulcs_sender_acse_requirements,
+ { "sender-acse-requirements", "atn-ulcs.sender_acse_requirements",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "ACSE_requirements", HFILL }},
+ { &hf_atn_ulcs_mechanism_name,
+ { "mechanism-name", "atn-ulcs.mechanism_name",
+ FT_OID, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_calling_authentication_value,
+ { "calling-authentication-value", "atn-ulcs.calling_authentication_value",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Authentication_value_vals), 0,
+ "Authentication_value", HFILL }},
+ { &hf_atn_ulcs_application_context_name_list,
+ { "application-context-name-list", "atn-ulcs.application_context_name_list",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_implementation_information,
+ { "implementation-information", "atn-ulcs.implementation_information",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "Implementation_data", HFILL }},
+ { &hf_atn_ulcs_user_information,
+ { "user-information", "atn-ulcs.user_information",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "Association_information", HFILL }},
+ { &hf_atn_ulcs_aare_apdu_protocol_version,
+ { "protocol-version", "atn-ulcs.protocol_version",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "T_aare_apdu_protocol_version", HFILL }},
+ { &hf_atn_ulcs_result,
+ { "result", "atn-ulcs.result",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Associate_result_vals), 0,
+ "Associate_result", HFILL }},
+ { &hf_atn_ulcs_result_source_diagnostic,
+ { "result-source-diagnostic", "atn-ulcs.result_source_diagnostic",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Associate_source_diagnostic_vals), 0,
+ "Associate_source_diagnostic", HFILL }},
+ { &hf_atn_ulcs_responding_AP_title,
+ { "responding-AP-title", "atn-ulcs.responding_AP_title",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_AP_title_vals), 0,
+ "AP_title", HFILL }},
+ { &hf_atn_ulcs_responding_AE_qualifier,
+ { "responding-AE-qualifier", "atn-ulcs.responding_AE_qualifier",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_AE_qualifier_vals), 0,
+ "AE_qualifier", HFILL }},
+ { &hf_atn_ulcs_responding_AP_invocation_identifier,
+ { "responding-AP-invocation-identifier", "atn-ulcs.responding_AP_invocation_identifier",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "AP_invocation_identifier", HFILL }},
+ { &hf_atn_ulcs_responding_AE_invocation_identifier,
+ { "responding-AE-invocation-identifier", "atn-ulcs.responding_AE_invocation_identifier",
+ FT_INT32, BASE_DEC, NULL, 0,
+ "AE_invocation_identifier", HFILL }},
+ { &hf_atn_ulcs_responder_acse_requirements,
+ { "responder-acse-requirements", "atn-ulcs.responder_acse_requirements",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "ACSE_requirements", HFILL }},
+ { &hf_atn_ulcs_responding_authentication_value,
+ { "responding-authentication-value", "atn-ulcs.responding_authentication_value",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Authentication_value_vals), 0,
+ "Authentication_value", HFILL }},
+ { &hf_atn_ulcs_rlrq_apdu_request_reason,
+ { "reason", "atn-ulcs.reason",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Release_request_reason_vals), 0,
+ "Release_request_reason", HFILL }},
+ { &hf_atn_ulcs_rlre_apdu_response_reason,
+ { "reason", "atn-ulcs.reason",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Release_response_reason_vals), 0,
+ "Release_response_reason", HFILL }},
+ { &hf_atn_ulcs_abort_source,
+ { "abort-source", "atn-ulcs.abort_source",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_ABRT_source_vals), 0,
+ "ABRT_source", HFILL }},
+ { &hf_atn_ulcs_abort_diagnostic,
+ { "abort-diagnostic", "atn-ulcs.abort_diagnostic",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_ABRT_diagnostic_vals), 0,
+ "ABRT_diagnostic", HFILL }},
+ { &hf_atn_ulcs_Application_context_name_list_item,
+ { "Application-context-name", "atn-ulcs.Application_context_name",
+ FT_OID, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_ap_title_form2,
+ { "ap-title-form2", "atn-ulcs.ap_title_form2",
+ FT_OID, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_ap_title_form1,
+ { "ap-title-form1", "atn-ulcs.ap_title_form1",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_Name_vals), 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_ae_qualifier_form2,
+ { "ae-qualifier-form2", "atn-ulcs.ae_qualifier_form2",
+ FT_INT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_ae_qualifier_form1,
+ { "ae-qualifier-form1", "atn-ulcs.ae_qualifier_form1",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_acse_service_user,
+ { "acse-service-user", "atn-ulcs.acse_service_user",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_T_acse_service_user_vals), 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_acse_service_provider,
+ { "acse-service-provider", "atn-ulcs.acse_service_provider",
+ FT_UINT32, BASE_DEC, VALS(atn_ulcs_T_acse_service_provider_vals), 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_Association_information_item,
+ { "EXTERNALt", "atn-ulcs.EXTERNALt_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_charstring,
+ { "charstring", "atn-ulcs.charstring",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "OCTET_STRING", HFILL }},
+ { &hf_atn_ulcs_bitstring,
+ { "bitstring", "atn-ulcs.bitstring",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ "BIT_STRING", HFILL }},
+ { &hf_atn_ulcs_external,
+ { "external", "atn-ulcs.external_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_other,
+ { "other", "atn-ulcs.other_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_other_mechanism_name,
+ { "other-mechanism-name", "atn-ulcs.other_mechanism_name",
+ FT_OID, BASE_NONE, NULL, 0,
+ "OBJECT_IDENTIFIER", HFILL }},
+ { &hf_atn_ulcs_other_mechanism_value,
+ { "other-mechanism-value", "atn-ulcs.other_mechanism_value_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_rdnSequence,
+ { "rdnSequence", "atn-ulcs.rdnSequence",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_RDNSequence_item,
+ { "RelativeDistinguishedName", "atn-ulcs.RelativeDistinguishedName",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_RelativeDistinguishedName_item,
+ { "AttributeTypeAndValue", "atn-ulcs.AttributeTypeAndValue_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_null,
+ { "null", "atn-ulcs.null_element",
+ FT_NONE, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_T_aarq_apdu_protocol_version_version1,
+ { "version1", "atn.ulcs.T.aarq.apdu.protocol.version.version1",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_T_aare_apdu_protocol_version_version1,
+ { "version1", "atn.ulcs.T.aare.apdu.protocol.version.version1",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_ACSE_requirements_authentication,
+ { "authentication", "atn.ulcs.ACSE.requirements.authentication",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }},
+ { &hf_atn_ulcs_ACSE_requirements_application_context_negotiation,
+ { "application-context-negotiation", "atn.ulcs.ACSE.requirements.application.context.negotiation",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ NULL, HFILL }},
+ {&hf_atn_ses_type,
+ { "SPDU Type",
+ "atn-ulcs.ses.type",
+ FT_UINT8,
+ BASE_HEX,
+ VALS(atn_ses_type),
+ 0xf8,
+ "Indicates presence of session parameters",
+ HFILL}},
+ {&hf_atn_ses_param_ind,
+ { "SPDU Parameter Indication",
+ "atn-ulcs.ses.parameter-indication",
+ FT_UINT8,
+ BASE_HEX,
+ VALS(atn_ses_param_ind),
+ SES_PARAM_IND_MASK,
+ "Indicates presence of session parameters",
+ HFILL}},
+ {&hf_atn_ses_param_b1,
+ { "SRF Parameter B1",
+ "atn-ulcs.ses.srf-b1",
+ FT_UINT8,
+ BASE_HEX,
+ VALS(srf_b1),
+ 0x01,
+ "Determines if transport connection reject is transient or persistent",
+ HFILL}},
+ {&hf_atn_ses_param_b2,
+ { "SRF Parameter B2",
+ "atn-ulcs.ses.srf-b2",
+ FT_UINT8,
+ BASE_HEX,
+ VALS(srf_b2),
+ 0x02,
+ "Determines if transport connection is retained or released",
+ HFILL}},
+ { &hf_atn_pres_err,
+ { "Error Code", "atn-ulcs.pres.cpr-error",
+ FT_UINT8,
+ BASE_HEX,
+ VALS(atn_pres_err),
+ PRES_CPR_ER_MASK,
+ NULL,
+ HFILL}},
+ { &hf_atn_pres_pdu_type,
+ { "PDU type", "atn-ulcs.pres.pdu_type",
+ FT_UINT16,
+ BASE_HEX,
+ NULL,
+ ATN_SES_PRES_MASK,
+ NULL,
+ HFILL}},
+ };
+
+ static gint *ett[] = {
+ &ett_atn_ulcs_Fully_encoded_data,
+ &ett_atn_ulcs_PDV_list,
+ &ett_atn_ulcs_T_presentation_data_values,
+ &ett_atn_ulcs_EXTERNALt,
+ &ett_atn_ulcs_T_encoding,
+ &ett_atn_ulcs_ACSE_apdu,
+ &ett_atn_ulcs_AARQ_apdu,
+ &ett_atn_ulcs_T_aarq_apdu_protocol_version,
+ &ett_atn_ulcs_AARE_apdu,
+ &ett_atn_ulcs_T_aare_apdu_protocol_version,
+ &ett_atn_ulcs_RLRQ_apdu,
+ &ett_atn_ulcs_RLRE_apdu,
+ &ett_atn_ulcs_ABRT_apdu,
+ &ett_atn_ulcs_ACSE_requirements,
+ &ett_atn_ulcs_Application_context_name_list,
+ &ett_atn_ulcs_AP_title,
+ &ett_atn_ulcs_AE_qualifier,
+ &ett_atn_ulcs_Associate_source_diagnostic,
+ &ett_atn_ulcs_Association_information,
+ &ett_atn_ulcs_Authentication_value,
+ &ett_atn_ulcs_T_other,
+ &ett_atn_ulcs_Name,
+ &ett_atn_ulcs_RDNSequence,
+ &ett_atn_ulcs_RelativeDistinguishedName,
+ &ett_atn_ulcs_AttributeTypeAndValue,
+ &ett_atn_ses,
+ &ett_atn_pres,
+ &ett_atn_acse,
+ &ett_atn_ulcs
+ };
+
+ proto_atn_ulcs = proto_register_protocol (
+ ATN_ULCS_PROTO ,
+ "ATN-ULCS",
+ "atn-ulcs");
+
+ proto_register_field_array (
+ proto_atn_ulcs,
+ hf_atn_ulcs,
+ array_length(hf_atn_ulcs));
+
+ proto_register_subtree_array (
+ ett,
+ array_length (ett));
+
+ register_dissector(
+ "atn-ulcs",
+ dissect_atn_ulcs,
+ proto_atn_ulcs);
+
+ /* initiate sub dissector list */
+ atn_ulcs_heur_subdissector_list = register_heur_dissector_list("atn-ulcs", proto_atn_ulcs);
+
+ /* init aare/aare data */
+ aarq_data_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+
+ atn_conversation_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
+}
+
+void proto_reg_handoff_atn_ulcs(void)
+{
+ atn_cm_handle = find_dissector_add_dependency("atn-cm", proto_atn_ulcs);
+ atn_cpdlc_handle = find_dissector_add_dependency("atn-cpdlc", proto_atn_ulcs);
+
+ /* add session dissector to cotp dissector list dissector list*/
+ heur_dissector_add(
+ "cotp",
+ dissect_atn_ulcs_heur,
+ "ATN-ULCS over COTP",
+ "atn-ucls_cotp",
+ proto_atn_ulcs, HEURISTIC_ENABLE);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */