/* packet-etheric.c * Routines for Etheric dissection a Ericsson propriatary protocol. * See * * http://watersprings.org/pub/id/draft-toivanen-sccp-etheric-00.txt * * XXX - the version in that draft appears to use the same codes for * parameters as ISUP does, although it doesn't use all of them. Should * we use the ISUP dissector's #defines and tables for them, as we do * now, or should we use our own? * * We also use its table for message types, but have our own #defines * for them; should we adopt the ISUP dissector's #defines, or have our * own table? * * Copyright 2004, Anders Broman * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include "packet-e164.h" #include "packet-q931.h" #include "packet-isup.h" /* Initialize the protocol and registered fields */ static int proto_etheric = -1; static int hf_etheric_protocol_version = -1; static int hf_etheric_message_length = -1; static int hf_etheric_cic = -1; static int hf_etheric_message_type = -1; static int hf_etheric_parameter_type = -1; static int hf_etheric_calling_partys_category = -1; static int hf_etheric_forw_call_isdn_access_indicator = -1; static int hf_etheric_transmission_medium_requirement = -1; static int hf_etheric_odd_even_indicator = -1; static int hf_etheric_called_party_nature_of_address_indicator = -1; static int hf_etheric_ni_indicator = -1; static int hf_etheric_calling_party_nature_of_address_indicator = -1; static int hf_etheric_inn_indicator = -1; static int hf_etheric_numbering_plan_indicator = -1; static int hf_etheric_address_presentation_restricted_indicator = -1; static int hf_etheric_screening_indicator = -1; static int hf_etheric_called_party_odd_address_signal_digit = -1; static int hf_etheric_calling_party_odd_address_signal_digit = -1; static int hf_etheric_called_party_even_address_signal_digit = -1; static int hf_etheric_calling_party_even_address_signal_digit = -1; static int hf_etheric_mandatory_variable_parameter_pointer = -1; static int hf_etheric_parameter_length = -1; static int hf_etheric_pointer_to_start_of_optional_part = -1; static int hf_etheric_inband_information_ind = -1; static int hf_etheric_cause_indicator = -1; static int hf_etheric_event_ind = -1; static int hf_etheric_event_presentation_restricted_ind = -1; /* Initialize the subtree pointers */ static gint ett_etheric = -1; static gint ett_etheric_parameter = -1; static gint ett_etheric_address_digits = -1; static gint ett_etheric_circuit_state_ind = -1; /* set the tcp port */ static guint ethericTCPport1 =1806; static guint ethericTCPport2 =10002; static dissector_handle_t q931_ie_handle = NULL; /* Value strings */ static const value_string protocol_version_vals[] = { { 0x00, "Etheric 1.0" }, { 0x10, "Etheric 2.0" }, { 0x11, "Etheric 2.1" }, { 0, NULL } }; /* Definition of Message Types */ #define ETHERIC_MESSAGE_TYPE_INITIAL_ADDR 1 #define ETHERIC_MESSAGE_TYPE_SUBSEQ_ADDR 2 #define ETHERIC_MESSAGE_TYPE_INFO_REQ 3 #define ETHERIC_MESSAGE_TYPE_INFO 4 #define ETHERIC_MESSAGE_TYPE_CONTINUITY 5 #define ETHERIC_MESSAGE_TYPE_ADDR_CMPL 6 #define ETHERIC_MESSAGE_TYPE_CONNECT 7 #define ETHERIC_MESSAGE_TYPE_FORW_TRANS 8 #define ETHERIC_MESSAGE_TYPE_ANSWER 9 #define ETHERIC_MESSAGE_TYPE_RELEASE 12 #define ETHERIC_MESSAGE_TYPE_SUSPEND 13 #define ETHERIC_MESSAGE_TYPE_RESUME 14 #define ETHERIC_MESSAGE_TYPE_REL_CMPL 16 #define ETHERIC_MESSAGE_TYPE_CONT_CHECK_REQ 17 #define ETHERIC_MESSAGE_TYPE_RESET_CIRCUIT 18 #define ETHERIC_MESSAGE_TYPE_BLOCKING 19 #define ETHERIC_MESSAGE_TYPE_UNBLOCKING 20 #define ETHERIC_MESSAGE_TYPE_BLOCK_ACK 21 #define ETHERIC_MESSAGE_TYPE_UNBLOCK_ACK 22 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_RST 23 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_BLCK 24 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_UNBL 25 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_BL_ACK 26 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_UNBL_ACK 27 #define ETHERIC_MESSAGE_TYPE_FACILITY_REQ 31 #define ETHERIC_MESSAGE_TYPE_FACILITY_ACC 32 #define ETHERIC_MESSAGE_TYPE_FACILITY_REJ 33 #define ETHERIC_MESSAGE_TYPE_LOOP_BACK_ACK 36 #define ETHERIC_MESSAGE_TYPE_PASS_ALONG 40 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_RST_ACK 41 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_QRY 42 #define ETHERIC_MESSAGE_TYPE_CIRC_GRP_QRY_RSP 43 #define ETHERIC_MESSAGE_TYPE_CALL_PROGRSS 44 #define ETHERIC_MESSAGE_TYPE_USER2USER_INFO 45 #define ETHERIC_MESSAGE_TYPE_UNEQUIPPED_CIC 46 #define ETHERIC_MESSAGE_TYPE_CONFUSION 47 #define ETHERIC_MESSAGE_TYPE_OVERLOAD 48 #define ETHERIC_MESSAGE_TYPE_CHARGE_INFO 49 #define ETHERIC_MESSAGE_TYPE_NETW_RESRC_MGMT 50 #define ETHERIC_MESSAGE_TYPE_FACILITY 51 #define ETHERIC_MESSAGE_TYPE_USER_PART_TEST 52 #define ETHERIC_MESSAGE_TYPE_USER_PART_AVAIL 53 #define ETHERIC_MESSAGE_TYPE_IDENT_REQ 54 #define ETHERIC_MESSAGE_TYPE_IDENT_RSP 55 #define ETHERIC_MESSAGE_TYPE_SEGMENTATION 56 #define ETHERIC_MESSAGE_TYPE_LOOP_PREVENTION 64 #define ETHERIC_MESSAGE_TYPE_APPLICATION_TRANS 65 #define ETHERIC_MESSAGE_TYPE_PRE_RELEASE_INFO 66 #define ETHERIC_MESSAGE_TYPE_SUBSEQUENT_DIR_NUM 67 static const true_false_string isup_ISDN_originating_access_ind_value = { "originating access ISDN", "originating access non-ISDN" }; static const value_string etheric_calling_partys_category_value[] = { { 0, "Reserved"}, { 1, "Reserved"}, { 2, "Reserved"}, { 3, "Reserved"}, { 4, "Reserved"}, { 5, "Reserved"}, { 10, "Ordinary calling subscriber"}, { 11, "Reserved"}, { 12, "Reserved"}, { 13, "Test call"}, /* q.763-200212Amd2 */ { 14, "Reserved"}, { 15, "Reserved"}, { 0, NULL}}; static const true_false_string isup_odd_even_ind_value = { "odd number of address signals", "even number of address signals" }; static const value_string isup_called_party_nature_of_address_ind_value[] = { { 0, "Spare"}, { 1, "Reserved"}, { 2, "Reserved"}, { 3, "national (significant) number"}, { 4, "international number"}, { 5, "Reserved"}, { 0, NULL}}; static const true_false_string isup_NI_ind_value = { "incomplete", "complete" }; static const value_string etheric_location_number_nature_of_address_ind_value[] = { { 0, "Spare"}, { 1, "subscriber number (national use)"}, { 2, "unknown (national use)"}, { 3, "national (significant) number"}, { 4, "international number"}, { 0,NULL}}; static const value_string isup_address_presentation_restricted_ind_value[] = { { 0, "Presentation allowed"}, { 1, "Presentation restricted"}, { 2, "Reserved"}, { 3, "Spare"}, { 0, NULL}}; static const value_string isup_screening_ind_value[] = { { 0, "Not available"}, { 1, "User provided, verified and passed"}, { 2, "reserved"}, { 3, "Network provided"}, { 0, NULL}}; static const value_string isup_called_party_address_digit_value[] = { { 0, "0"}, { 1, "1"}, { 2, "2"}, { 3, "3"}, { 4, "4"}, { 5, "5"}, { 6, "6"}, { 7, "7"}, { 8, "8"}, { 9, "9"}, { 10, "spare"}, { 11, "code 11 "}, { 12, "code 12"}, { 15, "Stop sending"}, { 0, NULL}}; static const value_string isup_calling_party_address_digit_value[] = { { 0, "0"}, { 1, "1"}, { 2, "2"}, { 3, "3"}, { 4, "4"}, { 5, "5"}, { 6, "6"}, { 7, "7"}, { 8, "8"}, { 9, "9"}, { 10, "spare"}, { 11, "code 11 "}, { 12, "code 12"}, { 15, "spare"}, { 0, NULL}}; static const true_false_string isup_INN_ind_value = { "routing to internal network number not allowed", "routing to internal network number allowed " }; static const value_string isup_numbering_plan_ind_value[] = { { 1, "ISDN (Telephony) numbering plan"}, { 3, "Data numbering plan (national use)"}, { 4, "Telex numbering plan (national use)"}, { 5, "Reserved for national use"}, { 6, "Reserved for national use"}, { 0, NULL}}; static const true_false_string isup_inband_information_ind_value = { /* according 3.37/Q.763 */ "in-band information or an appropirate pattern is now available", "no indication" }; static const true_false_string isup_event_presentation_restricted_ind_value = { /* according 3.21/Q.763 */ "presentation restricted", "no indication" }; static const value_string isup_event_ind_value[] = { /* according 3.21/Q.763 */ { 1, "ALERTING"}, { 2, "PROGRESS"}, { 3, "in-band information or an appropriate pattern is now available"}, { 4, "call forwarded on busy (national use)"}, { 5, "call forwarded on no reply (national use)"}, { 6, "call forwarded unconditional (national use)"}, { 0, NULL}}; static void dissect_etheric_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *etheric_tree, guint8 etheric_version, guint8 message_length); /* ------------------------------------------------------------------ Mapping number to ASCII-character ------------------------------------------------------------------ */ static char number_to_char_2(int number) { if (number < 10) return ((char) number + 0x30); else return ((char) number + 0x37); } /* Code to actually dissect the packets */ static int dissect_etheric(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *etheric_tree; gint offset = 0; guint8 message_length; guint16 cic; guint8 message_type,etheric_version; tvbuff_t *message_tvb; /* Do we have the version number? */ if (!tvb_bytes_exist(tvb, 0, 1)) { /* No - reject this packet. */ return 0; } etheric_version = tvb_get_guint8(tvb, 0); /* Do we know the version? */ if (match_strval(etheric_version, protocol_version_vals) == NULL) { /* No - reject this packet. */ return 0; } /* Make entries in Protocol column and Info column on summary display */ if (check_col(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, "Etheric"); if (check_col(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO); message_type = tvb_get_guint8(tvb, 4); if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(message_type, isup_message_type_value_acro, "reserved")); if(tree){ /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_etheric, tvb, 0, -1, FALSE); etheric_tree = proto_item_add_subtree(ti, ett_etheric); proto_tree_add_item(etheric_tree, hf_etheric_protocol_version, tvb, offset, 1, FALSE); offset++; message_length = tvb_get_guint8(tvb, offset); proto_tree_add_item(etheric_tree, hf_etheric_message_length, tvb, offset, 1, FALSE); offset++; cic = tvb_get_letohs(tvb, offset) & 0x0FFF; /*since upper 4 bits spare */ proto_tree_add_uint_format(etheric_tree, hf_etheric_cic, tvb, offset, 2, cic, "CIC: %u", cic); offset = offset + 2; message_tvb = tvb_new_subset(tvb, offset, -1, -1); dissect_etheric_message(message_tvb, pinfo, etheric_tree,etheric_version, message_length); }/* end end if tree */ return tvb_length(tvb); } /* ------------------------------------------------------------------ Dissector Parameter Forward Call Indicators */ static void dissect_etheric_forward_call_indicators_parameter(tvbuff_t *parameter_tvb,proto_tree *parameter_tree, proto_item *parameter_item) { guint8 forward_call_ind; forward_call_ind = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_boolean(parameter_tree, hf_etheric_forw_call_isdn_access_indicator, parameter_tvb, 0, 1, forward_call_ind); proto_item_set_text(parameter_item, "Forward Call Indicators: 0x%x", forward_call_ind ); } /* ------------------------------------------------------------------ Dissector Parameter Calling Party's Category */ static void dissect_etheric_calling_partys_category_parameter(tvbuff_t *parameter_tvb,proto_tree *parameter_tree, proto_item *parameter_item) { guint8 calling_partys_category; calling_partys_category = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_uint(parameter_tree, hf_etheric_calling_partys_category, parameter_tvb, 0, 1, calling_partys_category); proto_item_set_text(parameter_item, "Calling Party's category: 0x%x (%s)", calling_partys_category, val_to_str(calling_partys_category, etheric_calling_partys_category_value, "reserved/spare")); } /* ------------------------------------------------------------------ Dissector Parameter Transmission medium requirement */ static void dissect_etheric_transmission_medium_requirement_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { guint8 transmission_medium_requirement; transmission_medium_requirement = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_uint(parameter_tree, hf_etheric_transmission_medium_requirement, parameter_tvb, 0, 1,transmission_medium_requirement); proto_item_set_text(parameter_item, "Transmission medium requirement: %u (%s)", transmission_medium_requirement, val_to_str(transmission_medium_requirement, isup_transmission_medium_requirement_value, "spare")); } /* ------------------------------------------------------------------ Dissector Parameter Called party number */ static void dissect_etheric_called_party_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { proto_item *address_digits_item; proto_tree *address_digits_tree; guint8 indicators1; guint8 address_digit_pair=0; gint offset=0; gint i=0; gint length; char *called_number; e164_info_t e164_info; indicators1 = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_boolean(parameter_tree, hf_etheric_odd_even_indicator, parameter_tvb, 0, 1, indicators1); proto_tree_add_uint(parameter_tree, hf_etheric_called_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1); offset = 1; address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb, offset, -1, "Called Party Number"); address_digits_tree = proto_item_add_subtree(address_digits_item, ett_etheric_address_digits); length = tvb_reported_length_remaining(parameter_tvb, offset); called_number = ep_alloc((length+1) *2); while((length = tvb_reported_length_remaining(parameter_tvb, offset)) > 0){ address_digit_pair = tvb_get_guint8(parameter_tvb, offset); proto_tree_add_uint(address_digits_tree, hf_etheric_called_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair); called_number[i++] = number_to_char_2(address_digit_pair & 0x0F); if ((length - 1) > 0 ){ proto_tree_add_uint(address_digits_tree, hf_etheric_called_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair); called_number[i++] = number_to_char_2((address_digit_pair & 0xf0) / 0x10); } offset++; } if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */ proto_tree_add_uint(address_digits_tree, hf_etheric_called_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair); called_number[i++] = number_to_char_2((address_digit_pair & 0xf0) / 0x10); } called_number[i++] = '\0'; e164_info.e164_number_type = CALLED_PARTY_NUMBER; e164_info.nature_of_address = indicators1 & 0x7f; e164_info.E164_number_str = called_number; e164_info.E164_number_length = i - 1; dissect_e164_number(parameter_tvb, address_digits_tree, 2, (offset - 2), e164_info); proto_item_set_text(address_digits_item, "Called Party Number: %s", called_number); proto_item_set_text(parameter_item, "Called Party Number: %s", called_number); } /* ------------------------------------------------------------------ Dissector Parameter calling party number */ static void dissect_etheric_calling_party_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { proto_item *address_digits_item; proto_tree *address_digits_tree; guint8 indicators1, indicators2; guint8 address_digit_pair=0; gint offset=0; gint i=0; gint length; char *calling_number; e164_info_t e164_info; indicators1 = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_boolean(parameter_tree, hf_etheric_odd_even_indicator, parameter_tvb, 0, 1, indicators1); proto_tree_add_uint(parameter_tree, hf_etheric_called_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1); indicators2 = tvb_get_guint8(parameter_tvb, 1); proto_tree_add_uint(parameter_tree, hf_etheric_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2); proto_tree_add_uint(parameter_tree, hf_etheric_screening_indicator, parameter_tvb, 1, 1, indicators2); offset = 2; address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb, offset, -1, "Calling Party Number"); address_digits_tree = proto_item_add_subtree(address_digits_item, ett_etheric_address_digits); length = tvb_length_remaining(parameter_tvb, offset); /* prevent running behind the end of calling_number array by throwing an exception */ calling_number = ep_alloc((length+1) *2); while(length > 0){ address_digit_pair = tvb_get_guint8(parameter_tvb, offset); proto_tree_add_uint(address_digits_tree, hf_etheric_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair); calling_number[i++] = number_to_char_2(address_digit_pair & 0x0F); if ((length - 1) > 0 ){ proto_tree_add_uint(address_digits_tree, hf_etheric_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair); calling_number[i++] = number_to_char_2((address_digit_pair & 0xF0) / 0x10); } offset++; length = tvb_length_remaining(parameter_tvb, offset); } if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */ proto_tree_add_uint(address_digits_tree, hf_etheric_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair); calling_number[i++] = number_to_char_2((address_digit_pair & 0xF0) / 0x10); } calling_number[i++] = '\0'; proto_item_set_text(address_digits_item, "Calling Party Number: %s", calling_number); proto_item_set_text(parameter_item, "Calling Party Number: %s", calling_number); e164_info.e164_number_type = CALLING_PARTY_NUMBER; e164_info.nature_of_address = indicators1 & 0x7f; e164_info.E164_number_str = calling_number; e164_info.E164_number_length = i - 1; dissect_e164_number(parameter_tvb, address_digits_tree, 2, (offset - 2), e164_info); } /* ------------------------------------------------------------------ Dissector Parameter location number */ static void dissect_etheric_location_number_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { proto_item *address_digits_item; proto_tree *address_digits_tree; guint8 indicators1, indicators2; guint8 address_digit_pair=0; gint offset=0; gint i=0; gint length; char *calling_number; indicators1 = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_boolean(parameter_tree, hf_etheric_odd_even_indicator, parameter_tvb, 0, 1, indicators1); proto_tree_add_uint(parameter_tree, hf_etheric_calling_party_nature_of_address_indicator, parameter_tvb, 0, 1, indicators1); indicators2 = tvb_get_guint8(parameter_tvb, 1); proto_tree_add_boolean(parameter_tree, hf_etheric_inn_indicator, parameter_tvb, 1, 1, indicators2); proto_tree_add_uint(parameter_tree, hf_etheric_numbering_plan_indicator, parameter_tvb, 1, 1, indicators2); if ((indicators2 & 0x70) == 0x50) proto_tree_add_text(parameter_tree, parameter_tvb, 1, 1, "Different meaning for Location Number: Numbering plan indicator = private numbering plan"); proto_tree_add_uint(parameter_tree, hf_etheric_address_presentation_restricted_indicator, parameter_tvb, 1, 1, indicators2); proto_tree_add_uint(parameter_tree, hf_etheric_screening_indicator, parameter_tvb, 1, 1, indicators2); /* NOTE When the address presentation restricted indicator indicates address not available, the * subfields in items a), b), c) and d) are coded with 0's, and the screening indicator is set to 11 * (network provided). */ if ( indicators2 == 0x0b ){ proto_tree_add_text(parameter_tree, parameter_tvb, 1, -1, "Location number: address not available"); proto_item_set_text(parameter_item, "Location number: address not available"); return; } offset = 2; address_digits_item = proto_tree_add_text(parameter_tree, parameter_tvb, offset, -1, "Location number"); address_digits_tree = proto_item_add_subtree(address_digits_item, ett_etheric_address_digits); length = tvb_length_remaining(parameter_tvb, offset); calling_number = ep_alloc((length+1) *2); while(length > 0){ address_digit_pair = tvb_get_guint8(parameter_tvb, offset); proto_tree_add_uint(address_digits_tree, hf_etheric_calling_party_odd_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair); calling_number[i++] = number_to_char_2(address_digit_pair & 0x0f); if ((length - 1) > 0 ){ proto_tree_add_uint(address_digits_tree, hf_etheric_calling_party_even_address_signal_digit, parameter_tvb, offset, 1, address_digit_pair); calling_number[i++] = number_to_char_2((address_digit_pair & 0xf0) / 0x10); } offset++; length = tvb_length_remaining(parameter_tvb, offset); } if (((indicators1 & 0x80) == 0) && (tvb_length(parameter_tvb) > 0)){ /* Even Indicator set -> last even digit is valid & has be displayed */ proto_tree_add_uint(address_digits_tree, hf_etheric_calling_party_even_address_signal_digit, parameter_tvb, offset - 1, 1, address_digit_pair); calling_number[i++] = number_to_char_2((address_digit_pair & 0xf0) / 0x10); } calling_number[i++] = '\0'; proto_item_set_text(address_digits_item, "Location number: %s", calling_number); proto_item_set_text(parameter_item, "Location number: %s", calling_number); } /* ------------------------------------------------------------------ Dissector Parameter User service information- no detailed dissection since defined in Rec. Q.931 */ static void dissect_etheric_user_service_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { guint length = tvb_length(parameter_tvb); proto_tree_add_text(parameter_tree, parameter_tvb, 0, length, "User service information (-> Q.931 Bearer_capability)"); proto_item_set_text(parameter_item, "User service information, (%u byte%s length)", length , plurality(length, "", "s")); dissect_q931_bearer_capability_ie(parameter_tvb, 0, length, parameter_tree); } /* ------------------------------------------------------------------ Dissector Parameter Access Transport - no detailed dissection since defined in Rec. Q.931 */ static void dissect_etheric_access_transport_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item, packet_info *pinfo) { guint length = tvb_reported_length(parameter_tvb); proto_tree_add_text(parameter_tree, parameter_tvb, 0, -1, "Access transport parameter field (-> Q.931)"); if (q931_ie_handle) call_dissector(q931_ie_handle, parameter_tvb, pinfo, parameter_tree); proto_item_set_text(parameter_item, "Access transport (%u byte%s length)", length , plurality(length, "", "s")); } /* ------------------------------------------------------------------ Dissector Parameter Backward Call Indicators */ static void dissect_etheric_backward_call_indicators_parameter(tvbuff_t *parameter_tvb,proto_tree *parameter_tree, proto_item *parameter_item) { guint8 backward_call_ind; backward_call_ind = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_boolean(parameter_tree, hf_etheric_inband_information_ind, parameter_tvb, 0, 1, backward_call_ind); proto_item_set_text(parameter_item, "Backward Call Indicators: 0x%x", backward_call_ind); } /* ------------------------------------------------------------------ Dissector Parameter Cause Indicators - no detailed dissection since defined in Rec. Q.850 */ /* ------------------------------------------------------------------ Dissector Message Type release message */ static gint dissect_etheric_release_message(tvbuff_t *message_tvb, proto_tree *etheric_tree) { proto_item* parameter_item; proto_tree* parameter_tree; gint offset = 0; gint parameter_type, parameter_pointer, parameter_length; /* Do stuff for mandatory variable parameter Cause indicators */ parameter_type = PARAM_TYPE_CAUSE_INDICATORS; parameter_pointer = 0; parameter_length = 1; parameter_item = proto_tree_add_text(etheric_tree, message_tvb, offset + parameter_pointer, 1,"Cause indicators, see Q.850"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 1, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); proto_tree_add_item(parameter_tree, hf_etheric_cause_indicator, message_tvb, 0, 1,FALSE); offset += 1; return offset; } /* ------------------------------------------------------------------ Dissector Parameter Event information */ static void dissect_etheric_event_information_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item) { guint8 indicators; indicators = tvb_get_guint8(parameter_tvb, 0); proto_tree_add_uint_format(parameter_tree, hf_etheric_event_ind, parameter_tvb, 0, 1, indicators, "Event indicator: %s (%u)", val_to_str(indicators & 0x7f, isup_event_ind_value, "spare"), indicators & 0x7f); proto_tree_add_boolean(parameter_tree, hf_etheric_event_presentation_restricted_ind, parameter_tvb, 0, 1, indicators); proto_item_set_text(parameter_item,"Event information: %s (%u)", val_to_str(indicators & 0x7f, isup_event_ind_value, "spare"),indicators ); } /* ------------------------------------------------------------------ */ static void dissect_etheric_unknown_parameter(tvbuff_t *parameter_tvb, proto_item *parameter_item) { guint length = tvb_length(parameter_tvb); proto_item_set_text(parameter_item, "Parameter Type unknown/reserved (%u Byte%s)", length , plurality(length, "", "s")); } /* ------------------------------------------------------------------ */ /* Dissectors for all used message types */ /* Called by dissect_etheric_message(), */ /* call parameter dissectors in order of mandatory parameters */ /* (since not labeled) */ /* ------------------------------------------------------------------ Dissector Message Type Initial address message */ static gint dissect_etheric_initial_address_message(tvbuff_t *message_tvb, proto_tree *etheric_tree) { proto_item* parameter_item; proto_tree* parameter_tree; tvbuff_t *parameter_tvb; gint offset = 0; gint parameter_type, parameter_pointer, parameter_length, actual_length; /* Do stuff for 1nd mandatory fixed parameter: Forward Call Indicators */ parameter_type = PARAM_TYPE_FORW_CALL_IND; parameter_item = proto_tree_add_text(etheric_tree, message_tvb, offset, 1, "Forward Call Indicators"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); actual_length = tvb_ensure_length_remaining(message_tvb, offset); parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(2, actual_length), 2 ); dissect_etheric_forward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item); offset += 1; /* Do stuff for 2nd mandatory fixed parameter: Calling party's category */ parameter_type = PARAM_TYPE_CALLING_PRTY_CATEG; parameter_item = proto_tree_add_text(etheric_tree, message_tvb, offset, 1, "Calling Party's category"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); actual_length = tvb_ensure_length_remaining(message_tvb, offset); parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(1, actual_length),1 ); dissect_etheric_calling_partys_category_parameter(parameter_tvb, parameter_tree, parameter_item); offset += 1; /* Do stuff for 3d mandatory fixed parameter: Transmission medium requirement */ parameter_type = PARAM_TYPE_TRANSM_MEDIUM_REQU; parameter_item = proto_tree_add_text(etheric_tree, message_tvb, offset, 1, "Transmission medium requirement"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); actual_length = tvb_ensure_length_remaining(message_tvb, offset); parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(1, actual_length), 1); dissect_etheric_transmission_medium_requirement_parameter(parameter_tvb, parameter_tree, parameter_item); offset += 1; /* Do stuff for mandatory variable parameter Called party number */ parameter_type = PARAM_TYPE_CALLED_PARTY_NR; parameter_pointer = tvb_get_guint8(message_tvb, offset); parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer); parameter_item = proto_tree_add_text(etheric_tree, message_tvb, offset + parameter_pointer, parameter_length + 1, "Called Party Number"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); proto_tree_add_uint_format(parameter_tree, hf_etheric_mandatory_variable_parameter_pointer, message_tvb, offset, 1, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_length, message_tvb, offset + parameter_pointer, 1, parameter_length, "Parameter length: %u", parameter_length); actual_length = tvb_ensure_length_remaining(message_tvb, offset); parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + 1, MIN(parameter_length, actual_length), parameter_length ); dissect_etheric_called_party_number_parameter(parameter_tvb, parameter_tree, parameter_item); offset += 1; /* Do stuff for mandatory variable parameter Calling party number */ parameter_type = PARAM_TYPE_CALLING_PARTY_NR; parameter_pointer = tvb_get_guint8(message_tvb, offset); parameter_length = tvb_get_guint8(message_tvb, offset + parameter_pointer); parameter_item = proto_tree_add_text(etheric_tree, message_tvb, offset + parameter_pointer, parameter_length + 1, "Calling Party Number"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); proto_tree_add_uint_format(parameter_tree, hf_etheric_mandatory_variable_parameter_pointer, message_tvb, offset, 1, parameter_pointer, "Pointer to Parameter: %u", parameter_pointer); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_length, message_tvb, offset + parameter_pointer, 1, parameter_length, "Parameter length: %u", parameter_length); actual_length = tvb_ensure_length_remaining(message_tvb, offset); parameter_tvb = tvb_new_subset(message_tvb, offset + parameter_pointer + 1, MIN(parameter_length, actual_length), parameter_length ); dissect_etheric_calling_party_number_parameter(parameter_tvb, parameter_tree, parameter_item); offset += 1; return offset; } /* ------------------------------------------------------------------ Dissector Message Type Address complete */ static gint dissect_etheric_address_complete_message(tvbuff_t *message_tvb, proto_tree *etheric_tree) { proto_item* parameter_item; proto_tree* parameter_tree; tvbuff_t *parameter_tvb; gint offset = 0; gint parameter_type, actual_length; /* Do stuff for first mandatory fixed parameter: backward call indicators*/ parameter_type = PARAM_TYPE_BACKW_CALL_IND; parameter_item = proto_tree_add_text(etheric_tree, message_tvb, offset, 1, "Backward Call Indicators"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); actual_length = tvb_ensure_length_remaining(message_tvb, offset); parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(1, actual_length), 1); dissect_etheric_backward_call_indicators_parameter(parameter_tvb, parameter_tree, parameter_item); offset += 1; return offset; } /* ------------------------------------------------------------------ Dissector Message Type Call Progress */ static gint dissect_etheric_call_progress_message(tvbuff_t *message_tvb, proto_tree *isup_tree) { proto_item* parameter_item; proto_tree* parameter_tree; tvbuff_t *parameter_tvb; gint offset = 0; gint parameter_type, actual_length; /* Do stuff for first mandatory fixed parameter: Event information*/ parameter_type = PARAM_TYPE_EVENT_INFO; parameter_item = proto_tree_add_text(isup_tree, message_tvb, offset, 1, "Event information"); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, message_tvb, 0, 0, parameter_type, "Mandatory Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); actual_length = tvb_ensure_length_remaining(message_tvb, offset); parameter_tvb = tvb_new_subset(message_tvb, offset, MIN(1, actual_length), 1); dissect_etheric_event_information_parameter(parameter_tvb, parameter_tree, parameter_item); offset += 1; return offset; } /* ------------------------------------------------------------------ Dissector all optional parameters */ static void dissect_etheric_optional_parameter(tvbuff_t *optional_parameters_tvb,packet_info *pinfo, proto_tree *etheric_tree) { proto_item* parameter_item; proto_tree* parameter_tree; gint offset = 0; guint parameter_type, parameter_length, actual_length; tvbuff_t *parameter_tvb; /* Dissect all optional parameters while end of message isn't reached */ parameter_type = 0xFF; /* Start-initializiation since parameter_type is used for while-condition */ while ((tvb_length_remaining(optional_parameters_tvb, offset) >= 1) && (parameter_type != PARAM_TYPE_END_OF_OPT_PARAMS)){ parameter_type = tvb_get_guint8(optional_parameters_tvb, offset); if (parameter_type != PARAM_TYPE_END_OF_OPT_PARAMS){ parameter_length = tvb_get_guint8(optional_parameters_tvb, offset + 1); parameter_item = proto_tree_add_text(etheric_tree, optional_parameters_tvb, offset, parameter_length + 1 + 1, "Parameter: type %u", parameter_type); parameter_tree = proto_item_add_subtree(parameter_item, ett_etheric_parameter); proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_type, optional_parameters_tvb, offset, 1, parameter_type, "Optional Parameter: %u (%s)", parameter_type, val_to_str(parameter_type, isup_parameter_type_value,"unknown")); offset += 1; proto_tree_add_uint_format(parameter_tree, hf_etheric_parameter_length, optional_parameters_tvb, offset, 1, parameter_length, "Parameter length: %u", parameter_length); offset += 1; actual_length = tvb_length_remaining(optional_parameters_tvb, offset); if (actual_length > 0){ parameter_tvb = tvb_new_subset(optional_parameters_tvb, offset, MIN(parameter_length, actual_length), parameter_length); switch (parameter_type) { case PARAM_TYPE_USER_SERVICE_INFO: dissect_etheric_user_service_information_parameter(parameter_tvb, parameter_tree, parameter_item); break; case PARAM_TYPE_ACC_TRANSP: dissect_etheric_access_transport_parameter(parameter_tvb, parameter_tree, parameter_item, pinfo); break; case PARAM_TYPE_LOCATION_NR: dissect_etheric_location_number_parameter(parameter_tvb, parameter_tree, parameter_item); break; default: dissect_etheric_unknown_parameter(parameter_tvb, parameter_item); break; } offset += MIN(parameter_length, actual_length); } } else { /* End of optional parameters is reached */ proto_tree_add_uint_format(etheric_tree, hf_etheric_message_type, optional_parameters_tvb , offset, 1, parameter_type, "End of optional parameters (%u)", parameter_type); } } } static void dissect_etheric_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *etheric_tree, guint8 etheric_version, guint8 message_length) { tvbuff_t *parameter_tvb; tvbuff_t *optional_parameter_tvb; gint offset, bufferlength; guint8 message_type; guint8 opt_parameter_pointer = 0; gint opt_part_possible = FALSE; /* default setting - for message types allowing optional params explicitely set to TRUE in case statement */ offset = 0; /* Extract message type field */ message_type = tvb_get_guint8(message_tvb,0); proto_tree_add_item(etheric_tree, hf_etheric_message_type, message_tvb, 0, 1,FALSE); offset ++; parameter_tvb = tvb_new_subset(message_tvb, offset, -1, -1); switch (message_type) { case ETHERIC_MESSAGE_TYPE_ADDR_CMPL: offset += dissect_etheric_address_complete_message(parameter_tvb, etheric_tree); opt_part_possible = FALSE; break; case ETHERIC_MESSAGE_TYPE_ANSWER: /* no dissector necessary since no mandatory parameters included */ if (etheric_version > 0x10 ) /* 0x10, "Etheric 2.0" */ opt_part_possible = TRUE; break; case ETHERIC_MESSAGE_TYPE_BLOCK_ACK: /* no dissector necessary since no mandatory parameters included */ break; case ETHERIC_MESSAGE_TYPE_BLOCKING: /* no dissector necessary since no mandatory parameters included */ break; case ETHERIC_MESSAGE_TYPE_CONNECT: if (etheric_version > 0x10 ) /* 0x10, "Etheric 2.0" */ opt_part_possible = TRUE; break; case ETHERIC_MESSAGE_TYPE_CALL_PROGRSS: offset += dissect_etheric_call_progress_message(parameter_tvb, etheric_tree); opt_part_possible = TRUE; break; case ETHERIC_MESSAGE_TYPE_CIRC_GRP_RST: /* no dissector necessary since no mandatory parameters included */ break; case ETHERIC_MESSAGE_TYPE_CIRC_GRP_RST_ACK: /* no dissector necessary since no mandatory parameters included */ break; case ETHERIC_MESSAGE_TYPE_INITIAL_ADDR: offset += dissect_etheric_initial_address_message(parameter_tvb, etheric_tree); if (etheric_version > 0 ) /* 0x00, "Etheric 1.0" */ opt_part_possible = TRUE; break; case ETHERIC_MESSAGE_TYPE_RELEASE: offset += dissect_etheric_release_message(parameter_tvb, etheric_tree); opt_part_possible = FALSE; break; case ETHERIC_MESSAGE_TYPE_REL_CMPL: /* no dissector necessary since no mandatory parameters included */ break; case ETHERIC_MESSAGE_TYPE_RESET_CIRCUIT: /* no dissector necessary since no mandatory parameters included */ break; case ETHERIC_MESSAGE_TYPE_UNBLOCKING: /* no dissector necessary since no mandatory parameters included */ break; case ETHERIC_MESSAGE_TYPE_UNBLOCK_ACK: /* no dissector necessary since no mandatory parameters included */ break; default: bufferlength = tvb_length_remaining(message_tvb, offset); if (bufferlength != 0) proto_tree_add_text(etheric_tree, parameter_tvb, 0, bufferlength, "Unknown Message type (possibly reserved/used in former ISUP version)"); break; } /* extract pointer to start of optional part (if any) */ if (opt_part_possible == TRUE){ if (message_length > 5 ) { opt_parameter_pointer = tvb_get_guint8(message_tvb, offset); proto_tree_add_uint_format(etheric_tree, hf_etheric_pointer_to_start_of_optional_part, message_tvb, offset, 1, opt_parameter_pointer, "Pointer to start of optional part: %u", opt_parameter_pointer); offset += opt_parameter_pointer; if (opt_parameter_pointer > 0){ optional_parameter_tvb = tvb_new_subset(message_tvb, offset, -1, -1 ); dissect_etheric_optional_parameter(optional_parameter_tvb, pinfo, etheric_tree); } } } else if (message_type !=ETHERIC_MESSAGE_TYPE_CHARGE_INFO) proto_tree_add_text(etheric_tree, message_tvb, 0, 0, "No optional parameters are possible with this message type"); } /* If this dissector uses sub-dissector registration add a registration routine. This format is required because a script is used to find these routines and create the code that calls these routines. */ void proto_reg_handoff_etheric(void) { static dissector_handle_t etheric_handle; static int tcp_port1 = 1806; static int tcp_port2 = 10002; static int Initialized=FALSE; if (!Initialized) { etheric_handle = find_dissector("etheric"); Initialized=TRUE; }else{ dissector_delete("udp.port", tcp_port1, etheric_handle); dissector_delete("udp.port", tcp_port2, etheric_handle); } tcp_port1 = ethericTCPport1; tcp_port2 = ethericTCPport2; dissector_add("tcp.port", ethericTCPport1, etheric_handle); dissector_add("tcp.port", ethericTCPport2, etheric_handle); q931_ie_handle = find_dissector("q931.ie"); } void proto_register_etheric(void) { /* Setup list of header fields See Section 1.6.1 for details*/ static hf_register_info hf[] = { { &hf_etheric_protocol_version, { "Protocol version", "etheric.protocol_version", FT_UINT8, BASE_HEX, VALS(&protocol_version_vals), 0x0, "Etheric protocol version", HFILL } }, { &hf_etheric_message_length, { "Message length", "etheric.message.length", FT_UINT8, BASE_DEC, NULL, 0x0, "Etheric Message length", HFILL } }, { &hf_etheric_cic, { "CIC", "etheric.cic", FT_UINT16, BASE_DEC, NULL, 0x0, "Etheric CIC", HFILL } }, { &hf_etheric_message_type, { "Message type", "etheric.message.type", FT_UINT8, BASE_HEX, VALS(&isup_message_type_value), 0x0, "Etheric message types", HFILL } }, { &hf_etheric_parameter_type, { "Parameter Type", "etheric.parameter_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_etheric_forw_call_isdn_access_indicator, { "ISDN access indicator", "etheric.forw_call_isdn_access_indicator", FT_BOOLEAN, 16, TFS(&isup_ISDN_originating_access_ind_value), 0x01, "", HFILL }}, { &hf_etheric_calling_partys_category, { "Calling Party's category", "etheric.calling_partys_category", FT_UINT8, BASE_HEX, VALS(etheric_calling_partys_category_value), 0x0, "", HFILL }}, { &hf_etheric_mandatory_variable_parameter_pointer, { "Pointer to Parameter", "etheric.mandatory_variable_parameter_pointer", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_etheric_pointer_to_start_of_optional_part, { "Pointer to optional parameter part", "etheric.optional_parameter_part_pointer", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_etheric_parameter_length, { "Parameter Length", "etheric.parameter_length", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }}, { &hf_etheric_transmission_medium_requirement, { "Transmission medium requirement", "etheric.transmission_medium_requirement", FT_UINT8, BASE_DEC, VALS(isup_transmission_medium_requirement_value), 0x0, "", HFILL }}, { &hf_etheric_odd_even_indicator, { "Odd/even indicator", "etheric.isdn_odd_even_indicator", FT_BOOLEAN, 8, TFS(&isup_odd_even_ind_value), 0x80, "", HFILL }}, { &hf_etheric_called_party_nature_of_address_indicator, { "Nature of address indicator", "etheric.called_party_nature_of_address_indicator", FT_UINT8, BASE_DEC, VALS(isup_called_party_nature_of_address_ind_value), 0x3f, "", HFILL }}, { &hf_etheric_calling_party_nature_of_address_indicator, { "Nature of address indicator", "etheric.calling_party_nature_of_address_indicator", FT_UINT8, BASE_DEC, VALS(etheric_location_number_nature_of_address_ind_value), 0x7f, "", HFILL }}, { &hf_etheric_ni_indicator, { "NI indicator", "etheric.ni_indicator", FT_BOOLEAN, 8, TFS(&isup_NI_ind_value), 0x80, "", HFILL }}, { &hf_etheric_inn_indicator, { "INN indicator", "etheric.inn_indicator", FT_BOOLEAN, 8, TFS(&isup_INN_ind_value), 0x80, "", HFILL }}, { &hf_etheric_numbering_plan_indicator, { "Numbering plan indicator", "etheric.numbering_plan_indicator", FT_UINT8, BASE_DEC, VALS(isup_numbering_plan_ind_value), 0x70, "", HFILL }}, { &hf_etheric_address_presentation_restricted_indicator, { "Address presentation restricted indicator", "etheric.address_presentation_restricted_indicator", FT_UINT8, BASE_DEC, VALS(isup_address_presentation_restricted_ind_value), 0x0c, "", HFILL }}, { &hf_etheric_screening_indicator, { "Screening indicator", "etheric.screening_indicator", FT_UINT8, BASE_DEC, VALS(isup_screening_ind_value), 0x03, "", HFILL }}, { &hf_etheric_called_party_odd_address_signal_digit, { "Address signal digit", "etheric.called_party_odd_address_signal_digit", FT_UINT8, BASE_DEC, VALS(isup_called_party_address_digit_value), 0x0F, "", HFILL }}, { &hf_etheric_calling_party_odd_address_signal_digit, { "Address signal digit", "etheric.calling_party_odd_address_signal_digit", FT_UINT8, BASE_DEC, VALS(isup_calling_party_address_digit_value), 0x0F, "", HFILL }}, { &hf_etheric_called_party_even_address_signal_digit, { "Address signal digit", "etheric.called_party_even_address_signal_digit", FT_UINT8, BASE_DEC, VALS(isup_called_party_address_digit_value), 0xF0, "", HFILL }}, { &hf_etheric_calling_party_even_address_signal_digit, { "Address signal digit", "etheric.calling_party_even_address_signal_digit", FT_UINT8, BASE_DEC, VALS(isup_calling_party_address_digit_value), 0xF0, "", HFILL }}, { &hf_etheric_inband_information_ind, { "In-band information indicator", "etheric.inband_information_ind", FT_BOOLEAN, 8, TFS(&isup_inband_information_ind_value), 0x01, "", HFILL }}, { &hf_etheric_cause_indicator, { "Cause indicator", "etheric.cause_indicator", FT_UINT8, BASE_DEC, VALS(q850_cause_code_vals), 0x7f, "", HFILL }}, { &hf_etheric_event_ind, { "Event indicator", "etheric.event_ind", FT_UINT8, 8, VALS(isup_event_ind_value), 0x7f, "", HFILL }}, { &hf_etheric_event_presentation_restricted_ind, { "Event presentation restricted indicator", "etheric.event_presentatiation_restr_ind", FT_BOOLEAN, 8, TFS(&isup_event_presentation_restricted_ind_value), 0x80, "", HFILL }}, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_etheric, &ett_etheric_parameter, &ett_etheric_address_digits, &ett_etheric_circuit_state_ind, }; module_t *etheric_module; /* Register the protocol name and description */ proto_etheric = proto_register_protocol("Etheric", "ETHERIC", "etheric"); new_register_dissector("etheric", dissect_etheric, proto_etheric); /* Required function calls to register the header fields and subtrees used */ proto_register_field_array(proto_etheric, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); /* Register a configuration option for port */ etheric_module = prefs_register_protocol(proto_etheric, proto_reg_handoff_etheric); prefs_register_uint_preference(etheric_module, "tcp.port1", "etheric TCP Port 1", "Set TCP port 1 for etheric messages", 10, ðericTCPport1); prefs_register_uint_preference(etheric_module, "tcp.port2", "etheric TCP Port 2", "Set TCP port 2 for etheric messages", 10, ðericTCPport2); }