diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-actrace.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-actrace.c')
-rw-r--r-- | epan/dissectors/packet-actrace.c | 816 |
1 files changed, 816 insertions, 0 deletions
diff --git a/epan/dissectors/packet-actrace.c b/epan/dissectors/packet-actrace.c new file mode 100644 index 00000000..83a597d3 --- /dev/null +++ b/epan/dissectors/packet-actrace.c @@ -0,0 +1,816 @@ +/* packet-actrace.c + * Routines for AudioCodes Trunk traces packet disassembly + * + * Copyright (c) 2005 by Alejandro Vaquero <alejandro.vaquero@verso.com> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/tap.h> +#include <wiretap/wtap.h> +#include "packet-actrace.h" + +#define UDP_PORT_ACTRACE 2428 /* Not IANA registered */ + +#define NOT_ACTRACE 0 +#define ACTRACE_CAS 1 +#define ACTRACE_ISDN 2 + + +/* Forward declarations */ +void proto_register_actrace(void); +void proto_reg_handoff_actrace(void); + +static dissector_handle_t actrace_handle; + +/* Define the actrace proto */ +static int proto_actrace = -1; + +/* Define many headers for actrace */ +/* ISDN headers */ +static int hf_actrace_isdn_direction = -1; +static int hf_actrace_isdn_trunk = -1; +static int hf_actrace_isdn_length = -1; + + +/* CAS headers */ +static int hf_actrace_cas_time = -1; +static int hf_actrace_cas_source = -1; +static int hf_actrace_cas_current_state = -1; +static int hf_actrace_cas_event = -1; +static int hf_actrace_cas_next_state = -1; +static int hf_actrace_cas_function = -1; +static int hf_actrace_cas_par0 = -1; +static int hf_actrace_cas_par1 = -1; +static int hf_actrace_cas_par2 = -1; +static int hf_actrace_cas_trunk = -1; +static int hf_actrace_cas_bchannel = -1; +static int hf_actrace_cas_connection_id = -1; + + + +static dissector_handle_t lapd_phdr_handle; + +#define ACTRACE_CAS_SOURCE_DSP 0 +#define ACTRACE_CAS_SOURCE_USER 1 +#define ACTRACE_CAS_SOURCE_TABLE 2 + +static const value_string actrace_cas_source_vals[] = { + {ACTRACE_CAS_SOURCE_DSP, "DSP"}, + {ACTRACE_CAS_SOURCE_USER, "User"}, + {ACTRACE_CAS_SOURCE_TABLE, "Table"}, + {0, NULL } +}; + +static const value_string actrace_cas_source_vals_short[] = { + {ACTRACE_CAS_SOURCE_DSP, "D"}, + {ACTRACE_CAS_SOURCE_USER, "U"}, + {ACTRACE_CAS_SOURCE_TABLE, "T"}, + {0, NULL } +}; + +#define ACTRACE_CAS_EV_11 17 +#define ACTRACE_CAS_EV_10 18 +#define ACTRACE_CAS_EV_01 19 +#define ACTRACE_CAS_EV_00 20 + +#define ACTRACE_CAS_EV_DTMF 302 +#define ACTRACE_CAS_EV_FIRST_DIGIT 63 + +static const value_string actrace_cas_event_ab_vals[] = { + {ACTRACE_CAS_EV_11, "11"}, + {ACTRACE_CAS_EV_10, "10"}, + {ACTRACE_CAS_EV_01, "01"}, + {ACTRACE_CAS_EV_00, "00"}, + {0, NULL} +}; + +static const value_string actrace_cas_mf_vals[] = { + {32, "1"}, + {33, "2"}, + {34, "3"}, + {35, "4"}, + {36, "5"}, + {37, "6"}, + {38, "7"}, + {39, "8"}, + {40, "9"}, + {41, "0"}, + {42, "A"}, + {43, "B"}, + {44, "C"}, + {45, "*"}, + {46, "#"}, + {0, NULL} +}; +static value_string_ext actrace_cas_mf_vals_ext = VALUE_STRING_EXT_INIT(actrace_cas_mf_vals); + +static const value_string actrace_cas_event_vals[] = { + { 0, "FUNCTION0"}, + { 1, "FUNCTION1"}, + { 2, "FUNCTION2"}, + { 3, "FUNCTION3"}, + { 4, "EV_PLACE_CALL"}, + { 5, "EV_TIMER_EXPIRED1"}, + { 6, "EV_TIMER_EXPIRED2"}, + { 7, "EV_TIMER_EXPIRED3"}, + { 8, "EV_TIMER_EXPIRED4"}, + { 9, "EV_TIMER_EXPIRED5"}, + { 10, "EV_TIMER_EXPIRED6"}, + { 11, "EV_TIMER_EXPIRED7"}, + { 12, "EV_TIMER_EXPIRED8"}, + { 13, "EV_ANSWER"}, + { 14, "EV_DIAL_TONE_DETECTED"}, + { 15, "EV_DIAL_ENDED"}, + { 16, "EV_DISCONNECT"}, + { ACTRACE_CAS_EV_11, "EV_CAS_1_1"}, + { ACTRACE_CAS_EV_10, "EV_CAS_1_0"}, + { ACTRACE_CAS_EV_01, "EV_CAS_0_1"}, + { ACTRACE_CAS_EV_00, "EV_CAS_0_0"}, + { 21, "EV_RB_TONE_STARTED"}, + { 22, "EV_RB_TONE_STOPPED"}, + { 23, "EV_BUSY_TONE"}, + { 24, "EV_FAST_BUSY_TONE"}, + { 25, "EV_HELLO_DETECTED"}, + { 26, "EV_DIAL_TONE_STOPPED"}, + { 27, "EV_DISCONNECT_INCOMING"}, + { 28, "EV_RELEASE_CALL"}, + { 29, "EV_DIALED_NUM_DETECTED"}, + { 30, "EV_COUNTER1_EXPIRED"}, + { 31, "EV_COUNTER2_EXPIRED"}, + { 32, "EV_MFRn_1"}, + { 33, "EV_MFRn_2"}, + { 34, "EV_MFRn_3"}, + { 35, "EV_MFRn_4"}, + { 36, "EV_MFRn_5"}, + { 37, "EV_MFRn_6"}, + { 38, "EV_MFRn_7"}, + { 39, "EV_MFRn_8"}, + { 40, "EV_MFRn_9"}, + { 41, "EV_MFRn_10"}, + { 42, "EV_MFRn_11"}, + { 43, "EV_MFRn_12"}, + { 44, "EV_MFRn_13"}, + { 45, "EV_MFRn_14"}, + { 46, "EV_MFRn_15"}, + { 47, "EV_MFRn_1_STOPPED"}, + { 48, "EV_MFRn_2_STOPPED"}, + { 49, "EV_MFRn_3_STOPPED"}, + { 50, "EV_MFRn_4_STOPPED"}, + { 51, "EV_MFRn_5_STOPPED"}, + { 52, "EV_MFRn_6_STOPPED"}, + { 53, "EV_MFRn_7_STOPPED"}, + { 54, "EV_MFRn_8_STOPPED"}, + { 55, "EV_MFRn_9_STOPPED"}, + { 56, "EV_MFRn_10_STOPPED"}, + { 57, "EV_MFRn_11_STOPPED"}, + { 58, "EV_MFRn_12_STOPPED"}, + { 59, "EV_MFRn_13_STOPPED"}, + { 60, "EV_MFRn_14_STOPPED"}, + { 61, "EV_MFRn_15_STOPPED"}, + { 62, "EV_ANI_NUM_DETECTED"}, + { ACTRACE_CAS_EV_FIRST_DIGIT, "EV_FIRST_DIGIT"}, + { 64, "EV_END_OF_MF_DIGIT"}, + { 65, "EV_ACCEPT"}, + { 66, "EV_REJECT_BUSY"}, + { 67, "EV_REJECT_CONGESTION"}, + { 68, "EV_REJECT_UNALLOCATED"}, + { 69, "EV_REJECT_RESERVE1"}, + { 70, "EV_REJECT_RESERVE2"}, + { 71, "EV_NO_ANI"}, + { 100, "EV_INIT_CHANNEL"}, + { 101, "EV_BUSY_TONE_STOPPED"}, + { 102, "EV_FAST_BUSY_TONE_STOPPED"}, + { 103, "EV_TO_USER"}, + { 104, "SEND_FIRST_DIGIT"}, + { 110, "EV_CLOSE_CHANNEL"}, + { 111, "EV_OPEN_CHANNEL"}, + { 112, "EV_FAIL_DIAL"}, + { 113, "EV_FAIL_SEND_CAS"}, + { 114, "EV_ALARM"}, + { ACTRACE_CAS_EV_DTMF, "EV_DTMF"}, + {1010, "EV_TIMER_EXPIRED10"}, + {1020, "EV_DEBOUNCE_TIMER_EXPIRED"}, + {1030, "EV_INTER_DIGIT_TIMER_EXPIRED"}, + {0, NULL} +}; +static value_string_ext actrace_cas_event_vals_ext = VALUE_STRING_EXT_INIT(actrace_cas_event_vals); + +#define SEND_CAS 2 +#define SEND_EVENT 3 +#define CHANGE_COLLECT_TYPE 13 +#define SEND_MF 8 +#define SEND_DEST_NUM 4 + +static const value_string actrace_cas_function_vals[] = { + { 0, "NILL"}, + { 1, "SET_TIMER"}, + { SEND_CAS, "SEND_CAS"}, + { SEND_EVENT, "SEND_EVENT"}, + { SEND_DEST_NUM, "SEND_DEST_NUM"}, + { 5, "DEL_TIMER"}, + { 6, "START_COLLECT"}, + { 7, "STOP_COLLECT"}, + { SEND_MF, "SEND_MF"}, + { 9, "STOP_DIAL_MF"}, + {10, "SET_COUNTER"}, + {11, "DEC_COUNTER"}, + {12, "SEND_PROG_TON"}, + {CHANGE_COLLECT_TYPE, "CHANGE_COLLECT_TYPE"}, + {14, "GENERATE_CAS_EV"}, + {0, NULL} +}; +static value_string_ext actrace_cas_function_vals_ext = VALUE_STRING_EXT_INIT(actrace_cas_function_vals); + +static const value_string actrace_cas_pstn_event_vals[] = { + { 64, "acEV_PSTN_INTERNAL_ERROR"}, + { 65, "acEV_PSTN_CALL_CONNECTED"}, + { 66, "acEV_PSTN_INCOMING_CALL_DETECTED"}, + { 67, "acEV_PSTN_CALL_DISCONNECTED"}, + { 68, "acEV_PSTN_CALL_RELEASED"}, + { 69, "acEV_PSTN_REMOTE_ALERTING"}, + { 70, "acEV_PSTN_STARTED"}, + { 71, "acEV_PSTN_WARNING"}, + { 72, "acEV_ISDN_PROGRESS_INDICATION"}, + { 73, "acEV_PSTN_PROCEEDING_INDICATION"}, + { 74, "acEV_PSTN_ALARM"}, + { 75, "acEV_RESERVED"}, + { 76, "acEV_PSTN_LINE_INFO"}, + { 77, "acEV_PSTN_LOOP_CONFIRM"}, + { 78, "acEV_PSTN_RESTART_CONFIRM"}, + { 84, "acEV_ISDN_SETUP_ACK_IN"}, + { 85, "acEV_PSTN_CALL_INFORMATION"}, + {128, "acEV_CAS_SEIZURE_DETECTED"}, + {129, "acEV_CAS_CHANNEL_BLOCKED"}, + {130, "acEV_CAS_PROTOCOL_STARTED"}, + {131, "acEV_PSTN_CALL_STATE_RESPONSE"}, + {132, "acEV_CAS_SEIZURE_ACK"}, + {0, NULL} +}; +static value_string_ext actrace_cas_pstn_event_vals_ext = VALUE_STRING_EXT_INIT(actrace_cas_pstn_event_vals); + +static const value_string actrace_cas_collect_type_vals[] = { + {0, "COLLECT_TYPE_ADDRESS"}, + {1, "COLLECT_TYPE_ANI"}, + {2, "COLLECT_TYPE_SOURCE_CATEGORY"}, + {3, "COLLECT_TYPE_LINE_CATEGORY"}, + {0, NULL} +}; + +#define SEND_TYPE_ADDRESS 1 +#define SEND_TYPE_SPECIFIC 2 +#define SEND_TYPE_INTER_EXCHANGE_SWITCH 3 +#define SEND_TYPE_ANI 4 +#define SEND_TYPE_SOURCE_CATEGORY 5 +#define SEND_TYPE_TRANSFER_CAPABILITY 6 + +static const value_string actrace_cas_send_type_vals[] = { + {SEND_TYPE_ADDRESS, "ADDRESS"}, + {SEND_TYPE_SPECIFIC, "SPECIFIC"}, + {SEND_TYPE_INTER_EXCHANGE_SWITCH, "INTER_EXCHANGE_SWITCH"}, + {SEND_TYPE_ANI, "ANI"}, + {SEND_TYPE_SOURCE_CATEGORY, "SOURCE_CATEGORY"}, + {SEND_TYPE_TRANSFER_CAPABILITY, "TRANSFER_CAPABILITY"}, + {0, NULL} +}; + +static const value_string actrace_cas_cause_vals[] = { + { 1, "UNASSIGNED_NUMBER"}, + { 2, "NO_ROUTE_TO_TRANSIT_NET"}, + { 3, "NO_ROUTE_TO_DESTINATION"}, + { 6, "CHANNEL_UNACCEPTABLE"}, + { 7, "CALL_AWARDED_AND"}, + { 8, "PREEMPTION"}, + { 16, "NORMAL_CALL_CLEAR"}, + { 17, "USER_BUSY"}, + { 18, "NO_USER_RESPONDING"}, + { 19, "NO_ANSWER_FROM_USER_ALERTED"}, + { 20, "ACCEPT_DONE"}, + { 21, "CALL_REJECTED"}, + { 22, "NUMBER_CHANGED"}, + { 26, "NON_SELECTED_USER_CLEARING"}, + { 27, "DEST_OUT_OF_ORDER"}, + { 28, "INVALID_NUMBER_FORMAT"}, + { 29, "FACILITY_REJECT"}, + { 30, "RESPONSE_TO_STATUS_ENQUIRY"}, + { 31, "NORMAL_UNSPECIFIED"}, + { 32, "CIRCUIT_CONGESTION"}, + { 33, "USER_CONGESTION"}, + { 34, "NO_CIRCUIT_AVAILABLE"}, + { 38, "NETWORK_OUT_OF_ORDER"}, + { 39, "PERM_FR_MODE_CONN_OUT_OF_S"}, + { 40, "PERM_FR_MODE_CONN_OPERATIONAL"}, + { 41, "NETWORK_TEMPORARY_FAILURE"}, + { 42, "NETWORK_CONGESTION"}, + { 43, "ACCESS_INFORMATION_DISCARDED"}, + { 44, "REQUESTED_CIRCUIT_NOT_AVAILABLE"}, + { 46, "PRECEDENCE_CALL_BLOCKED"}, + { 47, "RESOURCE_UNAVAILABLE_UNSPECIFIED"}, + { 49, "QUALITY_OF_SERVICE_UNAVAILABLE"}, + { 50, "REQUESTED_FAC_NOT_SUBSCRIBED"}, + { 53, "CUG_OUT_CALLS_BARRED"}, + { 55, "CUG_INC_CALLS_BARRED"}, + { 57, "BC_NOT_AUTHORIZED"}, + { 58, "BC_NOT_PRESENTLY_AVAILABLE"}, + { 62, "ACCES_INFO_SUBS_CLASS_INCONS"}, + { 63, "SERVICE_NOT_AVAILABLE"}, + { 65, "BC_NOT_IMPLEMENTED"}, + { 66, "CHANNEL_TYPE_NOT_IMPLEMENTED"}, + { 69, "REQUESTED_FAC_NOT_IMPLEMENTED"}, + { 70, "ONLY_RESTRICTED_INFO_BEARER"}, + { 79, "SERVICE_NOT_IMPLEMENTED_UNSPECIFIED"}, + { 81, "INVALID_CALL_REF"}, + { 82, "IDENTIFIED_CHANNEL_NOT_EXIST"}, + { 83, "SUSPENDED_CALL_BUT_CALL_ID_NOT_EXIST"}, + { 84, "CALL_ID_IN_USE"}, + { 85, "NO_CALL_SUSPENDED"}, + { 86, "CALL_HAVING_CALL_ID_CLEARED"}, + { 87, "NOT_CUG_MEMBER"}, + { 88, "INCOMPATIBLE_DESTINATION"}, + { 90, "CUG_NON_EXISTENT"}, + { 91, "INVALID_TRANSIT_NETWORK_SELECTION"}, + { 95, "INVALID_MESSAGE_UNSPECIFIED"}, + { 96, "MANDATORY_IE_MISSING"}, + { 97, "MESSAGE_TYPE_NON_EXISTENT"}, + { 98, "MESSAGE_STATE_INCONSISTENCY"}, + { 99, "NON_EXISTENT_IE"}, + {100, "INVALID_IE_CONTENT"}, + {101, "MESSAGE_NOT_COMPATIBLE"}, + {102, "RECOVERY_ON_TIMER_EXPIRY"}, + {111, "PROTOCOL_ERROR_UNSPECIFIED"}, + {127, "INTERWORKING_UNSPECIFIED"}, + {128, "ACU_CAUSE_ACU_BAD_ADDRESS"}, + {129, "ACU_CAUSE_ACU_BAD_SERVICE"}, + {130, "ACU_CAUSE_ACU_COLLISION"}, + {131, "ACU_CAUSE_ACU_FAC_REJECTED"}, + {200, "C_ALREADY_BLOCKED"}, + {201, "C_CHANNEL_BLOCKED"}, + {202, "C_BLOCKING_DONE"}, + {203, "C_ALREADY_UNBLOCKED"}, + {204, "C_UNBLOCKING_DONE"}, + {255, "ACU_NETWORK_CAUSE_NIL"}, + {260, "CLRN_MFRn_A4"}, + {261, "CLRN_MFRn_B1"}, + {262, "CLRN_MFRn_B2"}, + {263, "CLRN_MFRn_B3"}, + {264, "CLRN_MFRn_B4"}, + {265, "CLRN_MFRn_B5"}, + {266, "CLRN_MFRn_B6"}, + {267, "CLRN_MFRn_B7"}, + {268, "CLRN_MFRn_B8"}, + {269, "CLRN_MFRn_B9"}, + {270, "CLRN_MFRn_B10"}, + {271, "CLRN_MFRn_B11"}, + {272, "CLRN_MFRn_B12"}, + {273, "CLRN_MFRn_B13"}, + {274, "CLRN_MFRn_B14"}, + {275, "CLRN_MFRn_B15"}, + {300, "ACURC_BUSY"}, + {301, "ACURC_NOPROCEED"}, + {302, "ACURC_NOANSWER"}, + {303, "ACURC_NOAUTOANSWER"}, + {304, "ACURC_CONGESTED"}, + {305, "ACURC_INCOMING"}, + {306, "ACURC_NOLINE"}, + {307, "ACURC_ERRNUM"}, + {308, "ACURC_INHNUM"}, + {309, "ACURC_2MNUM"}, + {310, "ACURC_HUNGUP"}, + {311, "ACURC_NETWORK_ERROR"}, + {312, "ACURC_TIMEOUT"}, + {313, "ACURC_BAD_SERVICE"}, + {314, "ACURC_INTERNAL"}, + {315, "ACURC_OK"}, + {316, "ACURC_BL_TIMEOUT"}, + {317, "ACURC_IN_CALL"}, + {318, "ACURC_CLEAR_RQ"}, + {0, NULL} +}; +static value_string_ext actrace_cas_cause_vals_ext = VALUE_STRING_EXT_INIT(actrace_cas_cause_vals); + +/* ISDN */ +#define PSTN_TO_BLADE 0x49446463 +#define BLADE_TO_PSTN 0x49644443 + +static const value_string actrace_isdn_direction_vals[] = { + {PSTN_TO_BLADE, "Blade <-- PSTN"}, + {BLADE_TO_PSTN, "Blade --> PSTN"}, + {0, NULL} +}; + +/* + * Define the tree for actrace + */ +static int ett_actrace = -1; + +/* + * Define the tap for actrace + */ +static int actrace_tap = -1; +static actrace_info_t *actrace_pi; + +/* Some basic utility functions that are specific to this dissector */ +static int is_actrace(tvbuff_t *tvb, gint offset); + +/* + * The dissect functions + */ +static void dissect_actrace_cas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *actrace_tree); +static void dissect_actrace_isdn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + proto_tree *actrace_tree); + +/************************************************************************ + * dissect_actrace - The dissector for the AudioCodes Trace prtocol + ************************************************************************/ +static int dissect_actrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + proto_tree *actrace_tree; + proto_item *ti; + int actrace_protocol; + + /* Initialize variables */ + actrace_tree = NULL; + + /* + * Check to see whether we're really dealing with AC trace by looking + * for a valid "source" and fixed len for CAS, and the direction for ISDN. + * This isn't infallible, but it's cheap and it's better than nothing. + */ + actrace_protocol = is_actrace(tvb, 0); + if (actrace_protocol != NOT_ACTRACE) + { + /* + * Set the columns now, so that they'll be set correctly if we throw + * an exception. We can set them later as well.... + */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "AC_TRACE"); + col_clear(pinfo->cinfo, COL_INFO); + + if (tree) + { + /* Create our actrace subtree */ + ti = proto_tree_add_item(tree,proto_actrace,tvb,0,-1, ENC_NA); + actrace_tree = proto_item_add_subtree(ti, ett_actrace); + } + + switch (actrace_protocol) + { + case ACTRACE_CAS: + dissect_actrace_cas(tvb, pinfo, actrace_tree); + break; + case ACTRACE_ISDN: + dissect_actrace_isdn(tvb, pinfo, tree, actrace_tree); + break; + } + return tvb_captured_length(tvb); + } + + return 0; +} + +/* Dissect an individual actrace CAS message */ +static void dissect_actrace_cas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *actrace_tree) +{ + /* Declare variables */ + gint32 value, function, trunk, bchannel, source, event, curr_state, next_state; + gint32 par0, par1, par2; + const gchar *frame_label = NULL; + int direction = 0; + int offset = 0; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "AC_CAS"); + + value = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_time, tvb, offset, 4, value); + offset += 4; + + source = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_source, tvb, offset, 4, source); + offset += 4; + + curr_state = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_current_state, tvb, offset, 4, curr_state); + offset += 4; + + event = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_event, tvb, offset, 4, event); + offset += 4; + + next_state = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_next_state, tvb, offset, 4, next_state); + offset += 4; + + function = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_function, tvb, offset, 4, function); + offset += 4; + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s|%d|%s|%d|%s|", + val_to_str_const(source, actrace_cas_source_vals_short, "ukn"), + curr_state, + val_to_str_ext(event, &actrace_cas_event_vals_ext, "%d"), + next_state, + val_to_str_ext(function, &actrace_cas_function_vals_ext, "%d")); + + par0 = tvb_get_ntohl(tvb, offset); + switch (function) + { + case SEND_EVENT: + proto_tree_add_int_format_value(actrace_tree, hf_actrace_cas_par0, tvb, offset, 4, + par0, "%s", val_to_str_ext(par0, &actrace_cas_pstn_event_vals_ext, "Unknown (%d)")); + col_append_fstr(pinfo->cinfo, COL_INFO, "%s|", + val_to_str_ext(par0, &actrace_cas_pstn_event_vals_ext, "%d")); + break; + case CHANGE_COLLECT_TYPE: + proto_tree_add_int_format_value(actrace_tree, hf_actrace_cas_par0, tvb, offset, 4, + par0, "%s", val_to_str(par0, actrace_cas_collect_type_vals, "Unknown (%d)")); + col_append_fstr(pinfo->cinfo, COL_INFO, "%s|", + val_to_str(par0, actrace_cas_collect_type_vals, "%d")); + break; + case SEND_MF: + case SEND_DEST_NUM: + proto_tree_add_int_format_value(actrace_tree, hf_actrace_cas_par0, tvb, offset, 4, + par0, "%s", val_to_str(par0, actrace_cas_send_type_vals, "Unknown (%d)")); + col_append_fstr(pinfo->cinfo, COL_INFO, "%s|", + val_to_str(par0, actrace_cas_send_type_vals, "%d")); + break; + default: + proto_tree_add_int(actrace_tree, hf_actrace_cas_par0, tvb, offset, 4, par0); + col_append_fstr(pinfo->cinfo, COL_INFO, "%d|", par0); + } + offset += 4; + + par1 = tvb_get_ntohl(tvb, offset); + if (function == SEND_EVENT) { + proto_tree_add_int_format_value(actrace_tree, hf_actrace_cas_par1, tvb, offset, 4, + par1, "%s", val_to_str_ext(par1, &actrace_cas_cause_vals_ext, "Unknown (%d)")); + col_append_fstr(pinfo->cinfo, COL_INFO, "%s|", + val_to_str_ext(par1, &actrace_cas_cause_vals_ext, "%d")); + } else { + proto_tree_add_int(actrace_tree, hf_actrace_cas_par1, tvb, offset, 4, par1); + col_append_fstr(pinfo->cinfo, COL_INFO, "%d|", par1); + } + offset += 4; + + par2 = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_par2, tvb, offset, 4, par2); + col_append_fstr(pinfo->cinfo, COL_INFO, "%d|", par2); + offset += 4; + + trunk = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_trunk, tvb, offset, 4, trunk); + offset += 4; + + bchannel = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_bchannel, tvb, offset, 4, bchannel); + offset += 4; + + col_prepend_fstr(pinfo->cinfo, COL_INFO, "t%db%d|", trunk, bchannel); + + value = tvb_get_ntohl(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_cas_connection_id, tvb, offset, 4, value); + + /* Add tap info for the Voip Graph */ + if (source == ACTRACE_CAS_SOURCE_DSP) { + direction = 1; + if ( (event >= ACTRACE_CAS_EV_11) && (event <= ACTRACE_CAS_EV_00 ) ) { + frame_label = wmem_strdup_printf(pinfo->pool, "AB: %s", val_to_str_const(event, actrace_cas_event_ab_vals, "ERROR") ); + } else if ( (event >= 32) && (event <= 46 ) ) { /* is an MF tone */ + frame_label = wmem_strdup_printf(pinfo->pool, "MF: %s", val_to_str_ext_const(event, &actrace_cas_mf_vals_ext, "ERROR") ); + } else if ( (event == ACTRACE_CAS_EV_DTMF ) || (event == ACTRACE_CAS_EV_FIRST_DIGIT ) ) { /* DTMF digit */ + frame_label = wmem_strdup_printf(pinfo->pool, "DTMF: %u", par0 ); + } + } else if (source == ACTRACE_CAS_SOURCE_TABLE) { + direction = 0; + if (function == SEND_MF) { + if (par0 == SEND_TYPE_SPECIFIC ) { + frame_label = wmem_strdup_printf(pinfo->pool, "MF: %u", par1); + } else if (par0 == SEND_TYPE_ADDRESS ) { + frame_label = wmem_strdup(pinfo->pool, "MF: DNIS digit"); + } else if (par0 == SEND_TYPE_ANI ) { + frame_label = wmem_strdup(pinfo->pool, "MF: ANI digit"); + } else if (par0 == SEND_TYPE_SOURCE_CATEGORY ) { + frame_label = wmem_strdup(pinfo->pool, "MF: src_category"); + } else if (par0 == SEND_TYPE_TRANSFER_CAPABILITY ) { + frame_label = wmem_strdup(pinfo->pool, "MF: trf_capability"); + } else if (par0 == SEND_TYPE_INTER_EXCHANGE_SWITCH ) { + frame_label = wmem_strdup(pinfo->pool, "MF: inter_exch_sw"); + } + } else if (function == SEND_CAS) { + frame_label = wmem_strdup_printf(pinfo->pool, "AB: %s", val_to_str_const(ACTRACE_CAS_EV_00-par0, actrace_cas_event_ab_vals, "ERROR")); + } else if (function == SEND_DEST_NUM) { + if (par0 == SEND_TYPE_ADDRESS ) { + frame_label = wmem_strdup(pinfo->pool, "DTMF/MF: sending DNIS"); + } else if (par0 == SEND_TYPE_ANI ) { + frame_label = wmem_strdup(pinfo->pool, "DTMF/MF: sending ANI"); + } + } + } + + if (frame_label != NULL) { + /* Initialise packet info for passing to tap */ + actrace_pi = wmem_new(pinfo->pool, actrace_info_t); + + actrace_pi->type = ACTRACE_CAS; + actrace_pi->direction = direction; + actrace_pi->trunk = trunk; + actrace_pi->cas_bchannel = bchannel; + actrace_pi->cas_frame_label = frame_label; + /* Report this packet to the tap */ + tap_queue_packet(actrace_tap, pinfo, actrace_pi); + } +} + +/* Dissect an individual actrace ISDN message */ +static void dissect_actrace_isdn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + proto_tree *actrace_tree) +{ + /* Declare variables */ + gint len; + gint32 value, trunk; + tvbuff_t *next_tvb; + int offset = 0; + struct isdn_phdr isdn; + + offset += 4; + + value = tvb_get_ntohl(tvb, offset+4); + proto_tree_add_int(actrace_tree, hf_actrace_isdn_direction, tvb, offset, 4, value); + offset += 4; + /* PSTN = Network */ + isdn.uton = (value==BLADE_TO_PSTN); + isdn.channel = 0; /* D channel */ + + trunk = tvb_get_ntohs(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_isdn_trunk, tvb, offset, 2, trunk); + offset += 4; + + offset += 32; + + len = tvb_get_ntohs(tvb, offset); + proto_tree_add_int(actrace_tree, hf_actrace_isdn_length, tvb, offset, 2, len); + + /* if it is a q931 packet (we don't want LAPD packets for Voip Graph) add tap info */ + if (len > 4) { + /* Initialise packet info for passing to tap */ + actrace_pi = wmem_new(pinfo->pool, actrace_info_t); + + actrace_pi->type = ACTRACE_ISDN; + actrace_pi->direction = (value==PSTN_TO_BLADE?1:0); + actrace_pi->trunk = trunk; + + /* Report this packet to the tap */ + tap_queue_packet(actrace_tap, pinfo, actrace_pi); + } + + /* Dissect lapd payload */ + offset += 2 ; + next_tvb = tvb_new_subset_length(tvb, offset, len); + call_dissector_with_data(lapd_phdr_handle, next_tvb, pinfo, tree, &isdn); + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "AC_ISDN"); + col_prepend_fstr(pinfo->cinfo, COL_INFO, "Trunk:%d Blade %s PSTN " + , trunk, value==PSTN_TO_BLADE?"<--":"-->"); +} + +/* + * is_actrace - A function for determining whether there is a + * AudioCodes packet at offset in tvb. The packet could be + * a CAS, ISDN or other Trunk protocol. Here we are only + * trying to decode CAS or ISDN protocols + * + * Parameter: + * tvb - The tvbuff in which we are looking for + * offset - The offset in tvb at which we are looking for + * + * Return: NOT_ACTRACE if there isn't an AudioCodes trace packet at offset + * in tvb, ACTRACE_CAS if there's a CAS packet there, ACTRACE_ISDN if + * there's an ISDN packet there. + */ +static int is_actrace(tvbuff_t *tvb, gint offset) +{ + gint tvb_len; + gint32 source, isdn_header; + + tvb_len = tvb_reported_length(tvb); + + /* is a CAS packet? + * the CAS messages are 48 byte fixed and the source should be 0,1 or 2 (DSP, User or Table) + */ + source = tvb_get_ntohl(tvb, offset+4); + if ( (tvb_len == 48) && ((source > -1) && (source <3)) ) + return ACTRACE_CAS; + /* is ISDN packet? + * the ISDN packets have 0x49446463 for packets from PSTN to the Blade and + * 0x49644443 for packets from the Blade to the PSTN at offset 4 + */ + isdn_header = tvb_get_ntohl(tvb, offset+4); + if ( (tvb_len >= 50) && ( (isdn_header == PSTN_TO_BLADE) || (isdn_header == BLADE_TO_PSTN)) ) + return ACTRACE_ISDN; + return NOT_ACTRACE; +} + +/* Register all the bits needed with the filtering engine */ +void proto_register_actrace(void) +{ + static hf_register_info hf[] = + { + /* CAS */ + { &hf_actrace_cas_time, + { "Time", "actrace.cas.time", FT_INT32, BASE_DEC, NULL, 0x0, + "Capture Time", HFILL }}, + { &hf_actrace_cas_source, + { "Source", "actrace.cas.source", FT_INT32, BASE_DEC, VALS(actrace_cas_source_vals), 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_current_state, + { "Current State", "actrace.cas.curr_state", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_event, + { "Event", "actrace.cas.event", FT_INT32, BASE_DEC|BASE_EXT_STRING, &actrace_cas_event_vals_ext, 0x0, + "New Event", HFILL }}, + { &hf_actrace_cas_next_state, + { "Next State", "actrace.cas.next_state", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_function, + { "Function", "actrace.cas.function", FT_INT32, BASE_DEC|BASE_EXT_STRING, &actrace_cas_function_vals_ext, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_par0, + { "Parameter 0", "actrace.cas.par0", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_par1, + { "Parameter 1", "actrace.cas.par1", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_par2, + { "Parameter 2", "actrace.cas.par2", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_trunk, + { "Trunk Number", "actrace.cas.trunk", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_bchannel, + { "BChannel", "actrace.cas.bchannel", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_cas_connection_id, + { "Connection ID", "actrace.cas.conn_id", FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + /* ISDN */ + { &hf_actrace_isdn_trunk, + { "Trunk Number", "actrace.isdn.trunk", FT_INT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_actrace_isdn_direction, + { "Direction", "actrace.isdn.dir", FT_INT32, BASE_DEC, VALS(actrace_isdn_direction_vals), 0x0, + NULL, HFILL }}, + { &hf_actrace_isdn_length, + { "Length", "actrace.isdn.length", FT_INT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + }; + + static gint *ett[] = + { + &ett_actrace, + }; + + module_t *actrace_module; + + /* Register protocol */ + proto_actrace = proto_register_protocol("AudioCodes Trunk Trace", "ACtrace", "actrace"); + proto_register_field_array(proto_actrace, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register our configuration options */ + actrace_module = prefs_register_protocol(proto_actrace, NULL); + + prefs_register_obsolete_preference(actrace_module, "display_dissect_tree"); + + actrace_handle = register_dissector("actrace", dissect_actrace, proto_actrace); + actrace_tap = register_tap("actrace"); +} + +/* The registration hand-off routine */ +void proto_reg_handoff_actrace(void) +{ + /* Get a handle for the LAPD-with-pseudoheader dissector. */ + lapd_phdr_handle = find_dissector_add_dependency("lapd-phdr", proto_actrace); + + dissector_add_uint_with_preference("udp.port", UDP_PORT_ACTRACE, actrace_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + * + * vi: set shiftwidth=8 tabstop=8 noexpandtab: + * :indentSize=8:tabSize=8:noTabs=false: + */ |