2000-12-17 07:38:14 +00:00
/* packet-xot.c
2002-04-09 08:15:04 +00:00
* Routines for X .25 over TCP dissection ( RFC 1613 )
2000-12-17 07:38:14 +00:00
*
* Copyright 2000 , Paul Ionescu < paul @ acorp . ro >
*
2004-07-18 00:24:25 +00:00
* $ Id $
2000-12-17 07:38:14 +00:00
*
2006-05-21 04:49:01 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
2000-12-17 07:38:14 +00:00
* Copyright 1998 Gerald Combs
2002-08-28 21:04:11 +00:00
*
2000-12-17 07:38:14 +00:00
* 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 .
2002-08-28 21:04:11 +00:00
*
2000-12-17 07:38:14 +00:00
* 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 .
2002-08-28 21:04:11 +00:00
*
2000-12-17 07:38:14 +00:00
* 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 . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <stdio.h>
# include <stdlib.h>
# include <ctype.h>
# include <string.h>
# include <glib.h>
2002-01-21 07:37:49 +00:00
# include <epan/packet.h>
2003-01-21 01:45:17 +00:00
# include "packet-tcp.h"
2004-09-27 22:55:15 +00:00
# include <epan/prefs.h>
2000-12-17 07:38:14 +00:00
# define TCP_PORT_XOT 1998
2008-04-23 19:49:40 +00:00
# define XOT_HEADER_LENGTH 4
# define XOT_VERSION 0
/* Some X25 macros from packet-x25.c - some adapted code as well below */
# define X25_MIN_HEADER_LENGTH 3
# define X25_MIN_M128_HEADER_LENGTH 4
# define X25_NONDATA_BIT 0x01
# define PACKET_IS_DATA(type) (!(type & X25_NONDATA_BIT))
# define X25_MBIT_MOD8 0x10
# define X25_MBIT_MOD128 0x01
static dissector_handle_t x25_handle ;
static dissector_handle_t xot_handle ;
2000-12-17 07:38:14 +00:00
static gint proto_xot = - 1 ;
2008-04-23 19:49:40 +00:00
static gint ett_xot = - 1 ;
2001-09-13 08:05:26 +00:00
static gint hf_xot_version = - 1 ;
static gint hf_xot_length = - 1 ;
2008-04-23 19:49:40 +00:00
/* desegmentation of X.25 over multiple TCP */
2002-04-09 08:15:04 +00:00
static gboolean xot_desegment = TRUE ;
2008-04-23 19:49:40 +00:00
/* desegmentation of X.25 packet sequences */
static gboolean x25_desegment = FALSE ;
If you register more than one field with the same name, the dfilter code
can now handle that; this allows us to register both the modulo-8 and
the modulo-128 versions of various X.25 bitfields with "x.25.XXX" names,
which lets us get rid of the "ex.25" protocol stuff completely and use
"x.25" for both modulo-8 and modulo-128 X.25. Do so. (Also, fix up
some cases where we appeared to be using the modulo-8 fields when
dissecting modulo-128 X.25.)
This, in turn, allows us to register the X.25 dissector, as there's now
only one protocol with which it's associated, and make it static and
have it called only through a handle, and to, when registering it with
the "llc.dsap" dissector table, associate it with "proto_x25".
That, in turn, allows us to get rid of the "CHECK_DISPLAY_AS_DATA()"
calls, and the code to set "pinfo->current_proto", in the X.25
dissector.
The code for the display filter expression dialog would, if there are
two fields with the same name registered under a protocol, list both of
them; have it list only one of them - the fields should have the same
type, the same radix, and the same value_string/true_false_string table
if any (if they don't, they're really not the same field...).
svn path=/trunk/; revision=3023
2001-02-12 09:06:19 +00:00
2006-10-31 09:29:07 +00:00
static guint get_xot_pdu_len ( packet_info * pinfo _U_ , tvbuff_t * tvb , int offset )
2000-12-17 07:38:14 +00:00
{
2008-04-23 19:49:40 +00:00
guint16 plen ;
int remain = tvb_length_remaining ( tvb , offset ) ;
if ( remain < XOT_HEADER_LENGTH ) {
/* We did not get the data we asked for, use up what we can */
return remain ;
}
2003-01-21 01:45:17 +00:00
2008-04-23 19:49:40 +00:00
/*
* Get the length of the X .25 - over - TCP packet .
*/
plen = tvb_get_ntohs ( tvb , offset + 2 ) ;
return XOT_HEADER_LENGTH + plen ;
}
2003-01-21 01:45:17 +00:00
2008-05-05 05:58:45 +00:00
static guint get_xot_pdu_len_mult ( packet_info * pinfo _U_ , tvbuff_t * tvb , int offset )
2008-04-23 19:49:40 +00:00
{
2008-05-05 05:58:45 +00:00
int offset_before = offset ; /* offset where we start this test */
int offset_next = offset + XOT_HEADER_LENGTH + X25_MIN_HEADER_LENGTH ;
2008-04-23 19:49:40 +00:00
int tvb_len ;
while ( tvb_len = tvb_length_remaining ( tvb , offset ) , tvb_len > 0 ) {
guint16 plen = 0 ;
int modulo ;
guint16 bytes0_1 ;
guint8 pkt_type ;
gboolean m_bit_set ;
2008-05-05 05:58:45 +00:00
int offset_x25 = offset + XOT_HEADER_LENGTH ;
2008-04-23 19:49:40 +00:00
2008-05-05 05:58:45 +00:00
/* Minimum where next starts */
offset_next = offset_x25 + X25_MIN_HEADER_LENGTH ;
if ( tvb_len < XOT_HEADER_LENGTH ) {
return offset_next - offset_before ;
2008-04-23 19:49:40 +00:00
}
/*
* Get the length of the current X .25 - over - TCP packet .
*/
plen = get_xot_pdu_len ( pinfo , tvb , offset ) ;
2008-05-05 05:58:45 +00:00
offset_next = offset + plen ;
2008-04-23 19:49:40 +00:00
/* Make sure we have enough data */
if ( tvb_len < plen ) {
2008-05-05 05:58:45 +00:00
return offset_next - offset_before ;
2008-04-23 19:49:40 +00:00
}
/*Some minor code copied from packet-x25.c */
bytes0_1 = tvb_get_ntohs ( tvb , offset_x25 + 0 ) ;
pkt_type = tvb_get_guint8 ( tvb , offset_x25 + 2 ) ;
/* If this is the first packet and it is not data, no sequence needed */
2008-05-05 05:58:45 +00:00
if ( offset = = offset_before & & ! PACKET_IS_DATA ( pkt_type ) ) {
return offset_next - offset_before ;
2008-04-23 19:49:40 +00:00
}
/* Check for data, there can be X25 control packets in the X25 data */
if ( PACKET_IS_DATA ( pkt_type ) ) {
modulo = ( ( bytes0_1 & 0x2000 ) ? 128 : 8 ) ;
if ( modulo = = 8 ) {
m_bit_set = pkt_type & X25_MBIT_MOD8 ;
} else {
m_bit_set = tvb_get_guint8 ( tvb , offset_x25 + 3 ) & X25_MBIT_MOD128 ;
}
if ( ! m_bit_set ) {
/* We are done with this sequence when the mbit is no longer set */
2008-05-05 05:58:45 +00:00
return offset_next - offset_before ;
2008-04-23 19:49:40 +00:00
}
}
offset = offset_next ;
2008-05-05 05:58:45 +00:00
offset_next + = XOT_HEADER_LENGTH + X25_MIN_HEADER_LENGTH ;
2008-04-23 19:49:40 +00:00
}
/* not enough data */
2008-05-05 05:58:45 +00:00
pinfo - > desegment_len = DESEGMENT_ONE_MORE_SEGMENT ;
return offset_next - offset_before ;
2003-01-21 01:45:17 +00:00
}
static void dissect_xot_pdu ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
int offset = 0 ;
2002-04-09 08:15:04 +00:00
guint16 version ;
guint16 plen ;
2000-12-17 07:38:14 +00:00
proto_item * ti ;
proto_tree * xot_tree ;
2002-08-28 21:04:11 +00:00
tvbuff_t * next_tvb ;
2001-09-13 08:05:26 +00:00
2003-01-21 01:45:17 +00:00
/*
* Dissect the X .25 - over - TCP packet .
*/
2008-04-23 19:49:40 +00:00
if ( check_col ( pinfo - > cinfo , COL_PROTOCOL ) )
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " XOT " ) ;
version = tvb_get_ntohs ( tvb , offset + 0 ) ;
plen = tvb_get_ntohs ( tvb , offset + 2 ) ;
if ( check_col ( pinfo - > cinfo , COL_INFO ) )
col_add_fstr ( pinfo - > cinfo , COL_INFO , " XOT Version = %u, size = %u " ,
version , plen ) ;
if ( check_col ( pinfo - > cinfo , COL_INFO ) & & offset = = 0 & &
tvb_length_remaining ( tvb , offset ) > XOT_HEADER_LENGTH + plen )
col_append_fstr ( pinfo - > cinfo , COL_INFO , " TotX25: %d " ,
tvb_length_remaining ( tvb , offset ) ) ;
2003-01-21 01:45:17 +00:00
2008-04-23 19:49:40 +00:00
if ( tree ) {
ti = proto_tree_add_protocol_format ( tree , proto_xot , tvb , offset , XOT_HEADER_LENGTH ,
" X.25 over TCP " ) ;
xot_tree = proto_item_add_subtree ( ti , ett_xot ) ;
2003-01-21 01:45:17 +00:00
2008-04-23 19:49:40 +00:00
proto_tree_add_uint ( xot_tree , hf_xot_version , tvb , offset , 2 , version ) ;
proto_tree_add_uint ( xot_tree , hf_xot_length , tvb , offset + 2 , 2 , plen ) ;
}
plen = tvb_get_ntohs ( tvb , offset + 2 ) ;
offset + = XOT_HEADER_LENGTH ;
/*
* Construct a tvbuff containing the amount of the payload we have
* available . Make its reported length the amount of data in the
* X .25 - over - TCP packet .
*/
if ( plen > = X25_MIN_HEADER_LENGTH ) {
next_tvb = tvb_new_subset ( tvb , offset ,
MIN ( plen , tvb_length_remaining ( tvb , offset ) ) , plen ) ;
call_dissector ( x25_handle , next_tvb , pinfo , tree ) ;
}
offset + = plen ;
2003-01-21 01:45:17 +00:00
}
2008-04-23 19:49:40 +00:00
static void dissect_xot_mult ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
2003-01-21 01:45:17 +00:00
{
2008-04-23 19:49:40 +00:00
int offset = 0 ;
int len = get_xot_pdu_len_mult ( pinfo , tvb , offset ) ;
tvbuff_t * next_tvb ;
int offset_max = offset + MIN ( len , tvb_length_remaining ( tvb , offset ) ) ;
proto_item * ti ;
proto_tree * xot_tree ;
2003-01-21 01:45:17 +00:00
2008-04-23 19:49:40 +00:00
if ( tree ) {
/* Special header to show segments */
ti = proto_tree_add_protocol_format ( tree , proto_xot , tvb , offset , offset_max - offset ,
" X.25 over TCP - X.25 Sequence " ) ;
xot_tree = proto_item_add_subtree ( ti , ett_xot ) ;
proto_tree_add_uint ( xot_tree , hf_xot_length , tvb , offset , offset_max , len ) ;
}
while ( offset < = offset_max - XOT_HEADER_LENGTH ) {
int plen = get_xot_pdu_len ( pinfo , tvb , offset ) ;
next_tvb = tvb_new_subset ( tvb , offset , plen , plen ) ;
/*MIN(plen,tvb_length_remaining(tvb, offset)),plen*/
dissect_xot_pdu ( next_tvb , pinfo , tree ) ;
offset + = plen ;
}
}
static int dissect_xot_tcp_heur ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
int tvb_len = tvb_length ( tvb ) ;
2008-05-05 05:58:45 +00:00
int len = 0 ;
2008-04-23 19:49:40 +00:00
if ( tvb_len > = 2 & & tvb_get_ntohs ( tvb , 0 ) ! = XOT_VERSION ) {
return 0 ;
}
2008-05-05 05:58:45 +00:00
2008-04-23 19:49:40 +00:00
if ( ! x25_desegment | | ! xot_desegment ) {
tcp_dissect_pdus ( tvb , pinfo , tree , xot_desegment ,
2008-05-05 05:58:45 +00:00
XOT_HEADER_LENGTH ,
get_xot_pdu_len ,
dissect_xot_pdu ) ;
len = get_xot_pdu_len ( pinfo , tvb , 0 ) ;
} else {
/* Use length version that "peeks" into X25, possibly several XOT packets */
tcp_dissect_pdus ( tvb , pinfo , tree , xot_desegment ,
XOT_HEADER_LENGTH ,
get_xot_pdu_len_mult ,
dissect_xot_mult ) ;
len = get_xot_pdu_len_mult ( pinfo , tvb , 0 ) ;
}
/*As tcp_dissect_pdus will not report the success/failure, we have to compute
again */
if ( len < XOT_HEADER_LENGTH ) {
/* TCP has reported bounds error */
len = 0 ;
} else if ( tvb_len < XOT_HEADER_LENGTH ) {
pinfo - > desegment_len = DESEGMENT_ONE_MORE_SEGMENT ;
len = tvb_len - XOT_HEADER_LENGTH ; /* bytes missing */
} else if ( tvb_len < len ) {
if ( x25_desegment ) {
/* As the "fixed_len" is not fixed here, just request new segments */
pinfo - > desegment_len = DESEGMENT_ONE_MORE_SEGMENT ;
} else {
pinfo - > desegment_len = len - tvb_len ;
}
len = tvb_len - len ; /* bytes missing */
}
return len ;
2000-12-17 07:38:14 +00:00
}
2002-04-09 08:15:04 +00:00
2006-05-21 04:49:01 +00:00
/* Register the protocol with Wireshark */
2002-08-28 21:04:11 +00:00
void
2001-09-13 08:05:26 +00:00
proto_register_xot ( void )
{
static hf_register_info hf [ ] = {
{ & hf_xot_version ,
{ " Version " , " xot.version " , FT_UINT16 , BASE_DEC ,
NULL , 0 , " Version of X.25 over TCP protocol " , HFILL } } ,
2000-12-17 07:38:14 +00:00
2001-09-13 08:05:26 +00:00
{ & hf_xot_length ,
{ " Length " , " xot.length " , FT_UINT16 , BASE_DEC ,
NULL , 0 , " Length of X.25 over TCP packet " , HFILL } }
2000-12-17 07:38:14 +00:00
2001-09-13 08:05:26 +00:00
} ;
2000-12-17 07:38:14 +00:00
2001-09-13 08:05:26 +00:00
static gint * ett [ ] = {
& ett_xot ,
} ;
2002-04-09 08:15:04 +00:00
module_t * xot_module ;
2000-12-17 07:38:14 +00:00
2001-09-13 08:05:26 +00:00
proto_xot = proto_register_protocol ( " X.25 over TCP " , " XOT " , " xot " ) ;
proto_register_field_array ( proto_xot , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2008-04-23 19:49:40 +00:00
new_register_dissector ( " xot " , dissect_xot_tcp_heur , proto_xot ) ;
xot_module = prefs_register_protocol ( proto_xot , NULL ) ;
2002-04-09 08:15:04 +00:00
prefs_register_bool_preference ( xot_module , " desegment " ,
2004-08-21 09:02:52 +00:00
" Reassemble X.25-over-TCP messages spanning multiple TCP segments " ,
" Whether the X.25-over-TCP dissector should reassemble messages spanning multiple TCP segments. "
2008-04-23 19:49:40 +00:00
" To use this option, you must also enable \" Allow subdissectors to reassemble TCP streams \" in the TCP protocol settings " ,
2002-04-09 08:15:04 +00:00
& xot_desegment ) ;
2008-04-23 19:49:40 +00:00
prefs_register_bool_preference ( xot_module , " x25_desegment " ,
" Reassemble X.25 packets with More flag to enable safe X.25 reassembly " ,
" Whether the X.25-over-TCP dissector should reassemble all X.25 packets before calling the X25 dissector. "
" If the TCP packets arrive out-of-order, the X.25 reassembly can otherwise fail. "
" To use this option, you should also enable \" Reassemble X.25-over-TCP messages spanning multiple TCP segments \" , \" Allow subdissectors to reassemble TCP streams \" in the TCP protocol settings and \" Reassemble fragmented X.25 packets \" in the X.25 protocol settings. " ,
& x25_desegment ) ;
2002-04-09 08:15:04 +00:00
}
2000-12-17 07:38:14 +00:00
void
proto_reg_handoff_xot ( void )
{
2008-04-23 19:49:40 +00:00
static gboolean initialized = FALSE ;
static int currentPort = - 1 ;
if ( ! initialized ) {
2001-12-03 04:00:26 +00:00
2001-09-13 08:05:26 +00:00
/*
* Get a handle for the X .25 dissector .
*/
x25_handle = find_dissector ( " x.25 " ) ;
If you register more than one field with the same name, the dfilter code
can now handle that; this allows us to register both the modulo-8 and
the modulo-128 versions of various X.25 bitfields with "x.25.XXX" names,
which lets us get rid of the "ex.25" protocol stuff completely and use
"x.25" for both modulo-8 and modulo-128 X.25. Do so. (Also, fix up
some cases where we appeared to be using the modulo-8 fields when
dissecting modulo-128 X.25.)
This, in turn, allows us to register the X.25 dissector, as there's now
only one protocol with which it's associated, and make it static and
have it called only through a handle, and to, when registering it with
the "llc.dsap" dissector table, associate it with "proto_x25".
That, in turn, allows us to get rid of the "CHECK_DISPLAY_AS_DATA()"
calls, and the code to set "pinfo->current_proto", in the X.25
dissector.
The code for the display filter expression dialog would, if there are
two fields with the same name registered under a protocol, list both of
them; have it list only one of them - the fields should have the same
type, the same radix, and the same value_string/true_false_string table
if any (if they don't, they're really not the same field...).
svn path=/trunk/; revision=3023
2001-02-12 09:06:19 +00:00
2008-04-23 19:49:40 +00:00
xot_handle = new_create_dissector_handle ( dissect_xot_tcp_heur , proto_xot ) ;
initialized = TRUE ;
}
if ( currentPort ! = - 1 ) {
dissector_delete ( " tcp.port " , currentPort , xot_handle ) ;
}
currentPort = TCP_PORT_XOT ;
dissector_add ( " tcp.port " , currentPort , xot_handle ) ;
2000-12-17 07:38:14 +00:00
}