forked from osmocom/wireshark
SAPRouter: Added SAP Router as main dissector
This commit is contained in:
parent
2128053e7c
commit
82b5201f79
|
@ -73,6 +73,7 @@ SAP Enqueue Server (SAPEnqueue)
|
|||
SAP HANA SQL Command Network Protocol (SAPHDB)
|
||||
SAP Internet Graphic Server (SAP IGS)
|
||||
SAP Network Interface (SAPNI)
|
||||
SAP Router (SAPROUTER)
|
||||
World of Warcraft World (WOWW) display filters have been changed to be more internally consistent.
|
||||
Support for almost all WoW 1.12 messages has been added.
|
||||
Management Component Transport Protocol (MCTP)
|
||||
|
|
|
@ -1772,6 +1772,7 @@ set(DISSECTOR_SRC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/packet-saphdb.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-sapigs.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-sapni.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-saprouter.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-sasp.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-sbus.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/packet-sbc.c
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <epan/conversation.h>
|
||||
#include <wsutil/wmem/wmem.h>
|
||||
|
||||
#include "packet-sapni.h"
|
||||
|
||||
|
||||
/*
|
||||
* Define default ports. The right range should be 32NN and 4NNNN, but as port numbers are proprietary and not
|
||||
|
@ -88,7 +90,7 @@ get_sap_protocol_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset _U_,
|
|||
* heuristics as a first try as some protocols uses the same TCP ports
|
||||
* (e.g. 3200/tcp for Enqueue Server and Diag).
|
||||
*/
|
||||
static void
|
||||
void
|
||||
dissect_sap_protocol_payload(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, guint16 sport, guint16 dport){
|
||||
guint16 low_port = 0, high_port = 0;
|
||||
tvbuff_t *next_tvb = NULL;
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* packet-sapni.h
|
||||
* Routines for SAP NI (Network Interface) 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
|
||||
*/
|
||||
|
||||
#ifndef __PACKET_SAPPROTOCOL_H__
|
||||
#define __PACKET_SAPPROTOCOL_H__
|
||||
|
||||
#include <epan/packet.h>
|
||||
|
||||
extern void
|
||||
dissect_sap_protocol_payload(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, guint16 sport, guint16 dport);
|
||||
|
||||
#endif /* __PACKET_SAPPROTOCOL_H__ */
|
|
@ -0,0 +1,949 @@
|
|||
/* packet-saprouter.c
|
||||
* Routines for SAP Router 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 Router protocol.
|
||||
*
|
||||
* Some details and example requests can be found in pysap's documentation: https://pysap.readthedocs.io/en/latest/protocols/SAPRouter.html.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/expert.h>
|
||||
#include <wsutil/wmem/wmem.h>
|
||||
#include <epan/conversation.h>
|
||||
|
||||
#include "packet-sapni.h"
|
||||
|
||||
|
||||
/* Define default ports */
|
||||
#define SAPROUTER_PORT_RANGE "3298-3299"
|
||||
|
||||
/*
|
||||
* Length of the frame header
|
||||
*/
|
||||
#define SAPROUTER_HEADER_LEN 8
|
||||
|
||||
/*
|
||||
* Offsets of header fields
|
||||
*/
|
||||
#define SAPROUTER_ROUTE_LENGTH_OFFSET 16
|
||||
#define SAPROUTER_ROUTE_OFFSET_OFFSET 20
|
||||
|
||||
/* SAP Router Eye Catcher strings */
|
||||
#define SAPROUTER_TYPE_NIPING_STRING "EYECATCHER"
|
||||
#define SAPROUTER_TYPE_ROUTE_STRING "NI_ROUTE"
|
||||
#define SAPROUTER_TYPE_ROUTE_ACCEPT "NI_PONG"
|
||||
#define SAPROUTER_TYPE_ERR_STRING "NI_RTERR"
|
||||
#define SAPROUTER_TYPE_ADMIN_STRING "ROUTER_ADM"
|
||||
|
||||
/* SAP Router Talk Modes */
|
||||
static const value_string saprouter_talk_mode_vals[] = {
|
||||
{ 0, "NI_MSG_IO" },
|
||||
{ 1, "NI_RAW_IO" },
|
||||
{ 2, "NI_ROUT_IO" },
|
||||
/* NULL */
|
||||
{ 0, NULL},
|
||||
};
|
||||
|
||||
/* SAP Router Operation values */
|
||||
static const value_string saprouter_opcode_vals[] = {
|
||||
{ 0, "Error information" },
|
||||
{ 1, "Version Request" },
|
||||
{ 2, "Version Response" },
|
||||
{ 5, "Send Handle (5)" }, /* TODO: Check this opcodes */
|
||||
{ 6, "Send Handle (6)" }, /* TODO: Check this opcodes */
|
||||
{ 8, "Send Handle (8)" }, /* TODO: Check this opcodes */
|
||||
{ 70, "SNC request" }, /* TODO: Check this opcodes NiSncOpcode: NISNC_REQ */
|
||||
{ 71, "SNC handshake complete" }, /* TODO: Check this opcodes NiSncOpcode: NISNC_ACK */
|
||||
/* NULL */
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
/* SAP Router Return Code values (as per SAP Note 63342 https://launchpad.support.sap.com/#/notes/63342) */
|
||||
static const value_string saprouter_return_code_vals[] = {
|
||||
{ -1, "NI-internal error (NIEINTERN)" },
|
||||
{ -2, "Host name unknown (NIEHOST_UNKNOWN)" },
|
||||
{ -3, "Service unknown (NIESERV_UNKNOWN)" },
|
||||
{ -4, "Service already used (NIESERV_USED)" },
|
||||
{ -5, "Time limit reached (NIETIMEOUT)" },
|
||||
{ -6, "Connection to partner broken (NIECONN_BROKEN)" },
|
||||
{ -7, "Data range too small (NIETOO_SMALL)" },
|
||||
{ -8, "Invalid parameters (NIEINVAL)" },
|
||||
{ -9, "Wake-Up (without data) (NIEWAKEUP)" },
|
||||
{-10, "Connection setup failed (NIECONN_REFUSED)" },
|
||||
{-11, "PING/PONG signal received (NIEPING)" },
|
||||
{-12, "Connection to partner via NiRouter not yet set up (NIECONN_PENDING)" },
|
||||
{-13, "Invalid version (NIEVERSION)" },
|
||||
{-14, "Local hostname cannot be found (NIEMYHOSTNAME)" },
|
||||
{-15, "No free port in range (NIENOFREEPORT)" },
|
||||
{-16, "Local hostname invalid (NIEMYHOST_VERIFY)" },
|
||||
{-17, "Error in the SNC shift in the saprouter ==> (NIESNC_FAILURE)" },
|
||||
{-18, "Opcode received (NIEOPCODE)" },
|
||||
{-19, "queue limit reached, next package not accepted (NIEQUE_FULL)" },
|
||||
{-20, "Requested package too large (NIETOO_BIG)" },
|
||||
{-90, "Host name unknown (NIEROUT_HOST_UNKNOWN)" },
|
||||
{-91, "Service unknown (NIEROUT_SERV_UNKNOWN)" },
|
||||
{-92, "Connection setup failed (NIEROUT_CONN_REFUSED)" },
|
||||
{-93, "NI-internal errors (NIEROUT_INTERN)" },
|
||||
{-94, "Connect from source to destination not allowed (NIEROUT_PERM_DENIED)" },
|
||||
{-95, "Connection terminated (NIEROUT_CONN_BROKEN)" },
|
||||
{-96, "Invalid client version (NIEROUT_VERSION)" },
|
||||
{-97, "Connection cancelled by administrator (NIEROUT_CANCELED)" },
|
||||
{-98, "saprouter shutdown (NIEROUT_SHUTDOWN)" },
|
||||
{-99, "Information request refused (NIEROUT_INFO_DENIED)" },
|
||||
{-100, "Max. number of clients reached (NIEROUT_OVERFLOW)" },
|
||||
{-101, "Talkmode not allowed (NIEROUT_MODE_DENIED)" },
|
||||
{-102, "Client not available (NIEROUT_NOCLIENT)" },
|
||||
{-103, "Error in external library (NIEROUT_EXTERN)" },
|
||||
{-104, "Error in the SNC shift (NIEROUT_SNC_FAILURE)" },
|
||||
/* NULL */
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
/* SAP Router Admin Command values */
|
||||
static const value_string saprouter_admin_command_vals[] = {
|
||||
{ 2, "Information Request" },
|
||||
{ 3, "New Route Table Request" },
|
||||
{ 4, "Toggle Trace Request" },
|
||||
{ 5, "Stop Request" },
|
||||
{ 6, "Cancel Route Request" },
|
||||
{ 7, "Dump Buffers Request" },
|
||||
{ 8, "Flush Buffers Request" },
|
||||
{ 9, "Soft Shutdown Request" },
|
||||
{ 10, "Set Trace Peer" },
|
||||
{ 11, "Clear Trace Peer" },
|
||||
{ 12, "Trace Connection" },
|
||||
{ 13, "Trace Connection" },
|
||||
{ 14, "Hide Error Information Request" },
|
||||
/* NULL */
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
static int proto_saprouter = -1;
|
||||
|
||||
/* General fields */
|
||||
static int hf_saprouter_type = -1;
|
||||
static int hf_saprouter_ni_version = -1;
|
||||
|
||||
/* Niping messages */
|
||||
static int hf_saprouter_niping_message = -1;
|
||||
|
||||
/* Route information */
|
||||
static int hf_saprouter_route_version = -1;
|
||||
static int hf_saprouter_entries = -1;
|
||||
static int hf_saprouter_talk_mode = -1;
|
||||
static int hf_saprouter_rest_nodes = -1;
|
||||
static int hf_saprouter_route_length = -1;
|
||||
static int hf_saprouter_route_offset = -1;
|
||||
static int hf_saprouter_route = -1;
|
||||
static int hf_saprouter_route_string = -1;
|
||||
|
||||
static int hf_saprouter_route_requested_in = -1;
|
||||
static int hf_saprouter_route_accepted_in = -1;
|
||||
|
||||
/* Route strings */
|
||||
static int hf_saprouter_route_string_hostname = -1;
|
||||
static int hf_saprouter_route_string_service = -1;
|
||||
static int hf_saprouter_route_string_password = -1;
|
||||
|
||||
|
||||
/* Error Information/Control Messages */
|
||||
static int hf_saprouter_opcode = -1;
|
||||
static int hf_saprouter_return_code = -1;
|
||||
static int hf_saprouter_unknown = -1;
|
||||
|
||||
/* Error Information Messages */
|
||||
static int hf_saprouter_error_length = -1;
|
||||
static int hf_saprouter_error_string = -1;
|
||||
static int hf_saprouter_error_eyecatcher = -1;
|
||||
static int hf_saprouter_error_counter = -1;
|
||||
static int hf_saprouter_error_error = -1;
|
||||
static int hf_saprouter_error_return_code= -1;
|
||||
static int hf_saprouter_error_component = -1;
|
||||
static int hf_saprouter_error_release = -1;
|
||||
static int hf_saprouter_error_version = -1;
|
||||
static int hf_saprouter_error_module = -1;
|
||||
static int hf_saprouter_error_line = -1;
|
||||
static int hf_saprouter_error_detail= -1;
|
||||
static int hf_saprouter_error_time = -1;
|
||||
static int hf_saprouter_error_system_call = -1;
|
||||
static int hf_saprouter_error_errorno = -1;
|
||||
static int hf_saprouter_error_errorno_text = -1;
|
||||
static int hf_saprouter_error_error_count = -1;
|
||||
static int hf_saprouter_error_location= -1;
|
||||
static int hf_saprouter_error_unknown= -1; /* TODO: Unknown fields */
|
||||
|
||||
/* Control Messages */
|
||||
static int hf_saprouter_control_length = -1;
|
||||
static int hf_saprouter_control_string = -1;
|
||||
static int hf_saprouter_control_unknown = -1;
|
||||
|
||||
/* Admin Messages */
|
||||
static int hf_saprouter_admin_command = -1;
|
||||
static int hf_saprouter_admin_password = -1;
|
||||
static int hf_saprouter_admin_client_count_short = -1;
|
||||
static int hf_saprouter_admin_client_count_int = -1;
|
||||
static int hf_saprouter_admin_client_ids = -1;
|
||||
static int hf_saprouter_admin_client_id = -1;
|
||||
static int hf_saprouter_admin_address_mask = -1;
|
||||
|
||||
static gint ett_saprouter = -1;
|
||||
|
||||
/* Expert info */
|
||||
static expert_field ei_saprouter_route_password_found = EI_INIT;
|
||||
static expert_field ei_saprouter_route_invalid_length = EI_INIT;
|
||||
static expert_field ei_saprouter_info_password_found = EI_INIT;
|
||||
static expert_field ei_saprouter_invalid_client_ids = EI_INIT;
|
||||
|
||||
/* Global port preference */
|
||||
static range_t *global_saprouter_port_range;
|
||||
|
||||
|
||||
/* Global SNC dissection preference */
|
||||
static gboolean global_saprouter_snc_dissection = TRUE;
|
||||
|
||||
/* Protocol handle */
|
||||
static dissector_handle_t saprouter_handle;
|
||||
|
||||
/* Session state information being tracked in a SAP Router conversation */
|
||||
typedef struct saprouter_session_state {
|
||||
gboolean route_information;
|
||||
guint route_requested_in;
|
||||
gboolean route_accepted;
|
||||
guint route_accepted_in;
|
||||
gboolean route_snc_protected;
|
||||
gchar *src_hostname; /* Source hostname (first entry in the route string) */
|
||||
guint32 src_port; /* Source port number */
|
||||
gchar *src_password; /* Source password XXX: Check if possible */
|
||||
gchar *dest_hostname; /* Destination hostname (last entry in the route string) */
|
||||
guint32 dest_port; /* Destination port number */
|
||||
gchar *dest_password; /* Destination password */
|
||||
} saprouter_session_state;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void proto_reg_handoff_saprouter(void);
|
||||
void proto_register_saprouter(void);
|
||||
|
||||
|
||||
static guint32
|
||||
dissect_serviceport(gchar *port){
|
||||
guint32 portnumber = 0;
|
||||
|
||||
if (g_ascii_isdigit(port[0])){
|
||||
portnumber = (guint32)strtoul(port, NULL, 10);
|
||||
} else if ((strlen(port)>5) && g_str_has_prefix(port, "sapdp")){
|
||||
portnumber = 3200 + (guint32)strtoul(port+5, NULL, 10);
|
||||
} else if ((strlen(port)>5) && g_str_has_prefix(port, "sapgw")){
|
||||
portnumber = 3300 + (guint32)strtoul(port+5, NULL, 10);
|
||||
} else if ((strlen(port)>5) && g_str_has_prefix(port, "sapms")){
|
||||
portnumber = 3600 + (guint32)strtoul(port+5, NULL, 10);
|
||||
}
|
||||
return (portnumber);
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_routestring(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, saprouter_session_state *session_state){
|
||||
int hop = 1;
|
||||
guint32 len, route_offset, int_port = 0;
|
||||
gchar *hostname = NULL, *port = NULL, *password = NULL;
|
||||
proto_item *route_hop = NULL, *route_password = NULL;
|
||||
proto_tree *route_hop_tree = NULL;
|
||||
|
||||
while (tvb_offset_exists(tvb, offset)){
|
||||
route_offset = offset; hostname = port = password = NULL;
|
||||
|
||||
/* Create the subtree for this route hop */
|
||||
route_hop = proto_tree_add_item(tree, hf_saprouter_route_string, tvb, offset, 0, ENC_NA);
|
||||
route_hop_tree = proto_item_add_subtree(route_hop, ett_saprouter);
|
||||
proto_item_append_text(route_hop, ", nro %d", hop);
|
||||
|
||||
/* Dissect the hostname string */
|
||||
len = tvb_strsize(tvb, offset);
|
||||
hostname = (gchar *)tvb_get_string_enc(wmem_file_scope(), tvb, offset, len - 1, ENC_ASCII);
|
||||
proto_tree_add_item(route_hop_tree, hf_saprouter_route_string_hostname, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
|
||||
/* Dissect the port string */
|
||||
len = tvb_strsize(tvb, offset);
|
||||
port = (gchar *)tvb_get_string_enc(pinfo->pool, tvb, offset, len - 1, ENC_ASCII);
|
||||
proto_tree_add_item(route_hop_tree, hf_saprouter_route_string_service, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
|
||||
/* Dissect the password string */
|
||||
len = tvb_strsize(tvb, offset);
|
||||
password = (gchar *)tvb_get_string_enc(wmem_file_scope(), tvb, offset, len - 1, ENC_ASCII);
|
||||
route_password = proto_tree_add_item(route_hop_tree, hf_saprouter_route_string_password, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
|
||||
/* If a password was found, add a expert warning in the security category */
|
||||
if (len > 1){
|
||||
expert_add_info(pinfo, route_password, &ei_saprouter_route_password_found);
|
||||
}
|
||||
offset += len;
|
||||
|
||||
/* Adjust the size of the route hop item now that we know the size */
|
||||
proto_item_set_len(route_hop, offset - route_offset);
|
||||
|
||||
/* Get the service port in numeric format */
|
||||
int_port = dissect_serviceport(port);
|
||||
|
||||
/* Add the first hostname/port as source in the conversation state*/
|
||||
if ((hop==1) && !(pinfo->fd->visited)){
|
||||
session_state->src_hostname = hostname;
|
||||
session_state->src_port = int_port;
|
||||
session_state->src_password = password;
|
||||
}
|
||||
hop++;
|
||||
}
|
||||
|
||||
if (!(pinfo->fd->visited)) {
|
||||
/* Add the last hostname/port as destination */
|
||||
if (hop!=1){
|
||||
session_state->dest_hostname = hostname;
|
||||
session_state->dest_port = int_port;
|
||||
session_state->dest_password = password;
|
||||
}
|
||||
/* Save the status of the conversation state */
|
||||
session_state->route_information = TRUE;
|
||||
session_state->route_accepted = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_errorstring(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
|
||||
{
|
||||
guint32 len;
|
||||
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_eyecatcher, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_counter, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_error, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_return_code, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_component, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_release, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_version, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_module, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_line, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_detail, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_time, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_system_call, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_errorno, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_errorno_text, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_error_count, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_location, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_unknown, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_unknown, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_unknown, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_unknown, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
offset += len;
|
||||
|
||||
len = tvb_strsize(tvb, offset);
|
||||
proto_tree_add_item(tree, hf_saprouter_error_eyecatcher, tvb, offset, len, ENC_ASCII|ENC_NA);
|
||||
}
|
||||
|
||||
|
||||
static tvbuff_t*
|
||||
dissect_saprouter_snc_frame(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint32 offset _U_){
|
||||
|
||||
/* Call the SNC dissector
|
||||
* TODO: This will be enabled when the SNC dissector is added
|
||||
if (global_saprouter_snc_dissection == TRUE){
|
||||
return dissect_sapsnc_frame(tvb, pinfo, tree, offset);
|
||||
}
|
||||
*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dissect_saprouter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||
{
|
||||
tvbuff_t *next_tvb = NULL;
|
||||
guint8 opcode = 0;
|
||||
guint32 offset = 0, eyecatcher_length = 0;
|
||||
conversation_t *conversation = NULL;
|
||||
saprouter_session_state *session_state = NULL;
|
||||
proto_item *ti = NULL, *ri = NULL, *ei = NULL, *ci = NULL, *gi = NULL, *admin_password = NULL;
|
||||
proto_tree *saprouter_tree = NULL, *route_tree = NULL, *text_tree = NULL, *clients_tree = NULL;
|
||||
|
||||
/* Search for a conversation */
|
||||
conversation = find_or_create_conversation(pinfo);
|
||||
session_state = (saprouter_session_state *)conversation_get_proto_data(conversation, proto_saprouter);
|
||||
if (!session_state){
|
||||
session_state = wmem_new(wmem_file_scope(), saprouter_session_state);
|
||||
if (session_state){
|
||||
session_state->route_information = FALSE;
|
||||
session_state->route_requested_in = 0;
|
||||
session_state->route_accepted = FALSE;
|
||||
session_state->route_accepted_in = 0;
|
||||
session_state->route_snc_protected = FALSE;
|
||||
session_state->src_hostname = NULL;
|
||||
session_state->src_port = 0;
|
||||
session_state->src_password = NULL;
|
||||
session_state->dest_hostname = NULL;
|
||||
session_state->dest_port = 0;
|
||||
session_state->dest_password = NULL;
|
||||
conversation_add_proto_data(conversation, proto_saprouter, session_state);
|
||||
} else {
|
||||
/* Unable to establish a conversation, break dissection of the packet */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the protocol to the column */
|
||||
col_add_str(pinfo->cinfo, COL_PROTOCOL, "SAPROUTER");
|
||||
|
||||
/* Add the main SAP Router subtree */
|
||||
ti = proto_tree_add_item(tree, proto_saprouter, tvb, offset, -1, ENC_NA);
|
||||
saprouter_tree = proto_item_add_subtree(ti, ett_saprouter);
|
||||
|
||||
/* Get the 'eye catcher' length */
|
||||
eyecatcher_length = tvb_strsize(tvb, offset);
|
||||
|
||||
/* Niping message */
|
||||
if (tvb_reported_length_remaining(tvb, offset) >= 10 && tvb_strneql(tvb, offset, SAPROUTER_TYPE_NIPING_STRING, 10) == 0) {
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Niping message");
|
||||
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_type, tvb, offset, 10, ENC_ASCII|ENC_NA);
|
||||
offset += 10;
|
||||
proto_item_append_text(ti, ", Niping message");
|
||||
|
||||
if (tvb_reported_length_remaining(tvb, offset)) {
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_niping_message, tvb, offset, -1, ENC_NA);
|
||||
}
|
||||
|
||||
}
|
||||
/* Admin Message Type */
|
||||
else if (tvb_strneql(tvb, offset, SAPROUTER_TYPE_ADMIN_STRING, eyecatcher_length) == 0) {
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Admin message");
|
||||
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_type, tvb, offset, eyecatcher_length, ENC_ASCII|ENC_NA);
|
||||
offset += eyecatcher_length;
|
||||
proto_item_append_text(ti, ", Admin message");
|
||||
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_ni_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset++;
|
||||
|
||||
opcode = tvb_get_guint8(tvb, offset);
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_admin_command, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset++;
|
||||
|
||||
switch (opcode){
|
||||
case 2:{ /* Info request */
|
||||
offset+=2; /* Skip 2 bytes */
|
||||
/* Check if a password was supplied */
|
||||
if (tvb_offset_exists(tvb, offset) && (tvb_strsize(tvb, offset) > 0)){
|
||||
admin_password = proto_tree_add_item(saprouter_tree, hf_saprouter_admin_password, tvb, offset, tvb_strsize(tvb, offset), ENC_ASCII|ENC_NA);
|
||||
expert_add_info(pinfo, admin_password, &ei_saprouter_info_password_found);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10: /* Set Peer Trace */
|
||||
case 11:{ /* Clear Peer Trace */
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_admin_address_mask, tvb, offset, 32, ENC_ASCII|ENC_NA);
|
||||
break;
|
||||
}
|
||||
case 6: /* Cancel Route request */
|
||||
case 12: /* Trace Connection */
|
||||
case 13: /* Trace Connection */
|
||||
{
|
||||
guint16 client_count = 0, client_count_actual = 0;
|
||||
|
||||
/* Retrieve the client count first */
|
||||
if (opcode == 6){
|
||||
offset+=2; /* Skip 2 bytes for Cancel Route request*/
|
||||
client_count = tvb_get_ntohs(tvb, offset);
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_admin_client_count_short, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
offset+=2;
|
||||
} else {
|
||||
client_count = tvb_get_ntohl(tvb, offset);
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_admin_client_count_int, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset+=4;
|
||||
}
|
||||
|
||||
/* Parse the list of client IDs */
|
||||
ci = proto_tree_add_item(saprouter_tree, hf_saprouter_admin_client_ids, tvb, offset, 4*client_count, ENC_NA);
|
||||
clients_tree = proto_item_add_subtree(ci, ett_saprouter);
|
||||
while (tvb_offset_exists(tvb, offset) && tvb_reported_length_remaining(tvb, offset)>=4){
|
||||
proto_tree_add_item(clients_tree, hf_saprouter_admin_client_id, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset+=4;
|
||||
client_count_actual+=1;
|
||||
}
|
||||
|
||||
/* Check if the actual count of IDs differes from the reported number */
|
||||
if ((client_count_actual != client_count) || tvb_reported_length_remaining(tvb, offset)>0){
|
||||
expert_add_info(pinfo, clients_tree, &ei_saprouter_invalid_client_ids);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* Skip 2 bytes */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Route Message Type */
|
||||
} else if (tvb_strneql(tvb, offset, SAPROUTER_TYPE_ROUTE_STRING, eyecatcher_length) == 0){
|
||||
guint32 route_length = 0, route_offset = 0;
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Route message");
|
||||
|
||||
/* Get the route length/offset */
|
||||
route_length = tvb_get_ntohl(tvb, offset + SAPROUTER_ROUTE_LENGTH_OFFSET);
|
||||
route_offset = offset + SAPROUTER_ROUTE_OFFSET_OFFSET + 4;
|
||||
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_type, tvb, 0, eyecatcher_length, ENC_ASCII|ENC_NA);
|
||||
offset += eyecatcher_length;
|
||||
proto_item_append_text(ti, ", Route message");
|
||||
/* Add the fields */
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_route_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset++;
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_ni_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset++;
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_entries, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset++;
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_talk_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset+=3; /* There're two unused bytes there */
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_rest_nodes, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset++;
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_route_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset+=4;
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_route_offset, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset+=4;
|
||||
/* Add the route tree */
|
||||
if ((guint32)tvb_reported_length_remaining(tvb, offset) != route_length){
|
||||
expert_add_info_format(pinfo, saprouter_tree, &ei_saprouter_route_invalid_length, "Route string length is invalid (remaining=%d, route_length=%d)", tvb_reported_length_remaining(tvb, offset), route_length);
|
||||
route_length = (guint32)tvb_reported_length_remaining(tvb, offset);
|
||||
}
|
||||
ri = proto_tree_add_item(saprouter_tree, hf_saprouter_route, tvb, offset, route_length, ENC_NA);
|
||||
route_tree = proto_item_add_subtree(ri, ett_saprouter);
|
||||
|
||||
/* Dissect the route string */
|
||||
dissect_routestring(tvb, pinfo, route_tree, route_offset, session_state);
|
||||
|
||||
/* If this is the first time we're seeing this packet, mark it as the one where the route was requested */
|
||||
if (!pinfo->fd->visited) {
|
||||
session_state->route_requested_in = pinfo->num;
|
||||
}
|
||||
|
||||
/* Add the route to the colinfo*/
|
||||
if (session_state->src_hostname){
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Source: Hostname=%s Service Port=%d", session_state->src_hostname, session_state->src_port);
|
||||
if (strlen(session_state->src_password)>0)
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, " Password=%s", session_state->src_password);
|
||||
}
|
||||
if (session_state->dest_hostname){
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", Destination: Hostname=%s Service Port=%d", session_state->dest_hostname, session_state->dest_port);
|
||||
if (strlen(session_state->dest_password)>0)
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, " Password=%s", session_state->dest_password);
|
||||
}
|
||||
|
||||
if (session_state->route_accepted && session_state->route_accepted_in) {
|
||||
gi = proto_tree_add_uint(saprouter_tree, hf_saprouter_route_accepted_in, tvb, 0, 0, session_state->route_accepted_in);
|
||||
proto_item_set_generated(gi);
|
||||
}
|
||||
|
||||
/* Error Information/Control Message Type */
|
||||
} else if (tvb_strneql(tvb, offset, SAPROUTER_TYPE_ERR_STRING, eyecatcher_length) == 0){
|
||||
|
||||
/* Extract the opcode if possible to determine the type of message */
|
||||
if (tvb_offset_exists(tvb, offset + 10)) {
|
||||
opcode = tvb_get_guint8(tvb, offset + 10);
|
||||
} else {
|
||||
opcode = 0;
|
||||
}
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_INFO, (opcode==0)? "Error information" : "Control message");
|
||||
|
||||
guint32 text_length = 0;
|
||||
|
||||
proto_item_append_text(ti, (opcode==0)? ", Error information" : ", Control message");
|
||||
/* Add the fields */
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_type, tvb, offset, eyecatcher_length, ENC_ASCII|ENC_NA);
|
||||
offset += eyecatcher_length;
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_ni_version, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset++;
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
|
||||
offset+=2; /* There's a unused byte there */
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_return_code, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset+=4;
|
||||
|
||||
text_length = tvb_get_ntohl(tvb, offset);
|
||||
/* Error Information Message */
|
||||
if (opcode == 0){
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_error_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset+=4;
|
||||
if ((text_length > 0) && tvb_offset_exists(tvb, offset+text_length)){
|
||||
/* Add the error string tree */
|
||||
ei = proto_tree_add_item(saprouter_tree, hf_saprouter_error_string, tvb, offset, text_length, ENC_NA);
|
||||
text_tree = proto_item_add_subtree(ei, ett_saprouter);
|
||||
dissect_errorstring(tvb, text_tree, offset);
|
||||
offset += text_length;
|
||||
}
|
||||
|
||||
/* Add an unknown int field */
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_unknown, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
|
||||
/* Control Message */
|
||||
} else {
|
||||
/* Add the opcode name */
|
||||
proto_item_append_text(ti, ", opcode=%s", val_to_str(opcode, saprouter_opcode_vals, "Unknown"));
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", opcode=%s", val_to_str(opcode, saprouter_opcode_vals, "Unknown"));
|
||||
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_control_length, tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||
offset+=4;
|
||||
if ((text_length >0) && tvb_offset_exists(tvb, offset+text_length)){
|
||||
/* Add the control string tree */
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_control_string, tvb, offset, text_length, ENC_ASCII|ENC_NA);
|
||||
offset += text_length;
|
||||
}
|
||||
|
||||
/* SNC request, mark the conversation as SNC protected and dissect the SNC frame */
|
||||
if (opcode == 70 || opcode == 71){
|
||||
session_state->route_snc_protected = TRUE;
|
||||
dissect_saprouter_snc_frame(tvb, pinfo, tree, offset);
|
||||
|
||||
/* Other opcodes */
|
||||
} else {
|
||||
proto_tree_add_item(saprouter_tree, hf_saprouter_control_unknown, tvb, offset, 4, ENC_ASCII|ENC_NA);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Route Acceptance (NI_PONG) Message Type */
|
||||
} else if (tvb_strneql(tvb, offset, SAPROUTER_TYPE_ROUTE_ACCEPT, eyecatcher_length) == 0){
|
||||
/* Route information available */
|
||||
if (session_state->route_information){
|
||||
/* If this is the first time we're seen the packet, mark is as the one where the route was accepted */
|
||||
if (!pinfo->fd->visited) {
|
||||
session_state->route_accepted = TRUE;
|
||||
session_state->route_accepted_in = pinfo->num;
|
||||
}
|
||||
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", from %s:%d to %s:%d", session_state->src_hostname, session_state->src_port, session_state->dest_hostname, session_state->dest_port);
|
||||
proto_item_append_text(ti, ", from %s:%d to %s:%d", session_state->src_hostname, session_state->src_port, session_state->dest_hostname, session_state->dest_port);
|
||||
|
||||
if (session_state->route_requested_in) {
|
||||
gi = proto_tree_add_uint(saprouter_tree, hf_saprouter_route_requested_in, tvb, 0, 0, session_state->route_requested_in);
|
||||
proto_item_set_generated(gi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Uknown Message Type */
|
||||
} else {
|
||||
|
||||
col_add_fstr(pinfo->cinfo, COL_INFO, "Routed message");
|
||||
proto_item_append_text(ti, ", Routed message");
|
||||
|
||||
/* If the session is protected with SNC, first dissect the SNC frame
|
||||
* and save the content for further dissection.
|
||||
*/
|
||||
if (session_state->route_snc_protected) {
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", SNC protected");
|
||||
proto_item_append_text(ti, ", SNC protected");
|
||||
next_tvb = dissect_saprouter_snc_frame(tvb, pinfo, tree, offset);
|
||||
|
||||
/* If the session is not protected dissect the entire payload */
|
||||
} else {
|
||||
next_tvb = tvb;
|
||||
}
|
||||
|
||||
/* If the session has information about the route requested */
|
||||
if (session_state->route_information){
|
||||
|
||||
/* Route accepted */
|
||||
if (session_state->route_accepted){
|
||||
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", from %s:%d to %s:%d ", session_state->src_hostname, session_state->src_port, session_state->dest_hostname, session_state->dest_port);
|
||||
proto_item_append_text(ti, ", from %s:%d to %s:%d ", session_state->src_hostname, session_state->src_port, session_state->dest_hostname, session_state->dest_port);
|
||||
|
||||
if (session_state->route_requested_in) {
|
||||
gi = proto_tree_add_uint(saprouter_tree, hf_saprouter_route_requested_in, tvb, 0, 0, session_state->route_requested_in);
|
||||
proto_item_set_generated(gi);
|
||||
}
|
||||
if (session_state->route_accepted_in) {
|
||||
gi = proto_tree_add_uint(saprouter_tree, hf_saprouter_route_accepted_in, tvb, 0, 0, session_state->route_accepted_in);
|
||||
proto_item_set_generated(gi);
|
||||
}
|
||||
|
||||
/* Route not accepted but some information available */
|
||||
} else {
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", to unknown destination");
|
||||
proto_item_append_text(ti, ", to unknown destination");
|
||||
}
|
||||
|
||||
/* Call the dissector in the NI protocol sub-dissectors table
|
||||
* according to the route destination port number. */
|
||||
if (next_tvb) {
|
||||
dissect_sap_protocol_payload(next_tvb, offset, pinfo, tree, 0, session_state->dest_port);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* No route information available */
|
||||
col_append_fstr(pinfo->cinfo, COL_INFO, ", to unknown destination");
|
||||
proto_item_append_text(ti, ", to unknown destination");
|
||||
}
|
||||
}
|
||||
|
||||
return tvb_reported_length(tvb);
|
||||
}
|
||||
|
||||
void
|
||||
proto_register_saprouter(void)
|
||||
{
|
||||
static hf_register_info hf[] = {
|
||||
{ &hf_saprouter_type,
|
||||
{ "Type", "saprouter.type", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
/* Niping message */
|
||||
{ &hf_saprouter_niping_message,
|
||||
{ "Niping message", "saprouter.message", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
/* NI Route messages */
|
||||
{ &hf_saprouter_route_version,
|
||||
{ "Route version", "saprouter.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_ni_version,
|
||||
{ "NI version", "saprouter.niversion", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_entries,
|
||||
{ "Entries", "saprouter.entries", FT_UINT8, BASE_DEC, NULL, 0x0, "Total number of entries", HFILL }},
|
||||
{ &hf_saprouter_talk_mode,
|
||||
{ "Talk Mode", "saprouter.talkmode", FT_UINT8, BASE_DEC, VALS(saprouter_talk_mode_vals), 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_rest_nodes,
|
||||
{ "Remaining Hops", "saprouter.restnodes", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_route_length,
|
||||
{ "Route String Length", "saprouter.routelength", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_route_offset,
|
||||
{ "Route String Offset", "saprouter.routeoffset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_route,
|
||||
{ "Route String", "saprouter.routestring", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_route_string,
|
||||
{ "Route Hop", "saprouter.routestring", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_route_string_hostname,
|
||||
{ "Hostname", "saprouter.routestring.hostname", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_route_string_service,
|
||||
{ "Service", "saprouter.routestring.service", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_route_string_password,
|
||||
{ "Password", "saprouter.routestring.password", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
{ &hf_saprouter_route_requested_in,
|
||||
{ "Route Requested in", "saprouter.requested_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "The route request for this packet is in this packet", HFILL }},
|
||||
{ &hf_saprouter_route_accepted_in,
|
||||
{ "Route Accepted in", "saprouter.accepted_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "The route for this packet was accepted in this packet", HFILL }},
|
||||
|
||||
/* NI error information / Control messages */
|
||||
{ &hf_saprouter_opcode,
|
||||
{ "Operation Code", "saprouter.opcode", FT_UINT8, BASE_DEC, VALS(saprouter_opcode_vals), 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_return_code,
|
||||
{ "Return Code", "saprouter.returncode", FT_INT32, BASE_DEC, VALS(saprouter_return_code_vals), 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_unknown,
|
||||
{ "Unknown field", "saprouter.unknown", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
/* NI Error Information messages */
|
||||
{ &hf_saprouter_error_length,
|
||||
{ "Error Information Text Length", "saprouter.errorlength", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_string,
|
||||
{ "Error Information Text", "saprouter.errortext", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_eyecatcher,
|
||||
{ "Eyecatcher", "saprouter.errortext.eyecatcher", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_counter,
|
||||
{ "Counter", "saprouter.errortext.counter", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_error,
|
||||
{ "Error", "saprouter.errortext.error", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_return_code,
|
||||
{ "Return code", "saprouter.errortext.returncode", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_component,
|
||||
{ "Component", "saprouter.errortext.component", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_release,
|
||||
{ "Release", "saprouter.errortext.release", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_version,
|
||||
{ "Version", "saprouter.errortext.version", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_module,
|
||||
{ "Module", "saprouter.errortext.module", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_line,
|
||||
{ "Line", "saprouter.errortext.line", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_detail,
|
||||
{ "Detail", "saprouter.errortext.detail", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_time,
|
||||
{ "Time", "saprouter.errortext.time", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_system_call,
|
||||
{ "System Call", "saprouter.errortext.system_call", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_errorno,
|
||||
{ "Error Number", "saprouter.errortext.errorno", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_errorno_text,
|
||||
{ "Error Number Text", "saprouter.errortext.errorno_text", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_location,
|
||||
{ "Location", "saprouter.errortext.location", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_error_count,
|
||||
{ "Error Count", "saprouter.errortext.error_count", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_error_unknown,
|
||||
{ "Unknown field", "saprouter.errortext.unknown", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
/* Control messages */
|
||||
{ &hf_saprouter_control_length,
|
||||
{ "Control Text Length", "saprouter.controllength", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_control_string,
|
||||
{ "Control Text", "saprouter.controltext", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_control_unknown,
|
||||
{ "Control Unknown field", "saprouter.controlunknown", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
|
||||
/* Router Admin messages */
|
||||
{ &hf_saprouter_admin_command,
|
||||
{ "Admin Command", "saprouter.command", FT_UINT8, BASE_DEC, VALS(saprouter_admin_command_vals), 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_admin_password,
|
||||
{ "Admin Command Info Password", "saprouter.password", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_admin_client_count_short,
|
||||
{ "Admin Command Client Count", "saprouter.client_count", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_admin_client_count_int,
|
||||
{ "Admin Command Client Count", "saprouter.client_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_admin_client_ids,
|
||||
{ "Admin Command Client IDs", "saprouter.client_ids", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_admin_client_id,
|
||||
{ "Admin Command Client ID", "saprouter.client_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
||||
{ &hf_saprouter_admin_address_mask,
|
||||
{ "Admin Command Address Mask", "saprouter.address_mask", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
|
||||
};
|
||||
|
||||
/* Setup protocol subtree array */
|
||||
static gint *ett[] = {
|
||||
&ett_saprouter
|
||||
};
|
||||
|
||||
/* Register the expert info */
|
||||
static ei_register_info ei[] = {
|
||||
{ &ei_saprouter_route_password_found, { "saprouter.routestring.password", PI_SECURITY, PI_WARN, "Route password found", EXPFILL }},
|
||||
{ &ei_saprouter_info_password_found, { "saprouter.password", PI_SECURITY, PI_WARN, "Info password found", EXPFILL }},
|
||||
{ &ei_saprouter_route_invalid_length, { "saprouter.routestring.routelength.invalid", PI_MALFORMED, PI_WARN, "The route string length is invalid", EXPFILL }},
|
||||
{ &ei_saprouter_invalid_client_ids, { "saprouter.client_ids.invalid", PI_MALFORMED, PI_WARN, "Client IDs list is malformed", EXPFILL }},
|
||||
};
|
||||
|
||||
module_t *saprouter_module;
|
||||
expert_module_t* saprouter_expert;
|
||||
|
||||
/* Register the protocol */
|
||||
proto_saprouter = proto_register_protocol("SAP Router Protocol", "SAPROUTER", "saprouter");
|
||||
|
||||
proto_register_field_array(proto_saprouter, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
saprouter_expert = expert_register_protocol(proto_saprouter);
|
||||
expert_register_field_array(saprouter_expert, ei, array_length(ei));
|
||||
|
||||
register_dissector("saprouter", dissect_saprouter, proto_saprouter);
|
||||
|
||||
/* Register the preferences */
|
||||
saprouter_module = prefs_register_protocol(proto_saprouter, proto_reg_handoff_saprouter);
|
||||
|
||||
range_convert_str(wmem_epan_scope(), &global_saprouter_port_range, SAPROUTER_PORT_RANGE, MAX_TCP_PORT);
|
||||
prefs_register_range_preference(saprouter_module, "tcp_ports", "SAP Router Protocol TCP port numbers", "Port numbers used for SAP Router Protocol (default " SAPROUTER_PORT_RANGE ")", &global_saprouter_port_range, MAX_TCP_PORT);
|
||||
|
||||
prefs_register_bool_preference(saprouter_module, "snc_dissection", "Dissect SAP SNC frames", "Whether the SAP Router Protocol dissector should call the SAP SNC dissector for SNC frames", &global_saprouter_snc_dissection);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helpers for dealing with the port range
|
||||
*/
|
||||
static void range_delete_callback (guint32 port, gpointer ptr _U_)
|
||||
{
|
||||
dissector_delete_uint("sapni.port", port, saprouter_handle);
|
||||
}
|
||||
|
||||
static void range_add_callback (guint32 port, gpointer ptr _U_)
|
||||
{
|
||||
dissector_add_uint("sapni.port", port, saprouter_handle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register Hand off for the SAP Router Protocol
|
||||
*/
|
||||
void
|
||||
proto_reg_handoff_saprouter(void)
|
||||
{
|
||||
static gboolean initialized = FALSE;
|
||||
static range_t *saprouter_port_range;
|
||||
|
||||
if (!initialized) {
|
||||
saprouter_handle = create_dissector_handle(dissect_saprouter, proto_saprouter);
|
||||
initialized = TRUE;
|
||||
} else {
|
||||
range_foreach(saprouter_port_range, range_delete_callback, NULL);
|
||||
wmem_free(wmem_epan_scope(), saprouter_port_range);
|
||||
}
|
||||
|
||||
saprouter_port_range = range_copy(wmem_epan_scope(), global_saprouter_port_range);
|
||||
range_foreach(saprouter_port_range, range_add_callback, NULL);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 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:
|
||||
*/
|
Loading…
Reference in New Issue