2008-08-09 18:36:22 +00:00
/* packet-teamspeak2.c
* Routines for TeamSpeak2 protocol packet disassembly
* By brooss < brooss . teambb @ gmail . com >
* Copyright 2008 brooss
*
* $ Id $
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998
*
* 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
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
2008-08-09 18:36:22 +00:00
*/
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
2012-05-15 19:23:35 +00:00
# include <glib.h>
2008-08-09 18:36:22 +00:00
# include <epan/packet.h>
2011-08-31 09:00:54 +00:00
# include <wsutil/crc32.h>
# include <epan/crc32-tvb.h>
2008-08-09 18:36:22 +00:00
# include <epan/reassemble.h>
# include <epan/conversation.h>
/* Packet Classes */
# define TS2C_STANDARD 0xbef0
# define TS2C_ACK 0xbef1
# define TS2C_CLIENT_VOICE 0xbef2
# define TS2C_SERVER_VOICE 0xbef3
# define TS2C_CONNECTION 0xbef4
/* Packet Types */
# define TS2T_PING 0x0001
# define TS2T_PINGREPLY 0x0002
# define TS2T_LOGINREQUEST 0x0003
# define TS2T_LOGINREPLY 0x0004
# define TS2T_LOGINPART2 0x0005
# define TS2T_CHANNELLIST 0x0006
# define TS2T_PLAYERLIST 0x0007
# define TS2T_LOGINEND 0x0008
# define TS2T_TEXTMESSAGE 0x0082
# define TS2T_CHANNEL_PLAYERLIST 0x006c
# define TS2T_CHANNELCHANGE 0x0067
# define TS2T_CHANNELLISTUPDATE 0x006e
# define TS2T_PLAYERKICKED 0x0066
# define TS2T_PLAYERLEFT 0x0065
# define TS2T_NEWPLAYERJOINED 0x0064
# define TS2T_KNOWNPLAYERUPDATE 0x0068
# define TS2T_CHANNELDELETED 0x0073
# define TS2T_CHANNELNAMECHANGED 0x006f
# define TS2T_CHANNELTOPICCHANGED 0x0070
# define TS2T_CHANNELPASSWORDCHANGED 0x0071
# define TS2T_CREATECHANNEL 0x00c9
# define TS2T_DISCONNECT 0x012c
# define TS2T_SWITCHCHANNEL 0x012f
# define TS2T_CHANGESTATUS 0x0130
# define TS2T_CHATMESSAGEBOUNCE 0xfc0f
# define TS2T_VOICE_DATA_CELP_5_1 0x0000
# define TS2T_VOICE_DATA_CELP_6_3 0x0100
# define TS2T_VOICE_DATA_GSM_14_8 0x0200
# define TS2T_VOICE_DATA_GSM_16_4 0x0300
# define TS2T_VOICE_DATA_CELP_WINDOWS_5_2 0x0400
# define TS2T_VOICE_DATA_SPEEX_3_4 0x0500
# define TS2T_VOICE_DATA_SPEEX_5_2 0x0600
# define TS2T_VOICE_DATA_SPEEX_7_2 0x0700
# define TS2T_VOICE_DATA_SPEEX_9_3 0x0800
# define TS2T_VOICE_DATA_SPEEX_12_3 0x0900
# define TS2T_VOICE_DATA_SPEEX_16_3 0x0a00
# define TS2T_VOICE_DATA_SPEEX_19_5 0x0b00
# define TS2T_VOICE_DATA_SPEEX_25_9 0x0c00
/* Codec Types */
# define TS2T_CODEC_CELP_5_1 0x0000
# define TS2T_CODEC_CELP_6_3 0x0001
# define TS2T_CODEC_GSM_14_8 0x0002
# define TS2T_CODEC_GSM_16_4 0x0003
# define TS2T_CODEC_CELP_WINDOWS_5_2 0x0004
# define TS2T_CODEC_SPEEX_3_4 0x0005
# define TS2T_CODEC_SPEEX_5_2 0x0006
# define TS2T_CODEC_SPEEX_7_2 0x0007
# define TS2T_CODEC_SPEEX_9_3 0x0008
# define TS2T_CODEC_SPEEX_12_3 0x0009
# define TS2T_CODEC_SPEEX_16_3 0x000a
# define TS2T_CODEC_SPEEX_19_5 0x000b
# define TS2T_CODEC_SPEEX_25_9 0x000c
/* Player Status Flags */
# define TS2_STATUS_CHANNELCOMMANDER 1
# define TS2_STATUS_BLOCKWHISPERS 4
# define TS2_STATUS_AWAY 8
# define TS2_STATUS_MUTEMICROPHONE 16
# define TS2_STATUS_MUTE 32
static int hf_msg_fragments = - 1 ;
static int hf_msg_fragment = - 1 ;
static int hf_msg_fragment_overlap = - 1 ;
static int hf_msg_fragment_overlap_conflicts = - 1 ;
static int hf_msg_fragment_multiple_tails = - 1 ;
static int hf_msg_fragment_too_long_fragment = - 1 ;
static int hf_msg_fragment_error = - 1 ;
2011-01-30 21:01:07 +00:00
static int hf_msg_fragment_count = - 1 ;
2008-08-09 18:36:22 +00:00
static int hf_msg_reassembled_in = - 1 ;
2010-02-02 16:01:52 +00:00
static int hf_msg_reassembled_length = - 1 ;
2008-08-09 18:36:22 +00:00
static gint ett_msg_fragment = - 1 ;
static gint ett_msg_fragments = - 1 ;
static const fragment_items msg_frag_items = {
/* Fragment subtrees */
& ett_msg_fragment ,
& ett_msg_fragments ,
/* Fragment fields */
& hf_msg_fragments ,
& hf_msg_fragment ,
& hf_msg_fragment_overlap ,
& hf_msg_fragment_overlap_conflicts ,
& hf_msg_fragment_multiple_tails ,
& hf_msg_fragment_too_long_fragment ,
& hf_msg_fragment_error ,
2011-01-30 21:01:07 +00:00
& hf_msg_fragment_count ,
2008-08-09 18:36:22 +00:00
/* Reassembled in field */
& hf_msg_reassembled_in ,
2010-02-02 16:01:52 +00:00
/* Reassembled length field */
& hf_msg_reassembled_length ,
2012-09-07 02:09:59 +00:00
/* Reassembled data field */
NULL ,
2008-08-09 18:36:22 +00:00
/* Tag */
" Message fragments "
} ;
/* Class names */
2009-10-11 04:29:06 +00:00
static const value_string classnames [ ] =
2008-08-09 18:36:22 +00:00
{
{ TS2C_CONNECTION , " Connection " } ,
{ TS2C_ACK , " ACK " } ,
{ TS2C_STANDARD , " Standard (reliable) " } ,
{ TS2C_SERVER_VOICE , " Voice " } ,
{ TS2C_CLIENT_VOICE , " Voice " } ,
{ 0 , NULL }
} ;
/* Type names */
static const value_string typenames [ ] = {
{ TS2T_PING , " Ping " } ,
{ TS2T_PINGREPLY , " Ping Reply " } ,
{ TS2T_LOGINREQUEST , " Login Request " } ,
{ TS2T_LOGINREPLY , " Login Reply " } ,
{ TS2T_LOGINPART2 , " Login Part 2 " } ,
{ TS2T_CHANNELLIST , " Channel List " } ,
{ TS2T_PLAYERLIST , " Player List " } ,
{ TS2T_LOGINEND , " Login End " } ,
{ TS2T_TEXTMESSAGE , " Text Message " } ,
{ TS2T_CHANNEL_PLAYERLIST , " Channel Player List " } ,
{ TS2T_CHANNELCHANGE , " Channel Change " } ,
{ TS2T_CHANNELLISTUPDATE , " Channel List Update " } ,
{ TS2T_PLAYERKICKED , " Player Kicked " } ,
{ TS2T_PLAYERLEFT , " Player Left " } ,
{ TS2T_NEWPLAYERJOINED , " New Player Joined " } ,
{ TS2T_KNOWNPLAYERUPDATE , " Known Player Update " } ,
{ TS2T_CHANNELDELETED , " Channel Deleted " } ,
{ TS2T_CHANNELNAMECHANGED , " Channel Name Change " } ,
{ TS2T_CHANNELTOPICCHANGED , " Channel Topic Change " } ,
{ TS2T_CHANNELPASSWORDCHANGED , " Channel Password Change " } ,
{ TS2T_CREATECHANNEL , " Create Channel " } ,
{ TS2T_DISCONNECT , " Disconnect " } ,
{ TS2T_SWITCHCHANNEL , " Switch Channel " } ,
{ TS2T_CHANGESTATUS , " Change Status " } ,
{ TS2T_CHATMESSAGEBOUNCE , " Chat Message Bounce " } ,
{ TS2T_VOICE_DATA_CELP_5_1 , " TS2T_VOICE_DATA_CELP_5_1 " } ,
{ TS2T_VOICE_DATA_CELP_6_3 , " TS2T_VOICE_DATA_CELP_6_3 " } ,
{ TS2T_VOICE_DATA_GSM_14_8 , " TS2T_VOICE_DATA_GSM_14_8 " } ,
{ TS2T_VOICE_DATA_GSM_16_4 , " TS2T_VOICE_DATA_GSM_16_4 " } ,
{ TS2T_VOICE_DATA_CELP_WINDOWS_5_2 , " TS2T_VOICE_DATA_CELP_WINDOWS_5_2 " } ,
{ TS2T_VOICE_DATA_SPEEX_3_4 , " TS2T_VOICE_DATA_SPEEX_3_4 " } ,
{ TS2T_VOICE_DATA_SPEEX_5_2 , " TS2T_VOICE_DATA_SPEEX_5_2 " } ,
{ TS2T_VOICE_DATA_SPEEX_7_2 , " TS2T_VOICE_DATA_SPEEX_7_2 " } ,
{ TS2T_VOICE_DATA_SPEEX_9_3 , " TS2T_VOICE_DATA_SPEEX_9_3 " } ,
{ TS2T_VOICE_DATA_SPEEX_12_3 , " TS2T_VOICE_DATA_SPEEX_12_3 " } ,
{ TS2T_VOICE_DATA_SPEEX_16_3 , " TS2T_VOICE_DATA_SPEEX_16_3 " } ,
{ TS2T_VOICE_DATA_SPEEX_19_5 , " TS2T_VOICE_DATA_SPEEX_19_5 " } ,
{ TS2T_VOICE_DATA_SPEEX_25_9 , " TS2T_VOICE_DATA_SPEEX_25_9 " } ,
2009-10-11 04:29:06 +00:00
2008-08-09 18:36:22 +00:00
{ 0 , NULL }
} ;
/* Codec Names */
2009-10-11 04:29:06 +00:00
static const value_string codecnames [ ] =
2008-08-09 18:36:22 +00:00
{
{ TS2T_CODEC_CELP_5_1 , " CELP 5.1 " } ,
{ TS2T_CODEC_CELP_6_3 , " CELP 6.3 " } ,
{ TS2T_CODEC_GSM_14_8 , " GSM 14.8 " } ,
{ TS2T_CODEC_GSM_16_4 , " GSM 16.4 " } ,
{ TS2T_CODEC_CELP_WINDOWS_5_2 , " CELP Windows 5.2 " } ,
{ TS2T_CODEC_SPEEX_3_4 , " Speex 3.4 " } ,
{ TS2T_CODEC_SPEEX_5_2 , " Speex 5.2 " } ,
{ TS2T_CODEC_SPEEX_7_2 , " Speex 7.2 " } ,
{ TS2T_CODEC_SPEEX_9_3 , " Speex 9.3 " } ,
{ TS2T_CODEC_SPEEX_12_3 , " Speex 12.3 " } ,
{ TS2T_CODEC_SPEEX_16_3 , " Speex 16.3 " } ,
{ TS2T_CODEC_SPEEX_19_5 , " Speex 19.5 " } ,
{ TS2T_CODEC_SPEEX_25_9 , " Speex 25.9 " } ,
{ 0 , NULL }
} ;
2008-10-05 23:08:54 +00:00
# define TS2_PORT 8767
2008-08-09 18:36:22 +00:00
static int proto_ts2 = - 1 ;
static int hf_ts2_type = - 1 ;
static int hf_ts2_class = - 1 ;
static int hf_ts2_clientid = - 1 ;
static int hf_ts2_sessionkey = - 1 ;
static int hf_ts2_crc32 = - 1 ;
static int hf_ts2_ackto = - 1 ;
static int hf_ts2_seqnum = - 1 ;
static int hf_ts2_protocol_string = - 1 ;
static int hf_ts2_string = - 1 ;
static int hf_ts2_registeredlogin = - 1 ;
static int hf_ts2_name = - 1 ;
static int hf_ts2_password = - 1 ;
static int hf_ts2_nick = - 1 ;
static int hf_ts2_badlogin = - 1 ;
static int hf_ts2_unknown = - 1 ;
static int hf_ts2_channel = - 1 ;
static int hf_ts2_subchannel = - 1 ;
static int hf_ts2_channelpassword = - 1 ;
static int hf_ts2_emptyspace = - 1 ;
static int hf_ts2_fragmentnumber = - 1 ;
static int hf_ts2_platform_string = - 1 ;
static int hf_ts2_server_name = - 1 ;
static int hf_ts2_server_welcome_message = - 1 ;
2010-02-24 22:17:52 +00:00
static int hf_ts2_parent_channel_id = - 1 ;
2008-08-09 18:36:22 +00:00
static int hf_ts2_codec = - 1 ;
static int hf_ts2_channel_flags = - 1 ;
static int hf_ts2_channel_id = - 1 ;
static int hf_ts2_channel_name = - 1 ;
static int hf_ts2_channel_topic = - 1 ;
static int hf_ts2_channel_description = - 1 ;
static int hf_ts2_player_id = - 1 ;
static int hf_ts2_player_status_flags = - 1 ;
static int hf_ts2_number_of_players = - 1 ;
static int hf_ts2_number_of_channels = - 1 ;
static int hf_ts2_resend_count = - 1 ;
static int hf_ts2_status_channelcommander = - 1 ;
static int hf_ts2_status_blockwhispers = - 1 ;
static int hf_ts2_status_away = - 1 ;
static int hf_ts2_status_mutemicrophone = - 1 ;
static int hf_ts2_status_mute = - 1 ;
2010-02-24 22:17:52 +00:00
static int hf_ts2_channel_unregistered = - 1 ;
static int hf_ts2_channel_moderated = - 1 ;
static int hf_ts2_channel_password = - 1 ;
static int hf_ts2_channel_subchannels = - 1 ;
static int hf_ts2_channel_default = - 1 ;
static int hf_ts2_channel_order = - 1 ;
static int hf_ts2_max_users = - 1 ;
2008-08-09 18:36:22 +00:00
static gint ett_ts2 = - 1 ;
2010-02-24 22:17:52 +00:00
static gint ett_ts2_channel_flags = - 1 ;
2008-08-09 18:36:22 +00:00
/* Conversation Variables */
2009-10-11 04:29:06 +00:00
typedef struct
2008-08-09 18:36:22 +00:00
{
guint32 last_inorder_server_frame ;
guint32 last_inorder_client_frame ;
address server_addr ;
guint32 server_port ;
guint32 server_frag_size ;
guint32 server_frag_num ;
guint32 client_frag_size ;
guint32 client_frag_num ;
} ts2_conversation ;
/* Packet Variables */
typedef struct
{
guint32 frag_num ;
guint32 frag_size ;
gboolean fragmented ;
gboolean outoforder ;
} ts2_frag ;
# define my_init_count 5
static GHashTable * msg_fragment_table = NULL ;
static GHashTable * msg_reassembled_table = NULL ;
/* forward reference */
static gboolean ts2_add_checked_crc32 ( proto_tree * tree , int hf_item , tvbuff_t * tvb , guint16 offset , guint32 icrc32 ) ;
static void ts2_parse_playerlist ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_channellist ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_newplayerjoined ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_knownplayerupdate ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_playerleft ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_loginend ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_changestatus ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_switchchannel ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_add_statusflags ( tvbuff_t * tvb , proto_tree * ts2_tree , guint32 offset ) ;
static void ts2_parse_channelchange ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
static void ts2_parse_loginpart2 ( tvbuff_t * tvb , proto_tree * ts2_tree ) ;
2009-10-11 04:29:06 +00:00
/*
* Check if a packet is in order and if it is set its fragmentation details into the passed pointers .
2008-08-09 18:36:22 +00:00
* Returns TRUE if the packet is fragmented .
* Must be run sequentially
* */
static gboolean ts2_standard_find_fragments ( tvbuff_t * tvb , guint32 * last_inorder_frame , guint32 * frag_size , guint32 * frag_num , gboolean * outoforder )
{
guint32 frag_count ;
gboolean ret ;
frag_count = tvb_get_letohs ( tvb , 18 ) ;
ret = FALSE ;
* outoforder = FALSE ;
2009-10-11 04:29:06 +00:00
2008-08-09 18:36:22 +00:00
/* if last_inorder_frame is zero, then this is the first reliable packet */
if ( * last_inorder_frame = = 0 )
{
* last_inorder_frame = tvb_get_letohl ( tvb , 12 ) ;
* frag_size = tvb_get_letohs ( tvb , 18 ) ;
* frag_num = 0 ;
if ( * frag_size > 0 )
ret = TRUE ;
2009-10-11 04:29:06 +00:00
else
2008-08-09 18:36:22 +00:00
ret = FALSE ;
}
/* This packet is in order */
else if ( * last_inorder_frame = = tvb_get_letohl ( tvb , 12 ) - 1 )
{
if ( * frag_size > 0 )
{
* frag_num = * frag_size - frag_count ;
if ( frag_count = = 0 )
{
* frag_size = 0 ;
}
ret = TRUE ;
}
else
{
* frag_size = tvb_get_letohs ( tvb , 18 ) ;
* frag_num = * frag_size - frag_count ;
if ( * frag_size > 0 )
ret = TRUE ;
else
ret = FALSE ;
}
* last_inorder_frame = tvb_get_letohl ( tvb , 12 ) ;
}
else /* out of order */
* outoforder = TRUE ;
return ret ;
}
/*
* Dissect a standard ( reliable ) ts2 packet , reassembling if required .
*/
static void ts2_standard_dissect ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * ts2_tree , ts2_conversation * conversation_data )
{
guint8 save_fragmented ;
tvbuff_t * new_tvb , * next_tvb ;
fragment_data * frag_msg ;
guint16 fragment_number ;
ts2_frag * frag ;
gboolean outoforder ;
2008-12-05 16:07:32 +00:00
2008-08-09 18:36:22 +00:00
guint16 type = tvb_get_letohs ( tvb , 2 ) ;
2009-10-11 04:29:06 +00:00
/*guint16 klass = tvb_get_letohs(tvb, 0);*/
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_seqnum , tvb , 12 , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 20:19:52 +00:00
2008-12-05 16:07:32 +00:00
/* XXX: Following fragmentation stuff should be separate from the GUI stuff ?? */
2008-08-09 20:19:52 +00:00
/* Get our stored fragmentation data or create one! */
if ( ! ( frag = p_get_proto_data ( pinfo - > fd , proto_ts2 ) ) ) {
2008-12-05 16:07:32 +00:00
frag = se_alloc ( sizeof ( ts2_frag ) ) ;
frag - > frag_num = 0 ;
2008-08-09 20:19:52 +00:00
}
2008-08-09 18:36:22 +00:00
/* decide if the packet is server to client or client to server
* then check its fragmentation
*/
if ( ! ( pinfo - > fd - > flags . visited ) )
{
if ( conversation_data - > server_port = = pinfo - > srcport )
{
frag - > fragmented = ts2_standard_find_fragments ( tvb , & conversation_data - > last_inorder_server_frame , & conversation_data - > server_frag_size , & conversation_data - > server_frag_num , & outoforder ) ;
frag - > frag_num = conversation_data - > server_frag_num ;
frag - > frag_size = conversation_data - > server_frag_size ;
}
else
{
2009-10-11 04:29:06 +00:00
2008-08-09 18:36:22 +00:00
frag - > fragmented = ts2_standard_find_fragments ( tvb , & conversation_data - > last_inorder_client_frame , & conversation_data - > client_frag_size , & conversation_data - > client_frag_num , & outoforder ) ;
frag - > frag_num = conversation_data - > client_frag_num ;
frag - > frag_size = conversation_data - > client_frag_size ;
}
frag - > outoforder = outoforder ;
p_add_proto_data ( pinfo - > fd , proto_ts2 , frag ) ;
}
/* Get our stored fragmentation data */
frag = p_get_proto_data ( pinfo - > fd , proto_ts2 ) ;
2009-10-11 04:29:06 +00:00
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_resend_count , tvb , 16 , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_fragmentnumber , tvb , 18 , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
ts2_add_checked_crc32 ( ts2_tree , hf_ts2_crc32 , tvb , 20 , tvb_get_letohl ( tvb , 20 ) ) ;
2009-10-11 04:29:06 +00:00
2008-08-09 18:36:22 +00:00
/* Reassemble the packet if its fragmented */
new_tvb = NULL ;
if ( frag - > fragmented )
{
save_fragmented = pinfo - > fragmented ;
frag_msg = NULL ;
pinfo - > fragmented = TRUE ;
fragment_number = tvb_get_letohs ( tvb , 18 ) ;
frag_msg = fragment_add_seq_check ( tvb , 24 , pinfo , type , msg_fragment_table , msg_reassembled_table , frag - > frag_num , tvb_length_remaining ( tvb , 24 ) , fragment_number ) ;
2010-02-06 18:20:21 +00:00
new_tvb = process_reassembled_data ( tvb , 24 , pinfo , " Reassembled TeamSpeak2 " , frag_msg , & msg_frag_items , NULL , ts2_tree ) ;
2008-08-09 18:36:22 +00:00
if ( frag_msg )
{ /* Reassembled */
2009-09-24 20:21:23 +00:00
col_append_str ( pinfo - > cinfo , COL_INFO , " (Message Reassembled) " ) ;
2009-10-11 04:29:06 +00:00
}
else
2008-08-09 18:36:22 +00:00
{ /* Not last packet of reassembled Short Message */
if ( check_col ( pinfo - > cinfo , COL_INFO ) ) col_append_fstr ( pinfo - > cinfo , COL_INFO , " (Message fragment %u) " , frag - > frag_num ) ;
2009-10-11 04:29:06 +00:00
}
2008-08-09 18:36:22 +00:00
if ( new_tvb )
next_tvb = new_tvb ;
else
2009-08-16 12:36:22 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , 24 ) ;
2008-08-09 18:36:22 +00:00
pinfo - > fragmented = save_fragmented ;
}
else
2009-08-16 12:36:22 +00:00
next_tvb = tvb_new_subset_remaining ( tvb , 24 ) ;
2009-10-11 04:29:06 +00:00
2008-08-09 18:36:22 +00:00
/* If we have a full packet now dissect it */
if ( ( new_tvb | | ! frag - > fragmented ) & & ! frag - > outoforder )
{
switch ( type )
{
case TS2T_LOGINPART2 :
ts2_parse_loginpart2 ( next_tvb , ts2_tree ) ;
break ;
case TS2T_CHANNELLIST :
ts2_parse_channellist ( next_tvb , ts2_tree ) ;
break ;
case TS2T_PLAYERLIST :
ts2_parse_playerlist ( next_tvb , ts2_tree ) ;
break ;
case TS2T_NEWPLAYERJOINED :
ts2_parse_newplayerjoined ( next_tvb , ts2_tree ) ;
break ;
case TS2T_KNOWNPLAYERUPDATE :
ts2_parse_knownplayerupdate ( next_tvb , ts2_tree ) ;
break ;
case TS2T_PLAYERLEFT :
ts2_parse_playerleft ( next_tvb , ts2_tree ) ;
break ;
case TS2T_PLAYERKICKED :
ts2_parse_playerleft ( next_tvb , ts2_tree ) ;
break ;
case TS2T_LOGINEND :
ts2_parse_loginend ( next_tvb , ts2_tree ) ;
break ;
case TS2T_CHANGESTATUS :
ts2_parse_changestatus ( next_tvb , ts2_tree ) ;
break ;
case TS2T_SWITCHCHANNEL :
ts2_parse_switchchannel ( next_tvb , ts2_tree ) ;
2009-10-11 04:29:06 +00:00
break ;
2008-08-09 18:36:22 +00:00
case TS2T_CHANNELCHANGE :
ts2_parse_channelchange ( next_tvb , ts2_tree ) ;
break ;
}
}
/* The packet is out of order, update the cinfo and ignore the packet */
if ( frag - > outoforder )
2009-09-24 20:21:23 +00:00
col_append_str ( pinfo - > cinfo , COL_INFO , " (Out Of Order, ignored) " ) ;
2008-08-09 18:36:22 +00:00
}
/* Parses a ts2 new player joined (TS2_NEWPLAYERJOINED) packet and adds it to the tree */
static void ts2_parse_newplayerjoined ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , 6 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 6 ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_nick , tvb , offset , 1 , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 30 ;
}
/* Parses TS2_LOGINEND packet and adds it to the tree */
static void ts2_parse_loginend ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , tvb_length_remaining ( tvb , offset ) , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
}
/* Parses a ts2 known player joined (TS2_KNOWNPLAYERUPDATE) packet and adds it to the tree */
static void ts2_parse_knownplayerupdate ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_status_flags , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
ts2_add_statusflags ( tvb , ts2_tree , offset ) ;
}
/* Parses a ts2 switch channel (TS2_SWITCHCHANNEL) packet and adds it to the tree */
static void ts2_parse_switchchannel ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_password , tvb , offset , 1 , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 30 ;
}
/* Parses a ts2 channel change (TS2T_CHANNELCHANGE) packet and adds it to the tree */
static void ts2_parse_channelchange ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , 2 , ENC_NA ) ;
2009-10-11 04:29:06 +00:00
2008-08-09 18:36:22 +00:00
}
/* Parses a ts2 change status (TS2_CHANGESTATUS) packet and adds it to the tree */
static void ts2_parse_changestatus ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_status_flags , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
ts2_add_statusflags ( tvb , ts2_tree , offset ) ;
2009-10-11 04:29:06 +00:00
2008-08-09 18:36:22 +00:00
}
/* Parses a ts2 known player left (TS2_PLAYERLEFT) packet and adds it to the tree */
static void ts2_parse_playerleft ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , 4 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , 4 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , tvb_length_remaining ( tvb , offset ) , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
}
/* Parses a ts2 login part 2 (TS2T_LOGINPART2) packet and adds it to the tree */
static void ts2_parse_loginpart2 ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
offset = 0 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , 0 , 2 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 2 ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel , tvb , offset , 1 , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 30 ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_subchannel , tvb , offset , 1 , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 30 ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channelpassword , tvb , offset , 1 , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 30 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , 4 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
}
/* Parses a ts2 channel list (TS2T_CHANNELLIST) and adds it to the tree */
static void ts2_parse_channellist ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
guint32 string_len ;
2010-02-24 22:17:52 +00:00
proto_tree * subtree ;
proto_item * item ;
2008-08-09 18:36:22 +00:00
offset = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_number_of_channels , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
while ( offset < tvb_length_remaining ( tvb , 0 ) )
{
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2010-02-24 22:17:52 +00:00
/* Channel flags */
2011-10-06 03:35:44 +00:00
item = proto_tree_add_item ( ts2_tree , hf_ts2_channel_flags , tvb , offset , 1 , ENC_LITTLE_ENDIAN ) ;
2010-02-24 22:17:52 +00:00
subtree = proto_item_add_subtree ( item , ett_ts2_channel_flags ) ;
2011-10-10 00:39:31 +00:00
proto_tree_add_item ( subtree , hf_ts2_channel_unregistered , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( subtree , hf_ts2_channel_moderated , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( subtree , hf_ts2_channel_password , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( subtree , hf_ts2_channel_subchannels , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
proto_tree_add_item ( subtree , hf_ts2_channel_default , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 1 ;
2010-02-24 22:17:52 +00:00
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , 1 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 1 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_codec , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 2 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_parent_channel_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_order , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
2010-02-24 22:17:52 +00:00
offset + = 2 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_max_users , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
2010-02-24 22:17:52 +00:00
offset + = 2 ;
2008-08-09 18:36:22 +00:00
tvb_get_ephemeral_stringz ( tvb , offset , & string_len ) ;
2011-10-15 18:46:26 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_name , tvb , offset , string_len , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = string_len ;
tvb_get_ephemeral_stringz ( tvb , offset , & string_len ) ;
2011-10-15 18:46:26 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_topic , tvb , offset , string_len , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = string_len ;
tvb_get_ephemeral_stringz ( tvb , offset , & string_len ) ;
2011-10-15 18:46:26 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_description , tvb , offset , string_len , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = string_len ;
}
}
static void ts2_add_statusflags ( tvbuff_t * tvb , proto_tree * ts2_tree , guint32 offset )
{
2011-10-10 00:39:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_status_channelcommander , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_status_blockwhispers , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_status_away , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_status_mutemicrophone , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_status_mute , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
}
/* Parses a ts2 player list (TS2T_PLAYERLIST) and adds it to the tree */
static void ts2_parse_playerlist ( tvbuff_t * tvb , proto_tree * ts2_tree )
{
gint32 offset ;
gint32 number_of_players ;
2009-10-11 04:29:06 +00:00
gint32 x ;
2008-08-09 18:36:22 +00:00
offset = 0 ;
x = 0 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_number_of_players , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
number_of_players = tvb_get_letohl ( tvb , 0 ) ;
offset + = 4 ;
while ( offset < tvb_length_remaining ( tvb , 0 ) & & x < number_of_players )
2009-10-11 04:29:06 +00:00
{
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_channel_id , tvb , offset , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , offset , 4 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 4 ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_player_status_flags , tvb , offset , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
ts2_add_statusflags ( tvb , ts2_tree , offset ) ;
offset + = 2 ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_nick , tvb , offset , 1 , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
offset + = 30 ;
x + + ;
}
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_emptyspace , tvb , offset , tvb_length_remaining ( tvb , 0 ) , ENC_NA ) ;
2009-10-11 04:29:06 +00:00
}
2008-08-09 18:36:22 +00:00
/* Find the current conversation or make a new one if required */
static ts2_conversation * ts2_get_conversation ( packet_info * pinfo )
{
conversation_t * conversation ;
ts2_conversation * conversation_data ;
conversation = find_conversation ( pinfo - > fd - > num , & pinfo - > src , & pinfo - > dst , pinfo - > ptype , pinfo - > srcport , pinfo - > destport , 0 ) ;
if ( conversation )
{
conversation_data = ( ts2_conversation * ) conversation_get_proto_data ( conversation , proto_ts2 ) ;
}
else
{
2009-10-11 10:00:01 +00:00
conversation_data = se_alloc ( sizeof ( * conversation_data ) ) ;
2008-08-09 18:36:22 +00:00
conversation_data - > last_inorder_server_frame = 0 ; /* sequence number should never be zero so we can use this as an initial number */
conversation_data - > last_inorder_client_frame = 0 ;
conversation_data - > server_port = pinfo - > srcport ;
conversation_data - > server_frag_size = 0 ;
conversation_data - > server_frag_num = 0 ;
conversation_data - > client_frag_size = 0 ;
conversation_data - > client_frag_num = 0 ;
conversation = conversation_new ( pinfo - > fd - > num , & pinfo - > src , & pinfo - > dst , pinfo - > ptype , pinfo - > srcport , pinfo - > destport , 0 ) ;
conversation_add_proto_data ( conversation , proto_ts2 , ( void * ) conversation_data ) ;
}
return conversation_data ;
}
/* Dissect a TS2 packet */
static void dissect_ts2 ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree )
{
ts2_conversation * conversation_data ;
guint16 type = tvb_get_letohs ( tvb , 2 ) ;
2009-10-11 04:29:06 +00:00
guint16 klass = tvb_get_letohs ( tvb , 0 ) ;
2008-08-09 18:36:22 +00:00
conversation_data = ts2_get_conversation ( pinfo ) ;
2009-10-11 04:36:43 +00:00
2009-08-09 07:59:51 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " TS2 " ) ;
2009-10-11 04:36:43 +00:00
if ( check_col ( pinfo - > cinfo , COL_INFO ) ) {
2009-10-11 04:29:06 +00:00
if ( klass = = TS2C_ACK )
col_add_fstr ( pinfo - > cinfo , COL_INFO , " Class: %s " , val_to_str ( klass , classnames , " Unknown (0x%02x) " ) ) ;
2008-08-09 18:36:22 +00:00
else
2009-10-11 04:29:06 +00:00
col_add_fstr ( pinfo - > cinfo , COL_INFO , " Type: %s, Class: %s " , val_to_str ( type , typenames , " Unknown (0x%02x) " ) , val_to_str ( klass , classnames , " Unknown (0x%02x) " ) ) ;
2008-08-09 18:36:22 +00:00
}
2008-12-05 16:07:32 +00:00
/* XXX: We need to do all the non GUI stuff whether or not if(tree) */
/* Do only once by checking visited ? */
/* ToDo: Rewrite ?? */
if ( ! tree ) {
2009-10-11 04:29:06 +00:00
switch ( klass ) {
2008-12-05 16:07:32 +00:00
case TS2C_CONNECTION :
switch ( type ) {
case TS2T_LOGINREQUEST :
conversation_data - > server_port = pinfo - > destport ;
conversation_data - > server_addr = pinfo - > dst ;
break ;
}
break ;
case TS2C_STANDARD :
ts2_standard_dissect ( tvb , pinfo , tree , conversation_data ) ;
break ;
}
}
2008-08-09 18:36:22 +00:00
if ( tree ) { /* we are being asked for details */
proto_item * ti = NULL ;
proto_tree * ts2_tree = NULL ;
2011-10-21 02:10:19 +00:00
ti = proto_tree_add_item ( tree , proto_ts2 , tvb , 0 , - 1 , ENC_NA ) ;
2008-08-09 18:36:22 +00:00
ts2_tree = proto_item_add_subtree ( ti , ett_ts2 ) ;
2009-10-11 04:29:06 +00:00
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_class , tvb , 0 , 2 , ENC_LITTLE_ENDIAN ) ;
2009-10-11 04:29:06 +00:00
if ( klass = = TS2C_ACK )
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_resend_count , tvb , 2 , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
else
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_type , tvb , 2 , 2 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_sessionkey , tvb , 4 , 4 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_clientid , tvb , 8 , 4 , ENC_LITTLE_ENDIAN ) ;
2009-10-11 04:29:06 +00:00
switch ( klass )
2008-08-09 18:36:22 +00:00
{
case TS2C_CONNECTION :
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_seqnum , tvb , 12 , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
ts2_add_checked_crc32 ( ts2_tree , hf_ts2_crc32 , tvb , 16 , tvb_get_letohl ( tvb , 16 ) ) ;
switch ( type )
{
case TS2T_PING :
break ;
case TS2T_PINGREPLY :
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_ackto , tvb , 20 , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
break ;
case TS2T_LOGINREQUEST :
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_protocol_string , tvb , 20 , 1 , ENC_ASCII | ENC_NA ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_platform_string , tvb , 50 , 1 , ENC_ASCII | ENC_NA ) ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , 80 , 9 , ENC_NA ) ;
2011-10-10 00:39:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_registeredlogin , tvb , 90 , 1 , ENC_LITTLE_ENDIAN ) ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_name , tvb , 90 , 1 , ENC_ASCII | ENC_NA ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_password , tvb , 120 , 1 , ENC_ASCII | ENC_NA ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_nick , tvb , 150 , 1 , ENC_ASCII | ENC_NA ) ;
2008-08-09 18:36:22 +00:00
conversation_data - > server_port = pinfo - > destport ;
conversation_data - > server_addr = pinfo - > dst ;
break ;
case TS2T_LOGINREPLY :
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_server_name , tvb , 20 , 1 , ENC_ASCII | ENC_NA ) ;
proto_tree_add_item ( ts2_tree , hf_ts2_platform_string , tvb , 50 , 1 , ENC_ASCII | ENC_NA ) ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , 80 , 9 , ENC_NA ) ;
2011-10-10 00:39:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_badlogin , tvb , 89 , 3 , ENC_LITTLE_ENDIAN ) ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , 92 , 80 , ENC_NA ) ;
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_sessionkey , tvb , 172 , 4 , ENC_LITTLE_ENDIAN ) ;
2011-10-04 22:44:31 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_unknown , tvb , 178 , 3 , ENC_NA ) ;
2012-04-27 18:58:37 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_server_welcome_message , tvb , 180 , 1 , ENC_ASCII | ENC_NA ) ;
2008-12-05 16:27:31 +00:00
break ;
2008-08-09 18:36:22 +00:00
}
break ;
case TS2C_ACK :
/* Ignore the type for ACK, its always zero and clashes with CELP_5_1 */
2009-10-11 04:29:06 +00:00
2011-10-06 03:35:44 +00:00
proto_tree_add_item ( ts2_tree , hf_ts2_seqnum , tvb , 12 , 4 , ENC_LITTLE_ENDIAN ) ;
2008-08-09 18:36:22 +00:00
break ;
case TS2C_STANDARD :
ts2_standard_dissect ( tvb , pinfo , ts2_tree , conversation_data ) ;
2008-12-05 16:07:32 +00:00
break ;
2008-08-09 18:36:22 +00:00
}
2009-10-11 04:29:06 +00:00
} /* if (tree) */
2008-08-09 18:36:22 +00:00
}
2009-10-11 04:29:06 +00:00
/* Calculates a CRC32 checksum from the tvb zeroing out four bytes at the offset and checks it with the given crc32 and adds the result to the tree
2008-08-09 18:36:22 +00:00
* Returns true if the calculated CRC32 matches the passed CRC32 .
* */
static gboolean ts2_add_checked_crc32 ( proto_tree * tree , int hf_item , tvbuff_t * tvb , guint16 offset , guint32 icrc32 )
{
guint8 * zero ;
guint32 ocrc32 ;
2008-10-05 23:08:54 +00:00
zero = ep_alloc0 ( 4 ) ;
2008-08-09 18:36:22 +00:00
ocrc32 = crc32_ccitt_tvb ( tvb , offset ) ;
ocrc32 = crc32_ccitt_seed ( zero , 4 , 0xffffffff - ocrc32 ) ;
ocrc32 = crc32_ccitt_tvb_offset_seed ( tvb , offset + 4 , tvb_reported_length_remaining ( tvb , offset + 4 ) , 0xffffffff - ocrc32 ) ;
if ( icrc32 = = ocrc32 )
{
proto_tree_add_uint_format ( tree , hf_item , tvb , offset , 4 , tvb_get_letohl ( tvb , 16 ) , " crc32: 0x%04x [correct] " , tvb_get_letohl ( tvb , offset ) ) ;
return TRUE ;
}
else
{
proto_tree_add_uint_format ( tree , hf_item , tvb , offset , 4 , tvb_get_letohl ( tvb , 16 ) , " crc32: 0x%04x [incorrect, should be 0x%04x] " , tvb_get_letohl ( tvb , offset ) , ocrc32 ) ;
return FALSE ;
}
}
2009-01-28 21:52:57 +00:00
2009-10-11 10:00:01 +00:00
static void ts2_init ( void )
{
2009-01-28 21:52:57 +00:00
fragment_table_init ( & msg_fragment_table ) ;
reassembled_table_init ( & msg_reassembled_table ) ;
}
2009-10-11 04:29:06 +00:00
/*
2009-01-28 21:52:57 +00:00
* proto_register_ts2 ( )
* */
void proto_register_ts2 ( void )
{
static hf_register_info hf [ ] = {
{ & hf_ts2_class ,
{ " Class " , " ts2.class " ,
FT_UINT16 , BASE_HEX ,
VALS ( classnames ) , 0x0 ,
NULL , HFILL }
2009-10-11 04:29:06 +00:00
} ,
2009-01-28 21:52:57 +00:00
{ & hf_ts2_type ,
{ " Type " , " ts2.type " ,
FT_UINT16 , BASE_HEX ,
VALS ( typenames ) , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_clientid ,
{ " Client id " , " ts2.clientid " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_sessionkey ,
{ " Session Key " , " ts2.sessionkey " ,
FT_UINT32 , BASE_HEX ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_ackto ,
{ " Ping Reply To " , " ts2.ping_ackto " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_crc32 ,
{ " CRC32 Checksum " , " ts2.crc32 " ,
FT_UINT32 , BASE_HEX ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_seqnum ,
{ " Sequence Number " , " ts2.sequencenum " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_protocol_string ,
{ " Protocol String " , " ts2.protocolstring " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_string ,
{ " String " , " ts2.string " ,
FT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_registeredlogin ,
{ " Registered Login " , " ts2.registeredlogin " ,
FT_BOOLEAN , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_name ,
{ " Name " , " ts2.name " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_password ,
{ " Password " , " ts2.password " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_nick ,
{ " Nick " , " ts2.nick " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_badlogin ,
{ " Bad Login " , " ts2.badlogin " ,
FT_BOOLEAN , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_unknown ,
{ " Unknown " , " ts2.unknown " ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
FT_BYTES , BASE_NONE ,
2009-01-28 21:52:57 +00:00
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel ,
{ " Channel " , " ts2.channel " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_subchannel ,
{ " Sub-Channel " , " ts2.subchannel " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_channelpassword ,
{ " Channel Password " , " ts2.channelpassword " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_emptyspace ,
{ " Empty Space " , " ts2.emptyspace " ,
FT_NONE , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_fragmentnumber ,
{ " Fragment Number " , " ts2.fragmentnumber " ,
FT_UINT16 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_platform_string ,
{ " Platform String " , " ts2.platformstring " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_server_name ,
{ " Server Name " , " ts2.servername " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_server_welcome_message ,
{ " Server Welcome Message " , " ts2.serverwelcomemessage " ,
FT_UINT_STRING , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
2010-02-24 22:17:52 +00:00
{ & hf_ts2_parent_channel_id ,
{ " Parent Channel ID " , " ts2.parentchannelid " ,
FT_UINT32 , BASE_HEX ,
2009-01-28 21:52:57 +00:00
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_codec ,
{ " Codec " , " ts2.codec " ,
FT_UINT16 , BASE_HEX ,
VALS ( codecnames ) , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_flags ,
{ " Channel Flags " , " ts2.channelflags " ,
2010-02-24 22:17:52 +00:00
FT_UINT8 , BASE_HEX ,
2009-01-28 21:52:57 +00:00
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_id ,
{ " Channel Id " , " ts2.chanelid " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_name ,
{ " Channel Name " , " ts2.chanelname " ,
FT_STRINGZ , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_topic ,
{ " Channel Topic " , " ts2.chaneltopic " ,
FT_STRINGZ , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_description ,
{ " Channel Description " , " ts2.chaneldescription " ,
FT_STRINGZ , BASE_NONE ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_player_id ,
{ " Player Id " , " ts2.playerid " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_player_status_flags ,
{ " Player Status Flags " , " ts2.playerstatusflags " ,
FT_UINT16 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_number_of_players ,
{ " Number Of Players " , " ts2.numberofplayers " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_number_of_channels ,
{ " Number Of Channels " , " ts2.numberofchannels " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_resend_count ,
{ " Resend Count " , " ts2.resendcount " ,
FT_UINT16 , BASE_DEC ,
NULL , 0x0 ,
NULL , HFILL }
} ,
{ & hf_ts2_status_channelcommander ,
{ " Channel Commander " , " ts2.playerstatusflags.channelcommander " ,
2009-10-11 04:29:06 +00:00
FT_BOOLEAN , 8 ,
2009-01-28 21:52:57 +00:00
NULL , TS2_STATUS_CHANNELCOMMANDER ,
NULL , HFILL }
} ,
{ & hf_ts2_status_blockwhispers ,
{ " Block Whispers " , " ts2.playerstatusflags.blockwhispers " ,
2009-10-11 04:29:06 +00:00
FT_BOOLEAN , 8 ,
2009-01-28 21:52:57 +00:00
NULL , TS2_STATUS_BLOCKWHISPERS ,
NULL , HFILL }
} ,
{ & hf_ts2_status_away ,
{ " Away " , " ts2.playerstatusflags.away " ,
2009-10-11 04:29:06 +00:00
FT_BOOLEAN , 8 ,
2009-01-28 21:52:57 +00:00
NULL , TS2_STATUS_AWAY ,
NULL , HFILL }
} ,
{ & hf_ts2_status_mutemicrophone ,
{ " Mute Microphone " , " ts2.playerstatusflags.mutemicrophone " ,
2009-10-11 04:29:06 +00:00
FT_BOOLEAN , 8 ,
2009-01-28 21:52:57 +00:00
NULL , TS2_STATUS_MUTEMICROPHONE ,
NULL , HFILL }
} ,
{ & hf_ts2_status_mute ,
{ " Mute " , " ts2.playerstatusflags.mute " ,
2009-10-11 04:29:06 +00:00
FT_BOOLEAN , 8 ,
2009-01-28 21:52:57 +00:00
NULL , TS2_STATUS_MUTE ,
NULL , HFILL }
} ,
{ & hf_msg_fragments ,
{ " Message fragments " , " ts2.fragments " ,
FT_NONE , BASE_NONE ,
NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_msg_fragment ,
{ " Message fragment " , " ts2.fragment " ,
FT_FRAMENUM , BASE_NONE ,
NULL , 0x00 ,
2009-10-11 04:29:06 +00:00
NULL , HFILL }
2009-01-28 21:52:57 +00:00
} ,
{ & hf_msg_fragment_overlap ,
{ " Message fragment overlap " , " ts2.fragment.overlap " ,
FT_BOOLEAN , BASE_NONE ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , 0x0 ,
2009-10-11 04:29:06 +00:00
NULL , HFILL }
2009-01-28 21:52:57 +00:00
} ,
{ & hf_msg_fragment_overlap_conflicts ,
{ " Message fragment overlapping with conflicting data " ,
" ts2.fragment.overlap.conflicts " ,
FT_BOOLEAN , BASE_NONE ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , 0x0 ,
2009-10-11 04:29:06 +00:00
NULL , HFILL }
2009-01-28 21:52:57 +00:00
} ,
{ & hf_msg_fragment_multiple_tails ,
{ " Message has multiple tail fragments " ,
2009-10-11 04:29:06 +00:00
" ts2.fragment.multiple_tails " ,
2009-01-28 21:52:57 +00:00
FT_BOOLEAN , BASE_NONE ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , 0x0 ,
2009-10-11 04:29:06 +00:00
NULL , HFILL }
2009-01-28 21:52:57 +00:00
} ,
{ & hf_msg_fragment_too_long_fragment ,
{ " Message fragment too long " , " ts2.fragment.too_long_fragment " ,
FT_BOOLEAN , BASE_NONE ,
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
NULL , 0x0 ,
2009-10-11 04:29:06 +00:00
NULL , HFILL }
2009-01-28 21:52:57 +00:00
} ,
{ & hf_msg_fragment_error ,
{ " Message defragmentation error " , " ts2.fragment.error " ,
FT_FRAMENUM , BASE_NONE ,
NULL , 0x00 ,
2009-10-11 04:29:06 +00:00
NULL , HFILL }
2009-01-28 21:52:57 +00:00
} ,
2011-01-30 21:01:07 +00:00
{ & hf_msg_fragment_count ,
{ " Message fragment count " , " ts2.fragment.count " ,
FT_UINT32 , BASE_DEC ,
NULL , 0x00 ,
NULL , HFILL }
} ,
2009-01-28 21:52:57 +00:00
{ & hf_msg_reassembled_in ,
{ " Reassembled in " , " ts2.reassembled.in " ,
FT_FRAMENUM , BASE_NONE ,
NULL , 0x00 ,
NULL , HFILL }
2010-02-02 16:01:52 +00:00
} ,
{ & hf_msg_reassembled_length ,
2010-02-06 18:20:21 +00:00
{ " Reassembled TeamSpeak2 length " , " ts2.reassembled.length " ,
2010-02-02 16:01:52 +00:00
FT_UINT32 , BASE_DEC ,
NULL , 0x00 ,
NULL , HFILL }
2010-02-24 22:17:52 +00:00
} ,
{ & hf_ts2_channel_unregistered ,
{ " Unregistered " , " ts2.channelflags.unregistered " ,
FT_BOOLEAN , 8 ,
NULL , 0x01 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_moderated ,
{ " Moderated " , " ts2.channelflags.moderated " ,
FT_BOOLEAN , 8 ,
NULL , 0x02 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_password ,
{ " Has password " , " ts2.channelflags.has_password " ,
FT_BOOLEAN , 8 ,
NULL , 0x04 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_subchannels ,
{ " Has subchannels " , " ts2.channelflags.has_subchannels " ,
FT_BOOLEAN , 8 ,
NULL , 0x08 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_default ,
{ " Default " , " ts2.channelflags.default " ,
FT_BOOLEAN , 8 ,
NULL , 0x10 ,
NULL , HFILL }
} ,
{ & hf_ts2_channel_order ,
{ " Channel order " , " ts2.channelorder " ,
FT_UINT16 , BASE_DEC ,
NULL , 0x00 ,
NULL , HFILL }
} ,
{ & hf_ts2_max_users ,
{ " Max users " , " ts2.maxusers " ,
FT_UINT16 , BASE_DEC ,
NULL , 0x00 ,
NULL , HFILL }
2009-01-28 21:52:57 +00:00
}
} ;
static gint * ett [ ] = {
& ett_ts2 ,
& ett_msg_fragment ,
2010-02-24 22:17:52 +00:00
& ett_msg_fragments ,
& ett_ts2_channel_flags
2009-01-28 21:52:57 +00:00
} ;
/* Setup protocol subtree array */
proto_ts2 = proto_register_protocol (
" Teamspeak2 Protocol " , /* name */
" TeamSpeak2 " , /* short name */
" ts2 " /* abbrev */
) ;
proto_register_field_array ( proto_ts2 , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
register_init_routine ( ts2_init ) ;
}
/*
* proto_reg_handoff_ts2 ( )
* */
void proto_reg_handoff_ts2 ( void )
{
dissector_handle_t ts2_handle ;
ts2_handle = create_dissector_handle ( dissect_ts2 , proto_ts2 ) ;
2010-12-20 05:35:29 +00:00
dissector_add_uint ( " udp.port " , TS2_PORT , ts2_handle ) ;
2009-01-28 21:52:57 +00:00
}