2014-04-07 20:33:51 +00:00
/* packet-lbtru.c
* Routines for LBT - RU Packet dissection
*
* Copyright ( c ) 2005 - 2014 Informatica Corporation . All Rights Reserved .
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
# include "config.h"
# include <glib.h>
# include <epan/packet.h>
# include <epan/prefs.h>
# include <epan/proto.h>
# include <epan/expert.h>
# include <epan/uat.h>
# include <epan/tfs.h>
# include <epan/value_string.h>
# include <epan/wmem/wmem.h>
# include <epan/conversation.h>
# include <epan/to_str.h>
# include "packet-lbm.h"
# include "packet-lbtru.h"
/* Protocol handle */
static int proto_lbtru = - 1 ;
/* Dissector handle */
static dissector_handle_t lbtru_dissector_handle ;
/*----------------------------------------------------------------------------*/
/* LBT-RU transport management. */
/*----------------------------------------------------------------------------*/
static const address lbtru_null_address = { AT_NONE , - 1 , 0 , NULL } ;
static lbtru_transport_t * lbtru_transport_find ( const address * source_address , guint16 source_port , guint32 session_id , guint32 frame )
{
lbtru_transport_t * entry = NULL ;
wmem_tree_t * session_tree = NULL ;
conversation_t * conv = NULL ;
conv = find_conversation ( frame , source_address , & lbtru_null_address , PT_UDP , source_port , 0 , 0 ) ;
if ( conv ! = NULL )
{
if ( frame ! = 0 )
{
if ( conv - > setup_frame = = 0 )
{
conv - > setup_frame = frame ;
}
if ( frame > conv - > last_frame )
{
conv - > last_frame = frame ;
}
}
session_tree = ( wmem_tree_t * ) conversation_get_proto_data ( conv , proto_lbtru ) ;
if ( session_tree ! = NULL )
{
entry = ( lbtru_transport_t * ) wmem_tree_lookup32 ( session_tree , session_id ) ;
}
}
return ( entry ) ;
}
lbtru_transport_t * lbtru_transport_add ( const address * source_address , guint16 source_port , guint32 session_id , guint32 frame )
{
lbtru_transport_t * entry = NULL ;
wmem_tree_t * session_tree = NULL ;
conversation_t * conv = NULL ;
conv = find_conversation ( frame , source_address , & lbtru_null_address , PT_UDP , source_port , 0 , 0 ) ;
if ( conv = = NULL )
{
conv = conversation_new ( frame , source_address , & lbtru_null_address , PT_UDP , source_port , 0 , 0 ) ;
}
if ( frame ! = 0 )
{
if ( conv - > setup_frame = = 0 )
{
conv - > setup_frame = frame ;
}
if ( frame > conv - > last_frame )
{
conv - > last_frame = frame ;
}
}
session_tree = ( wmem_tree_t * ) conversation_get_proto_data ( conv , proto_lbtru ) ;
if ( session_tree = = NULL )
{
session_tree = wmem_tree_new ( wmem_file_scope ( ) ) ;
conversation_add_proto_data ( conv , proto_lbtru , ( void * ) session_tree ) ;
}
entry = ( lbtru_transport_t * ) wmem_tree_lookup32 ( session_tree , session_id ) ;
if ( entry ! = NULL )
{
return ( entry ) ;
}
entry = wmem_new ( wmem_file_scope ( ) , lbtru_transport_t ) ;
SE_COPY_ADDRESS ( & ( entry - > source_address ) , source_address ) ;
entry - > source_port = source_port ;
entry - > session_id = session_id ;
entry - > channel = lbm_channel_assign ( LBM_CHANNEL_TRANSPORT_LBTRU ) ;
entry - > next_client_id = 1 ;
entry - > client_list = wmem_list_new ( wmem_file_scope ( ) ) ;
wmem_tree_insert32 ( session_tree , session_id , ( void * ) entry ) ;
return ( entry ) ;
}
static lbtru_client_transport_t * lbtru_client_transport_find ( lbtru_transport_t * transport , const address * receiver_address , guint16 receiver_port , guint32 frame )
{
lbtru_client_transport_t * entry = NULL ;
conversation_t * client_conv = NULL ;
if ( transport = = NULL )
{
return ( NULL ) ;
}
client_conv = find_conversation ( frame , & ( transport - > source_address ) , receiver_address , PT_UDP , transport - > source_port , receiver_port , 0 ) ;
if ( client_conv ! = NULL )
{
wmem_tree_t * session_tree = NULL ;
session_tree = ( wmem_tree_t * ) conversation_get_proto_data ( client_conv , proto_lbtru ) ;
if ( session_tree ! = NULL )
{
entry = ( lbtru_client_transport_t * ) wmem_tree_lookup32 ( session_tree , transport - > session_id ) ;
}
}
return ( entry ) ;
}
static lbtru_client_transport_t * lbtru_client_transport_add ( lbtru_transport_t * transport , const address * receiver_address , guint16 receiver_port , guint32 frame )
{
lbtru_client_transport_t * entry = NULL ;
conversation_t * client_conv = NULL ;
wmem_tree_t * session_tree = NULL ;
if ( transport = = NULL )
{
return ( NULL ) ;
}
entry = lbtru_client_transport_find ( transport , receiver_address , receiver_port , frame ) ;
if ( entry ! = NULL )
{
return ( entry ) ;
}
entry = wmem_new0 ( wmem_file_scope ( ) , lbtru_client_transport_t ) ;
SE_COPY_ADDRESS ( & ( entry - > receiver_address ) , receiver_address ) ;
entry - > receiver_port = receiver_port ;
entry - > transport = transport ;
entry - > id = transport - > next_client_id + + ;
entry - > frame = wmem_tree_new ( wmem_file_scope ( ) ) ;
entry - > last_frame = NULL ;
entry - > last_data_frame = NULL ;
entry - > last_sm_frame = NULL ;
entry - > last_nak_frame = NULL ;
entry - > last_ncf_frame = NULL ;
entry - > last_ack_frame = NULL ;
entry - > last_creq_frame = NULL ;
entry - > last_rst_frame = NULL ;
entry - > data_sqn = wmem_tree_new ( wmem_file_scope ( ) ) ;
entry - > sm_sqn = wmem_tree_new ( wmem_file_scope ( ) ) ;
entry - > data_high_sqn = 0 ;
entry - > sm_high_sqn = 0 ;
/* See if a conversation for this address/port pair exists. */
client_conv = find_conversation ( frame , & ( transport - > source_address ) , receiver_address , PT_UDP , transport - > source_port , receiver_port , 0 ) ;
if ( client_conv = = NULL )
{
client_conv = conversation_new ( frame , & ( transport - > source_address ) , receiver_address , PT_UDP , transport - > source_port , receiver_port , 0 ) ;
session_tree = wmem_tree_new ( wmem_file_scope ( ) ) ;
conversation_add_proto_data ( client_conv , proto_lbtru , ( void * ) session_tree ) ;
}
else
{
session_tree = ( wmem_tree_t * ) conversation_get_proto_data ( client_conv , proto_lbtru ) ;
if ( session_tree = = NULL )
{
session_tree = wmem_tree_new ( wmem_file_scope ( ) ) ;
conversation_add_proto_data ( client_conv , proto_lbtru , ( void * ) session_tree ) ;
}
}
wmem_tree_insert32 ( session_tree , transport - > session_id , ( void * ) entry ) ;
/* Add this client to the transport. */
wmem_list_append ( transport - > client_list , ( void * ) entry ) ;
return ( entry ) ;
}
static lbm_transport_sqn_t * lbtru_client_transport_sqn_find ( lbtru_client_transport_t * client , guint8 type , guint32 sqn )
{
lbm_transport_sqn_t * sqn_entry = NULL ;
switch ( type )
{
case LBTRU_PACKET_TYPE_DATA :
sqn_entry = ( lbm_transport_sqn_t * ) wmem_tree_lookup32 ( client - > data_sqn , sqn ) ;
break ;
case LBTRU_PACKET_TYPE_SM :
sqn_entry = ( lbm_transport_sqn_t * ) wmem_tree_lookup32 ( client - > sm_sqn , sqn ) ;
break ;
case LBTRU_PACKET_TYPE_NAK :
case LBTRU_PACKET_TYPE_NCF :
case LBTRU_PACKET_TYPE_ACK :
case LBTRU_PACKET_TYPE_CREQ :
case LBTRU_PACKET_TYPE_RST :
default :
sqn_entry = NULL ;
break ;
}
return ( sqn_entry ) ;
}
static lbm_transport_sqn_t * lbtru_client_transport_sqn_add ( lbtru_client_transport_t * client , lbm_transport_frame_t * frame )
{
wmem_tree_t * sqn_list = NULL ;
lbm_transport_sqn_t * sqn_entry = NULL ;
switch ( frame - > type )
{
case LBTRU_PACKET_TYPE_DATA :
sqn_list = client - > data_sqn ;
break ;
case LBTRU_PACKET_TYPE_SM :
sqn_list = client - > sm_sqn ;
break ;
case LBTRU_PACKET_TYPE_NAK :
case LBTRU_PACKET_TYPE_NCF :
case LBTRU_PACKET_TYPE_ACK :
case LBTRU_PACKET_TYPE_CREQ :
case LBTRU_PACKET_TYPE_RST :
default :
return ( NULL ) ;
break ;
}
/* Add the sqn. */
sqn_entry = lbm_transport_sqn_add ( sqn_list , frame ) ;
return ( sqn_entry ) ;
}
static lbm_transport_frame_t * lbtru_client_transport_frame_find ( lbtru_client_transport_t * client , guint32 frame )
{
return ( ( lbm_transport_frame_t * ) wmem_tree_lookup32 ( client - > frame , frame ) ) ;
}
static lbm_transport_frame_t * lbtru_client_transport_frame_add ( lbtru_client_transport_t * client , guint8 type , guint32 frame , guint32 sqn , gboolean retransmission )
{
lbm_transport_sqn_t * dup_sqn_entry = NULL ;
lbm_transport_frame_t * frame_entry = NULL ;
/* Locate the frame. */
frame_entry = lbtru_client_transport_frame_find ( client , frame ) ;
if ( frame_entry ! = NULL )
{
return ( frame_entry ) ;
}
frame_entry = lbm_transport_frame_add ( client - > frame , type , frame , sqn , retransmission ) ;
if ( client - > last_frame ! = NULL )
{
frame_entry - > previous_frame = client - > last_frame - > frame ;
client - > last_frame - > next_frame = frame ;
}
client - > last_frame = frame_entry ;
switch ( type )
{
case LBTRU_PACKET_TYPE_DATA :
if ( client - > last_data_frame ! = NULL )
{
frame_entry - > previous_type_frame = client - > last_data_frame - > frame ;
client - > last_data_frame - > next_type_frame = frame ;
/* Ideally, this frame's sqn is 1 more than the highest data sqn seen */
if ( frame_entry - > sqn < = client - > data_high_sqn )
{
dup_sqn_entry = lbtru_client_transport_sqn_find ( client , type , frame_entry - > sqn ) ;
if ( ! frame_entry - > retransmission )
{
/* Out of order */
if ( dup_sqn_entry ! = NULL )
{
frame_entry - > duplicate = TRUE ;
}
if ( frame_entry - > sqn ! = client - > data_high_sqn )
{
frame_entry - > ooo_gap = client - > data_high_sqn - frame_entry - > sqn ;
}
}
}
else
{
if ( ! frame_entry - > retransmission )
{
if ( frame_entry - > sqn ! = ( client - > data_high_sqn + 1 ) )
{
/* Gap */
frame_entry - > sqn_gap = frame_entry - > sqn - ( client - > last_data_frame - > sqn + 1 ) ;
}
}
}
}
if ( ( frame_entry - > sqn > client - > data_high_sqn ) & & ! frame_entry - > retransmission )
{
client - > data_high_sqn = frame_entry - > sqn ;
}
client - > last_data_frame = frame_entry ;
break ;
case LBTRU_PACKET_TYPE_SM :
if ( client - > last_sm_frame ! = NULL )
{
frame_entry - > previous_type_frame = client - > last_sm_frame - > frame ;
client - > last_sm_frame - > next_type_frame = frame ;
/* Ideally, this frame's sqn is 1 more than the highest SM sqn seen */
if ( frame_entry - > sqn < = client - > sm_high_sqn )
{
/* Out of order */
dup_sqn_entry = lbtru_client_transport_sqn_find ( client , type , frame_entry - > sqn ) ;
if ( dup_sqn_entry ! = NULL )
{
frame_entry - > duplicate = TRUE ;
}
if ( frame_entry - > sqn ! = client - > sm_high_sqn )
{
frame_entry - > ooo_gap = client - > sm_high_sqn - frame_entry - > sqn ;
}
}
else
{
if ( frame_entry - > sqn ! = ( client - > sm_high_sqn + 1 ) )
{
/* Gap */
frame_entry - > sqn_gap = frame_entry - > sqn - ( client - > sm_high_sqn + 1 ) ;
}
}
}
if ( frame_entry - > sqn > client - > sm_high_sqn )
{
client - > sm_high_sqn = frame_entry - > sqn ;
}
client - > last_sm_frame = frame_entry ;
break ;
case LBTRU_PACKET_TYPE_NAK :
if ( client - > last_nak_frame ! = NULL )
{
frame_entry - > previous_type_frame = client - > last_nak_frame - > frame ;
client - > last_nak_frame - > next_type_frame = frame ;
}
client - > last_nak_frame = frame_entry ;
break ;
case LBTRU_PACKET_TYPE_NCF :
if ( client - > last_ncf_frame ! = NULL )
{
frame_entry - > previous_type_frame = client - > last_ncf_frame - > frame ;
client - > last_ncf_frame - > next_type_frame = frame ;
}
client - > last_ncf_frame = frame_entry ;
break ;
case LBTRU_PACKET_TYPE_ACK :
if ( client - > last_ack_frame ! = NULL )
{
frame_entry - > previous_type_frame = client - > last_ack_frame - > frame ;
client - > last_ack_frame - > next_type_frame = frame ;
}
client - > last_ack_frame = frame_entry ;
break ;
case LBTRU_PACKET_TYPE_CREQ :
if ( client - > last_creq_frame ! = NULL )
{
frame_entry - > previous_type_frame = client - > last_creq_frame - > frame ;
client - > last_creq_frame - > next_type_frame = frame ;
}
client - > last_creq_frame = frame_entry ;
break ;
case LBTRU_PACKET_TYPE_RST :
if ( client - > last_rst_frame ! = NULL )
{
frame_entry - > previous_type_frame = client - > last_rst_frame - > frame ;
client - > last_rst_frame - > next_type_frame = frame ;
}
client - > last_rst_frame = frame_entry ;
break ;
}
/* Add the sqn. */
( void ) lbtru_client_transport_sqn_add ( client , frame_entry ) ;
return ( frame_entry ) ;
}
char * lbtru_transport_source_string ( const address * source_address , guint16 source_port , guint32 session_id )
{
char * bufptr = NULL ;
if ( session_id = = 0 )
{
bufptr = wmem_strdup_printf ( wmem_file_scope ( ) , " LBT-RU:%s:% " G_GUINT16_FORMAT , address_to_str ( wmem_packet_scope ( ) , source_address ) , source_port ) ;
}
else
{
bufptr = wmem_strdup_printf ( wmem_file_scope ( ) , " LBT-RU:%s:% " G_GUINT16_FORMAT " :%08x " , address_to_str ( wmem_packet_scope ( ) , source_address ) , source_port , session_id ) ;
}
return ( bufptr ) ;
}
/*----------------------------------------------------------------------------*/
/* Packet layouts. */
/*----------------------------------------------------------------------------*/
/* LBT-RU main header */
typedef struct
{
lbm_uint8_t ver_type ;
lbm_uint8_t next_hdr ;
lbm_uint16_t flags_or_res ;
} lbtru_hdr_t ;
# define O_LBTRU_HDR_T_VER_TYPE OFFSETOF(lbtru_hdr_t, ver_type)
# define L_LBTRU_HDR_T_VER_TYPE SIZEOF(lbtru_hdr_t, ver_type)
# define O_LBTRU_HDR_T_NEXT_HDR OFFSETOF(lbtru_hdr_t, next_hdr)
# define L_LBTRU_HDR_T_NEXT_HDR SIZEOF(lbtru_hdr_t, next_hdr)
# define O_LBTRU_HDR_T_FLAGS_OR_RES OFFSETOF(lbtru_hdr_t, flags_or_res)
# define L_LBTRU_HDR_T_FLAGS_OR_RES SIZEOF(lbtru_hdr_t, flags_or_res)
# define L_LBTRU_HDR_T (gint) sizeof(lbtru_hdr_t)
# define LBTRU_VERSION 0x00
# define LBTRU_HDR_VER(x) (x >> 4)
# define LBTRU_HDR_TYPE(x) (x & 0x0F)
# define LBTRU_HDR_VER_VER_MASK 0xF0
# define LBTRU_HDR_VER_TYPE_MASK 0x0F
# define LBTRU_RETRANSMISSION_FLAG 0x4000
/* LBT-RU data header */
typedef struct
{
lbm_uint32_t sqn ;
lbm_uint32_t trail_sqn ;
} lbtru_data_hdr_t ;
# define O_LBTRU_DATA_HDR_T_SQN OFFSETOF(lbtru_data_hdr_t, sqn)
# define L_LBTRU_DATA_HDR_T_SQN SIZEOF(lbtru_data_hdr_t, sqn)
# define O_LBTRU_DATA_HDR_T_TRAIL_SQN OFFSETOF(lbtru_data_hdr_t, trail_sqn)
# define L_LBTRU_DATA_HDR_T_TRAIL_SQN SIZEOF(lbtru_data_hdr_t, trail_sqn)
# define L_LBTRU_DATA_HDR_T (gint) (sizeof(lbtru_data_hdr_t))
/* LBT-RU Session Message header */
typedef struct
{
lbm_uint32_t sm_sqn ;
lbm_uint32_t lead_sqn ;
lbm_uint32_t trail_sqn ;
} lbtru_sm_hdr_t ;
# define O_LBTRU_SM_HDR_T_SM_SQN OFFSETOF(lbtru_sm_hdr_t, sm_sqn)
# define L_LBTRU_SM_HDR_T_SM_SQN SIZEOF(lbtru_sm_hdr_t, sm_sqn)
# define O_LBTRU_SM_HDR_T_LEAD_SQN OFFSETOF(lbtru_sm_hdr_t, lead_sqn)
# define L_LBTRU_SM_HDR_T_LEAD_SQN SIZEOF(lbtru_sm_hdr_t, lead_sqn)
# define O_LBTRU_SM_HDR_T_TRAIL_SQN OFFSETOF(lbtru_sm_hdr_t, trail_sqn)
# define L_LBTRU_SM_HDR_T_TRAIL_SQN SIZEOF(lbtru_sm_hdr_t, trail_sqn)
# define L_LBTRU_SM_HDR_T (gint) (sizeof(lbtru_sm_hdr_t))
# define LBTRU_SM_SYN_FLAG 0x8000
/* LBT-RU NAK header */
typedef struct
{
lbm_uint16_t num_naks ;
lbm_uint16_t format ;
} lbtru_nak_hdr_t ;
# define O_LBTRU_NAK_HDR_T_NUM_NAKS OFFSETOF(lbtru_nak_hdr_t, num_naks)
# define L_LBTRU_NAK_HDR_T_NUM_NAKS SIZEOF(lbtru_nak_hdr_t, num_naks)
# define O_LBTRU_NAK_HDR_T_FORMAT OFFSETOF(lbtru_nak_hdr_t, format)
# define L_LBTRU_NAK_HDR_T_FORMAT SIZEOF(lbtru_nak_hdr_t, format)
# define L_LBTRU_NAK_HDR_T (gint) (sizeof(lbtru_nak_hdr_t))
# define LBTRU_NAK_SELECTIVE_FORMAT 0x0
# define LBTRU_NAK_HDR_FORMAT_MASK 0x000F
# define LBTRU_NAK_HDR_FORMAT(x) (x & 0xF)
/* LBT-RU NAK Confirmation header */
typedef struct
{
lbm_uint32_t trail_sqn ;
lbm_uint16_t num_ncfs ;
lbm_uint8_t reserved ;
lbm_uint8_t reason_format ;
} lbtru_ncf_hdr_t ;
# define O_LBTRU_NCF_HDR_T_TRAIL_SQN OFFSETOF(lbtru_ncf_hdr_t, trail_sqn)
# define L_LBTRU_NCF_HDR_T_TRAIL_SQN SIZEOF(lbtru_ncf_hdr_t, trail_sqn)
# define O_LBTRU_NCF_HDR_T_NUM_NCFS OFFSETOF(lbtru_ncf_hdr_t, num_ncfs)
# define L_LBTRU_NCF_HDR_T_NUM_NCFS SIZEOF(lbtru_ncf_hdr_t, num_ncfs)
# define O_LBTRU_NCF_HDR_T_RESERVED OFFSETOF(lbtru_ncf_hdr_t, reserved)
# define L_LBTRU_NCF_HDR_T_RESERVED SIZEOF(lbtru_ncf_hdr_t, reserved)
# define O_LBTRU_NCF_HDR_T_REASON_FORMAT OFFSETOF(lbtru_ncf_hdr_t, reason_format)
# define L_LBTRU_NCF_HDR_T_REASON_FORMAT SIZEOF(lbtru_ncf_hdr_t, reason_format)
# define L_LBTRU_NCF_HDR_T (gint) (sizeof(lbtru_ncf_hdr_t))
# define LBTRU_NCF_SELECTIVE_FORMAT 0x0
# define LBTRU_NCF_REASON_NO_RETRY 0x0
# define LBTRU_NCF_REASON_IGNORED 0x1
# define LBTRU_NCF_REASON_RX_DELAY 0x2
# define LBTRU_NCF_REASON_SHED 0x3
# define LBTRU_NCF_HDR_REASON(x) ((x & 0xF0) >> 4)
# define LBTRU_NCF_HDR_FORMAT(x) (x & 0xF)
# define LBTRU_NCF_HDR_REASON_MASK 0xF0
# define LBTRU_NCF_HDR_FORMAT_MASK 0x0F
/* LBT-RU ACK header */
typedef struct
{
lbm_uint32_t ack_sqn ;
} lbtru_ack_hdr_t ;
# define O_LBTRU_ACK_HDR_T_ACK_SQN OFFSETOF(lbtru_ack_hdr_t, ack_sqn)
# define L_LBTRU_ACK_HDR_T_ACK_SQN SIZEOF(lbtru_ack_hdr_t, ack_sqn)
# define L_LBTRU_ACK_HDR_T (gint) (sizeof(lbtru_ack_hdr_t))
/* LBT-RU basic option header */
typedef struct
{
lbm_uint8_t next_hdr ;
lbm_uint8_t hdr_len ;
lbm_uint16_t res ;
} lbtru_basic_opt_t ;
# define O_LBTRU_BASIC_OPT_T_NEXT_HDR OFFSETOF(lbtru_basic_opt_t, next_hdr)
# define L_LBTRU_BASIC_OPT_T_NEXT_HDR SIZEOF(lbtru_basic_opt_t, next_hdr)
# define O_LBTRU_BASIC_OPT_T_HDR_LEN OFFSETOF(lbtru_basic_opt_t, hdr_len)
# define L_LBTRU_BASIC_OPT_T_HDR_LEN SIZEOF(lbtru_basic_opt_t, hdr_len)
# define O_LBTRU_BASIC_OPT_T_RES OFFSETOF(lbtru_basic_opt_t, res)
# define L_LBTRU_BASIC_OPT_T_RES SIZEOF(lbtru_basic_opt_t, res)
# define L_LBTRU_BASIC_OPT_T (gint) (sizeof(lbtru_basic_opt_t))
/* LBT-RU Session ID option header */
typedef struct
{
lbm_uint32_t session_id ;
} lbtru_sid_opt_t ;
# define O_LBTRU_SID_OPT_T_SESSION_ID OFFSETOF(lbtru_sid_opt_t, session_id)
# define L_LBTRU_SID_OPT_T_SESSION_ID SIZEOF(lbtru_sid_opt_t, session_id)
# define L_LBTRU_SID_OPT_T (gint) (sizeof(lbtru_sid_opt_t))
/* LBT-RU Client ID option header */
typedef struct
{
lbm_uint32_t client_sid ;
} lbtru_cid_opt_t ;
# define O_LBTRU_CID_OPT_T_CLIENT_SID OFFSETOF(lbtru_cid_opt_t, client_sid)
# define L_LBTRU_CID_OPT_T_CLIENT_SID SIZEOF(lbtru_cid_opt_t, client_sid)
# define L_LBTRU_CID_OPT_T (gint) (sizeof(lbtru_cid_opt_t))
# define LBTRU_OPT_IGNORE 0x8000
# define LBTRU_NHDR_DATA 0x00
# define LBTRU_NHDR_SID 0x01
# define LBTRU_NHDR_CID 0x02
/* CREQ and RST use the normal header */
# define LBTRU_CREQ_REQUEST_SYN 0x0
# define LBTRU_RST_REASON_DEFAULT 0x0
/*----------------------------------------------------------------------------*/
/* Value translation tables. */
/*----------------------------------------------------------------------------*/
static const value_string lbtru_packet_type [ ] =
{
{ LBTRU_PACKET_TYPE_DATA , " DATA " } ,
{ LBTRU_PACKET_TYPE_SM , " SM " } ,
{ LBTRU_PACKET_TYPE_NAK , " NAK " } ,
{ LBTRU_PACKET_TYPE_NCF , " NCF " } ,
{ LBTRU_PACKET_TYPE_ACK , " ACK " } ,
{ LBTRU_PACKET_TYPE_CREQ , " CREQ " } ,
{ LBTRU_PACKET_TYPE_RST , " RST " } ,
{ 0x0 , NULL }
} ;
static const value_string lbtru_nak_format [ ] =
{
{ LBTRU_NAK_SELECTIVE_FORMAT , " Selective " } ,
{ 0x0 , NULL }
} ;
static const value_string lbtru_ncf_format [ ] =
{
{ LBTRU_NCF_SELECTIVE_FORMAT , " Selective " } ,
{ 0x0 , NULL }
} ;
static const value_string lbtru_ncf_reason [ ] =
{
{ LBTRU_NCF_REASON_NO_RETRY , " Do not retry " } ,
{ LBTRU_NCF_REASON_IGNORED , " NAK Ignored " } ,
{ LBTRU_NCF_REASON_RX_DELAY , " Retransmit Delay " } ,
{ LBTRU_NCF_REASON_SHED , " NAK Shed " } ,
{ 0x0 , NULL }
} ;
static const value_string lbtru_creq_request [ ] =
{
{ LBTRU_CREQ_REQUEST_SYN , " SYN " } ,
{ 0x0 , NULL }
} ;
static const value_string lbtru_rst_reason [ ] =
{
{ LBTRU_RST_REASON_DEFAULT , " Default " } ,
{ 0x0 , NULL }
} ;
static const value_string lbtru_next_header [ ] =
{
{ LBTRU_NHDR_DATA , " DATA " } ,
{ LBTRU_NHDR_SID , " SID " } ,
{ LBTRU_NHDR_CID , " CID " } ,
{ 0x0 , NULL }
} ;
/*----------------------------------------------------------------------------*/
/* Preferences. */
/*----------------------------------------------------------------------------*/
/* Preferences default values. */
# define LBTRU_DEFAULT_SOURCE_PORT_LOW 14380
# define LBTRU_DEFAULT_SOURCE_PORT_HIGH 14389
# define LBTRU_DEFAULT_RECEIVER_PORT_LOW 14360
# define LBTRU_DEFAULT_RECEIVER_PORT_HIGH 14379
/* Global preferences variables (altered by the preferences dialog). */
static guint32 global_lbtru_source_port_low = LBTRU_DEFAULT_SOURCE_PORT_LOW ;
static guint32 global_lbtru_source_port_high = LBTRU_DEFAULT_SOURCE_PORT_HIGH ;
static guint32 global_lbtru_receiver_port_low = LBTRU_DEFAULT_RECEIVER_PORT_LOW ;
static guint32 global_lbtru_receiver_port_high = LBTRU_DEFAULT_RECEIVER_PORT_HIGH ;
static gboolean global_lbtru_expert_separate_naks = FALSE ;
static gboolean global_lbtru_expert_separate_ncfs = FALSE ;
static gboolean global_lbtru_use_tag = FALSE ;
static gboolean global_lbtru_sequence_analysis = FALSE ;
/* Local preferences variables (used by the dissector). */
static guint32 lbtru_source_port_low = LBTRU_DEFAULT_SOURCE_PORT_LOW ;
static guint32 lbtru_source_port_high = LBTRU_DEFAULT_SOURCE_PORT_HIGH ;
static guint32 lbtru_receiver_port_low = LBTRU_DEFAULT_RECEIVER_PORT_LOW ;
static guint32 lbtru_receiver_port_high = LBTRU_DEFAULT_RECEIVER_PORT_HIGH ;
static gboolean lbtru_expert_separate_naks = FALSE ;
static gboolean lbtru_expert_separate_ncfs = FALSE ;
static gboolean lbtru_use_tag = FALSE ;
static gboolean lbtru_sequence_analysis = FALSE ;
/*----------------------------------------------------------------------------*/
/* Tag management. */
/*----------------------------------------------------------------------------*/
typedef struct
{
char * name ;
guint32 source_port_low ;
guint32 source_port_high ;
guint32 receiver_port_low ;
guint32 receiver_port_high ;
} lbtru_tag_entry_t ;
static lbtru_tag_entry_t * lbtru_tag_entry = NULL ;
static guint lbtru_tag_count = 0 ;
UAT_CSTRING_CB_DEF ( lbtru_tag , name , lbtru_tag_entry_t )
UAT_DEC_CB_DEF ( lbtru_tag , source_port_low , lbtru_tag_entry_t )
UAT_DEC_CB_DEF ( lbtru_tag , source_port_high , lbtru_tag_entry_t )
UAT_DEC_CB_DEF ( lbtru_tag , receiver_port_low , lbtru_tag_entry_t )
UAT_DEC_CB_DEF ( lbtru_tag , receiver_port_high , lbtru_tag_entry_t )
static uat_field_t lbtru_tag_array [ ] =
{
UAT_FLD_CSTRING ( lbtru_tag , name , " Tag name " , " Tag name " ) ,
UAT_FLD_DEC ( lbtru_tag , source_port_low , " Source port low " , " Source port low " ) ,
UAT_FLD_DEC ( lbtru_tag , source_port_high , " Source port high " , " Source port high " ) ,
UAT_FLD_DEC ( lbtru_tag , receiver_port_low , " Receiver port low " , " Receiver port low " ) ,
UAT_FLD_DEC ( lbtru_tag , receiver_port_high , " Receiver port high " , " Receiver port high " ) ,
UAT_END_FIELDS
} ;
/*----------------------------------------------------------------------------*/
/* UAT callback functions. */
/*----------------------------------------------------------------------------*/
static void lbtru_tag_update_cb ( void * record , const char * * error_string )
{
lbtru_tag_entry_t * tag = ( lbtru_tag_entry_t * ) record ;
if ( tag - > name = = NULL )
{
* error_string = g_strdup_printf ( " Tag name can't be empty " ) ;
}
else
{
g_strstrip ( tag - > name ) ;
if ( tag - > name [ 0 ] = = 0 )
{
* error_string = g_strdup_printf ( " Tag name can't be empty " ) ;
}
}
}
static void * lbtru_tag_copy_cb ( void * destination , const void * source , size_t length _U_ )
{
const lbtru_tag_entry_t * src = ( const lbtru_tag_entry_t * ) source ;
lbtru_tag_entry_t * dest = ( lbtru_tag_entry_t * ) destination ;
dest - > name = g_strdup ( src - > name ) ;
dest - > source_port_low = src - > source_port_low ;
dest - > source_port_high = src - > source_port_high ;
dest - > receiver_port_low = src - > receiver_port_low ;
dest - > receiver_port_high = src - > receiver_port_high ;
return ( dest ) ;
}
static void lbtru_tag_free_cb ( void * record )
{
lbtru_tag_entry_t * tag = ( lbtru_tag_entry_t * ) record ;
if ( tag - > name ! = NULL )
{
g_free ( tag - > name ) ;
tag - > name = NULL ;
}
}
static char * lbtru_tag_find ( packet_info * pinfo )
{
guint idx ;
lbtru_tag_entry_t * tag = NULL ;
if ( ! lbtru_use_tag )
{
return ( NULL ) ;
}
for ( idx = 0 ; idx < lbtru_tag_count ; + + idx )
{
tag = & ( lbtru_tag_entry [ idx ] ) ;
if ( ( ( pinfo - > destport > = tag - > source_port_low )
& & ( pinfo - > destport < = tag - > source_port_high )
& & ( pinfo - > srcport > = tag - > receiver_port_low )
& & ( pinfo - > srcport < = tag - > receiver_port_high ) )
| | ( ( pinfo - > destport > = tag - > receiver_port_low )
& & ( pinfo - > destport < = tag - > receiver_port_high )
& & ( pinfo - > srcport > = tag - > source_port_low )
& & ( pinfo - > srcport < = tag - > source_port_high ) ) )
{
/* One of ours. */
return tag - > name ;
}
}
return ( NULL ) ;
}
/*----------------------------------------------------------------------------*/
/* Handles of all types. */
/*----------------------------------------------------------------------------*/
/* Dissector tree handles */
static gint ett_lbtru = - 1 ;
static gint ett_lbtru_channel = - 1 ;
static gint ett_lbtru_hdr = - 1 ;
static gint ett_lbtru_hdr_ver_type = - 1 ;
static gint ett_lbtru_hdr_flags = - 1 ;
static gint ett_lbtru_data = - 1 ;
static gint ett_lbtru_sm = - 1 ;
static gint ett_lbtru_nak = - 1 ;
static gint ett_lbtru_nak_format = - 1 ;
static gint ett_lbtru_nak_list = - 1 ;
static gint ett_lbtru_ncf = - 1 ;
static gint ett_lbtru_ncf_reason_format = - 1 ;
static gint ett_lbtru_ncf_list = - 1 ;
static gint ett_lbtru_ack = - 1 ;
static gint ett_lbtru_opt = - 1 ;
static gint ett_lbtru_opt_sid_flags = - 1 ;
static gint ett_lbtru_opt_cid_flags = - 1 ;
static gint ett_lbtru_transport = - 1 ;
static gint ett_lbtru_transport_sqn = - 1 ;
/* Dissector field handles */
static int hf_lbtru_channel = - 1 ;
static int hf_lbtru_channel_id = - 1 ;
static int hf_lbtru_channel_client = - 1 ;
static int hf_lbtru_tag = - 1 ;
static int hf_lbtru_hdr = - 1 ;
static int hf_lbtru_hdr_ver_type = - 1 ;
static int hf_lbtru_hdr_ver_type_ver = - 1 ;
static int hf_lbtru_hdr_ver_type_type = - 1 ;
static int hf_lbtru_hdr_next_hdr = - 1 ;
static int hf_lbtru_hdr_res = - 1 ;
static int hf_lbtru_hdr_flags = - 1 ;
static int hf_lbtru_hdr_flags_syn = - 1 ;
static int hf_lbtru_hdr_flags_rx = - 1 ;
static int hf_lbtru_hdr_request = - 1 ;
static int hf_lbtru_hdr_reason = - 1 ;
static int hf_lbtru_data = - 1 ;
static int hf_lbtru_data_sqn = - 1 ;
static int hf_lbtru_data_trail_sqn = - 1 ;
static int hf_lbtru_sm = - 1 ;
static int hf_lbtru_sm_sqn = - 1 ;
static int hf_lbtru_sm_lead_sqn = - 1 ;
static int hf_lbtru_sm_trail_sqn = - 1 ;
static int hf_lbtru_nak = - 1 ;
static int hf_lbtru_nak_num = - 1 ;
static int hf_lbtru_nak_format = - 1 ;
static int hf_lbtru_nak_format_format = - 1 ;
static int hf_lbtru_nak_list = - 1 ;
static int hf_lbtru_nak_list_nak = - 1 ;
static int hf_lbtru_ncf = - 1 ;
static int hf_lbtru_ncf_trail_sqn = - 1 ;
static int hf_lbtru_ncf_num = - 1 ;
static int hf_lbtru_ncf_reserved = - 1 ;
static int hf_lbtru_ncf_reason_format = - 1 ;
static int hf_lbtru_ncf_reason = - 1 ;
static int hf_lbtru_ncf_format = - 1 ;
static int hf_lbtru_ncf_list = - 1 ;
static int hf_lbtru_ncf_list_ncf = - 1 ;
static int hf_lbtru_ack = - 1 ;
static int hf_lbtru_ack_sqn = - 1 ;
static int hf_lbtru_opt_sid = - 1 ;
static int hf_lbtru_opt_sid_next_hdr = - 1 ;
static int hf_lbtru_opt_sid_hdr_len = - 1 ;
static int hf_lbtru_opt_sid_flags = - 1 ;
static int hf_lbtru_opt_sid_flags_ignore = - 1 ;
static int hf_lbtru_opt_sid_session_id = - 1 ;
static int hf_lbtru_opt_cid = - 1 ;
static int hf_lbtru_opt_cid_next_hdr = - 1 ;
static int hf_lbtru_opt_cid_hdr_len = - 1 ;
static int hf_lbtru_opt_cid_flags = - 1 ;
static int hf_lbtru_opt_cid_flags_ignore = - 1 ;
static int hf_lbtru_opt_cid_client_id = - 1 ;
2014-04-10 01:30:03 +00:00
static int hf_lbtru_opt_unknown = - 1 ;
static int hf_lbtru_opt_unknown_next_hdr = - 1 ;
static int hf_lbtru_opt_unknown_hdr_len = - 1 ;
2014-04-07 20:33:51 +00:00
static int hf_lbtru_analysis = - 1 ;
static int hf_lbtru_analysis_prev_frame = - 1 ;
static int hf_lbtru_analysis_prev_data_frame = - 1 ;
static int hf_lbtru_analysis_prev_sm_frame = - 1 ;
static int hf_lbtru_analysis_prev_nak_frame = - 1 ;
static int hf_lbtru_analysis_prev_ncf_frame = - 1 ;
static int hf_lbtru_analysis_prev_ack_frame = - 1 ;
static int hf_lbtru_analysis_prev_creq_frame = - 1 ;
static int hf_lbtru_analysis_prev_rst_frame = - 1 ;
static int hf_lbtru_analysis_next_frame = - 1 ;
static int hf_lbtru_analysis_next_data_frame = - 1 ;
static int hf_lbtru_analysis_next_sm_frame = - 1 ;
static int hf_lbtru_analysis_next_nak_frame = - 1 ;
static int hf_lbtru_analysis_next_ncf_frame = - 1 ;
static int hf_lbtru_analysis_next_ack_frame = - 1 ;
static int hf_lbtru_analysis_next_creq_frame = - 1 ;
static int hf_lbtru_analysis_next_rst_frame = - 1 ;
static int hf_lbtru_analysis_sqn = - 1 ;
static int hf_lbtru_analysis_sqn_frame = - 1 ;
static int hf_lbtru_analysis_data_retransmission = - 1 ;
static int hf_lbtru_analysis_data_sqn_gap = - 1 ;
static int hf_lbtru_analysis_data_ooo_gap = - 1 ;
static int hf_lbtru_analysis_data_duplicate = - 1 ;
static int hf_lbtru_analysis_sm_sqn_gap = - 1 ;
static int hf_lbtru_analysis_sm_ooo_gap = - 1 ;
static int hf_lbtru_analysis_sm_duplicate = - 1 ;
/* Expert info handles */
static expert_field ei_lbtru_analysis_unknown_type = EI_INIT ;
static expert_field ei_lbtru_analysis_unknown_header = EI_INIT ;
2014-04-10 01:30:03 +00:00
static expert_field ei_lbtru_analysis_zero_length_header = EI_INIT ;
2014-04-07 20:33:51 +00:00
static expert_field ei_lbtru_analysis_ack = EI_INIT ;
static expert_field ei_lbtru_analysis_ncf = EI_INIT ;
static expert_field ei_lbtru_analysis_ncf_ncf = EI_INIT ;
static expert_field ei_lbtru_analysis_nak = EI_INIT ;
static expert_field ei_lbtru_analysis_nak_nak = EI_INIT ;
static expert_field ei_lbtru_analysis_sm = EI_INIT ;
static expert_field ei_lbtru_analysis_sm_syn = EI_INIT ;
static expert_field ei_lbtru_analysis_creq = EI_INIT ;
static expert_field ei_lbtru_analysis_rst = EI_INIT ;
static expert_field ei_lbtru_analysis_data_rx = EI_INIT ;
static expert_field ei_lbtru_analysis_data_gap = EI_INIT ;
static expert_field ei_lbtru_analysis_data_ooo = EI_INIT ;
static expert_field ei_lbtru_analysis_data_dup = EI_INIT ;
static expert_field ei_lbtru_analysis_sm_gap = EI_INIT ;
static expert_field ei_lbtru_analysis_sm_ooo = EI_INIT ;
static expert_field ei_lbtru_analysis_sm_dup = EI_INIT ;
/*----------------------------------------------------------------------------*/
/* LBT-RU data payload dissection functions. */
/*----------------------------------------------------------------------------*/
static int dissect_lbtru_data_contents ( tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree , const char * tag_name , guint64 channel )
{
tvbuff_t * next_tvb ;
next_tvb = tvb_new_subset ( tvb , offset , - 1 , - 1 ) ;
return ( lbmc_dissect_lbmc_packet ( next_tvb , 0 , pinfo , tree , tag_name , channel ) ) ;
}
/*----------------------------------------------------------------------------*/
/* LBT-RU ACK packet dissection functions. */
/*----------------------------------------------------------------------------*/
static int dissect_lbtru_ack ( tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree )
{
proto_tree * ack_tree = NULL ;
proto_item * ack_item = NULL ;
proto_item * ack = NULL ;
ack_item = proto_tree_add_item ( tree , hf_lbtru_ack , tvb , offset , L_LBTRU_ACK_HDR_T , ENC_NA ) ;
ack_tree = proto_item_add_subtree ( ack_item , ett_lbtru_ack ) ;
ack = proto_tree_add_item ( ack_tree , hf_lbtru_ack_sqn , tvb , offset + O_LBTRU_ACK_HDR_T_ACK_SQN , L_LBTRU_ACK_HDR_T_ACK_SQN , ENC_BIG_ENDIAN ) ;
expert_add_info ( pinfo , ack , & ei_lbtru_analysis_ack ) ;
return ( L_LBTRU_ACK_HDR_T ) ;
}
/*----------------------------------------------------------------------------*/
/* LBT-RU NAK confirmation packet dissection functions. */
/*----------------------------------------------------------------------------*/
static int dissect_lbtru_ncf_list ( tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree , int ncf_count , int reason )
{
proto_tree * ncf_tree = NULL ;
proto_item * ncf_item = NULL ;
lbm_uint32_t ncf ;
int idx = 0 ;
int len = 0 ;
ncf_item = proto_tree_add_item ( tree , hf_lbtru_ncf_list , tvb , offset , - 1 , ENC_NA ) ;
ncf_tree = proto_item_add_subtree ( ncf_item , ett_lbtru_ncf_list ) ;
for ( idx = 0 ; idx < ncf_count ; idx + + )
{
proto_item * sep_ncf_item = NULL ;
ncf = tvb_get_ntohl ( tvb , offset + len ) ;
sep_ncf_item = proto_tree_add_item ( ncf_tree , hf_lbtru_ncf_list_ncf , tvb , offset + len , sizeof ( lbm_uint32_t ) , ENC_BIG_ENDIAN ) ;
if ( lbtru_expert_separate_ncfs )
{
expert_add_info_format ( pinfo , sep_ncf_item , & ei_lbtru_analysis_ncf_ncf , " NCF 0x%08x %s " , ncf , val_to_str ( reason , lbtru_ncf_reason , " Unknown (0x%02x) " ) ) ;
}
len + = ( int ) sizeof ( lbm_uint32_t ) ;
}
proto_item_set_len ( ncf_item , len ) ;
return ( len ) ;
}
static int dissect_lbtru_ncf ( tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree )
{
int len_dissected ;
guint16 num_ncfs ;
guint8 reason_format ;
proto_tree * ncf_tree = NULL ;
proto_item * ncf_item = NULL ;
proto_tree * rf_tree = NULL ;
proto_item * rf_item = NULL ;
ncf_item = proto_tree_add_item ( tree , hf_lbtru_ncf , tvb , offset , - 1 , ENC_NA ) ;
ncf_tree = proto_item_add_subtree ( ncf_item , ett_lbtru_ncf ) ;
proto_tree_add_item ( ncf_tree , hf_lbtru_ncf_trail_sqn , tvb , offset + O_LBTRU_NCF_HDR_T_TRAIL_SQN , L_LBTRU_NCF_HDR_T_TRAIL_SQN , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ncf_tree , hf_lbtru_ncf_num , tvb , offset + O_LBTRU_NCF_HDR_T_NUM_NCFS , L_LBTRU_NCF_HDR_T_NUM_NCFS , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( ncf_tree , hf_lbtru_ncf_reserved , tvb , offset + O_LBTRU_NCF_HDR_T_RESERVED , L_LBTRU_NCF_HDR_T_RESERVED , ENC_BIG_ENDIAN ) ;
rf_item = proto_tree_add_item ( ncf_tree , hf_lbtru_ncf_reason_format , tvb , offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT , L_LBTRU_NCF_HDR_T_REASON_FORMAT , ENC_NA ) ;
rf_tree = proto_item_add_subtree ( rf_item , ett_lbtru_ncf_reason_format ) ;
proto_tree_add_item ( rf_tree , hf_lbtru_ncf_reason , tvb , offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT , L_LBTRU_NCF_HDR_T_REASON_FORMAT , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( rf_tree , hf_lbtru_ncf_format , tvb , offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT , L_LBTRU_NCF_HDR_T_REASON_FORMAT , ENC_BIG_ENDIAN ) ;
len_dissected = L_LBTRU_NCF_HDR_T ;
num_ncfs = tvb_get_ntohs ( tvb , offset + O_LBTRU_NCF_HDR_T_NUM_NCFS ) ;
reason_format = tvb_get_guint8 ( tvb , offset + O_LBTRU_NCF_HDR_T_REASON_FORMAT ) ;
len_dissected + = dissect_lbtru_ncf_list ( tvb , offset + L_LBTRU_NCF_HDR_T , pinfo , ncf_tree , num_ncfs , LBTRU_NCF_HDR_REASON ( reason_format ) ) ;
if ( ! lbtru_expert_separate_ncfs )
{
expert_add_info_format ( pinfo , ncf_item , & ei_lbtru_analysis_ncf , " NCF %s " , val_to_str ( LBTRU_NCF_HDR_REASON ( reason_format ) , lbtru_ncf_reason , " Unknown (0x%02x) " ) ) ;
}
proto_item_set_len ( ncf_item , len_dissected ) ;
return ( len_dissected ) ;
}
/*----------------------------------------------------------------------------*/
/* LBT-RU NAK packet dissection functions. */
/*----------------------------------------------------------------------------*/
static int dissect_lbtru_nak_list ( tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree , int nak_count )
{
proto_tree * nak_tree = NULL ;
proto_item * nak_item = NULL ;
int idx = 0 ;
int len = 0 ;
nak_item = proto_tree_add_item ( tree , hf_lbtru_nak_list , tvb , offset , - 1 , ENC_NA ) ;
nak_tree = proto_item_add_subtree ( nak_item , ett_lbtru_nak_list ) ;
for ( idx = 0 ; idx < nak_count ; idx + + )
{
proto_item * sep_nak_item = NULL ;
lbm_uint32_t nak ;
nak = tvb_get_ntohl ( tvb , offset + len ) ;
sep_nak_item = proto_tree_add_item ( nak_tree , hf_lbtru_nak_list_nak , tvb , offset + len , sizeof ( lbm_uint32_t ) , ENC_BIG_ENDIAN ) ;
if ( lbtru_expert_separate_naks )
{
expert_add_info_format ( pinfo , sep_nak_item , & ei_lbtru_analysis_nak_nak , " NAK 0x%08x " , nak ) ;
}
len + = ( int ) sizeof ( lbm_uint32_t ) ;
}
proto_item_set_len ( nak_item , len ) ;
return ( len ) ;
}
static int dissect_lbtru_nak ( tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree )
{
int len_dissected ;
guint16 num_naks ;
proto_tree * nak_tree = NULL ;
proto_item * nak_item = NULL ;
proto_tree * format_tree = NULL ;
proto_item * format_item = NULL ;
nak_item = proto_tree_add_item ( tree , hf_lbtru_nak , tvb , offset , - 1 , ENC_NA ) ;
nak_tree = proto_item_add_subtree ( nak_item , ett_lbtru_nak ) ;
proto_tree_add_item ( nak_tree , hf_lbtru_nak_num , tvb , offset + O_LBTRU_NAK_HDR_T_NUM_NAKS , L_LBTRU_NAK_HDR_T_NUM_NAKS , ENC_BIG_ENDIAN ) ;
format_item = proto_tree_add_item ( nak_tree , hf_lbtru_nak_format , tvb , offset + O_LBTRU_NAK_HDR_T_FORMAT , L_LBTRU_NAK_HDR_T_FORMAT , ENC_NA ) ;
format_tree = proto_item_add_subtree ( format_item , ett_lbtru_nak_format ) ;
proto_tree_add_item ( format_tree , hf_lbtru_nak_format_format , tvb , offset + O_LBTRU_NAK_HDR_T_FORMAT , L_LBTRU_NAK_HDR_T_FORMAT , ENC_BIG_ENDIAN ) ;
len_dissected = L_LBTRU_NAK_HDR_T ;
num_naks = tvb_get_ntohs ( tvb , offset + O_LBTRU_NAK_HDR_T_NUM_NAKS ) ;
len_dissected + = dissect_lbtru_nak_list ( tvb , offset + L_LBTRU_NAK_HDR_T , pinfo , nak_tree , num_naks ) ;
if ( ! lbtru_expert_separate_naks )
{
expert_add_info ( pinfo , nak_item , & ei_lbtru_analysis_nak ) ;
}
proto_item_set_len ( nak_item , len_dissected ) ;
return ( len_dissected ) ;
}
/*----------------------------------------------------------------------------*/
/* LBT-RU session message packet dissection function. */
/*----------------------------------------------------------------------------*/
static int dissect_lbtru_sm ( tvbuff_t * tvb , int offset , packet_info * pinfo , proto_tree * tree , int syn )
{
proto_tree * sm_tree = NULL ;
proto_item * sm_item = NULL ;
proto_item * sm_sqn = NULL ;
sm_item = proto_tree_add_item ( tree , hf_lbtru_sm , tvb , offset , L_LBTRU_SM_HDR_T , ENC_NA ) ;
sm_tree = proto_item_add_subtree ( sm_item , ett_lbtru_sm ) ;
sm_sqn = proto_tree_add_item ( sm_tree , hf_lbtru_sm_sqn , tvb , offset + O_LBTRU_SM_HDR_T_SM_SQN , L_LBTRU_SM_HDR_T_SM_SQN , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( sm_tree , hf_lbtru_sm_lead_sqn , tvb , offset + O_LBTRU_SM_HDR_T_LEAD_SQN , L_LBTRU_SM_HDR_T_LEAD_SQN , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( sm_tree , hf_lbtru_sm_trail_sqn , tvb , offset + O_LBTRU_SM_HDR_T_TRAIL_SQN , L_LBTRU_SM_HDR_T_TRAIL_SQN , ENC_BIG_ENDIAN ) ;
if ( syn )
{
expert_add_info ( pinfo , sm_sqn , & ei_lbtru_analysis_sm_syn ) ;
}
else
{
expert_add_info ( pinfo , sm_sqn , & ei_lbtru_analysis_sm ) ;
}
return ( L_LBTRU_SM_HDR_T ) ;
}
/*----------------------------------------------------------------------------*/
/* LBT-RU data packet dissection functions. */
/*----------------------------------------------------------------------------*/
static int dissect_lbtru_data ( tvbuff_t * tvb , int offset , packet_info * pinfo _U_ , proto_tree * tree )
{
proto_tree * data_tree = NULL ;
proto_item * data_item = NULL ;
data_item = proto_tree_add_item ( tree , hf_lbtru_data , tvb , offset , L_LBTRU_DATA_HDR_T , ENC_NA ) ;
data_tree = proto_item_add_subtree ( data_item , ett_lbtru_data ) ;
proto_tree_add_item ( data_tree , hf_lbtru_data_sqn , tvb , offset + O_LBTRU_DATA_HDR_T_SQN , L_LBTRU_DATA_HDR_T_SQN , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( data_tree , hf_lbtru_data_trail_sqn , tvb , offset + O_LBTRU_DATA_HDR_T_TRAIL_SQN , L_LBTRU_DATA_HDR_T_TRAIL_SQN , ENC_BIG_ENDIAN ) ;
return ( L_LBTRU_DATA_HDR_T ) ;
}
/*----------------------------------------------------------------------------*/
/* LBT-RU packet dissector. */
/*----------------------------------------------------------------------------*/
typedef struct
{
proto_tree * tree ;
tvbuff_t * tvb ;
guint32 current_frame ;
} lbtru_sqn_frame_list_callback_data_t ;
static gboolean dissect_lbtru_sqn_frame_list_callback ( void * frame , void * user_data )
{
lbtru_sqn_frame_list_callback_data_t * cb_data = ( lbtru_sqn_frame_list_callback_data_t * ) user_data ;
proto_item * transport_item = NULL ;
lbm_transport_sqn_frame_t * sqn_frame = ( lbm_transport_sqn_frame_t * ) frame ;
if ( sqn_frame - > frame ! = cb_data - > current_frame )
{
if ( sqn_frame - > retransmission )
{
transport_item = proto_tree_add_uint_format_value ( cb_data - > tree , hf_lbtru_analysis_sqn_frame , cb_data - > tvb , 0 , 0 , sqn_frame - > frame , " % " G_GUINT32_FORMAT " (RX) " , sqn_frame - > frame ) ;
}
else
{
transport_item = proto_tree_add_uint ( cb_data - > tree , hf_lbtru_analysis_sqn_frame , cb_data - > tvb , 0 , 0 , sqn_frame - > frame ) ;
}
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
return ( FALSE ) ;
}
static int dissect_lbtru ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * user_data _U_ )
{
proto_tree * lbtru_tree = NULL ;
proto_item * lbtru_item = NULL ;
proto_tree * flags_tree = NULL ;
proto_item * flags_item ;
int ofs = 0 ;
guint32 session_id = 0 ;
char * tag_name = NULL ;
int dissected_len ;
int total_dissected_len = 0 ;
proto_tree * ver_type_tree = NULL ;
proto_item * ver_type_item = NULL ;
proto_tree * header_tree = NULL ;
proto_item * header_item = NULL ;
proto_tree * transport_tree = NULL ;
proto_item * transport_item = NULL ;
gboolean from_source = TRUE ;
guint8 packet_type = 0 ;
address source_address ;
address receiver_address ;
guint16 source_port = 0 ;
guint16 receiver_port = 0 ;
lbtru_transport_t * transport = NULL ;
lbtru_client_transport_t * client = NULL ;
guint64 channel = LBM_CHANNEL_NO_CHANNEL ;
proto_tree * channel_tree = NULL ;
proto_item * channel_item = NULL ;
guint8 ver_type = 0 ;
guint8 next_hdr = 0 ;
guint32 packet_sqn = 0 ;
guint16 flags_or_res = 0 ;
guint16 num_naks = 0 ;
guint16 num_ncfs = 0 ;
gboolean retransmission = FALSE ;
proto_item * fld_item = NULL ;
proto_item * ei_item = NULL ;
proto_item * type_item = NULL ;
proto_item * next_hdr_item = NULL ;
col_add_str ( pinfo - > cinfo , COL_PROTOCOL , " LBT-RU " ) ;
if ( lbtru_use_tag )
{
tag_name = lbtru_tag_find ( pinfo ) ;
}
col_clear ( pinfo - > cinfo , COL_INFO ) ;
if ( tag_name ! = NULL )
{
col_add_fstr ( pinfo - > cinfo , COL_INFO , " [Tag: %s] " , tag_name ) ;
}
col_set_fence ( pinfo - > cinfo , COL_INFO ) ;
ver_type = tvb_get_guint8 ( tvb , O_LBTRU_HDR_T_VER_TYPE ) ;
next_hdr = tvb_get_guint8 ( tvb , O_LBTRU_HDR_T_NEXT_HDR ) ;
flags_or_res = tvb_get_ntohs ( tvb , O_LBTRU_HDR_T_FLAGS_OR_RES ) ;
packet_type = LBTRU_HDR_TYPE ( ver_type ) ;
if ( tag_name ! = NULL )
{
lbtru_item = proto_tree_add_protocol_format ( tree , proto_lbtru , tvb , ofs , - 1 , " LBT-RU Protocol (Tag: %s): Version %u, Type %s " , tag_name ,
LBTRU_HDR_VER ( ver_type ) , val_to_str ( LBTRU_HDR_TYPE ( ver_type ) , lbtru_packet_type , " Unknown (0x%02x) " ) ) ;
}
else
{
lbtru_item = proto_tree_add_protocol_format ( tree , proto_lbtru , tvb , ofs , - 1 , " LBT-RU Protocol: Version %u, Type %s " , LBTRU_HDR_VER ( ver_type ) ,
val_to_str ( LBTRU_HDR_TYPE ( ver_type ) , lbtru_packet_type , " Unknown (0x%02x) " ) ) ;
}
lbtru_tree = proto_item_add_subtree ( lbtru_item , ett_lbtru ) ;
if ( tag_name ! = NULL )
{
proto_item * item = NULL ;
item = proto_tree_add_string ( lbtru_tree , hf_lbtru_tag , tvb , 0 , 0 , tag_name ) ;
PROTO_ITEM_SET_GENERATED ( item ) ;
}
channel_item = proto_tree_add_item ( lbtru_tree , hf_lbtru_channel , tvb , 0 , 0 , ENC_NA ) ;
PROTO_ITEM_SET_GENERATED ( channel_item ) ;
channel_tree = proto_item_add_subtree ( channel_item , ett_lbtru_channel ) ;
header_item = proto_tree_add_item ( lbtru_tree , hf_lbtru_hdr , tvb , 0 , - 1 , ENC_NA ) ;
header_tree = proto_item_add_subtree ( header_item , ett_lbtru_hdr ) ;
ver_type_item = proto_tree_add_none_format ( header_tree , hf_lbtru_hdr_ver_type , tvb , O_LBTRU_HDR_T_VER_TYPE , L_LBTRU_HDR_T_VER_TYPE , " Version/Type: Version %u, Type %s " ,
LBTRU_HDR_VER ( ver_type ) , val_to_str ( LBTRU_HDR_TYPE ( ver_type ) , lbtru_packet_type , " Unknown (0x%02x) " ) ) ;
ver_type_tree = proto_item_add_subtree ( ver_type_item , ett_lbtru_hdr_ver_type ) ;
proto_tree_add_item ( ver_type_tree , hf_lbtru_hdr_ver_type_ver , tvb , O_LBTRU_HDR_T_VER_TYPE , L_LBTRU_HDR_T_VER_TYPE , ENC_BIG_ENDIAN ) ;
type_item = proto_tree_add_item ( ver_type_tree , hf_lbtru_hdr_ver_type_type , tvb , O_LBTRU_HDR_T_VER_TYPE , L_LBTRU_HDR_T_VER_TYPE , ENC_BIG_ENDIAN ) ;
next_hdr_item = proto_tree_add_item ( header_tree , hf_lbtru_hdr_next_hdr , tvb , O_LBTRU_HDR_T_NEXT_HDR , L_LBTRU_HDR_T_NEXT_HDR , ENC_BIG_ENDIAN ) ;
total_dissected_len = L_LBTRU_HDR_T_VER_TYPE + L_LBTRU_HDR_T_NEXT_HDR ;
ofs = L_LBTRU_HDR_T_VER_TYPE + L_LBTRU_HDR_T_NEXT_HDR ;
switch ( packet_type )
{
case LBTRU_PACKET_TYPE_DATA :
packet_sqn = tvb_get_ntohl ( tvb , L_LBTRU_HDR_T + O_LBTRU_DATA_HDR_T_SQN ) ;
if ( ( flags_or_res & LBTRU_RETRANSMISSION_FLAG ) ! = 0 )
{
retransmission = TRUE ;
}
if ( retransmission )
{
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " DATA(RX) sqn 0x%x " , packet_sqn ) ;
}
else
{
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " DATA sqn 0x%x " , packet_sqn ) ;
}
from_source = TRUE ;
break ;
case LBTRU_PACKET_TYPE_SM :
packet_sqn = tvb_get_ntohl ( tvb , L_LBTRU_HDR_T + O_LBTRU_SM_HDR_T_SM_SQN ) ;
if ( ( flags_or_res & LBTRU_SM_SYN_FLAG ) ! = 0 )
{
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " SM sqn 0x%x SYN " , packet_sqn ) ;
}
else
{
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " SM sqn 0x%x " , packet_sqn ) ;
}
from_source = TRUE ;
break ;
case LBTRU_PACKET_TYPE_NAK :
num_naks = tvb_get_ntohs ( tvb , L_LBTRU_HDR_T + O_LBTRU_NAK_HDR_T_NUM_NAKS ) ;
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " NAK % " G_GUINT16_FORMAT " naks " , num_naks ) ;
from_source = FALSE ;
break ;
case LBTRU_PACKET_TYPE_NCF :
num_ncfs = tvb_get_ntohs ( tvb , L_LBTRU_HDR_T + O_LBTRU_NCF_HDR_T_NUM_NCFS ) ;
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " NCF % " G_GUINT16_FORMAT " ncfs " , num_ncfs ) ;
from_source = TRUE ;
break ;
case LBTRU_PACKET_TYPE_ACK :
packet_sqn = tvb_get_ntohl ( tvb , L_LBTRU_HDR_T + O_LBTRU_ACK_HDR_T_ACK_SQN ) ;
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " ACK sqn 0x%x " , packet_sqn ) ;
from_source = FALSE ;
break ;
case LBTRU_PACKET_TYPE_CREQ :
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " CREQ %s " , val_to_str ( flags_or_res , lbtru_creq_request , " Unknown (0x%02x) " ) ) ;
from_source = FALSE ;
break ;
case LBTRU_PACKET_TYPE_RST :
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " RST %s " , val_to_str ( flags_or_res , lbtru_rst_reason , " Unknown (0x%02x) " ) ) ;
from_source = TRUE ;
break ;
default :
col_append_sep_fstr ( pinfo - > cinfo , COL_INFO , " " , " Unknown (0x%02x) " , LBTRU_HDR_TYPE ( ver_type ) ) ;
expert_add_info_format ( pinfo , type_item , & ei_lbtru_analysis_unknown_type , " Unrecognized type 0x%02x " , LBTRU_HDR_TYPE ( ver_type ) ) ;
return ( 0 ) ;
break ;
}
/* Handle the flags_or_res field. */
switch ( packet_type )
{
case LBTRU_PACKET_TYPE_DATA :
flags_item = proto_tree_add_none_format ( header_tree , hf_lbtru_hdr_flags , tvb , O_LBTRU_HDR_T_FLAGS_OR_RES , L_LBTRU_HDR_T_FLAGS_OR_RES , " Flags: 0x%04x " , flags_or_res ) ;
flags_tree = proto_item_add_subtree ( flags_item , ett_lbtru_hdr_flags ) ;
proto_tree_add_item ( flags_tree , hf_lbtru_hdr_flags_rx , tvb , O_LBTRU_HDR_T_FLAGS_OR_RES , L_LBTRU_HDR_T_FLAGS_OR_RES , ENC_BIG_ENDIAN ) ;
total_dissected_len + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
ofs + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
break ;
case LBTRU_PACKET_TYPE_NAK :
case LBTRU_PACKET_TYPE_NCF :
case LBTRU_PACKET_TYPE_ACK :
proto_tree_add_item ( header_tree , hf_lbtru_hdr_res , tvb , O_LBTRU_HDR_T_FLAGS_OR_RES , L_LBTRU_HDR_T_FLAGS_OR_RES , ENC_BIG_ENDIAN ) ;
total_dissected_len + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
ofs + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
break ;
case LBTRU_PACKET_TYPE_SM :
flags_item = proto_tree_add_none_format ( header_tree , hf_lbtru_hdr_flags , tvb , O_LBTRU_HDR_T_FLAGS_OR_RES , L_LBTRU_HDR_T_FLAGS_OR_RES , " Flags: 0x%04x " , flags_or_res ) ;
flags_tree = proto_item_add_subtree ( flags_item , ett_lbtru_hdr_flags ) ;
proto_tree_add_item ( flags_tree , hf_lbtru_hdr_flags_syn , tvb , O_LBTRU_HDR_T_FLAGS_OR_RES , L_LBTRU_HDR_T_FLAGS_OR_RES , ENC_BIG_ENDIAN ) ;
total_dissected_len + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
ofs + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
break ;
case LBTRU_PACKET_TYPE_CREQ :
ei_item = proto_tree_add_item ( header_tree , hf_lbtru_hdr_request , tvb , O_LBTRU_HDR_T_FLAGS_OR_RES , L_LBTRU_HDR_T_FLAGS_OR_RES , ENC_BIG_ENDIAN ) ;
expert_add_info_format ( pinfo , ei_item , & ei_lbtru_analysis_creq , " CREQ %s " , val_to_str ( flags_or_res , lbtru_creq_request , " Unknown (0x%04x) " ) ) ;
total_dissected_len + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
ofs + = L_LBTRU_HDR_T_FLAGS_OR_RES ;
break ;
case LBTRU_PACKET_TYPE_RST :
ei_item = proto_tree_add_item ( header_tree , hf_lbtru_hdr_reason , tvb , O_LBTRU_HDR_T_FLAGS_OR_RES , L_LBTRU_HDR_T_FLAGS_OR_RES , ENC_BIG_ENDIAN ) ;
expert_add_info_format ( pinfo , ei_item , & ei_lbtru_analysis_rst , " RST %s " , val_to_str ( flags_or_res , lbtru_rst_reason , " Unknown (0x%04x) " ) ) ;
break ;
default :
break ;
}
/* Handle the packet-specific data */
switch ( LBTRU_HDR_TYPE ( ver_type ) )
{
case LBTRU_PACKET_TYPE_DATA :
dissected_len = dissect_lbtru_data ( tvb , L_LBTRU_HDR_T , pinfo , lbtru_tree ) ;
break ;
case LBTRU_PACKET_TYPE_SM :
dissected_len = dissect_lbtru_sm ( tvb , L_LBTRU_HDR_T , pinfo , lbtru_tree , ( flags_or_res & LBTRU_SM_SYN_FLAG ) ) ;
break ;
case LBTRU_PACKET_TYPE_NAK :
dissected_len = dissect_lbtru_nak ( tvb , ofs , pinfo , lbtru_tree ) ;
break ;
case LBTRU_PACKET_TYPE_NCF :
dissected_len = dissect_lbtru_ncf ( tvb , ofs , pinfo , lbtru_tree ) ;
break ;
case LBTRU_PACKET_TYPE_ACK :
dissected_len = dissect_lbtru_ack ( tvb , ofs , pinfo , lbtru_tree ) ;
break ;
default :
dissected_len = 0 ;
break ;
}
total_dissected_len + = dissected_len ;
ofs + = dissected_len ;
/* If we're doing sequence analysis, the tree goes here. */
if ( lbtru_sequence_analysis )
{
transport_item = proto_tree_add_item ( lbtru_tree , hf_lbtru_analysis , tvb , 0 , 0 , ENC_NA ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
transport_tree = proto_item_add_subtree ( transport_item , ett_lbtru_transport ) ;
}
while ( next_hdr ! = LBTRU_NHDR_DATA )
{
2014-04-10 01:30:03 +00:00
proto_item * hdr_length_item ;
2014-04-07 20:33:51 +00:00
proto_tree * opt_tree = NULL ;
proto_item * opt_flags_item = NULL ;
proto_tree * opt_flags_tree = NULL ;
int hdrlen ;
guint8 cur_next_hdr ;
cur_next_hdr = tvb_get_guint8 ( tvb , ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR ) ;
hdrlen = ( int ) tvb_get_guint8 ( tvb , ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN ) ;
switch ( next_hdr )
{
case LBTRU_NHDR_SID :
fld_item = proto_tree_add_item ( lbtru_tree , hf_lbtru_opt_sid , tvb , ofs , L_LBTRU_BASIC_OPT_T + L_LBTRU_SID_OPT_T , ENC_NA ) ;
opt_tree = proto_item_add_subtree ( fld_item , ett_lbtru_opt ) ;
next_hdr_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_sid_next_hdr , tvb , ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR , L_LBTRU_BASIC_OPT_T_NEXT_HDR , ENC_BIG_ENDIAN ) ;
2014-04-10 01:30:03 +00:00
hdr_length_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_sid_hdr_len , tvb , ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN , L_LBTRU_BASIC_OPT_T_HDR_LEN , ENC_BIG_ENDIAN ) ;
2014-04-10 13:53:48 +00:00
if ( hdrlen = = 0 )
{
2014-04-10 01:30:03 +00:00
expert_add_info ( pinfo , hdr_length_item , & ei_lbtru_analysis_zero_length_header ) ;
return ( total_dissected_len ) ;
}
2014-04-07 20:33:51 +00:00
opt_flags_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_sid_flags , tvb , ofs + O_LBTRU_BASIC_OPT_T_RES , L_LBTRU_BASIC_OPT_T_RES , ENC_NA ) ;
opt_flags_tree = proto_item_add_subtree ( opt_flags_item , ett_lbtru_opt_sid_flags ) ;
proto_tree_add_item ( opt_flags_tree , hf_lbtru_opt_sid_flags_ignore , tvb , ofs + O_LBTRU_BASIC_OPT_T_RES , L_LBTRU_BASIC_OPT_T_RES , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( opt_tree , hf_lbtru_opt_sid_session_id , tvb , ofs + L_LBTRU_BASIC_OPT_T + O_LBTRU_SID_OPT_T_SESSION_ID , L_LBTRU_SID_OPT_T_SESSION_ID , ENC_BIG_ENDIAN ) ;
session_id = tvb_get_ntohl ( tvb , ofs + L_LBTRU_BASIC_OPT_T + O_LBTRU_SID_OPT_T_SESSION_ID ) ;
break ;
case LBTRU_NHDR_CID :
fld_item = proto_tree_add_item ( lbtru_tree , hf_lbtru_opt_cid , tvb , ofs , L_LBTRU_BASIC_OPT_T + L_LBTRU_CID_OPT_T , ENC_NA ) ;
opt_tree = proto_item_add_subtree ( fld_item , ett_lbtru_opt ) ;
next_hdr_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_cid_next_hdr , tvb , ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR , L_LBTRU_BASIC_OPT_T_NEXT_HDR , ENC_BIG_ENDIAN ) ;
2014-04-10 01:30:03 +00:00
hdr_length_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_cid_hdr_len , tvb , ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN , L_LBTRU_BASIC_OPT_T_HDR_LEN , ENC_BIG_ENDIAN ) ;
2014-04-10 13:53:48 +00:00
if ( hdrlen = = 0 )
{
2014-04-10 01:30:03 +00:00
expert_add_info ( pinfo , hdr_length_item , & ei_lbtru_analysis_zero_length_header ) ;
return ( total_dissected_len ) ;
}
2014-04-07 20:33:51 +00:00
opt_flags_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_cid_flags , tvb , ofs + O_LBTRU_BASIC_OPT_T_RES , L_LBTRU_BASIC_OPT_T_RES , ENC_NA ) ;
opt_flags_tree = proto_item_add_subtree ( opt_flags_item , ett_lbtru_opt_cid_flags ) ;
proto_tree_add_item ( opt_flags_tree , hf_lbtru_opt_cid_flags_ignore , tvb , ofs + O_LBTRU_BASIC_OPT_T_RES , L_LBTRU_BASIC_OPT_T_RES , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( opt_tree , hf_lbtru_opt_cid_client_id , tvb , ofs + L_LBTRU_BASIC_OPT_T + O_LBTRU_CID_OPT_T_CLIENT_SID , L_LBTRU_CID_OPT_T_CLIENT_SID , ENC_BIG_ENDIAN ) ;
break ;
default :
expert_add_info_format ( pinfo , next_hdr_item , & ei_lbtru_analysis_unknown_header , " Unrecognized header 0x%02x " , next_hdr ) ;
2014-04-10 01:30:03 +00:00
fld_item = proto_tree_add_item ( lbtru_tree , hf_lbtru_opt_unknown , tvb , ofs , L_LBTRU_BASIC_OPT_T + L_LBTRU_CID_OPT_T , ENC_NA ) ;
opt_tree = proto_item_add_subtree ( fld_item , ett_lbtru_opt ) ;
next_hdr_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_unknown_next_hdr , tvb , ofs + O_LBTRU_BASIC_OPT_T_NEXT_HDR , L_LBTRU_BASIC_OPT_T_NEXT_HDR , ENC_BIG_ENDIAN ) ;
hdr_length_item = proto_tree_add_item ( opt_tree , hf_lbtru_opt_unknown_hdr_len , tvb , ofs + O_LBTRU_BASIC_OPT_T_HDR_LEN , L_LBTRU_BASIC_OPT_T_HDR_LEN , ENC_BIG_ENDIAN ) ;
2014-04-10 13:53:48 +00:00
if ( hdrlen = = 0 )
{
2014-04-10 01:30:03 +00:00
expert_add_info ( pinfo , hdr_length_item , & ei_lbtru_analysis_zero_length_header ) ;
return ( total_dissected_len ) ;
}
2014-04-07 20:33:51 +00:00
break ;
}
next_hdr = cur_next_hdr ;
ofs + = hdrlen ;
total_dissected_len + = hdrlen ;
}
/* Find (or create) the transport and client entries */
if ( from_source )
{
COPY_ADDRESS_SHALLOW ( & source_address , & ( pinfo - > src ) ) ;
source_port = pinfo - > srcport ;
COPY_ADDRESS_SHALLOW ( & receiver_address , & ( pinfo - > dst ) ) ;
receiver_port = pinfo - > destport ;
}
else
{
COPY_ADDRESS_SHALLOW ( & source_address , & ( pinfo - > dst ) ) ;
source_port = pinfo - > destport ;
COPY_ADDRESS_SHALLOW ( & receiver_address , & ( pinfo - > src ) ) ;
receiver_port = pinfo - > srcport ;
}
if ( pinfo - > fd - > flags . visited = = 0 )
{
transport = lbtru_transport_add ( & source_address , source_port , session_id , pinfo - > fd - > num ) ;
}
else
{
transport = lbtru_transport_find ( & source_address , source_port , session_id , pinfo - > fd - > num ) ;
}
if ( transport ! = NULL )
{
if ( pinfo - > fd - > flags . visited = = 0 )
{
client = lbtru_client_transport_add ( transport , & receiver_address , receiver_port , pinfo - > fd - > num ) ;
if ( client ! = NULL )
{
if ( lbtru_sequence_analysis )
{
lbtru_client_transport_frame_add ( client , packet_type , pinfo - > fd - > num , packet_sqn , retransmission ) ;
}
}
}
else
{
client = lbtru_client_transport_find ( transport , & receiver_address , receiver_port , pinfo - > fd - > num ) ;
}
}
if ( transport ! = NULL )
{
channel = transport - > channel ;
fld_item = proto_tree_add_uint64 ( channel_tree , hf_lbtru_channel_id , tvb , 0 , 0 , channel ) ;
PROTO_ITEM_SET_GENERATED ( fld_item ) ;
if ( client ! = NULL )
{
fld_item = proto_tree_add_uint ( channel_tree , hf_lbtru_channel_client , tvb , 0 , 0 , client - > id ) ;
PROTO_ITEM_SET_GENERATED ( fld_item ) ;
}
}
if ( ( packet_type = = LBTRU_PACKET_TYPE_DATA ) & & ( next_hdr = = LBTRU_NHDR_DATA ) )
{
total_dissected_len + = dissect_lbtru_data_contents ( tvb , ofs , pinfo , tree , tag_name , channel ) ;
}
if ( lbtru_sequence_analysis )
{
if ( ( transport ! = NULL ) & & ( client ! = NULL ) )
{
lbm_transport_frame_t * frame = NULL ;
/* Fill in the tree */
frame = lbtru_client_transport_frame_find ( client , pinfo - > fd - > num ) ;
if ( frame ! = NULL )
{
lbm_transport_sqn_t * sqn = NULL ;
if ( frame - > previous_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_frame , tvb , 0 , 0 , frame - > previous_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_frame , tvb , 0 , 0 , frame - > next_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
switch ( packet_type )
{
case LBTRU_PACKET_TYPE_DATA :
if ( frame - > previous_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_data_frame , tvb , 0 , 0 , frame - > previous_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_data_frame , tvb , 0 , 0 , frame - > next_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
sqn = lbtru_client_transport_sqn_find ( client , packet_type , packet_sqn ) ;
if ( sqn ! = NULL )
{
if ( sqn - > frame_count > 1 )
{
proto_tree * frame_tree = NULL ;
proto_item * frame_tree_item = NULL ;
lbtru_sqn_frame_list_callback_data_t cb_data ;
frame_tree_item = proto_tree_add_item ( transport_tree , hf_lbtru_analysis_sqn , tvb , 0 , 0 , ENC_NA ) ;
PROTO_ITEM_SET_GENERATED ( frame_tree_item ) ;
frame_tree = proto_item_add_subtree ( frame_tree_item , ett_lbtru_transport_sqn ) ;
cb_data . tree = frame_tree ;
cb_data . tvb = tvb ;
cb_data . current_frame = pinfo - > fd - > num ;
wmem_tree_foreach ( sqn - > frame , dissect_lbtru_sqn_frame_list_callback , ( void * ) & cb_data ) ;
}
}
if ( frame - > retransmission )
{
transport_item = proto_tree_add_boolean ( transport_tree , hf_lbtru_analysis_data_retransmission , tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
expert_add_info ( pinfo , transport_item , & ei_lbtru_analysis_data_rx ) ;
}
if ( frame - > sqn_gap ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_data_sqn_gap , tvb , 0 , 0 , frame - > sqn_gap ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
expert_add_info_format ( pinfo , transport_item , & ei_lbtru_analysis_data_gap , " Data sequence gap (% " G_GUINT32_FORMAT " ) " , frame - > sqn_gap ) ;
}
if ( frame - > ooo_gap ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_data_ooo_gap , tvb , 0 , 0 , frame - > ooo_gap ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
expert_add_info_format ( pinfo , transport_item , & ei_lbtru_analysis_data_ooo , " Data sequence out of order gap (% " G_GUINT32_FORMAT " ) " , frame - > ooo_gap ) ;
}
if ( frame - > duplicate )
{
transport_item = proto_tree_add_boolean ( transport_tree , hf_lbtru_analysis_data_duplicate , tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
expert_add_info ( pinfo , transport_item , & ei_lbtru_analysis_data_dup ) ;
}
break ;
case LBTRU_PACKET_TYPE_SM :
if ( frame - > previous_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_sm_frame , tvb , 0 , 0 , frame - > previous_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_sm_frame , tvb , 0 , 0 , frame - > next_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
sqn = lbtru_client_transport_sqn_find ( client , packet_type , packet_sqn ) ;
if ( sqn ! = NULL )
{
if ( sqn - > frame_count > 1 )
{
proto_tree * frame_tree = NULL ;
proto_item * frame_tree_item = NULL ;
lbtru_sqn_frame_list_callback_data_t cb_data ;
frame_tree_item = proto_tree_add_item ( transport_tree , hf_lbtru_analysis_sqn , tvb , 0 , 0 , ENC_NA ) ;
PROTO_ITEM_SET_GENERATED ( frame_tree_item ) ;
frame_tree = proto_item_add_subtree ( frame_tree_item , ett_lbtru_transport_sqn ) ;
cb_data . tree = frame_tree ;
cb_data . tvb = tvb ;
cb_data . current_frame = pinfo - > fd - > num ;
wmem_tree_foreach ( sqn - > frame , dissect_lbtru_sqn_frame_list_callback , ( void * ) & cb_data ) ;
}
}
if ( frame - > sqn_gap ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_sm_sqn_gap , tvb , 0 , 0 , frame - > sqn_gap ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
expert_add_info_format ( pinfo , transport_item , & ei_lbtru_analysis_sm_gap , " SM sequence gap (% " G_GUINT32_FORMAT " ) " , frame - > sqn_gap ) ;
}
if ( frame - > ooo_gap ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_sm_ooo_gap , tvb , 0 , 0 , frame - > ooo_gap ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
expert_add_info_format ( pinfo , transport_item , & ei_lbtru_analysis_sm_ooo , " SM sequence out of order gap (% " G_GUINT32_FORMAT " ) " , frame - > ooo_gap ) ;
}
if ( frame - > duplicate )
{
transport_item = proto_tree_add_boolean ( transport_tree , hf_lbtru_analysis_sm_duplicate , tvb , 0 , 0 , TRUE ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
expert_add_info ( pinfo , transport_item , & ei_lbtru_analysis_sm_dup ) ;
}
break ;
case LBTRU_PACKET_TYPE_NAK :
if ( frame - > previous_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_nak_frame , tvb , 0 , 0 , frame - > previous_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_nak_frame , tvb , 0 , 0 , frame - > next_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
break ;
case LBTRU_PACKET_TYPE_NCF :
if ( frame - > previous_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_ncf_frame , tvb , 0 , 0 , frame - > previous_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_ncf_frame , tvb , 0 , 0 , frame - > next_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
break ;
case LBTRU_PACKET_TYPE_ACK :
if ( frame - > previous_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_ack_frame , tvb , 0 , 0 , frame - > previous_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_ack_frame , tvb , 0 , 0 , frame - > next_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
break ;
case LBTRU_PACKET_TYPE_CREQ :
if ( frame - > previous_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_creq_frame , tvb , 0 , 0 , frame - > previous_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_creq_frame , tvb , 0 , 0 , frame - > next_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
break ;
case LBTRU_PACKET_TYPE_RST :
if ( frame - > previous_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_prev_rst_frame , tvb , 0 , 0 , frame - > previous_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
if ( frame - > next_type_frame ! = 0 )
{
transport_item = proto_tree_add_uint ( transport_tree , hf_lbtru_analysis_next_rst_frame , tvb , 0 , 0 , frame - > next_type_frame ) ;
PROTO_ITEM_SET_GENERATED ( transport_item ) ;
}
break ;
default :
break ;
}
}
}
}
return ( total_dissected_len ) ;
}
static gboolean test_lbtru_packet ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * user_data )
{
gboolean valid_packet = FALSE ;
/* Must be a UDP packet. */
if ( pinfo - > ptype ! = PT_UDP )
{
return ( FALSE ) ;
}
/* Destination address must be IPV4 and 4 bytes in length. */
if ( ( pinfo - > dst . type ! = AT_IPv4 ) | | ( pinfo - > dst . len ! = 4 ) )
{
return ( FALSE ) ;
}
if ( lbtru_use_tag )
{
if ( lbtru_tag_find ( pinfo ) ! = NULL )
{
valid_packet = TRUE ;
}
}
else
{
/*
Source port must be in the source port range and destination port must be in the receiver port range ,
or vice - versa .
*/
if ( ( ( pinfo - > destport > = lbtru_source_port_low )
& & ( pinfo - > destport < = lbtru_source_port_high )
& & ( pinfo - > srcport > = lbtru_receiver_port_low )
& & ( pinfo - > srcport < = lbtru_receiver_port_high ) )
| | ( ( pinfo - > destport > = lbtru_receiver_port_low )
& & ( pinfo - > destport < = lbtru_receiver_port_high )
& & ( pinfo - > srcport > = lbtru_source_port_low )
& & ( pinfo - > srcport < = lbtru_source_port_high ) ) )
{
/* One of ours. */
valid_packet = TRUE ;
}
}
if ( valid_packet )
{
dissect_lbtru ( tvb , pinfo , tree , user_data ) ;
return ( TRUE ) ;
}
/* Not one of ours. */
return ( FALSE ) ;
}
/* The registration hand-off routine */
void proto_reg_handoff_lbtru ( void )
{
static gboolean already_registered = FALSE ;
if ( ! already_registered )
{
lbtru_dissector_handle = new_create_dissector_handle ( dissect_lbtru , proto_lbtru ) ;
dissector_add_uint ( " udp.port " , 0 , lbtru_dissector_handle ) ;
heur_dissector_add ( " udp " , test_lbtru_packet , proto_lbtru ) ;
}
/* Make sure the low source port is <= the high source port. If not, don't change them. */
if ( global_lbtru_source_port_low < = global_lbtru_source_port_high )
{
lbtru_source_port_low = global_lbtru_source_port_low ;
lbtru_source_port_high = global_lbtru_source_port_high ;
}
/* Make sure the low receiver port is <= the high receiver port. If not, don't change them. */
if ( global_lbtru_receiver_port_low < = global_lbtru_receiver_port_high )
{
lbtru_receiver_port_low = global_lbtru_receiver_port_low ;
lbtru_receiver_port_high = global_lbtru_receiver_port_high ;
}
lbtru_expert_separate_naks = global_lbtru_expert_separate_naks ;
lbtru_expert_separate_ncfs = global_lbtru_expert_separate_ncfs ;
lbtru_sequence_analysis = global_lbtru_sequence_analysis ;
lbtru_use_tag = global_lbtru_use_tag ;
already_registered = TRUE ;
}
/* Register all the bits needed with the filtering engine */
void proto_register_lbtru ( void )
{
static hf_register_info hf [ ] =
{
{ & hf_lbtru_channel ,
{ " Channel " , " lbtru.channel " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_channel_id ,
{ " Channel ID " , " lbtru.channel.channel " , FT_UINT64 , BASE_HEX_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_channel_client ,
{ " Channel Client " , " lbtru.channel.client " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_tag ,
{ " Tag " , " lbtru.tag " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_hdr ,
{ " Header " , " lbtru.hdr " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_hdr_ver_type ,
{ " Version/Type " , " lbtru.hdr.ver_type " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_hdr_ver_type_ver ,
{ " Version " , " lbtru.hdr.ver_type.ver " , FT_UINT8 , BASE_DEC , NULL , LBTRU_HDR_VER_VER_MASK , NULL , HFILL } } ,
{ & hf_lbtru_hdr_ver_type_type ,
{ " Type " , " lbtru.hdr.ver_type.type " , FT_UINT8 , BASE_HEX , VALS ( lbtru_packet_type ) , LBTRU_HDR_VER_TYPE_MASK , NULL , HFILL } } ,
{ & hf_lbtru_hdr_next_hdr ,
{ " Next Header " , " lbtru.hdr.next_hdr " , FT_UINT8 , BASE_HEX , VALS ( lbtru_next_header ) , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_hdr_res ,
{ " Reserved " , " lbtru.hdr.res " , FT_UINT16 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_hdr_flags ,
{ " Flags " , " lbtru.hdr.flags " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_hdr_flags_rx ,
{ " Retransmission " , " lbtru.hdr.flags.rx " , FT_BOOLEAN , L_LBTRU_HDR_T_FLAGS_OR_RES * 8 , TFS ( & tfs_set_notset ) , LBTRU_RETRANSMISSION_FLAG , NULL , HFILL } } ,
{ & hf_lbtru_hdr_flags_syn ,
{ " SYN " , " lbtru.hdr.flags.syn " , FT_BOOLEAN , L_LBTRU_HDR_T_FLAGS_OR_RES * 8 , TFS ( & tfs_set_notset ) , LBTRU_SM_SYN_FLAG , NULL , HFILL } } ,
{ & hf_lbtru_hdr_request ,
{ " Request " , " lbtru.hdr.request " , FT_UINT16 , BASE_HEX , VALS ( lbtru_creq_request ) , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_hdr_reason ,
{ " Reason " , " lbtru.hdr.reason " , FT_UINT16 , BASE_HEX , VALS ( lbtru_rst_reason ) , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_data ,
{ " Data Header " , " lbtru.data " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_data_sqn ,
{ " Sequence Number " , " lbtru.data.sqn " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_data_trail_sqn ,
{ " Trailing Edge Sequence Number " , " lbtru.data.trail " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_sm ,
{ " Session Message Header " , " lbtru.sm " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_sm_sqn ,
{ " Sequence Number " , " lbtru.sm.sqn " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_sm_lead_sqn ,
{ " Leading Edge Sequence Number " , " lbtru.sm.lead " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_sm_trail_sqn ,
{ " Trailing Edge Sequence Number " , " lbtru.sm.trail " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_nak ,
{ " NAK Header " , " lbtru.nak " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_nak_num ,
{ " Number of NAKs " , " lbtru.nak.num " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_nak_format ,
{ " Format " , " lbtru.nak.format " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_nak_format_format ,
{ " Format " , " lbtru.nak.format.format " , FT_UINT16 , BASE_DEC , VALS ( lbtru_nak_format ) , LBTRU_NAK_HDR_FORMAT_MASK , NULL , HFILL } } ,
{ & hf_lbtru_nak_list ,
{ " NAK List " , " lbtru.nak.list " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_nak_list_nak ,
{ " NAK " , " lbtru.nak.list.nak " , FT_UINT32 , BASE_DEC_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ncf ,
{ " NAK Confirmation Header " , " lbtru.ncf " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ncf_trail_sqn ,
{ " Trailing Edge Sequence Number " , " lbtru.ncf.trail " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ncf_num ,
{ " Number of Individual NCFs " , " lbtru.ncf.num " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ncf_reserved ,
{ " Reserved " , " lbtru.ncf.reserved " , FT_UINT8 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ncf_reason_format ,
{ " Reason/Format " , " lbtru.ncf.reason_format " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ncf_reason ,
{ " Reason " , " lbtru.ncf.reason_format.reason " , FT_UINT8 , BASE_HEX , VALS ( lbtru_ncf_reason ) , LBTRU_NCF_HDR_REASON_MASK , NULL , HFILL } } ,
{ & hf_lbtru_ncf_format ,
{ " Format " , " lbtru.ncf.reason_format.format " , FT_UINT8 , BASE_HEX , VALS ( lbtru_ncf_format ) , LBTRU_NCF_HDR_FORMAT_MASK , NULL , HFILL } } ,
{ & hf_lbtru_ncf_list ,
{ " NCF List " , " lbtru.ncf.list " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ncf_list_ncf ,
{ " NCF " , " lbtru.ncf.list.ncf " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ack ,
{ " ACK Header " , " lbtru.ack " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_ack_sqn ,
{ " ACK Sequence Number " , " lbtru.ack.sqn " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_sid ,
{ " SID Option " , " lbtru.opt_sid " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_sid_next_hdr ,
{ " Next Header " , " lbtru.opt_sid.next_hdr " , FT_UINT8 , BASE_DEC_HEX , VALS ( lbtru_next_header ) , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_sid_hdr_len ,
{ " Header Length " , " lbtru.opt_sid.hdr_len " , FT_UINT8 , BASE_DEC_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_sid_flags ,
{ " Flags " , " lbtru.opt_sid.flags " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_sid_flags_ignore ,
{ " Ignore " , " lbtru.opt_sid.flags.ignore " , FT_BOOLEAN , L_LBTRU_BASIC_OPT_T_RES * 8 , & ( tfs_set_notset ) , LBTRU_OPT_IGNORE , NULL , HFILL } } ,
{ & hf_lbtru_opt_sid_session_id ,
{ " Session ID " , " lbtru.opt_sid.session_id " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_cid ,
{ " CID Option " , " lbtru.opt_cid " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_cid_next_hdr ,
{ " Next Header " , " lbtru.opt_cid.next_hdr " , FT_UINT8 , BASE_DEC_HEX , VALS ( lbtru_next_header ) , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_cid_hdr_len ,
{ " Header Length " , " lbtru.opt_cid.hdr_len " , FT_UINT8 , BASE_DEC_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_cid_flags ,
{ " Flags " , " lbtru.opt_cid.flags " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_cid_flags_ignore ,
{ " Ignore " , " lbtru.opt_cid.flags.ignore " , FT_BOOLEAN , L_LBTRU_BASIC_OPT_T_RES * 8 , & ( tfs_set_notset ) , LBTRU_OPT_IGNORE , NULL , HFILL } } ,
{ & hf_lbtru_opt_cid_client_id ,
{ " Client ID " , " lbtru.opt_cid.client_id " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
2014-04-10 01:30:03 +00:00
{ & hf_lbtru_opt_unknown ,
{ " Unknown Option " , " lbtru.opt_unknown " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_unknown_next_hdr ,
{ " Next Header " , " lbtru.opt_unknown.next_hdr " , FT_UINT8 , BASE_DEC_HEX , VALS ( lbtru_next_header ) , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_opt_unknown_hdr_len ,
{ " Header Length " , " lbtru.opt_unknown.hdr_len " , FT_UINT8 , BASE_DEC_HEX , NULL , 0x0 , NULL , HFILL } } ,
2014-04-07 20:33:51 +00:00
{ & hf_lbtru_analysis ,
{ " Transport Analysis " , " lbtru.analysis " , FT_NONE , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_frame ,
{ " Previous Transport Frame " , " lbtru.analysis.prev_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_data_frame ,
{ " Previous Transport DATA Frame " , " lbtru.analysis.prev_data_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_sm_frame ,
{ " Previous Transport SM Frame " , " lbtru.analysis.prev_sm_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_nak_frame ,
{ " Previous Transport NAK Frame " , " lbtru.analysis.prev_nak_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_ncf_frame ,
{ " Previous Transport NCF Frame " , " lbtru.analysis.prev_ncf_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_ack_frame ,
{ " Previous Transport ACK Frame " , " lbtru.analysis.prev_ack_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_creq_frame ,
{ " Previous Transport CREQ Frame " , " lbtru.analysis.prev_creq_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_prev_rst_frame ,
{ " Previous Transport RST Frame " , " lbtru.analysis.prev_rst_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_frame ,
{ " Next Transport Frame " , " lbtru.analysis.next_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_data_frame ,
{ " Next Transport DATA Frame " , " lbtru.analysis.next_data_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_sm_frame ,
{ " Next Transport SM Frame " , " lbtru.analysis.next_sm_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_nak_frame ,
{ " Next Transport NAK Frame " , " lbtru.analysis.next_nak_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_ncf_frame ,
{ " Next Transport NCF Frame " , " lbtru.analysis.next_ncf_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_ack_frame ,
{ " Next Transport ACK Frame " , " lbtru.analysis.next_ack_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_creq_frame ,
{ " Next Transport CREQ Frame " , " lbtru.analysis.next_creq_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_next_rst_frame ,
{ " Next Transport RST Frame " , " lbtru.analysis.next_rst_frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_sqn ,
{ " SQN Also in " , " lbtru.analysis.sqn " , FT_NONE , BASE_NONE , NULL , 0x0 , " Sequence number also appears in these frames " , HFILL } } ,
{ & hf_lbtru_analysis_sqn_frame ,
{ " Frame " , " lbtru.analysis.sqn.frame " , FT_FRAMENUM , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_data_retransmission ,
{ " Frame is a Data Retransmission " , " lbtru.analysis.data_retransmission " , FT_BOOLEAN , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_data_sqn_gap ,
{ " Gap in Data Sequence " , " lbtru.analysis.data_sqn_gap " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_data_ooo_gap ,
{ " Data Sequence Out of Order Gap " , " lbtru.analysis.data_ooo_gap " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_data_duplicate ,
{ " Duplicate Data Frame " , " lbtru.analysis.data_duplicate " , FT_BOOLEAN , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_sm_sqn_gap ,
{ " Gap in SM Sequence " , " lbtru.analysis.sm_sqn_gap " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_sm_ooo_gap ,
{ " SM Sequence Out of Order Gap " , " lbtru.analysis.sm_ooo_gap " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_lbtru_analysis_sm_duplicate ,
{ " Duplicate SM Frame " , " lbtru.analysis.sm_duplicate " , FT_BOOLEAN , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
} ;
static gint * ett [ ] =
{
& ett_lbtru ,
& ett_lbtru_channel ,
& ett_lbtru_hdr ,
& ett_lbtru_hdr_ver_type ,
& ett_lbtru_hdr_flags ,
& ett_lbtru_data ,
& ett_lbtru_sm ,
& ett_lbtru_nak ,
& ett_lbtru_nak_format ,
& ett_lbtru_nak_list ,
& ett_lbtru_ncf ,
& ett_lbtru_ncf_reason_format ,
& ett_lbtru_ncf_list ,
& ett_lbtru_ack ,
& ett_lbtru_opt ,
& ett_lbtru_opt_sid_flags ,
& ett_lbtru_opt_cid_flags ,
& ett_lbtru_transport ,
& ett_lbtru_transport_sqn ,
} ;
static ei_register_info ei [ ] =
{
{ & ei_lbtru_analysis_unknown_type , { " lbtru.analysis.unknown_type " , PI_MALFORMED , PI_ERROR , " Unrecognized type " , EXPFILL } } ,
{ & ei_lbtru_analysis_unknown_header , { " lbtru.analysis.unknown_header " , PI_MALFORMED , PI_ERROR , " Unrecognized header " , EXPFILL } } ,
2014-04-10 01:30:03 +00:00
{ & ei_lbtru_analysis_zero_length_header , { " lbtru.analysis.zero_length_header " , PI_MALFORMED , PI_ERROR , " Zero-length header " , EXPFILL } } ,
2014-04-07 20:33:51 +00:00
{ & ei_lbtru_analysis_ack , { " lbtru.analysis.ack " , PI_SEQUENCE , PI_CHAT , " ACK " , EXPFILL } } ,
{ & ei_lbtru_analysis_ncf , { " lbtru.analysis.ncf " , PI_SEQUENCE , PI_NOTE , " NCF " , EXPFILL } } ,
{ & ei_lbtru_analysis_ncf_ncf , { " lbtru.analysis.ncf.ncf " , PI_SEQUENCE , PI_NOTE , " NCF " , EXPFILL } } ,
{ & ei_lbtru_analysis_nak , { " lbtru.analysis.nak " , PI_SEQUENCE , PI_WARN , " NAK " , EXPFILL } } ,
{ & ei_lbtru_analysis_nak_nak , { " lbtru.analysis.nak.nak " , PI_SEQUENCE , PI_WARN , " NAK " , EXPFILL } } ,
{ & ei_lbtru_analysis_sm , { " lbtru.analysis.sm " , PI_SEQUENCE , PI_CHAT , " SM " , EXPFILL } } ,
{ & ei_lbtru_analysis_sm_syn , { " lbtru.analysis.sm.syn " , PI_SEQUENCE , PI_CHAT , " SM SYN " , EXPFILL } } ,
{ & ei_lbtru_analysis_creq , { " lbtru.analysis.creq " , PI_SEQUENCE , PI_CHAT , " Connection REQuest " , EXPFILL } } ,
{ & ei_lbtru_analysis_rst , { " lbtru.analysis.rst " , PI_SEQUENCE , PI_CHAT , " ReSeT " , EXPFILL } } ,
{ & ei_lbtru_analysis_data_rx , { " lbtru.analysis.data.rx " , PI_SEQUENCE , PI_NOTE , " Data retransmission " , EXPFILL } } ,
{ & ei_lbtru_analysis_data_gap , { " lbtru.analysis.data.gap " , PI_SEQUENCE , PI_NOTE , " Data sequence gap " , EXPFILL } } ,
{ & ei_lbtru_analysis_data_ooo , { " lbtru.analysis.data.ooo " , PI_SEQUENCE , PI_NOTE , " Data sequence out of order " , EXPFILL } } ,
{ & ei_lbtru_analysis_data_dup , { " lbtru.analysis.data.dup " , PI_SEQUENCE , PI_NOTE , " Duplicate data " , EXPFILL } } ,
{ & ei_lbtru_analysis_sm_gap , { " lbtru.analysis.sm.gap " , PI_SEQUENCE , PI_NOTE , " SM sequence gap " , EXPFILL } } ,
{ & ei_lbtru_analysis_sm_ooo , { " lbtru.analysis.sm.ooo " , PI_SEQUENCE , PI_NOTE , " SM sequence out of order " , EXPFILL } } ,
{ & ei_lbtru_analysis_sm_dup , { " lbtru.analysis.sm.dup " , PI_SEQUENCE , PI_NOTE , " Duplicate SM " , EXPFILL } } ,
} ;
module_t * lbtru_module ;
uat_t * tag_uat ;
expert_module_t * expert_lbtru ;
proto_lbtru = proto_register_protocol ( " LBT Reliable Unicast Protocol " ,
" LBT-RU " , " lbtru " ) ;
proto_register_field_array ( proto_lbtru , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
expert_lbtru = expert_register_protocol ( proto_lbtru ) ;
expert_register_field_array ( expert_lbtru , ei , array_length ( ei ) ) ;
lbtru_module = prefs_register_protocol_subtree ( " 29West " , proto_lbtru , proto_reg_handoff_lbtru ) ;
prefs_register_uint_preference ( lbtru_module ,
" source_port_low " ,
" Source port range low (default " MAKESTRING ( LBTRU_DEFAULT_SOURCE_PORT_LOW ) " ) " ,
" Set the low end of the LBT-RU source UDP port range (context transport_lbtru_port_low) " ,
10 ,
& global_lbtru_source_port_low ) ;
prefs_register_uint_preference ( lbtru_module ,
" source_port_high " ,
" Source port range high (default " MAKESTRING ( LBTRU_DEFAULT_SOURCE_PORT_HIGH ) " ) " ,
" Set the high end of the LBT-RU source UDP port range (context transport_lbtru_port_high) " ,
10 ,
& global_lbtru_source_port_high ) ;
prefs_register_uint_preference ( lbtru_module ,
" receiver_port_low " ,
" Receiver port range low (default " MAKESTRING ( LBTRU_DEFAULT_RECEIVER_PORT_LOW ) " ) " ,
" Set the low end of the LBT-RU receiver UDP port range (receiver transport_lbtru_port_low) " ,
10 ,
& global_lbtru_receiver_port_low ) ;
prefs_register_uint_preference ( lbtru_module ,
" receiver_port_high " ,
" Receiver port range high (default " MAKESTRING ( LBTRU_DEFAULT_RECEIVER_PORT_HIGH ) " ) " ,
" Set the high end of the LBT-RU receiver UDP port range (receiver transport_lbtru_port_high) " ,
10 ,
& global_lbtru_receiver_port_high ) ;
lbtru_expert_separate_naks = global_lbtru_expert_separate_naks ;
prefs_register_bool_preference ( lbtru_module ,
" expert_separate_naks " ,
" Separate NAKs in Expert Info " ,
" Separate multiple NAKs from a single packet into distinct Expert Info entries " ,
& global_lbtru_expert_separate_naks ) ;
lbtru_expert_separate_ncfs = global_lbtru_expert_separate_ncfs ;
prefs_register_bool_preference ( lbtru_module ,
" expert_separate_ncfs " ,
" Separate NCFs in Expert Info " ,
" Separate multiple NCFs from a single packet into distinct Expert Info entries " ,
& global_lbtru_expert_separate_ncfs ) ;
lbtru_sequence_analysis = global_lbtru_sequence_analysis ;
prefs_register_bool_preference ( lbtru_module ,
" sequence_analysis " ,
" Perform Sequence Number Analysis " ,
" Perform analysis on LBT-RU sequence numbers to determine out-of-order, gaps, loss, etc " ,
& global_lbtru_sequence_analysis ) ;
prefs_register_bool_preference ( lbtru_module ,
" use_lbtru_domain " ,
" Use LBT-RU tag table " ,
" Use table of LBT-RU tags to decode the packet instead of above values " ,
& global_lbtru_use_tag ) ;
tag_uat = uat_new ( " LBT-RU tag definitions " ,
sizeof ( lbtru_tag_entry_t ) ,
" lbtru_domains " ,
TRUE ,
( void * * ) & lbtru_tag_entry ,
& lbtru_tag_count ,
UAT_AFFECTS_DISSECTION ,
NULL ,
lbtru_tag_copy_cb ,
lbtru_tag_update_cb ,
lbtru_tag_free_cb ,
NULL ,
lbtru_tag_array ) ;
prefs_register_uat_preference ( lbtru_module ,
" tnw_lbtru_tags " ,
" LBT-RU Tags " ,
" A table to define LBT-RU tags " ,
tag_uat ) ;
}
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local variables :
* c - basic - offset : 4
* tab - width : 4
* indent - tabs - mode : nil
* End :
*
* vi : set shiftwidth = 4 tabstop = 4 expandtab :
* : indentSize = 4 : tabSize = 4 : noTabs = true :
*/