2022-11-21 15:01:59 +00:00
/* 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>
2023-01-22 21:27:08 +00:00
# include <epan/tap.h>
# include <ui/tap-credentials.h>
2022-11-21 15:01:59 +00:00
# include "packet-sapni.h"
2022-11-29 13:34:38 +00:00
# include "packet-sapsnc.h"
2022-11-21 15:01:59 +00:00
/* 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 }
} ;
2023-01-22 21:27:08 +00:00
static int credentials_tap = - 1 ;
2022-11-21 15:01:59 +00:00
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 ) ;
2023-01-22 21:27:08 +00:00
/* Add the password to the credential tap */
tap_credential_t * auth = wmem_new0 ( pinfo - > pool , tap_credential_t ) ;
auth - > num = pinfo - > num ;
auth - > password_hf_id = hf_saprouter_route_string_password ;
auth - > proto = " SAP Router Route String password " ;
auth - > username = wmem_strdup ( pinfo - > pool , TAP_CREDENTIALS_PLACEHOLDER ) ;
tap_queue_packet ( credentials_tap , pinfo , auth ) ;
2022-11-21 15:01:59 +00:00
}
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_ ) {
2022-11-29 13:34:38 +00:00
/* Call the SNC dissector */
2022-11-21 15:01:59 +00:00
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 ;
2022-11-20 21:18:22 +00:00
guint8 opcode ;
2022-11-21 15:01:59 +00:00
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 ) ;
2023-01-22 21:27:08 +00:00
/* Add the password to the credential tap */
tap_credential_t * auth = wmem_new0 ( pinfo - > pool , tap_credential_t ) ;
auth - > num = pinfo - > num ;
auth - > password_hf_id = hf_saprouter_admin_password ;
auth - > proto = " SAP Router Info Request password " ;
auth - > username = wmem_strdup ( pinfo - > pool , TAP_CREDENTIALS_PLACEHOLDER ) ;
tap_queue_packet ( credentials_tap , pinfo , auth ) ;
2022-11-21 15:01:59 +00:00
}
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 [ ] = {
2023-01-25 22:17:11 +00:00
{ & ei_saprouter_route_password_found , { " saprouter.routestring.password.found " , PI_SECURITY , PI_WARN , " Route password found " , EXPFILL } } ,
{ & ei_saprouter_info_password_found , { " saprouter.password.found " , PI_SECURITY , PI_WARN , " Info password found " , EXPFILL } } ,
2022-11-21 15:01:59 +00:00
{ & 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 ) ;
2023-01-22 21:27:08 +00:00
/* Register the tap*/
credentials_tap = register_tap ( " credentials " ) ;
2022-11-21 15:01:59 +00:00
}
/**
* 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 :
*/