/* packet-ossp.c * Routines for Organization Specific Slow Protocol dissection * IEEE Std 802.3, Annex 57B * * Copyright 2002 Steve Housley * Copyright 2009 Artem Tamazov * Copyright 2010 Roberto Morro * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include #include #include /* General declarations */ void proto_register_ossp(void); void proto_reg_handoff_ossp(void); static dissector_handle_t ossp_handle; /* * ESMC */ #define OUI_SIZE 3 #define ESMC_ITU_SUBTYPE 0x0001 #define ESMC_VERSION_1 0x01 #define ESMC_QL_TLV_TYPE 0x01 #define ESMC_QL_TLV_LENGTH 0x04 #define ESMC_EXTENDED_QL_TLV_TYPE 0x02 #define ESMC_EXTENDED_QL_TLV_LENGTH 0x14 static const true_false_string esmc_event_flag_tfs = { "Time-critical Event ESMC PDU", "Information ESMC PDU" }; static const value_string esmc_tlv_type_vals[] = { { 1, "Quality Level" }, { 2, "Extended Quality Level" }, { 0, NULL } }; /* G.781 5.5.1.1 Option I SDH (same in G.707) */ static const value_string esmc_quality_level_opt_1_vals[] = { // SSM only codes { 2, "QL-PRC, Primary reference clock (G.811)" }, { 4, "QL-SSU-A, Type I or V SSU clock (G.812), 'transit node clock'" }, { 8, "QL-SSU-B, Type VI SSU clock (G.812), 'local node clock'" }, { 11, "QL-EEC1, EEC (G.8262, Option I) or SEC clock (G.813, Option I)" }, { 15, "QL-DNU, 'Do Not Use'" }, // SSM+eSSM codes { (0xFF<<8) | 2, "QL-PRC, Primary reference clock (G.811)" }, { (0xFF<<8) | 4, "QL-SSU-A, Type I or V SSU clock (G.812), 'transit node clock'" }, { (0xFF<<8) | 8, "QL-SSU-B, Type VI SSU clock (G.812), 'local node clock'" }, { (0xFF<<8) | 11, "QL-EEC1, EEC (G.8262, Option I) or SEC clock (G.813, Option I)" }, { (0xFF<<8) | 15, "QL-DNU, 'Do Not Use'" }, { (0x20<<8) | 2, "QL-PRTC, Primary Reference Time Clock" }, { (0x21<<8) | 2, "QL-ePRTC, Enhanced Primary Reference Time Clock"}, { (0x22<<8) | 11, "QL-eEEC, Enhanced Ethernet Equipment Clock" }, { (0x23<<8) | 2, "QL-ePRC, Enhanced Primary Reference Clock" }, { 0, NULL } }; static const value_string esmc_quality_level_opt_1_vals_short[] = { // SSM codes { 2, "QL-PRC" }, { 4, "QL-SSU-A" }, { 8, "QL-SSU-B" }, { 11, "QL-EEC1" }, { 15, "QL-DNU" }, // SSM+eSSM codes { (0xFF<<8) | 2, "QL-PRC" }, { (0xFF<<8) | 4, "QL-SSU-A" }, { (0xFF<<8) | 8, "QL-SSU-B" }, { (0xFF<<8) | 11, "QL-EEC1" }, { (0xFF<<8) | 15, "QL-DNU" }, { (0x20<<8) | 2, "QL-PRTC" }, { (0x21<<8) | 2, "QL-ePRTC"}, { (0x22<<8) | 11, "QL-eEEC" }, { (0x23<<8) | 2, "QL-ePRC" }, { 0, NULL } }; /* G.781 5.5.1.2 Option II SDH synchronization networking */ static const value_string esmc_quality_level_opt_2_vals[] = { // SSM codes { 0, "QL-STU, unknown - signal does not carry the QL message of the source" }, { 1, "QL-PRS, PRS clock (G.811) / ST1, Stratum 1 Traceable" }, { 4, "QL-TNC, Transit Node Clock (G.812, Type V)" }, { 7, "QL-ST2, Stratum 2 clock (G.812, Type II)" }, { 10, "QL-ST3, Stratum 3 clock (G.812, Type IV) or QL-EEC2 (G.8262)" }, { 13, "QL-ST3E, Stratum 3E clock (G.812, Type III)" }, { 14, "QL-PROV, provisionable by the network operator / Reserved for Network Synchronization" }, { 15, "QL-DUS, shall not be used for synchronization" }, // SSM+eSSM codes { (0xFF<<8) | 0, "QL-STU, unknown - signal does not carry the QL message of the source" }, { (0xFF<<8) | 1, "QL-PRS, PRS clock (G.811) / ST1, Stratum 1 Traceable" }, { (0xFF<<8) | 4, "QL-TNC, Transit Node Clock (G.812, Type V)" }, { (0xFF<<8) | 7, "QL-ST2, Stratum 2 clock (G.812, Type II)" }, { (0xFF<<8) | 10, "QL-ST3, Stratum 3 clock (G.812, Type IV) or QL-EEC2 (G.8262)" }, { (0xFF<<8) | 13, "QL-ST3E, Stratum 3E clock (G.812, Type III)" }, { (0xFF<<8) | 14, "QL-PROV, provisionable by the network operator / Reserved for Network Synchronization" }, { (0xFF<<8) | 15, "QL-DUS, shall not be used for synchronization" }, { (0x20<<8) | 1, "QL-PRTC, Primary Reference Time Clock" }, { (0x21<<8) | 1, "QL-ePRTC, Enhanced Primary Reference Time Clock" }, { (0x22<<8) | 10, "QL-eEEC, Enhanced Ethernet Equipment Clock" }, { (0x23<<8) | 1, "QL-ePRC, Enhanced Primary Reference Clock" }, { 0, NULL } }; static const value_string esmc_quality_level_opt_2_vals_short[] = { // SSM codes { 0, "QL-STU" }, { 1, "QL-PRS" }, { 4, "QL-TNC" }, { 7, "QL-ST2" }, { 10, "QL-ST3" }, { 13, "QL-ST3E" }, { 14, "QL-PROV" }, { 15, "QL-DUS" }, // SSM+eSSM codes { (0xFF<<8) | 0, "QL-STU" }, { (0xFF<<8) | 1, "QL-PRS" }, { (0xFF<<8) | 4, "QL-TNC" }, { (0xFF<<8) | 7, "QL-ST2" }, { (0xFF<<8) | 10, "QL-ST3" }, { (0xFF<<8) | 13, "QL-ST3E" }, { (0xFF<<8) | 14, "QL-PROV" }, { (0xFF<<8) | 15, "QL-DUS" }, { (0x20<<8) | 1, "QL-PRTC" }, { (0x21<<8) | 1, "QL-ePRTC" }, { (0x22<<8) | 10, "QL-eEEC" }, { (0x23<<8) | 1, "QL-ePRC" }, { 0, NULL } }; /* G.781 5.5.1.3 Option III SDH synchronization networking */ static const value_string esmc_quality_level_opt_3_vals[] = { // SSM { 0, "QL-UNK, Unknown" }, { 11, "QL-EEC1, EEC (G.8262, Option I) or SEC clock (G.813, Option I)" }, // SSM+eSSM codes { (0xFF<<8) | 0, "QL-UNK, Unknown" }, { (0xFF<<8) | 11, "QL-EEC1, EEC (G.8262, Option I) or SEC clock (G.813, Option I)" }, { 0, NULL } }; static const value_string esmc_quality_level_opt_3_vals_short[] = { // SSM { 0, "QL-UNK" }, { 11, "QL-EEC1" }, // SSM+eSSM codes { (0xFF<<8) | 0, "QL-UNK" }, { (0xFF<<8) | 11, "QL-EEC1" }, { 0, NULL } }; static const value_string *esmc_quality_level_vals[] = { NULL, esmc_quality_level_opt_1_vals, esmc_quality_level_opt_2_vals, esmc_quality_level_opt_3_vals }; static const value_string *esmc_quality_level_vals_short[] = { NULL, esmc_quality_level_opt_1_vals_short, esmc_quality_level_opt_2_vals_short, esmc_quality_level_opt_3_vals_short }; /* Initialise the protocol and registered fields */ static int proto_ossp = -1; static int hf_ossp_oui = -1; static int hf_itu_subtype = -1; static int hf_esmc_version = -1; static int hf_esmc_event_flag = -1; static int hf_esmc_reserved_bits = -1; static int hf_esmc_reserved_octets = -1; static int hf_esmc_tlv = -1; static int hf_esmc_tlv_type = -1; static int hf_esmc_tlv_length = -1; static int hf_esmc_tlv_ql_unused = -1; static int hf_esmc_tlv_ql_ssm = -1; static int hf_esmc_tlv_ext_ql_essm = -1; static int hf_esmc_tlv_ext_ql_clockid = -1; static int hf_esmc_tlv_ext_ql_flag_reserved = -1; static int hf_esmc_tlv_ext_ql_flag_chain = -1; static int hf_esmc_tlv_ext_ql_flag_mixed = -1; static int hf_esmc_tlv_ext_ql_eeec = -1; static int hf_esmc_tlv_ext_ql_eec = -1; static int hf_esmc_tlv_ext_ql_reserved = -1; static int hf_esmc_quality_level = -1; static int hf_esmc_padding = -1; /* Initialise the subtree pointers */ static gint ett_ossppdu = -1; static gint ett_itu_ossp = -1; static gint ett_esmc = -1; static expert_field ei_esmc_tlv_type_ql_type_not_first = EI_INIT; static expert_field ei_esmc_tlv_type_not_ext_ql = EI_INIT; static expert_field ei_esmc_quality_level_invalid = EI_INIT; static expert_field ei_esmc_tlv_ql_unused_not_zero = EI_INIT; static expert_field ei_esmc_tlv_type_decoded_as_ext_ql = EI_INIT; static expert_field ei_esmc_tlv_type_decoded_as_ql_type = EI_INIT; static expert_field ei_esmc_version_compliance = EI_INIT; static expert_field ei_esmc_tlv_length_bad = EI_INIT; static expert_field ei_esmc_reserved_not_zero = EI_INIT; static gint pref_option_network = 1; static const enum_val_t pref_option_network_vals[] = { { "1", "Option I network", 1 }, /* G.781 5.5.1.1 Option I SDH (same in G.707) */ { "2", "Option II network", 2 }, /* G.781 5.5.1.2 Option II SDH synchronization networking */ //{ "3", "Option III network", 3 }, /* G.781 5.5.1.3 Option III SDH synchronization networking */ { NULL, NULL, 0 } }; static void dissect_esmc_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *treex); static void dissect_itu_ossp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); /* * Name: dissect_ossp_pdu * * Description: * This function is used to dissect the Organization Specific Slow * Protocol defined in IEEE 802.3 Annex 57B. Currently only the ESMC * slow protocol as defined in ITU-T G.8264 is implemented * * Input Arguments: * tvb: buffer associated with the rcv packet (see tvbuff.h). * pinfo: structure associated with the rcv packet (see packet_info.h). * tree: the protocol tree associated with the rcv packet (see proto.h). * * Return Values: None * * Notes: * Roberto Morro (roberto.morro[AT]tilab.com) */ static int dissect_ossp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { gint offset = 0; const gchar *str; proto_item *ossp_item; proto_tree *ossp_tree; tvbuff_t *ossp_tvb; guint32 oui; col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSSP"); ossp_item = proto_tree_add_protocol_format(tree, proto_ossp, tvb, 0, -1, "Organization Specific Slow Protocol"); ossp_tree = proto_item_add_subtree(ossp_item, ett_ossppdu); proto_tree_add_item_ret_uint(ossp_tree, hf_ossp_oui, tvb, offset, OUI_SIZE, ENC_BIG_ENDIAN, &oui); str = uint_get_manuf_name_if_known(oui); col_add_fstr(pinfo->cinfo, COL_INFO, "OUI: %s", (str != NULL) ? str : "(Unknown OSSP organization)"); offset += 3; /* * XXX - should have a dissector table here, but we don't yet * support OUIs as keys in dissector tables. */ ossp_tvb = tvb_new_subset_remaining(tvb, offset); if (OUI_ITU_T == oui) { dissect_itu_ossp(ossp_tvb, pinfo, ossp_tree); } /* new Organization Specific Slow Protocols go hereafter */ #if 0 else if (OUI_XXX == oui) { dissect_xxx_ossp(ossp_tvb, pinfo, ossp_tree); } else if (OUI_YYY == oui) { dissect_yyy_ossp(ossp_tvb, pinfo, ossp_tree); } #endif return tvb_captured_length(tvb); } /* * Name: dissect_itu_ossp * * Description: * This function is used to dissect the ITU-T OSSP (Organization Specific * Slow Protocol). Currently only the Ethernet Synchronization * Messaging Channel (ESMC) slow protocol as defined in ITU-T G.8264 * is implemented * * Input Arguments: * tvb: buffer associated with the rcv packet (see tvbuff.h). * pinfo: structure associated with the rcv packet (see packet_info.h). * tree: the protocol tree associated with the rcv packet (see proto.h). * subtype: the protocol subtype (according to IEEE802.3 annex 57B) * * Return Values: None * * Notes: * Roberto Morro (roberto.morro[AT]tilab.com) */ static void dissect_itu_ossp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 subtype; proto_item *ti; proto_tree *itu_ossp_tree; tvbuff_t *ossp_subtype_tvb; /* ITU-T OSSP Subtype */ subtype = tvb_get_ntohs(tvb, 0); ti = proto_tree_add_item(tree, hf_itu_subtype, tvb, 0, 2, ENC_BIG_ENDIAN); itu_ossp_tree = proto_item_add_subtree(ti, ett_itu_ossp); ossp_subtype_tvb = tvb_new_subset_remaining(tvb, 2); switch (subtype) { case ESMC_ITU_SUBTYPE: dissect_esmc_pdu(ossp_subtype_tvb, pinfo, itu_ossp_tree); break; /* Other ITU-T defined slow protocols go hereafter */ #if 0 case XXXX_ITU_SUBTYPE: dissect_xxxx_pdu(tvb, pinfo, itu_ossp_tree); break; #endif default: proto_item_append_text(itu_ossp_tree, " (Unknown)"); } } /* * Description: * This function is used to dissect ESMC PDU defined G.8264/Y.1364 * clause 11.3.1. */ static void dissect_esmc_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *treex) { gint offset = 0; gboolean event_flag; gint ssm = 0; gint essm = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESMC"); proto_item_append_text(treex, ": ESMC"); { proto_tree *tree_a; tree_a = proto_item_add_subtree(treex, ett_esmc); { /* version */ proto_item *item_b; item_b = proto_tree_add_item(tree_a, hf_esmc_version, tvb, offset, 1, ENC_BIG_ENDIAN); if ((tvb_get_guint8(tvb, offset) >> 4) != ESMC_VERSION_1) { expert_add_info_format(pinfo, item_b, &ei_esmc_version_compliance, "Version must be 0x%.1x claim compliance with Version 1 of this protocol", ESMC_VERSION_1); } /*stay at the same octet in tvb*/ } { /* event flag */ event_flag = ((tvb_get_guint8(tvb, offset) & 0x08) != 0); proto_tree_add_item(tree_a, hf_esmc_event_flag, tvb, offset, 1, ENC_BIG_ENDIAN); /*stay at the same octet in tvb*/ } { /* reserved bits */ proto_item *item_b; guint8 reserved; reserved = tvb_get_guint8(tvb, offset) & 0x07; item_b = proto_tree_add_uint_format_value(tree_a, hf_esmc_reserved_bits, tvb, offset, 1, reserved, "0x%.2x", reserved); if (reserved != 0x0) { expert_add_info_format(pinfo, item_b, &ei_esmc_reserved_not_zero, "Reserved bits must be set to all zero on transmitter"); } offset += 1; } { /* reserved octets */ proto_item *item_b; guint32 reserved; reserved = tvb_get_ntoh24(tvb, offset); item_b = proto_tree_add_uint_format_value(tree_a, hf_esmc_reserved_octets, tvb, offset, 3, reserved, "0x%.6x", reserved); if (reserved != 0x0) { expert_add_info_format(pinfo, item_b, &ei_esmc_reserved_not_zero, "Reserved octets must be set to all zero on transmitter"); } offset += 3; } proto_item_append_text(treex, ", Event:%s", event_flag ? "Time-critical" : "Information"); col_add_fstr(pinfo->cinfo, COL_INFO, "Event:%s", event_flag ? "Time-critical" : "Information"); /* * Quality Level TLV is mandatory at fixed location. */ { proto_item *item_b; guint8 type; item_b = proto_tree_add_item(tree_a, hf_esmc_tlv, tvb, offset, ESMC_QL_TLV_LENGTH, ENC_NA); { proto_tree *tree_b; tree_b = proto_item_add_subtree(item_b, ett_esmc); { proto_item *item_c; guint16 length; guint8 unused; /* type */ type = tvb_get_guint8(tvb, offset); item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN); if (type != ESMC_QL_TLV_TYPE) { expert_add_info_format(pinfo, item_c, &ei_esmc_tlv_type_ql_type_not_first, "TLV Type must be == 0x%.2x (QL) because QL TLV must be first in the ESMC PDU", ESMC_QL_TLV_TYPE); expert_add_info(pinfo, item_c, &ei_esmc_tlv_type_decoded_as_ql_type); } proto_item_append_text(item_b, ", %s", val_to_str_const(type, esmc_tlv_type_vals, "Unknown")); offset += 1; /* length */ length = tvb_get_ntohs(tvb, offset); item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_length, tvb, offset, 2, ENC_BIG_ENDIAN); if (length != ESMC_QL_TLV_LENGTH) { expert_add_info_format(pinfo, item_c, &ei_esmc_tlv_length_bad, "QL TLV Length must be == 0x%.4x", ESMC_QL_TLV_LENGTH); expert_add_info_format(pinfo, item_c, &ei_esmc_tlv_type_decoded_as_ql_type, "Let's decode this TLV as if Length has valid value"); } offset += 2; /* value */ ssm = tvb_get_guint8(tvb, offset); unused = ssm & 0xf0; ssm &= 0x0f; item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_ql_unused, tvb, offset, 1, ENC_BIG_ENDIAN); if (unused != 0x00) { expert_add_info(pinfo, item_c, &ei_esmc_tlv_ql_unused_not_zero); } proto_tree_add_item(tree_b, hf_esmc_tlv_ql_ssm, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } } } /* * Extended Quality Level TLV is optional at fixed location. */ if (tvb_captured_length_remaining(tvb, offset) >= ESMC_EXTENDED_QL_TLV_LENGTH) { guint8 type; type = tvb_get_guint8(tvb, offset); if (type == ESMC_EXTENDED_QL_TLV_TYPE) { proto_item *item_b; item_b = proto_tree_add_item(tree_a, hf_esmc_tlv, tvb, offset, ESMC_EXTENDED_QL_TLV_LENGTH, ENC_NA); { proto_tree *tree_b; tree_b = proto_item_add_subtree(item_b, ett_esmc); { proto_item *item_c; guint16 length; guint64 reserved; /* type */ item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_type, tvb, offset, 1, ENC_BIG_ENDIAN); if (type != ESMC_EXTENDED_QL_TLV_TYPE) { expert_add_info_format(pinfo, item_c, &ei_esmc_tlv_type_not_ext_ql, "TLV Type must be == 0x%.2x (Extended QL)", ESMC_EXTENDED_QL_TLV_TYPE); expert_add_info(pinfo, item_c, &ei_esmc_tlv_type_decoded_as_ext_ql); } proto_item_append_text(item_b, ", %s", val_to_str_const(type, esmc_tlv_type_vals, "Unknown")); offset += 1; /* length */ length = tvb_get_ntohs(tvb, offset); item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_length, tvb, offset, 2, ENC_BIG_ENDIAN); if (length != ESMC_EXTENDED_QL_TLV_LENGTH) { expert_add_info_format(pinfo, item_c, &ei_esmc_tlv_length_bad, "Extended QL TLV Length must be == 0x%.4x", ESMC_EXTENDED_QL_TLV_LENGTH); expert_add_info_format(pinfo, item_c, &ei_esmc_tlv_type_decoded_as_ext_ql, "Let's decode this TLV as if Length has valid value"); } offset += 2; /* Enhanced SSM code */ essm = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_essm, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* SyncE clockIdentity */ proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_clockid, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Flag */ reserved = tvb_get_guint8(tvb, offset) & 0xfc; item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_flag_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); if (reserved != 0x0) { expert_add_info(pinfo, item_c, &ei_esmc_reserved_not_zero); } proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_flag_chain, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_flag_mixed, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Cascaded eEECs */ proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_eeec, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Cascaded EECs */ proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_eec, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Reserved */ reserved = tvb_get_guint40(tvb, offset, ENC_BIG_ENDIAN); item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_ext_ql_reserved, tvb, offset, 5, ENC_BIG_ENDIAN); if (reserved != 0x0) { expert_add_info(pinfo, item_c, &ei_esmc_reserved_not_zero); } offset += 5; } } } } } /* Derive Quality Level from SSM/eSSM based on * ITU-T G.8264/Y.1364 (2017)/Amd.1 (03.2018) * Table 11-7 and Table 11-8. */ { const value_string *ql_vals; const value_string *ql_vals_short; const gchar *ql_str; proto_item *item_b; ql_vals = esmc_quality_level_vals[pref_option_network]; ql_vals_short = esmc_quality_level_vals_short[pref_option_network]; ql_str = try_val_to_str((essm<<8) | ssm, ql_vals); item_b = proto_tree_add_uint_format_value(treex, hf_esmc_quality_level, tvb, 6, offset-6, (essm<<8) | ssm, "%s", (NULL != ql_str) ? ql_str : "Unknown Quality Level"); proto_item_set_generated(item_b); if (NULL == ql_str) { expert_add_info(pinfo, item_b, &ei_esmc_quality_level_invalid); } col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const((essm<<8) | ssm, ql_vals_short, "Unknown Quality Level")); } { /* padding */ gint padding_size; padding_size = tvb_captured_length_remaining(tvb, offset); if (0 != padding_size) { proto_tree* tree_a; tree_a = proto_item_add_subtree(treex, ett_esmc); { proto_item* item_b; tvbuff_t* tvb_next; tvb_next = tvb_new_subset_remaining(tvb, offset); item_b = proto_tree_add_item(tree_a, hf_esmc_padding, tvb_next, 0, -1, ENC_NA); proto_item_append_text(item_b, ", %d %s%s", padding_size, "octet", plurality(padding_size,"","s")); { proto_tree* tree_b; tree_b = proto_item_add_subtree(item_b, ett_esmc); call_data_dissector(tvb_next, pinfo, tree_b); } } } } } /* Register the protocol with Wireshark */ void proto_register_ossp(void) { /* Setup list of header fields */ static hf_register_info hf[] = { { &hf_ossp_oui, { "OUI", "ossp.oui", FT_UINT24, BASE_OUI, NULL, 0, "IEEE assigned Organizational Unique Identifier", HFILL }}, { &hf_itu_subtype, { "ITU-T OSSP Subtype", "ossp.itu.subtype", FT_UINT16, BASE_HEX, NULL, 0, "Subtype assigned by the ITU-T", HFILL }}, { &hf_esmc_version, { "Version", "ossp.esmc.version", FT_UINT8, BASE_HEX, NULL, 0xf0, "Version of ITU-T OSSP frame format", HFILL }}, { &hf_esmc_event_flag, { "Event Flag", "ossp.esmc.event_flag", FT_BOOLEAN, 8, TFS(&esmc_event_flag_tfs), 0x08, "This bit distinguishes the critical, time sensitive behaviour of the " "ESMC Event PDU from the ESMC Information PDU", HFILL }}, { &hf_esmc_reserved_bits, { "Reserved", "ossp.esmc.reserved_bits", FT_UINT8, BASE_HEX, NULL, 0x07, "Reserved. Set to all zero at the transmitter and ignored by the receiver", HFILL }}, { &hf_esmc_reserved_octets, { "Reserved", "ossp.esmc.reserved", FT_UINT24, BASE_HEX, NULL, 0, "Reserved. Set to all zero at the transmitter and ignored by the receiver", HFILL }}, { &hf_esmc_tlv, { "ESMC TLV", "ossp.esmc.tlv", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }}, { &hf_esmc_tlv_type, { "TLV Type", "ossp.esmc.tlv_type", FT_UINT8, BASE_HEX, VALS(esmc_tlv_type_vals), 0, NULL, HFILL }}, { &hf_esmc_tlv_length, { "TLV Length", "ossp.esmc.tlv_length", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }}, { &hf_esmc_tlv_ql_unused, { "Unused", "ossp.esmc.tlv_ql_unused", FT_UINT8, BASE_HEX, NULL, 0xf0, "This field is not used in QL TLV", HFILL }}, { &hf_esmc_tlv_ql_ssm, { "SSM Code", "ossp.esmc.tlv_ql_ssm", FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL }}, { &hf_esmc_tlv_ext_ql_essm, { "Enhanced SSM Code", "ossp.esmc.tlv_ext_ql_essm", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }}, { &hf_esmc_tlv_ext_ql_clockid, { "SyncE clockID", "ossp.esmc.tlv_ext_ql_clockid", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL }}, { &hf_esmc_tlv_ext_ql_flag_reserved, { "Reserved", "ossp.esmc.tlv_ext_ql_flag_reserved", FT_UINT8, BASE_HEX, NULL, 0xfc, "Reserved. Set to all zero at the transmitter and ignored by the receiver", HFILL }}, { &hf_esmc_tlv_ext_ql_flag_chain, { "Partial chain", "ossp.esmc.tlv_ext_ql_flag_chain", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02, "Whether or not the TLV has been generated in the middle of the chain", HFILL }}, { &hf_esmc_tlv_ext_ql_flag_mixed, { "Mixed EEC/eEEC clocks", "ossp.esmc.tlv_ext_ql_flag_mixed", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01, "Whether of not there is at least one non-eEEC clock in the chain", HFILL }}, { &hf_esmc_tlv_ext_ql_eeec, { "Cascaded eEECs", "ossp.esmc.tlv_ext_ql_eeec", FT_UINT8, BASE_DEC, NULL, 0, "Number of cascaded eEECs from nearest SSU/PRC", HFILL }}, { &hf_esmc_tlv_ext_ql_eec, { "Cascaded EECs", "ossp.esmc.tlv_ext_ql_eec", FT_UINT8, BASE_DEC, NULL, 0, "Number of cascaded EECs from nearest SSU/PRC", HFILL }}, { &hf_esmc_tlv_ext_ql_reserved, { "Reserved", "ossp.esmc.tlv_ext_ql_reserved", FT_UINT40, BASE_HEX, NULL, 0, "Reserved. Set to all zero at the transmitter and ignored by the receiver", HFILL }}, { &hf_esmc_quality_level, { "Quality Level", "ossp.esmc.ql", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }}, { &hf_esmc_padding, { "Padding", "ossp.esmc.padding", FT_BYTES, BASE_NONE, NULL, 0x0, "This field contains necessary padding to achieve the minimum frame size of 64 bytes at least", HFILL }}, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_esmc, &ett_ossppdu, &ett_itu_ossp }; /* Setup expert info array */ static ei_register_info ei[] = { { &ei_esmc_version_compliance, { "ossp.esmc.version.compliance", PI_MALFORMED, PI_ERROR, "Version must claim compliance with Version 1 of this protocol", EXPFILL }}, { &ei_esmc_tlv_type_ql_type_not_first, { "ossp.esmc.tlv_type.ql_type_not_first", PI_MALFORMED, PI_ERROR, "TLV Type must be QL because QL TLV must be first in the ESMC PDU", EXPFILL }}, { &ei_esmc_tlv_type_decoded_as_ql_type, { "ossp.esmc.tlv_type.decoded_as_ql_type", PI_UNDECODED, PI_NOTE, "Let's decode as if this is QL TLV", EXPFILL }}, { &ei_esmc_tlv_length_bad, { "ossp.esmc.tlv_length.bad", PI_MALFORMED, PI_ERROR, "QL TLV Length must be X", EXPFILL }}, { &ei_esmc_tlv_ql_unused_not_zero, { "ossp.esmc.tlv_ql_unused.not_zero", PI_MALFORMED, PI_WARN, "Unused bits of TLV must be all zeroes", EXPFILL }}, { &ei_esmc_quality_level_invalid, { "ossp.esmc.ql.invalid", PI_UNDECODED, PI_WARN, "Invalid SSM message, unknown QL code", EXPFILL }}, { &ei_esmc_tlv_type_not_ext_ql, { "ossp.esmc.tlv_type.not_ext_ql", PI_MALFORMED, PI_ERROR, "TLV Type must be == Extended QL", EXPFILL }}, { &ei_esmc_tlv_type_decoded_as_ext_ql, { "ossp.esmc.tlv_type.decoded_as_ext_ql", PI_UNDECODED, PI_NOTE, "Let's decode as if this is Extended QL TLV", EXPFILL }}, { &ei_esmc_reserved_not_zero, { "ossp.esmc.reserved_bits_must_be_set_to_all_zero", PI_PROTOCOL, PI_WARN, "Reserved bits must be set to all zero", EXPFILL }}, }; expert_module_t *expert_ossp; module_t *prefs_ossp; /* Register the protocol name and description */ proto_ossp = proto_register_protocol("OSSP", "Organization Specific Slow Protocol", "ossp"); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_ossp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); /* Register the exert items */ expert_ossp = expert_register_protocol(proto_ossp); expert_register_field_array(expert_ossp, ei, array_length(ei)); /* Register the preferences */ prefs_ossp = prefs_register_protocol(proto_ossp, NULL); prefs_register_enum_preference(prefs_ossp, "option_network", "Regional option", "Select the option of the network to interpret the Quality Level for", &pref_option_network, pref_option_network_vals, TRUE); /* Register the dissector */ ossp_handle = register_dissector("ossp", dissect_ossp_pdu, proto_ossp); } void proto_reg_handoff_ossp(void) { dissector_add_uint("slow.subtype", OSSP_SUBTYPE, ossp_handle); } /* * 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: */