From 44d5eca533034afd7a14be0de204aa3a64789fe7 Mon Sep 17 00:00:00 2001 From: Anders Broman Date: Tue, 6 Nov 2018 16:37:13 +0100 Subject: Add GCSNA General Circuit Services Notification Application Protocol dissector. Change-Id: I8c29b827cd5bc875bc40ee7e9315b0525b0d3263 Reviewed-on: https://code.wireshark.org/review/30520 Petri-Dish: Anders Broman Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- epan/dissectors/CMakeLists.txt | 1 + epan/dissectors/packet-gcsna.c | 452 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 453 insertions(+) create mode 100644 epan/dissectors/packet-gcsna.c (limited to 'epan/dissectors') diff --git a/epan/dissectors/CMakeLists.txt b/epan/dissectors/CMakeLists.txt index 3b4797db5d..76b108d979 100644 --- a/epan/dissectors/CMakeLists.txt +++ b/epan/dissectors/CMakeLists.txt @@ -1025,6 +1025,7 @@ set(DISSECTOR_SRC ${CMAKE_CURRENT_SOURCE_DIR}/packet-fw1.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-g723.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gadu-gadu.c + ${CMAKE_CURRENT_SOURCE_DIR}/packet-gcsna.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gdb.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gdsdb.c ${CMAKE_CURRENT_SOURCE_DIR}/packet-gearman.c diff --git a/epan/dissectors/packet-gcsna.c b/epan/dissectors/packet-gcsna.c new file mode 100644 index 0000000000..3d17ad65c8 --- /dev/null +++ b/epan/dissectors/packet-gcsna.c @@ -0,0 +1,452 @@ +/* + * packet-gcsna.c + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Ref GCSNA: 3GPP2 C.S0097 v2.0 + */ + +# include "config.h" + +#include +#include + + /* gcsna Handle for the dissection */ +static dissector_handle_t gcsna_handle; +static dissector_handle_t cdma2k_handle; + +/* Function handlers for each message/information fields */ +static void gcsna_message_decode(proto_item *item, tvbuff_t *tvb, proto_tree *tree, guint *offset, proto_tree *mainTree, guint16 *noerror, packet_info *pinfo); +static void gcsna_message_GCSNA1xCircuitService(proto_item *item, tvbuff_t *tvb, packet_info *pinfo, proto_tree *mainTree, proto_tree *tree, guint *offset); +static void gcsna_message_GCSNAL2Ack(proto_item *item, tvbuff_t *tvb, proto_tree *tree, guint *offset); +static void gcsna_message_GCSNAServiceReject(proto_item *item, tvbuff_t *tvb, proto_tree *tree, guint *offset); + +/*Initialize all the header parameters that are to be displayed*/ +int proto_gcsna = -1; +static int hf_gcsna_msghdr = -1; +static int hf_gcsna_msgid = -1; +static int hf_gcsna_rejSequence = -1; +static int hf_gcsna_cause = -1; +static int hf_gcsna_ackSequence = -1; +static int hf_gcsna_recordType = -1; +static int hf_gcsna_1xProtocolRevision = -1; +static int hf_gcsna_invalidMessageId = -1; +static int hf_gcsna_l2ack = -1; +static int hf_gcsna_servicereject = -1; +static int hf_gcsna_gcsna_option = -1; +static int hf_gcsna_gcsnaClass = -1; +static int hf_gcsna_gcsnaClassRev = -1; +static int hf_gcsna_altGCSNAOption = -1; +static int hf_gcsna_altGCSNAOptionIncluded = -1; +static int hf_gcsna_NumaltGCSNAOption = -1; +static int hf_gcsna_ackRequired = -1; +static int hf_gcsna_stopDupDetect = -1; +static int hf_gcsna_msgSequence = -1; +static int hf_gcsna_tlacEncapsulated = -1; +static int hf_gcsna_NumTLACEncapsulated1xL3PDU = -1; +static int hf_gcsna_tlacReserved = -1; +static int hf_gcsna_iwsidIncluded = -1; +static int hf_gcsna_iwsidValue = -1; +static int hf_gcsna_unsupported_reject_seq = -1; + +/* Toggle sub-tree items */ +static gint ett_gcsna_msghdr = -1; +static gint ett_gcsna_subtree = -1; +static gint ett_gcsna_option = -1; + +static expert_field ei_gcsna_error = EI_INIT; + +#define GCSNA1XCIRCUITSERVICE 0x01 +#define GCSNAL2ACK 0x02 +#define GCSNASERVICEREJECT 0x03 + +/* Msg Types */ +static const value_string gcsna_message_types[] = { + { 0x01, "GCSNA 1X Circuitservice" }, + { 0x02, "GCSNA L2 Ack"}, + { 0x03, "GCSNA Servicereject"}, + { 0, NULL }, +}; + +/* Cause Types */ +static const value_string gcsna_cause_types[] = { + { 0, "Invalid GCSNAOption" }, + { 1, "Invalid 1xProtocolRevision" }, + { 2, "Invalid GCSNAOption and 1xProtocolRevision"}, + { 3, "Invalid Message Id"}, + { 4, "GCSNA 1xParameters provisioning is not supported" }, + { 5, "Unsupported RecordType in GCSNA 1xParameters message"}, + { 0, NULL }, +}; + +/* + GCSNA Class GCSNA ClassRevision 1x Service + +----------+-------------------+--------------------------------+ + | | 0 | Release 8 1xCSFB from E-UTRAN | + | +-------------------+--------------------------------+ + | 0 | 1 | Release 9 e1xCSFB from E-UTRAN | + | +-------------------+--------------------------------+ + | | 2 | C.S0097-A supported eCSFB | + +----------+-------------------+--------------------------------+ + | 1 | 0 | SRVCC from E-UTRAN | + +----------+-------------------+--------------------------------+ + +*/ +static const value_string gcsna_option_values[] = { + { 0, "Release 8 1xCSFB from E-UTRAN" }, + { 1, "Release 9 e1xCSFB from E-UTRAN" }, + { 2, "C.S0097-A supported eCSFB"}, + { 8, "SRVCC from E-UTRAN"}, + { 0, NULL }, +}; + +/* Decoder for all the information elements of A21 Message Type */ +static void +gcsna_message_decode(proto_item *item, tvbuff_t *tvb, proto_tree *tree, guint *offset, proto_tree *mainTree, guint16 *noerror, packet_info *pinfo) +{ + guint16 msgId = -1; + msgId = tvb_get_guint8(tvb, *offset); + *offset += 1; + + switch (msgId) + { + case GCSNA1XCIRCUITSERVICE: + { + gcsna_message_GCSNA1xCircuitService(item, tvb, pinfo, mainTree, tree, offset); + break; + } + + case GCSNAL2ACK: + { + gcsna_message_GCSNAL2Ack(item, tvb, tree, offset); + break; + } + + case GCSNASERVICEREJECT: + { + gcsna_message_GCSNAServiceReject(item, tvb, tree, offset); + break; + } + + default: + { + *noerror = 0; + break; + } + } +} + +static void +gcsna_message_GCSNA1xCircuitService(proto_item *item, tvbuff_t *tvb, packet_info *pinfo, proto_tree *mainTree, proto_tree *tree, guint *offset) +{ + guint16 alt_gcsna_incl = 0, num_alt_gcsna_opt = -1, iws_incl = 0; + guint8 num_res; + guint bit_offset = *offset * 8; + proto_tree *subtree = NULL; + tvbuff_t *new_tvb; + + /* GCSNAOption 8 bits */ + item = proto_tree_add_item(tree, hf_gcsna_gcsna_option, tvb, *offset, 1, ENC_BIG_ENDIAN); + subtree = proto_item_add_subtree(item, ett_gcsna_option); + proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClass, tvb, bit_offset, 5, ENC_BIG_ENDIAN); + bit_offset += 5; + proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClassRev, tvb, bit_offset, 3, ENC_BIG_ENDIAN); + bit_offset += 3; + + alt_gcsna_incl = tvb_get_bits8(tvb, bit_offset, 1); + proto_tree_add_bits_item(subtree, hf_gcsna_altGCSNAOptionIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset += 1; + if (alt_gcsna_incl) + { + num_alt_gcsna_opt = tvb_get_bits8(tvb, bit_offset, 8); + proto_tree_add_bits_item(subtree, hf_gcsna_NumaltGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN); + bit_offset += 8; + + while (num_alt_gcsna_opt != 0) + { + proto_tree_add_bits_item(subtree, hf_gcsna_altGCSNAOption, tvb, bit_offset, 8, ENC_BIG_ENDIAN); + bit_offset += 8; + num_alt_gcsna_opt--; + } + } + + iws_incl = tvb_get_bits8(tvb, bit_offset, 1); + proto_tree_add_bits_item(subtree, hf_gcsna_iwsidIncluded, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + + if (iws_incl) + { + proto_tree_add_bits_item(subtree, hf_gcsna_iwsidValue, tvb, bit_offset, 16, ENC_BIG_ENDIAN); + bit_offset += 16; + } + + proto_tree_add_bits_item(subtree, hf_gcsna_ackRequired, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + proto_tree_add_bits_item(subtree, hf_gcsna_stopDupDetect, tvb, bit_offset, 1, ENC_BIG_ENDIAN); + bit_offset++; + proto_tree_add_bits_item(subtree, hf_gcsna_msgSequence, tvb, bit_offset, 6, ENC_BIG_ENDIAN); + bit_offset += 6; + + proto_tree_add_bits_item(subtree, hf_gcsna_NumTLACEncapsulated1xL3PDU, tvb, bit_offset, 2, ENC_BIG_ENDIAN); + bit_offset += 2; + + /* The sender shall include reserved bits to make this message integral number of octets up to TLACEncapsulated1xL3PDU field. + * The sender 5 shall set all bits in this field to '0'. The receiver shall ignore this field. + */ + + /* calculate number of reserved bits */ + num_res = 8 - (bit_offset & 0x3); + proto_tree_add_bits_item(subtree, hf_gcsna_tlacReserved, tvb, bit_offset, num_res, ENC_BIG_ENDIAN); + bit_offset = bit_offset + num_res; + *offset = bit_offset >> 3; + + proto_tree_add_item(subtree, hf_gcsna_tlacEncapsulated, tvb, *offset, -1, ENC_NA); + + if (cdma2k_handle) { + new_tvb = tvb_new_subset_length_caplen(tvb, *offset, -1, -1); + call_dissector(cdma2k_handle, new_tvb, pinfo, mainTree); + } + /* set the offset to the end of the message */ + *offset += tvb_reported_length_remaining(tvb, *offset); + +} + +static void gcsna_message_GCSNAL2Ack(proto_item *item, tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + proto_tree *subtree = NULL; + + item = proto_tree_add_item(tree, hf_gcsna_l2ack, tvb, *offset, 1, ENC_NA); + subtree = proto_item_add_subtree(item, ett_gcsna_subtree); + + proto_tree_add_bits_item(subtree, hf_gcsna_ackSequence, tvb, *offset * 8, 6, ENC_BIG_ENDIAN); + *offset += 1; +} + +static void gcsna_message_GCSNAServiceReject(proto_item *item, tvbuff_t *tvb, proto_tree *tree, guint *offset) +{ + guint16 cause_val = -1, num_fields = -1, l_offset = -1; + proto_tree *subtree = NULL; + + item = proto_tree_add_item(tree, hf_gcsna_servicereject, tvb, *offset, 1, ENC_NA); + subtree = proto_item_add_subtree(item, ett_gcsna_subtree); + + l_offset = *offset * 8; + proto_tree_add_bits_item(subtree, hf_gcsna_rejSequence, tvb, l_offset, 6, ENC_BIG_ENDIAN); + l_offset += 6; + proto_tree_add_bits_item(subtree, hf_gcsna_cause, tvb, l_offset, 8, ENC_BIG_ENDIAN); + cause_val = tvb_get_bits8(tvb, *offset * 8 + 6, 8); + l_offset += 8; + + switch (cause_val) + { + case 0: + case 2: + { + num_fields = tvb_get_bits8(tvb, l_offset, 8); + l_offset += 8; + + while (num_fields > 0) + { + proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClass, tvb, l_offset, 5, ENC_BIG_ENDIAN); + l_offset += 5; + proto_tree_add_bits_item(subtree, hf_gcsna_gcsnaClassRev, tvb, l_offset, 3, ENC_BIG_ENDIAN); + l_offset += 3; + num_fields--; + } + + if (cause_val == 2) + { + proto_tree_add_bits_item(subtree, hf_gcsna_1xProtocolRevision, tvb, l_offset, 8, ENC_BIG_ENDIAN); + l_offset += 8; + } + + break; + } + + case 1: + { + proto_tree_add_bits_item(subtree, hf_gcsna_1xProtocolRevision, tvb, l_offset, 8, ENC_BIG_ENDIAN); + l_offset += 8; + break; + } + + case 3: + { + proto_tree_add_bits_item(subtree, hf_gcsna_invalidMessageId, tvb, l_offset, 8, ENC_BIG_ENDIAN); + l_offset += 8; + break; + } + + /*This Cause Value is not supported in IWS Stack*/ + case 5: + { + num_fields = tvb_get_bits8(tvb, l_offset, 8); + l_offset += 8; + + while (num_fields > 0) + { + proto_tree_add_bits_item(subtree, hf_gcsna_recordType, tvb, l_offset, 8, ENC_BIG_ENDIAN); + l_offset += 8; + num_fields--; + } + break; + } + + default: + { + proto_tree_add_item(subtree, hf_gcsna_unsupported_reject_seq, tvb, l_offset, -1, ENC_NA); + break; + } + } + + if (l_offset % 8 == 0) + { + *offset = (l_offset / 8); + } else + { + *offset = (l_offset / 8) + 1; + } + +} + +/*Method called when the dissection starts.....Starting point*/ +static int +dissect_gcsna(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_) +{ + + /* Initialization*/ + proto_tree *gcsna_msghdr_tree_start = NULL; + + proto_item *item = NULL; + + guint32 offset = 0; + guint16 noerror = 1; + + + /*Add the protocol name to display*/ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "gcsna"); + col_add_fstr(pinfo->cinfo, COL_INFO, "[gcsna]"); + + item = proto_tree_add_item(tree, hf_gcsna_msghdr, tvb, 0, -1, ENC_NA); + gcsna_msghdr_tree_start = proto_item_add_subtree(item, ett_gcsna_msghdr); + + if (tree) + { + proto_tree_add_item(gcsna_msghdr_tree_start, hf_gcsna_msgid, tvb, offset, 1, ENC_BIG_ENDIAN); + + while (tvb_captured_length_remaining(tvb, offset) != 0 && noerror == 1) + gcsna_message_decode(item, tvb, gcsna_msghdr_tree_start, &offset, tree, &noerror, pinfo); + + if (noerror == 0) + { + expert_add_info(pinfo, item, &ei_gcsna_error); + } + } + return tvb_reported_length(tvb); +} + +/*Register gcsna to be accessed by other dissectors/plugins*/ +void +proto_register_gcsna(void) +{ + static hf_register_info hf[] = { + { &hf_gcsna_servicereject, + { "GCSNA SERVICEREJECT", "gcsna.servicereject", FT_NONE, BASE_NONE,NULL, 0x0, NULL, HFILL } }, + /*{ & hf_gcsna_msgid, + { "GCSNA Message Type", "gcsna.MsgType", FT_UINT8, BASE_HEX_DEC, VALS(A21_Message_Types), 0x0, NULL, HFILL } },*/ + { &hf_gcsna_l2ack, + { "L2ACK", "gcsna.l2ack", FT_NONE, BASE_NONE,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_msghdr, + { "General Circuit Services Notification Application Protocol", "gcsna.msghdr", FT_NONE, BASE_NONE,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_NumTLACEncapsulated1xL3PDU, + { "NumTLACEncapsulated1xL3PDU", "gcsna.NumTLACEncapsulated1xL3PDU", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_tlacReserved, + { "Reserved", "gcsna.tlacReserved", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_tlacEncapsulated, + { "TLAC Encapsulated", "gcsna.tlacEncapsulated", FT_BYTES, BASE_NONE,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_msgSequence, + { "Msg Sequence", "gcsna.msgSequence", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_stopDupDetect, + { "Stop Dup Detect", "gcsna.stopDupDetect", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_ackRequired, + { "Ack Required", "gcsna.ackRequired", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_altGCSNAOptionIncluded, + { "AlternativeGCSNAOption_INCL", "gcsna.altGCSNAOptionIncluded", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_altGCSNAOption, + { "Alternate GCSNA Option", "gcsna.altGCSNAOption", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_gcsna_option, + { "GCSNA Option", "gcsna.Option", FT_UINT8, BASE_HEX, VALS(gcsna_option_values), 0x0, NULL, HFILL } }, + { &hf_gcsna_NumaltGCSNAOption, + { "NumAlternativeGCSNAOptions", "gcsna.NumaltGCSNAOption", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_iwsidValue, + { "IWS_ID", "gcsna.iwsidValue", FT_UINT16, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_iwsidIncluded, + { "IWSIDIncl", "gcsna.iwsidIncluded", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_gcsnaClassRev, + { "GCSNA Class revision", "gcsna.ClassRev", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_gcsnaClass, + { "GCSNA Class", "gcsna.Class", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_invalidMessageId, + { "InvalidMessageId", "gcsna.invalidMessageId", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_1xProtocolRevision, + { "1xProtocolRevision", "gcsna.1xProtocolRevision", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_recordType, + { "Record Type", "gcsna.recordType", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_ackSequence, + { "Ack Sequence", "gcsna.ackSequence", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_cause, + { "Cause", "gcsna.cause", FT_UINT8, BASE_HEX_DEC,VALS(gcsna_cause_types), 0x0, NULL, HFILL } }, + { &hf_gcsna_rejSequence, + { "Reject Sequence", "gcsna.rejSequence", FT_UINT8, BASE_HEX_DEC,NULL, 0x0, NULL, HFILL } }, + { &hf_gcsna_msgid, + { "GCSNA Message Type", "gcsna.msgId", FT_UINT8, BASE_HEX_DEC,VALS(gcsna_message_types), 0x0, NULL, HFILL } }, + { &hf_gcsna_unsupported_reject_seq, + { "Invalid / Unsupported GCSNA Message Reject Sequence", "gcsna.unsupportedrejectseq", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } } + }; + + + static gint *ett[] = { + &ett_gcsna_msghdr, + &ett_gcsna_subtree, + &ett_gcsna_option + }; + + + static ei_register_info ei[] = { + { &ei_gcsna_error, { "gcsna.error", PI_PROTOCOL, PI_ERROR, "Violation of protocol specs (e.g. invalid information element)", EXPFILL }}, + }; + + expert_module_t* expert_gcsna; + + proto_gcsna = proto_register_protocol( + "GCSNA", /* name */ + "GCSNA", /* short name */ + "gcsna" /* abbrev */ + ); + + register_dissector("gcsna", dissect_gcsna, proto_gcsna); + + proto_register_field_array(proto_gcsna, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + expert_gcsna = expert_register_protocol(proto_gcsna); + expert_register_field_array(expert_gcsna, ei, array_length(ei)); + +} + +void +proto_reg_handoff_gcsna(void) +{ + static int once = 1; + + if (once == 1) + { + cdma2k_handle = find_dissector("cdma2k"); + gcsna_handle = create_dissector_handle(dissect_gcsna, proto_gcsna); + once = 0; + } +} -- cgit v1.2.3