wireshark/epan/dissectors/packet-sapenqueue.c

633 lines
26 KiB
C

/* packet-sapenqueue.c
* Routines for SAP Enqueue (Enqueue Server) dissection
* Copyright 2022, Martin Gallo <martin.gallo [AT] gmail.com>
* Code contributed by SecureAuth Corp.
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
/*
* This is a dissector for the SAP Enqueue Server protocol.
*
* Some details and example requests can be found in pysap's documentation: https://pysap.readthedocs.io/en/latest/protocols/SAPEnqueue.html.
*/
#include <config.h>
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/expert.h>
#include <epan/conversation.h>
/* Enqueue Server Type values */
static const value_string sapenqueue_type_vals[] = {
{ 0, "SYNC_REQUEST" },
{ 1, "ASYNC_REQUEST" },
{ 2, "RESPONSE" },
/* NULL */
{ 0, NULL }
};
/* Enqueue Server Destination values */
static const value_string sapenqueue_dest_vals[] = {
{ 1, "SYNC_ENQUEUE" },
{ 2, "ASYNC_ENQUEUE" },
{ 3, "SERVER_ADMIN" },
{ 5, "STAT_QUERY" },
{ 6, "CONECTION_ADMIN" },
{ 7, "ENQ_TO_REP" },
{ 8, "REP_TO_ENQ" },
/* NULL */
{ 0, NULL },
};
/* Enqueue Server Admin Opcode values */
static const value_string sapenqueue_server_admin_opcode_vals[] = {
{ 1, "EnAdmDummyRequest" },
{ 2, "EnAdmShutdownRequest" },
{ 4, "EnAdmGetReplInfoRequest" },
{ 6, "EnAdmTraceRequest" },
/* NULL */
{ 0, NULL },
};
/* Enqueue Server Connection Admin Trace Action values */
static const value_string sapenqueue_server_admin_trace_action_vals[] = {
{ 1, "Raise level" },
{ 2, "Lower level" },
{ 3, "Get trace state" },
{ 4, "Set trace status" },
{ 5, "Reset trace files" },
/* NULL */
{ 0, NULL }
};
/* Enqueue Server Connection Admin Trace Limit values */
static const value_string sapenqueue_server_admin_trace_limit_vals[] = {
{ 0, "Globally" },
{ 1, "Only in enserver" },
{ 2, "Only in repserver" },
{ 3, "Only in threads of type" },
{ 4, "Only in one thread of type" },
/* NULL */
{ 0, NULL }
};
/* Enqueue Server Connection Admin Trace Thread values */
static const value_string sapenqueue_server_admin_trace_thread_vals[] = {
{ 0, "All threads" },
{ 1, "All I/O threads" },
{ 2, "Enqueue Worker thread" },
{ 3, "Replication thread" },
{ 4, "ADM thread" },
{ 5, "Signal thread" },
{ 6, "Listener thread" },
/* NULL */
{ 0, NULL }
};
/* Enqueue Server Connection Admin Opcode values */
static const value_string sapenqueue_conn_admin_opcode_vals[] = {
{ 0, "Loopback packet" },
{ 1, "Parameter Request" },
{ 2, "Parameter Response" },
{ 3, "Shutdown Read" },
{ 4, "Shutdown Write" },
{ 5, "Shutdown Both" },
{ 6, "Keepalive" },
/* NULL */
{ 0, NULL }
};
/* Enqueue Server Connection Admin Parameter values */
static const value_string sapenqueue_conn_admin_param_vals[] = {
{ 0, "ENCPARAM_RECV_LEN" },
{ 1, "ENCPARAM_SEND_LEN" },
{ 2, "ENCPARAM_MSG_TYPE" },
{ 3, "ENCPARAM_SET_NAME" },
{ 4, "ENCPARAM_SET_NOSUPP" },
{ 5, "ENCPARAM_SET_VERSION" },
{ 6, "ENCPARAM_SET_UCSUPPORT" },
/* NULL */
{ 0, NULL }
};
static int proto_sapenqueue = -1;
static int hf_sapenqueue_magic = -1;
static int hf_sapenqueue_id = -1;
static int hf_sapenqueue_length = -1;
static int hf_sapenqueue_length_frag = -1;
static int hf_sapenqueue_dest = -1;
static int hf_sapenqueue_conn_admin_opcode = -1;
static int hf_sapenqueue_more_frags = -1;
static int hf_sapenqueue_type = -1;
static int hf_sapenqueue_server_admin = -1;
static int hf_sapenqueue_server_admin_eyecatcher = -1;
static int hf_sapenqueue_server_admin_version = -1;
static int hf_sapenqueue_server_admin_flag = -1;
static int hf_sapenqueue_server_admin_length = -1;
static int hf_sapenqueue_server_admin_opcode = -1;
static int hf_sapenqueue_server_admin_flags = -1;
static int hf_sapenqueue_server_admin_rc = -1;
static int hf_sapenqueue_server_admin_value = -1;
static int hf_sapenqueue_server_admin_trace_request = -1;
static int hf_sapenqueue_server_admin_trace_protocol_version = -1;
static int hf_sapenqueue_server_admin_trace_action = -1;
static int hf_sapenqueue_server_admin_trace_limit = -1;
static int hf_sapenqueue_server_admin_trace_thread = -1;
static int hf_sapenqueue_server_admin_trace_level = -1;
static int hf_sapenqueue_server_admin_trace_logging = -1;
static int hf_sapenqueue_server_admin_trace_max_file_size = -1;
static int hf_sapenqueue_server_admin_trace_nopatterns = -1;
static int hf_sapenqueue_server_admin_trace_eyecatcher = -1;
static int hf_sapenqueue_server_admin_trace_patterns = -1;
static int hf_sapenqueue_server_admin_trace_unknown = -1;
static int hf_sapenqueue_server_admin_trace_pattern = -1;
static int hf_sapenqueue_server_admin_trace_pattern_len = -1;
static int hf_sapenqueue_server_admin_trace_pattern_value = -1;
static int hf_sapenqueue_conn_admin = -1;
static int hf_sapenqueue_conn_admin_params_count = -1;
static int hf_sapenqueue_conn_admin_params = -1;
static int hf_sapenqueue_conn_admin_param = -1;
static int hf_sapenqueue_conn_admin_param_id = -1;
static int hf_sapenqueue_conn_admin_param_len = -1;
static int hf_sapenqueue_conn_admin_param_value = -1;
static int hf_sapenqueue_conn_admin_param_name = -1;
static gint ett_sapenqueue = -1;
/* Expert info */
static expert_field ei_sapenqueue_pattern_invalid_length= EI_INIT;
static expert_field ei_sapenqueue_support_invalid_offset = EI_INIT;
static expert_field ei_sapenqueue_support_invalid_length = EI_INIT;
/* Protocol handle */
static dissector_handle_t sapenqueue_handle;
/*
*
*/
void proto_reg_handoff_sapenqueue(void);
void proto_register_sapenqueue(void);
static void
dissect_sapenqueue_server_admin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset){
guint8 opcode = 0;
proto_item *server_admin = NULL;
proto_tree *server_admin_tree = NULL;
server_admin = proto_tree_add_item(tree, hf_sapenqueue_server_admin, tvb, offset, -1, ENC_NA);
server_admin_tree = proto_item_add_subtree(server_admin, ett_sapenqueue);
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_eyecatcher, tvb, offset, 4, ENC_ASCII|ENC_NA);
offset += 4;
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_version, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
offset += 3; /* Unknown bytes */
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_eyecatcher, tvb, offset, 4, ENC_ASCII|ENC_NA);
offset += 4;
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_length, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
opcode = tvb_get_guint8(tvb, offset);
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_rc, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_eyecatcher, tvb, offset, 4, ENC_ASCII|ENC_NA);
offset += 4;
if (tvb_reported_length_remaining(tvb, offset) > 0){
switch(opcode){
case 0x06:{ /* EnAdmTraceRequest */
guint8 pattern_length = 0;
guint32 nopatterns = 0, total_length = 0;
proto_item *trace_request = NULL, *trace_request_patterns = NULL, *trace_request_pattern = NULL;
proto_tree *trace_request_tree = NULL, *trace_request_patterns_tree = NULL, *trace_request_pattern_tree = NULL;
trace_request = proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_trace_request, tvb, offset, -1, ENC_NA);
trace_request_tree = proto_item_add_subtree(trace_request, ett_sapenqueue);
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_protocol_version, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_action, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_limit, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_thread, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_unknown, tvb, offset, 4, ENC_NA);
offset += 4;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_level, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_unknown, tvb, offset, 4, ENC_NA);
offset += 4;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_logging, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_max_file_size, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
nopatterns = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_nopatterns, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_unknown, tvb, offset, 8, ENC_NA);
offset += 8;
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_eyecatcher, tvb, offset, 4, ENC_ASCII|ENC_NA);
offset += 4;
/* As we don't have the right size yet, start with 1 byte */
trace_request_patterns = proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_patterns, tvb, offset, 1, ENC_NA);
trace_request_patterns_tree = proto_item_add_subtree(trace_request_patterns, ett_sapenqueue);
while (nopatterns > 0 && tvb_offset_exists(tvb, offset)){
/* As we don't have the right size yet, start with 1 byte */
trace_request_pattern = proto_tree_add_item(trace_request_patterns_tree, hf_sapenqueue_server_admin_trace_pattern, tvb, offset, 1, ENC_NA);
trace_request_pattern_tree = proto_item_add_subtree(trace_request_pattern, ett_sapenqueue);
pattern_length = tvb_get_guint8(tvb, offset) + 1; /* Pattern string is null terminated */
proto_tree_add_item(trace_request_pattern_tree, hf_sapenqueue_server_admin_trace_pattern_len, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
/* Set the max length to the remaining of the packet, just in case a malformed packet arrives */
if (!tvb_offset_exists(tvb, offset + pattern_length)) {
pattern_length = (guint8)tvb_reported_length_remaining(tvb, offset);
expert_add_info(pinfo, trace_request_pattern, &ei_sapenqueue_pattern_invalid_length);
}
proto_tree_add_item(trace_request_pattern_tree, hf_sapenqueue_server_admin_trace_pattern_value, tvb, offset, pattern_length, ENC_ASCII|ENC_NA);
offset += pattern_length;
/* Set the right size for the pattern tree */
pattern_length += 1; /* Add also the length field */
proto_item_set_len(trace_request_pattern, pattern_length);
nopatterns -= 1;
total_length += pattern_length;
}
proto_item_set_len(trace_request_patterns, total_length);
proto_tree_add_item(trace_request_tree, hf_sapenqueue_server_admin_trace_eyecatcher, tvb, offset, 4, ENC_ASCII|ENC_NA);
break;
}
default:{
proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_value, tvb, offset, -1, ENC_NA);
break;
}
}
}
}
static void
dissect_sapenqueue_conn_admin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint8 opcode){
proto_item *conn_admin = NULL;
proto_tree *conn_admin_tree = NULL;
conn_admin = proto_tree_add_item(tree, hf_sapenqueue_conn_admin, tvb, offset, -1, ENC_NA);
conn_admin_tree = proto_item_add_subtree(conn_admin, ett_sapenqueue);
switch (opcode){
case 0x01: /* Parameter Request */
case 0x02:{ /* Parameter Response */
gint name_length_remaining = 0;
guint8 length = 0, total_length = 0;
guint32 count = 0, id = 0, name_length = 0;
proto_item *params = NULL, *param = NULL;
proto_tree *params_tree = NULL, *param_tree = NULL;
count = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(conn_admin_tree, hf_sapenqueue_conn_admin_params_count, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
params = proto_tree_add_item(conn_admin_tree, hf_sapenqueue_conn_admin_params, tvb, offset, 1, ENC_NA);
params_tree = proto_item_add_subtree(params, ett_sapenqueue);
while (count > 0 && tvb_offset_exists(tvb, offset)){
/* As we don't have the right size yet, start with 1 byte */
param = proto_tree_add_item(params_tree, hf_sapenqueue_conn_admin_param, tvb, offset, 1, ENC_NA);
param_tree = proto_item_add_subtree(param, ett_sapenqueue);
id = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_id, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
length = 4;
switch(id){
case 0x03:{ /* Set Name parameter */
name_length = tvb_strsize(tvb, offset);
if (name_length > 0) {
proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_name, tvb, offset, name_length, ENC_ASCII|ENC_NA);
offset += name_length;
length += name_length;
}
break;
} case 0x04:{ /* No support parameter */
/* This parameter appears to have more fields only for responses */
if (opcode == 0x02) {
proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_value, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
length += 4;
}
break;
} case 0x06:{ /* Set Unicode Support Parameter */
name_length = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_len, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
/* If the reported length is not correct, use the remaining of the packet as length */
name_length_remaining = tvb_reported_length_remaining(tvb, offset);
if (name_length_remaining < 0){
expert_add_info(pinfo, param, &ei_sapenqueue_support_invalid_offset);
break;
}
if ((guint32)name_length_remaining < name_length) {
name_length = (guint32)name_length_remaining;
expert_add_info(pinfo, param, &ei_sapenqueue_support_invalid_length);
}
proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_value, tvb, offset, name_length, ENC_BIG_ENDIAN);
offset += name_length;
length += 4 + name_length;
break;
} default: {
/* The rest of the parameters have an integer value field */
proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_value, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
length += 4;
}
}
/* Set the right size for the parameter tree */
proto_item_set_len(param, length);
count -= 1;
total_length += length;
}
proto_item_set_len(params, total_length);
break;
}
}
}
static int
dissect_sapenqueue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
guint8 dest = 0, type = 0, opcode = 0;
guint32 offset = 4;
proto_item *ti = NULL;
proto_tree *sapenqueue_tree = NULL;
/* If the packet has less than 20 bytes we can be sure that is not an
* Enqueue server packet.
*/
if (tvb_reported_length(tvb) < 20){
return 0;
}
/* Add the protocol to the column */
col_add_str(pinfo->cinfo, COL_PROTOCOL, "SAPENQUEUE");
/* Clear out stuff in the info column */
col_clear(pinfo->cinfo,COL_INFO);
dest = tvb_get_guint8(tvb, offset + 16);
col_append_fstr(pinfo->cinfo, COL_INFO, "Dest=%s", val_to_str(dest, sapenqueue_dest_vals, "Unknown"));
opcode = tvb_get_guint8(tvb, offset + 17);
type = tvb_get_guint8(tvb, offset + 19);
col_append_fstr(pinfo->cinfo, COL_INFO, ",Type=%s", val_to_str(type, sapenqueue_type_vals, "Unknown"));
if (dest == 0x06){
col_append_fstr(pinfo->cinfo, COL_INFO, ",Opcode=%s", val_to_str(opcode, sapenqueue_conn_admin_opcode_vals, "Unknown"));
}
/* Add the main sapenqueue subtree */
ti = proto_tree_add_item(tree, proto_sapenqueue, tvb, 0, -1, ENC_NA);
sapenqueue_tree = proto_item_add_subtree(ti, ett_sapenqueue);
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_magic, tvb, offset, 4, ENC_NA);
offset += 4;
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_id, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_length, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_length_frag, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_dest, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
if (dest == 0x06){ /* This field is only relevant if the destination is Connection Admin */
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_conn_admin_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
}
offset += 1;
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_more_frags, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_type, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
switch (dest){
case 0x03:{ /* Server Admin */
dissect_sapenqueue_server_admin(tvb, pinfo, sapenqueue_tree, offset);
break;
}
case 0x06:{ /* Connection Admin */
dissect_sapenqueue_conn_admin(tvb, pinfo, sapenqueue_tree, offset, opcode);
break;
}
}
return tvb_reported_length(tvb);
}
static gboolean
dissect_sapenqueue_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_){
conversation_t *conversation = NULL;
/* If the first 4 bytes are the magic bytes, we can guess that the
* packet is a Enqueue server packet.
*/
if (tvb_get_ntohl(tvb, 0) != 0xabcde123){
return (FALSE);
}
/* From now on this conversation is dissected as SAP Enqueue traffic */
conversation = find_or_create_conversation(pinfo);
conversation_set_dissector(conversation, sapenqueue_handle);
/* Now dissect the packet */
dissect_sapenqueue(tvb, pinfo, tree, data);
return (TRUE);
}
void
proto_register_sapenqueue(void)
{
static hf_register_info hf[] = {
/* General Header fields */
{ &hf_sapenqueue_magic,
{ "Magic Bytes", "sapenqueue.magic", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_id,
{ "ID", "sapenqueue.id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_length,
{ "Length", "sapenqueue.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_length_frag,
{ "Fragment Length", "sapenqueue.fragment_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_dest,
{ "Destination", "sapenqueue.destination", FT_UINT8, BASE_DEC, VALS(sapenqueue_dest_vals), 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_opcode,
{ "Opcode", "sapenqueue.opcode", FT_UINT8, BASE_DEC, VALS(sapenqueue_conn_admin_opcode_vals), 0x0, NULL, HFILL }},
{ &hf_sapenqueue_more_frags,
{ "More Fragments", "sapenqueue.more_frags", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_type,
{ "Type", "sapenqueue.type", FT_UINT8, BASE_DEC, VALS(sapenqueue_type_vals), 0x0, NULL, HFILL }},
/* Server Admin fields */
{ &hf_sapenqueue_server_admin,
{ "Server Admin", "sapenqueue.server_admin", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_eyecatcher,
{ "Eye Catcher", "sapenqueue.server_admin.eyecatcher", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_version,
{ "Version", "sapenqueue.server_admin.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_flag,
{ "Flag", "sapenqueue.server_admin.flag", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_length,
{ "Length", "sapenqueue.server_admin.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_opcode,
{ "Opcode", "sapenqueue.server_admin.opcode", FT_UINT8, BASE_DEC, VALS(sapenqueue_server_admin_opcode_vals), 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_flags,
{ "Flags", "sapenqueue.server_admin.flags", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_rc,
{ "Return Code", "sapenqueue.server_admin.rc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_value,
{ "Value", "sapenqueue.server_admin.value", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
/* Trace Request fields */
{ &hf_sapenqueue_server_admin_trace_request,
{ "Trace Request", "sapenqueue.server_admin.trace", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_protocol_version,
{ "Trace Protocol Version", "sapenqueue.server_admin.trace.protocol", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_action,
{ "Trace Action", "sapenqueue.server_admin.trace.action", FT_UINT8, BASE_DEC, VALS(sapenqueue_server_admin_trace_action_vals), 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_limit,
{ "Trace Limit", "sapenqueue.server_admin.trace.limit", FT_UINT8, BASE_DEC, VALS(sapenqueue_server_admin_trace_limit_vals), 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_thread,
{ "Trace Thread", "sapenqueue.server_admin.trace.thread", FT_UINT8, BASE_DEC, VALS(sapenqueue_server_admin_trace_thread_vals), 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_level,
{ "Trace Level", "sapenqueue.server_admin.trace.level", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_logging,
{ "Trace Logging", "sapenqueue.server_admin.trace.logging", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_max_file_size,
{ "Trace Max File Size", "sapenqueue.server_admin.trace.max_file_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_nopatterns,
{ "Trace No Patterns", "sapenqueue.server_admin.trace.nopatterns", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_eyecatcher,
{ "Trace Eye Catcher", "sapenqueue.server_admin.trace.eyecatcher", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_patterns,
{ "Trace Patterns", "sapenqueue.server_admin.trace.patterns", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_unknown,
{ "Unknown field", "sapenqueue.server_admin.trace.unknown", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
/* Trace Request Pattern fields */
{ &hf_sapenqueue_server_admin_trace_pattern,
{ "Trace Pattern", "sapenqueue.server_admin.trace.pattern", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_pattern_len,
{ "Trace Pattern Length", "sapenqueue.server_admin.trace.pattern.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_server_admin_trace_pattern_value,
{ "Trace Pattern Value", "sapenqueue.server_admin.trace.pattern.value", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
/* Connection Admin fields */
{ &hf_sapenqueue_conn_admin,
{ "Connection Admin", "sapenqueue.conn_admin", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_params_count,
{ "Parameters Count", "sapenqueue.conn_admin.params.count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_params,
{ "Parameters", "sapenqueue.conn_admin.params", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_param,
{ "Parameter", "sapenqueue.conn_admin.params.param", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_param_id,
{ "Parameter ID", "sapenqueue.conn_admin.params.param.id", FT_UINT32, BASE_DEC, VALS(sapenqueue_conn_admin_param_vals), 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_param_len,
{ "Parameter Length", "sapenqueue.conn_admin.params.param.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_param_value,
{ "Parameter Value", "sapenqueue.conn_admin.params.param.value", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
{ &hf_sapenqueue_conn_admin_param_name,
{ "Parameter Name", "sapenqueue.conn_admin.params.param.name", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
};
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_sapenqueue
};
/* Register the expert info */
static ei_register_info ei[] = {
{ &ei_sapenqueue_pattern_invalid_length, { "sapenqueue.server_admin.trace.pattern.length.invalid", PI_MALFORMED, PI_WARN, "The reported length is incorrect", EXPFILL }},
{ &ei_sapenqueue_support_invalid_offset, { "sapenqueue.conn_admin.params.param.offset.invalid", PI_MALFORMED, PI_ERROR, "Invalid offset", EXPFILL }},
{ &ei_sapenqueue_support_invalid_length, { "sapenqueue.conn_admin.params.param.length.invalid", PI_MALFORMED, PI_WARN, "The reported length is incorrect", EXPFILL }},
};
expert_module_t* sapenqueue_expert;
/* Register the protocol */
proto_sapenqueue = proto_register_protocol("SAP Enqueue Protocol", "SAPENQUEUE", "sapenqueue");
proto_register_field_array(proto_sapenqueue, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
sapenqueue_expert = expert_register_protocol(proto_sapenqueue);
expert_register_field_array(sapenqueue_expert, ei, array_length(ei));
register_dissector("sapenqueue", dissect_sapenqueue, proto_sapenqueue);
}
void
proto_reg_handoff_sapenqueue(void)
{
sapenqueue_handle = create_dissector_handle(dissect_sapenqueue, proto_sapenqueue);
/* Register the heuristic dissector. We need to use a heuristic dissector
* here as the Enqueue Server uses the same port number that the Dispatcher
* Service (32NN/tcp). */
heur_dissector_add("sapni", dissect_sapenqueue_heur, "SAP Enqueue Protocol", "sapenqueue", proto_sapenqueue, HEURISTIC_ENABLE);
}
/*
* 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:
*/