TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / epan / dissectors / packet-teamspeak2.c
blob18969ca0859a43a530332b3a5a35c4544e075f13
1 /* packet-teamspeak2.c
2 * Routines for TeamSpeak2 protocol packet disassembly
3 * By brooss <brooss.teambb@gmail.com>
4 * Copyright 2008 brooss
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/expert.h>
17 #include <wsutil/crc32.h>
18 #include <epan/crc32-tvb.h>
19 #include <epan/reassemble.h>
20 #include <epan/conversation.h>
21 #include <epan/proto_data.h>
23 /* Packet Classes */
24 #define TS2C_STANDARD 0xbef0
25 #define TS2C_ACK 0xbef1
26 #define TS2C_CLIENT_VOICE 0xbef2
27 #define TS2C_SERVER_VOICE 0xbef3
28 #define TS2C_CONNECTION 0xbef4
30 /* Packet Types */
31 #define TS2T_PING 0x0001
32 #define TS2T_PINGREPLY 0x0002
33 #define TS2T_LOGINREQUEST 0x0003
34 #define TS2T_LOGINREPLY 0x0004
35 #define TS2T_LOGINPART2 0x0005
36 #define TS2T_CHANNELLIST 0x0006
37 #define TS2T_PLAYERLIST 0x0007
38 #define TS2T_LOGINEND 0x0008
40 #define TS2T_TEXTMESSAGE 0x0082
41 #define TS2T_CHANNEL_PLAYERLIST 0x006c
42 #define TS2T_CHANNELCHANGE 0x0067
43 #define TS2T_CHANNELLISTUPDATE 0x006e
44 #define TS2T_PLAYERKICKED 0x0066
45 #define TS2T_PLAYERLEFT 0x0065
46 #define TS2T_NEWPLAYERJOINED 0x0064
47 #define TS2T_KNOWNPLAYERUPDATE 0x0068
48 #define TS2T_CHANNELDELETED 0x0073
49 #define TS2T_CHANNELNAMECHANGED 0x006f
50 #define TS2T_CHANNELTOPICCHANGED 0x0070
51 #define TS2T_CHANNELPASSWORDCHANGED 0x0071
52 #define TS2T_CREATECHANNEL 0x00c9
53 #define TS2T_DISCONNECT 0x012c
54 #define TS2T_SWITCHCHANNEL 0x012f
55 #define TS2T_CHANGESTATUS 0x0130
56 #define TS2T_CHATMESSAGEBOUNCE 0xfc0f
58 #define TS2T_VOICE_DATA_CELP_5_1 0x0000
59 #define TS2T_VOICE_DATA_CELP_6_3 0x0100
60 #define TS2T_VOICE_DATA_GSM_14_8 0x0200
61 #define TS2T_VOICE_DATA_GSM_16_4 0x0300
62 #define TS2T_VOICE_DATA_CELP_WINDOWS_5_2 0x0400
63 #define TS2T_VOICE_DATA_SPEEX_3_4 0x0500
64 #define TS2T_VOICE_DATA_SPEEX_5_2 0x0600
65 #define TS2T_VOICE_DATA_SPEEX_7_2 0x0700
66 #define TS2T_VOICE_DATA_SPEEX_9_3 0x0800
67 #define TS2T_VOICE_DATA_SPEEX_12_3 0x0900
68 #define TS2T_VOICE_DATA_SPEEX_16_3 0x0a00
69 #define TS2T_VOICE_DATA_SPEEX_19_5 0x0b00
70 #define TS2T_VOICE_DATA_SPEEX_25_9 0x0c00
72 /* Codec Types */
73 #define TS2T_CODEC_CELP_5_1 0x0000
74 #define TS2T_CODEC_CELP_6_3 0x0001
75 #define TS2T_CODEC_GSM_14_8 0x0002
76 #define TS2T_CODEC_GSM_16_4 0x0003
77 #define TS2T_CODEC_CELP_WINDOWS_5_2 0x0004
78 #define TS2T_CODEC_SPEEX_3_4 0x0005
79 #define TS2T_CODEC_SPEEX_5_2 0x0006
80 #define TS2T_CODEC_SPEEX_7_2 0x0007
81 #define TS2T_CODEC_SPEEX_9_3 0x0008
82 #define TS2T_CODEC_SPEEX_12_3 0x0009
83 #define TS2T_CODEC_SPEEX_16_3 0x000a
84 #define TS2T_CODEC_SPEEX_19_5 0x000b
85 #define TS2T_CODEC_SPEEX_25_9 0x000c
87 /* Player Status Flags */
88 #define TS2_STATUS_CHANNELCOMMANDER 1
89 #define TS2_STATUS_BLOCKWHISPERS 4
90 #define TS2_STATUS_AWAY 8
91 #define TS2_STATUS_MUTEMICROPHONE 16
92 #define TS2_STATUS_MUTE 32
94 void proto_reg_handoff_ts2(void);
95 void proto_register_ts2(void);
97 static dissector_handle_t ts2_handle;
99 static int hf_msg_fragments;
100 static int hf_msg_fragment;
101 static int hf_msg_fragment_overlap;
102 static int hf_msg_fragment_overlap_conflicts;
103 static int hf_msg_fragment_multiple_tails;
104 static int hf_msg_fragment_too_long_fragment;
105 static int hf_msg_fragment_error;
106 static int hf_msg_fragment_count;
107 static int hf_msg_reassembled_in;
108 static int hf_msg_reassembled_length;
110 static int ett_msg_fragment;
111 static int ett_msg_fragments;
113 static expert_field ei_ts2_crc32;
115 static const fragment_items msg_frag_items = {
116 /* Fragment subtrees */
117 &ett_msg_fragment,
118 &ett_msg_fragments,
119 /* Fragment fields */
120 &hf_msg_fragments,
121 &hf_msg_fragment,
122 &hf_msg_fragment_overlap,
123 &hf_msg_fragment_overlap_conflicts,
124 &hf_msg_fragment_multiple_tails,
125 &hf_msg_fragment_too_long_fragment,
126 &hf_msg_fragment_error,
127 &hf_msg_fragment_count,
128 /* Reassembled in field */
129 &hf_msg_reassembled_in,
130 /* Reassembled length field */
131 &hf_msg_reassembled_length,
132 /* Reassembled data field */
133 NULL,
134 /* Tag */
135 "Message fragments"
138 /* Class names */
139 static const value_string classnames[] =
141 { TS2C_CONNECTION, "Connection" },
142 { TS2C_ACK, "ACK"},
143 { TS2C_STANDARD, "Standard (reliable)"},
144 { TS2C_SERVER_VOICE, "Voice"},
145 { TS2C_CLIENT_VOICE, "Voice"},
146 { 0, NULL }
149 /* Type names */
150 static const value_string typenames[] = {
151 { TS2T_PING, "Ping" },
152 { TS2T_PINGREPLY, "Ping Reply" },
153 { TS2T_LOGINREQUEST, "Login Request" },
154 { TS2T_LOGINREPLY, "Login Reply" },
155 { TS2T_LOGINPART2, "Login Part 2" },
156 { TS2T_CHANNELLIST, "Channel List" },
157 { TS2T_PLAYERLIST, "Player List" },
158 { TS2T_LOGINEND, "Login End" },
159 { TS2T_TEXTMESSAGE, "Text Message" },
162 { TS2T_CHANNEL_PLAYERLIST, "Channel Player List" },
163 { TS2T_CHANNELCHANGE, "Channel Change" },
165 { TS2T_CHANNELLISTUPDATE, "Channel List Update" },
166 { TS2T_PLAYERKICKED, "Player Kicked" },
167 { TS2T_PLAYERLEFT, "Player Left" },
168 { TS2T_NEWPLAYERJOINED, "New Player Joined" },
169 { TS2T_KNOWNPLAYERUPDATE, "Known Player Update" },
170 { TS2T_CHANNELDELETED, "Channel Deleted" },
171 { TS2T_CHANNELNAMECHANGED, "Channel Name Change" },
172 { TS2T_CHANNELTOPICCHANGED, "Channel Topic Change" },
173 { TS2T_CHANNELPASSWORDCHANGED, "Channel Password Change" },
174 { TS2T_CREATECHANNEL, "Create Channel" },
175 { TS2T_DISCONNECT, "Disconnect" },
176 { TS2T_SWITCHCHANNEL, "Switch Channel"},
177 { TS2T_CHANGESTATUS, "Change Status" },
179 { TS2T_CHATMESSAGEBOUNCE, "Chat Message Bounce" },
181 { TS2T_VOICE_DATA_CELP_5_1, "TS2T_VOICE_DATA_CELP_5_1" },
182 { TS2T_VOICE_DATA_CELP_6_3, "TS2T_VOICE_DATA_CELP_6_3" },
183 { TS2T_VOICE_DATA_GSM_14_8, "TS2T_VOICE_DATA_GSM_14_8" },
184 { TS2T_VOICE_DATA_GSM_16_4, "TS2T_VOICE_DATA_GSM_16_4" },
185 { TS2T_VOICE_DATA_CELP_WINDOWS_5_2, "TS2T_VOICE_DATA_CELP_WINDOWS_5_2" },
186 { TS2T_VOICE_DATA_SPEEX_3_4, "TS2T_VOICE_DATA_SPEEX_3_4" },
187 { TS2T_VOICE_DATA_SPEEX_5_2, "TS2T_VOICE_DATA_SPEEX_5_2" },
188 { TS2T_VOICE_DATA_SPEEX_7_2, "TS2T_VOICE_DATA_SPEEX_7_2" },
189 { TS2T_VOICE_DATA_SPEEX_9_3, "TS2T_VOICE_DATA_SPEEX_9_3" },
190 { TS2T_VOICE_DATA_SPEEX_12_3, "TS2T_VOICE_DATA_SPEEX_12_3" },
191 { TS2T_VOICE_DATA_SPEEX_16_3, "TS2T_VOICE_DATA_SPEEX_16_3" },
192 { TS2T_VOICE_DATA_SPEEX_19_5, "TS2T_VOICE_DATA_SPEEX_19_5" },
193 { TS2T_VOICE_DATA_SPEEX_25_9, "TS2T_VOICE_DATA_SPEEX_25_9" },
195 { 0, NULL }
198 /* Codec Names */
199 static const value_string codecnames[] =
201 { TS2T_CODEC_CELP_5_1, "CELP 5.1" },
202 { TS2T_CODEC_CELP_6_3, "CELP 6.3" },
203 { TS2T_CODEC_GSM_14_8, "GSM 14.8" },
204 { TS2T_CODEC_GSM_16_4, "GSM 16.4" },
205 { TS2T_CODEC_CELP_WINDOWS_5_2, "CELP Windows 5.2" },
206 { TS2T_CODEC_SPEEX_3_4, "Speex 3.4" },
207 { TS2T_CODEC_SPEEX_5_2, "Speex 5.2" },
208 { TS2T_CODEC_SPEEX_7_2, "Speex 7.2" },
209 { TS2T_CODEC_SPEEX_9_3, "Speex 9.3" },
210 { TS2T_CODEC_SPEEX_12_3, "Speex 12.3" },
211 { TS2T_CODEC_SPEEX_16_3, "Speex 16.3" },
212 { TS2T_CODEC_SPEEX_19_5, "Speex 19.5" },
213 { TS2T_CODEC_SPEEX_25_9, "Speex 25.9" },
214 { 0, NULL }
217 #define TS2_PORT 8767 /* Not IANA registered */
219 static int proto_ts2;
221 static int hf_ts2_type;
222 static int hf_ts2_class;
223 static int hf_ts2_clientid;
224 static int hf_ts2_sessionkey;
225 static int hf_ts2_crc32;
226 static int hf_ts2_crc32_status;
227 static int hf_ts2_ackto;
228 static int hf_ts2_seqnum;
229 static int hf_ts2_protocol_string;
230 /* static int hf_ts2_string; */
231 static int hf_ts2_registeredlogin;
232 static int hf_ts2_name;
233 static int hf_ts2_password;
234 static int hf_ts2_nick;
235 static int hf_ts2_badlogin;
236 static int hf_ts2_unknown;
237 static int hf_ts2_channel;
238 static int hf_ts2_subchannel;
239 static int hf_ts2_channelpassword;
240 static int hf_ts2_emptyspace;
241 static int hf_ts2_fragmentnumber;
242 static int hf_ts2_platform_string;
243 static int hf_ts2_server_name;
244 static int hf_ts2_server_welcome_message;
245 static int hf_ts2_parent_channel_id;
246 static int hf_ts2_codec;
247 static int hf_ts2_channel_flags;
248 static int hf_ts2_channel_id;
249 static int hf_ts2_channel_name;
250 static int hf_ts2_channel_topic;
251 static int hf_ts2_channel_description;
252 static int hf_ts2_player_id;
253 static int hf_ts2_player_status_flags;
254 static int hf_ts2_number_of_players;
255 static int hf_ts2_number_of_channels;
256 static int hf_ts2_resend_count;
257 static int hf_ts2_status_channelcommander;
258 static int hf_ts2_status_blockwhispers;
259 static int hf_ts2_status_away;
260 static int hf_ts2_status_mutemicrophone;
261 static int hf_ts2_status_mute;
262 static int hf_ts2_channel_unregistered;
263 static int hf_ts2_channel_moderated;
264 static int hf_ts2_channel_password;
265 static int hf_ts2_channel_subchannels;
266 static int hf_ts2_channel_default;
267 static int hf_ts2_channel_order;
268 static int hf_ts2_max_users;
270 static int ett_ts2;
271 static int ett_ts2_channel_flags;
273 /* Conversation Variables */
274 typedef struct
276 uint32_t last_inorder_server_frame;
277 uint32_t last_inorder_client_frame;
278 address server_addr;
279 uint32_t server_port;
280 uint32_t server_frag_size;
281 uint32_t server_frag_num;
282 uint32_t client_frag_size;
283 uint32_t client_frag_num;
285 } ts2_conversation;
287 /* Packet Variables */
288 typedef struct
290 uint32_t frag_num;
291 uint32_t frag_size;
292 bool fragmented;
293 bool outoforder;
294 } ts2_frag;
296 #define my_init_count 5
298 static reassembly_table msg_reassembly_table;
300 /* forward reference */
301 static void ts2_add_checked_crc32(proto_tree *tree, int hf_item, int hf_item_status, expert_field* ei_item, tvbuff_t *tvb, packet_info *pinfo, uint16_t offset);
302 static void ts2_parse_playerlist(tvbuff_t *tvb, proto_tree *ts2_tree);
303 static void ts2_parse_channellist(tvbuff_t *tvb, proto_tree *ts2_tree, wmem_allocator_t *pool);
304 static void ts2_parse_newplayerjoined(tvbuff_t *tvb, proto_tree *ts2_tree);
305 static void ts2_parse_knownplayerupdate(tvbuff_t *tvb, proto_tree *ts2_tree);
306 static void ts2_parse_playerleft(tvbuff_t *tvb, proto_tree *ts2_tree);
307 static void ts2_parse_loginend(tvbuff_t *tvb, proto_tree *ts2_tree);
308 static void ts2_parse_changestatus(tvbuff_t *tvb, proto_tree *ts2_tree);
309 static void ts2_parse_switchchannel(tvbuff_t *tvb, proto_tree *ts2_tree);
310 static void ts2_add_statusflags(tvbuff_t *tvb, proto_tree *ts2_tree, uint32_t offset);
311 static void ts2_parse_channelchange(tvbuff_t *tvb, proto_tree *ts2_tree);
312 static void ts2_parse_loginpart2(tvbuff_t *tvb, proto_tree *ts2_tree);
315 * Check if a packet is in order and if it is set its fragmentation details into the passed pointers.
316 * Returns true if the packet is fragmented.
317 * Must be run sequentially
318 * */
319 static bool ts2_standard_find_fragments(tvbuff_t *tvb, uint32_t *last_inorder_frame, uint32_t *frag_size, uint32_t *frag_num, bool *outoforder)
321 uint32_t frag_count;
322 bool ret;
323 frag_count=tvb_get_letohs(tvb, 18);
324 ret=false;
325 *outoforder=false;
327 /* if last_inorder_frame is zero, then this is the first reliable packet */
328 if(*last_inorder_frame==0)
330 *last_inorder_frame=tvb_get_letohl(tvb, 12);
331 *frag_size=tvb_get_letohs(tvb, 18);
332 *frag_num=0;
333 if(*frag_size>0)
334 ret=true;
335 else
336 ret=false;
338 /* This packet is in order */
339 else if(*last_inorder_frame==tvb_get_letohl(tvb, 12)-1)
341 if(*frag_size>0)
343 *frag_num=*frag_size-frag_count;
344 if(frag_count==0)
346 *frag_size=0;
348 ret=true;
350 else
352 *frag_size=tvb_get_letohs(tvb, 18);
353 *frag_num=*frag_size-frag_count;
354 if(*frag_size>0)
355 ret=true;
356 else
357 ret=false;
359 *last_inorder_frame=tvb_get_letohl(tvb, 12);
361 else /* out of order */
362 *outoforder=true;
363 return ret;
369 * Dissect a standard (reliable) ts2 packet, reassembling if required.
371 static void ts2_standard_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ts2_tree, ts2_conversation *conversation_data)
373 uint8_t save_fragmented;
374 tvbuff_t *new_tvb, *next_tvb;
375 fragment_head *frag_msg ;
376 uint16_t fragment_number;
377 ts2_frag *frag;
378 bool outoforder;
380 uint16_t type = tvb_get_letohs(tvb, 2);
381 /*uint16_t klass = tvb_get_letohs(tvb, 0);*/
382 proto_tree_add_item(ts2_tree, hf_ts2_seqnum, tvb, 12, 4, ENC_LITTLE_ENDIAN);
384 /* XXX: Following fragmentation stuff should be separate from the GUI stuff ?? */
385 /* Get our stored fragmentation data or create one! */
386 if ( ! ( frag = (ts2_frag *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ts2, 0) ) ) {
387 frag = wmem_new(wmem_file_scope(), ts2_frag);
388 frag->frag_num=0;
391 /* decide if the packet is server to client or client to server
392 * then check its fragmentation
394 if(!(pinfo->fd->visited))
396 if(conversation_data->server_port == pinfo->srcport)
398 frag->fragmented = ts2_standard_find_fragments(tvb, &conversation_data->last_inorder_server_frame, &conversation_data->server_frag_size, &conversation_data->server_frag_num, &outoforder);
399 frag->frag_num=conversation_data->server_frag_num;
400 frag->frag_size=conversation_data->server_frag_size;
402 else
405 frag->fragmented = ts2_standard_find_fragments(tvb, &conversation_data->last_inorder_client_frame, &conversation_data->client_frag_size, &conversation_data->client_frag_num, &outoforder);
406 frag->frag_num=conversation_data->client_frag_num;
407 frag->frag_size=conversation_data->client_frag_size;
409 frag->outoforder=outoforder;
410 p_add_proto_data(wmem_file_scope(), pinfo, proto_ts2, 0, frag);
413 /* Get our stored fragmentation data */
414 frag = (ts2_frag *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ts2, 0);
416 proto_tree_add_item(ts2_tree, hf_ts2_resend_count, tvb, 16, 2, ENC_LITTLE_ENDIAN);
417 proto_tree_add_item(ts2_tree, hf_ts2_fragmentnumber, tvb, 18, 2, ENC_LITTLE_ENDIAN);
418 ts2_add_checked_crc32(ts2_tree, hf_ts2_crc32, hf_ts2_crc32_status, &ei_ts2_crc32, tvb, pinfo, 20);
420 /* Reassemble the packet if it's fragmented */
421 new_tvb = NULL;
422 if(frag && frag->fragmented)
424 save_fragmented = pinfo->fragmented;
425 frag_msg = NULL;
426 pinfo->fragmented = true;
427 fragment_number = tvb_get_letohs(tvb, 18);
428 frag_msg = fragment_add_seq_check(&msg_reassembly_table, tvb, 24, pinfo, type, NULL, frag->frag_num, tvb_captured_length_remaining(tvb, 24), fragment_number);
429 new_tvb = process_reassembled_data(tvb, 24, pinfo,"Reassembled TeamSpeak2", frag_msg, &msg_frag_items, NULL, ts2_tree);
430 if (frag_msg) /* XXX: should be if (new_tvb) ?? */
431 { /* Reassembled */
432 col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)");
434 else
435 { /* Not last packet of reassembled Short Message */
436 col_append_fstr(pinfo->cinfo, COL_INFO," (Message fragment %u)", frag->frag_num);
438 if (new_tvb)
439 next_tvb = new_tvb;
440 else
441 next_tvb = tvb_new_subset_remaining(tvb, 24);
442 pinfo->fragmented = save_fragmented;
444 else
445 next_tvb = tvb_new_subset_remaining(tvb, 24);
447 /* If we have a full packet now dissect it */
448 if((new_tvb || (frag && !frag->fragmented)) && !frag->outoforder)
450 switch(type)
452 case TS2T_LOGINPART2:
453 ts2_parse_loginpart2(next_tvb, ts2_tree);
454 break;
455 case TS2T_CHANNELLIST:
456 ts2_parse_channellist(next_tvb, ts2_tree, pinfo->pool);
457 break;
458 case TS2T_PLAYERLIST:
459 ts2_parse_playerlist(next_tvb, ts2_tree);
460 break;
461 case TS2T_NEWPLAYERJOINED:
462 ts2_parse_newplayerjoined(next_tvb, ts2_tree);
463 break;
464 case TS2T_KNOWNPLAYERUPDATE:
465 ts2_parse_knownplayerupdate(next_tvb, ts2_tree);
466 break;
467 case TS2T_PLAYERLEFT:
468 ts2_parse_playerleft(next_tvb, ts2_tree);
469 break;
470 case TS2T_PLAYERKICKED:
471 ts2_parse_playerleft(next_tvb, ts2_tree);
472 break;
473 case TS2T_LOGINEND:
474 ts2_parse_loginend(next_tvb, ts2_tree);
475 break;
476 case TS2T_CHANGESTATUS:
477 ts2_parse_changestatus(next_tvb, ts2_tree);
478 break;
479 case TS2T_SWITCHCHANNEL:
480 ts2_parse_switchchannel(next_tvb, ts2_tree);
481 break;
482 case TS2T_CHANNELCHANGE:
483 ts2_parse_channelchange(next_tvb, ts2_tree);
484 break;
487 /* The packet is out of order, update the cinfo and ignore the packet */
488 if(frag && frag->outoforder)
489 col_append_str(pinfo->cinfo, COL_INFO, " (Out Of Order, ignored)");
493 /* Parses a ts2 new player joined (TS2_NEWPLAYERJOINED) packet and adds it to the tree */
494 static void ts2_parse_newplayerjoined(tvbuff_t *tvb, proto_tree *ts2_tree)
496 int32_t offset;
497 offset=0;
498 proto_tree_add_item(ts2_tree, hf_ts2_player_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
499 offset+=4;
500 proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
501 offset+=4;
502 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 6, ENC_NA);
503 offset+=6;
504 proto_tree_add_item(ts2_tree, hf_ts2_nick, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN);
507 /* Parses TS2_LOGINEND packet and adds it to the tree */
508 static void ts2_parse_loginend(tvbuff_t *tvb, proto_tree *ts2_tree)
510 int32_t offset;
511 offset=0;
512 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA);
515 /* Parses a ts2 known player joined (TS2_KNOWNPLAYERUPDATE) packet and adds it to the tree */
516 static void ts2_parse_knownplayerupdate(tvbuff_t *tvb, proto_tree *ts2_tree)
518 int32_t offset;
519 offset=0;
520 proto_tree_add_item(ts2_tree, hf_ts2_player_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
521 offset+=4;
522 proto_tree_add_item(ts2_tree, hf_ts2_player_status_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN);
523 ts2_add_statusflags(tvb, ts2_tree, offset);
526 /* Parses a ts2 switch channel (TS2_SWITCHCHANNEL) packet and adds it to the tree */
527 static void ts2_parse_switchchannel(tvbuff_t *tvb, proto_tree *ts2_tree)
529 int32_t offset;
530 offset=0;
531 proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
532 offset+=4;
533 proto_tree_add_item(ts2_tree, hf_ts2_password, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN);
536 /* Parses a ts2 channel change (TS2T_CHANNELCHANGE) packet and adds it to the tree */
537 static void ts2_parse_channelchange(tvbuff_t *tvb, proto_tree *ts2_tree)
539 int32_t offset;
540 offset=0;
541 proto_tree_add_item(ts2_tree, hf_ts2_player_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
542 offset+=4;
543 proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
544 offset+=4;
545 proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
546 offset+=4;
547 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 2, ENC_NA);
551 /* Parses a ts2 change status (TS2_CHANGESTATUS) packet and adds it to the tree */
552 static void ts2_parse_changestatus(tvbuff_t *tvb, proto_tree *ts2_tree)
554 int32_t offset;
555 offset=0;
556 proto_tree_add_item(ts2_tree, hf_ts2_player_status_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN);
557 ts2_add_statusflags(tvb, ts2_tree, offset);
561 /* Parses a ts2 known player left (TS2_PLAYERLEFT) packet and adds it to the tree */
562 static void ts2_parse_playerleft(tvbuff_t *tvb, proto_tree *ts2_tree)
564 int32_t offset;
565 offset=0;
566 proto_tree_add_item(ts2_tree, hf_ts2_player_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
567 offset+=4;
568 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 4, ENC_NA);
569 offset+=4;
570 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 4, ENC_NA);
571 offset+=4;
572 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA);
575 /* Parses a ts2 login part 2 (TS2T_LOGINPART2) packet and adds it to the tree */
576 static void ts2_parse_loginpart2(tvbuff_t *tvb, proto_tree *ts2_tree)
578 int32_t offset;
579 offset=0;
580 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 0, 2, ENC_NA);
581 offset+=2;
582 proto_tree_add_item(ts2_tree, hf_ts2_channel, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN);
583 offset+=30;
584 proto_tree_add_item(ts2_tree, hf_ts2_subchannel, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN);
585 offset+=30;
586 proto_tree_add_item(ts2_tree, hf_ts2_channelpassword, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN);
587 offset+=30;
588 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 4, ENC_NA);
591 /* Parses a ts2 channel list (TS2T_CHANNELLIST) and adds it to the tree */
592 static void ts2_parse_channellist(tvbuff_t *tvb, proto_tree *ts2_tree, wmem_allocator_t *pool)
594 int32_t offset;
595 uint32_t string_len;
596 proto_tree *subtree;
597 proto_item *item;
599 offset=0;
600 proto_tree_add_item(ts2_tree, hf_ts2_number_of_channels, tvb, offset, 4, ENC_LITTLE_ENDIAN);
601 offset+=4;
602 while(offset<tvb_reported_length_remaining(tvb, 0))
604 proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
605 offset+=4;
607 /* Channel flags */
608 item = proto_tree_add_item(ts2_tree, hf_ts2_channel_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
609 subtree = proto_item_add_subtree(item, ett_ts2_channel_flags);
610 proto_tree_add_item(subtree, hf_ts2_channel_unregistered, tvb, offset, 1, ENC_BIG_ENDIAN);
611 proto_tree_add_item(subtree, hf_ts2_channel_moderated, tvb, offset, 1, ENC_BIG_ENDIAN);
612 proto_tree_add_item(subtree, hf_ts2_channel_password, tvb, offset, 1, ENC_BIG_ENDIAN);
613 proto_tree_add_item(subtree, hf_ts2_channel_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN);
614 proto_tree_add_item(subtree, hf_ts2_channel_default, tvb, offset, 1, ENC_BIG_ENDIAN);
615 offset+=1;
617 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 1, ENC_NA);
618 offset+=1;
619 proto_tree_add_item(ts2_tree, hf_ts2_codec, tvb, offset, 2, ENC_LITTLE_ENDIAN);
620 offset+=2;
621 proto_tree_add_item(ts2_tree, hf_ts2_parent_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
622 offset+=4;
623 proto_tree_add_item(ts2_tree, hf_ts2_channel_order, tvb, offset, 2, ENC_LITTLE_ENDIAN);
624 offset+=2;
625 proto_tree_add_item(ts2_tree, hf_ts2_max_users, tvb, offset, 2, ENC_LITTLE_ENDIAN);
626 offset+=2;
627 tvb_get_stringz_enc(pool, tvb, offset, &string_len, ENC_ASCII);
628 proto_tree_add_item(ts2_tree, hf_ts2_channel_name, tvb, offset, string_len, ENC_ASCII);
629 offset+=string_len;
630 tvb_get_stringz_enc(pool, tvb, offset, &string_len, ENC_ASCII);
631 proto_tree_add_item(ts2_tree, hf_ts2_channel_topic, tvb, offset, string_len, ENC_ASCII);
632 offset+=string_len;
633 tvb_get_stringz_enc(pool, tvb, offset, &string_len, ENC_ASCII);
634 proto_tree_add_item(ts2_tree, hf_ts2_channel_description, tvb, offset, string_len, ENC_ASCII);
635 offset+=string_len;
639 static void ts2_add_statusflags(tvbuff_t *tvb, proto_tree *ts2_tree, uint32_t offset)
641 proto_tree_add_item(ts2_tree, hf_ts2_status_channelcommander, tvb, offset, 2, ENC_LITTLE_ENDIAN);
642 proto_tree_add_item(ts2_tree, hf_ts2_status_blockwhispers, tvb, offset, 2, ENC_LITTLE_ENDIAN);
643 proto_tree_add_item(ts2_tree, hf_ts2_status_away, tvb, offset, 2, ENC_LITTLE_ENDIAN);
644 proto_tree_add_item(ts2_tree, hf_ts2_status_mutemicrophone, tvb, offset, 2, ENC_LITTLE_ENDIAN);
645 proto_tree_add_item(ts2_tree, hf_ts2_status_mute, tvb, offset, 2, ENC_LITTLE_ENDIAN);
649 /* Parses a ts2 player list (TS2T_PLAYERLIST) and adds it to the tree */
650 static void ts2_parse_playerlist(tvbuff_t *tvb, proto_tree *ts2_tree)
652 int32_t offset;
653 int32_t number_of_players;
654 int32_t x;
655 offset=0;
656 x=0;
657 proto_tree_add_item(ts2_tree, hf_ts2_number_of_players, tvb, offset, 4, ENC_LITTLE_ENDIAN);
658 number_of_players = tvb_get_letohl(tvb, 0);
659 offset+=4;
660 while(offset<tvb_reported_length_remaining(tvb, 0) && x<number_of_players)
662 proto_tree_add_item(ts2_tree, hf_ts2_player_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
663 offset+=4;
664 proto_tree_add_item(ts2_tree, hf_ts2_channel_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
665 offset+=4;
666 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, offset, 4, ENC_NA);
667 offset+=4;
668 proto_tree_add_item(ts2_tree, hf_ts2_player_status_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN);
669 ts2_add_statusflags(tvb, ts2_tree, offset);
670 offset+=2;
671 proto_tree_add_item(ts2_tree, hf_ts2_nick, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN);
672 offset+=30;
673 x++;
675 proto_tree_add_item(ts2_tree, hf_ts2_emptyspace, tvb, offset, tvb_captured_length_remaining(tvb, 0), ENC_NA);
680 /* Find the current conversation or make a new one if required */
681 static ts2_conversation* ts2_get_conversation(packet_info *pinfo)
683 conversation_t *conversation;
684 ts2_conversation *conversation_data;
685 conversation = find_or_create_conversation(pinfo);
687 conversation_data = (ts2_conversation*)conversation_get_proto_data(conversation, proto_ts2);
689 if (conversation_data == NULL)
691 conversation_data = wmem_new(wmem_file_scope(), ts2_conversation);
692 conversation_data->last_inorder_server_frame=0; /* sequence number should never be zero so we can use this as an initial number */
693 conversation_data->last_inorder_client_frame=0;
694 conversation_data->server_port=pinfo->srcport;
695 conversation_data->server_frag_size=0;
696 conversation_data->server_frag_num=0;
697 conversation_data->client_frag_size=0;
698 conversation_data->client_frag_num=0;
700 conversation_add_proto_data(conversation, proto_ts2, (void *)conversation_data);
702 return conversation_data;
707 /* Dissect a TS2 packet */
708 static int dissect_ts2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
710 ts2_conversation *conversation_data;
711 uint16_t type = tvb_get_letohs(tvb, 2);
712 uint16_t klass = tvb_get_letohs(tvb, 0);
714 conversation_data = ts2_get_conversation(pinfo);
716 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TS2");
718 if(klass==TS2C_ACK)
719 col_add_fstr(pinfo->cinfo, COL_INFO, "Class: %s", val_to_str(klass, classnames, "Unknown (0x%02x)"));
720 else
721 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)"));
723 /* XXX: We need to do all the non GUI stuff whether or not if(tree) */
724 /* Do only once by checking visited ? */
725 /* ToDo: Rewrite ?? */
726 if (!tree) {
727 switch(klass) {
728 case TS2C_CONNECTION:
729 switch(type) {
730 case TS2T_LOGINREQUEST:
731 conversation_data->server_port=pinfo->destport;
732 copy_address_shallow(&conversation_data->server_addr, &pinfo->dst);
733 break;
735 break;
736 case TS2C_STANDARD:
737 ts2_standard_dissect(tvb, pinfo, tree, conversation_data);
738 break;
742 if (tree) { /* we are being asked for details */
743 proto_item *ti = NULL;
744 proto_tree *ts2_tree = NULL;
746 ti = proto_tree_add_item(tree, proto_ts2, tvb, 0, -1, ENC_NA);
747 ts2_tree = proto_item_add_subtree(ti, ett_ts2);
749 proto_tree_add_item(ts2_tree, hf_ts2_class, tvb, 0, 2, ENC_LITTLE_ENDIAN);
750 if(klass==TS2C_ACK)
751 proto_tree_add_item(ts2_tree, hf_ts2_resend_count, tvb, 2, 2, ENC_LITTLE_ENDIAN);
752 else
753 proto_tree_add_item(ts2_tree, hf_ts2_type, tvb, 2, 2, ENC_LITTLE_ENDIAN);
755 proto_tree_add_item(ts2_tree, hf_ts2_sessionkey, tvb, 4, 4, ENC_LITTLE_ENDIAN);
756 proto_tree_add_item(ts2_tree, hf_ts2_clientid, tvb, 8, 4, ENC_LITTLE_ENDIAN);
757 switch(klass)
759 case TS2C_CONNECTION:
760 proto_tree_add_item(ts2_tree, hf_ts2_seqnum, tvb, 12, 4, ENC_LITTLE_ENDIAN);
761 ts2_add_checked_crc32(ts2_tree, hf_ts2_crc32, hf_ts2_crc32_status, &ei_ts2_crc32, tvb, pinfo, 16);
763 switch(type)
765 case TS2T_PING:
766 break;
767 case TS2T_PINGREPLY:
768 proto_tree_add_item(ts2_tree, hf_ts2_ackto, tvb, 20, 4, ENC_LITTLE_ENDIAN);
769 break;
770 case TS2T_LOGINREQUEST:
771 proto_tree_add_item(ts2_tree, hf_ts2_protocol_string, tvb, 20, 1, ENC_ASCII|ENC_BIG_ENDIAN);
772 proto_tree_add_item(ts2_tree, hf_ts2_platform_string, tvb, 50, 1, ENC_ASCII|ENC_BIG_ENDIAN);
773 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 80, 9, ENC_NA);
774 proto_tree_add_item(ts2_tree, hf_ts2_registeredlogin, tvb, 90, 1, ENC_LITTLE_ENDIAN);
775 proto_tree_add_item(ts2_tree, hf_ts2_name, tvb, 90, 1, ENC_ASCII|ENC_BIG_ENDIAN);
776 proto_tree_add_item(ts2_tree, hf_ts2_password, tvb, 120, 1, ENC_ASCII|ENC_BIG_ENDIAN);
777 proto_tree_add_item(ts2_tree, hf_ts2_nick, tvb, 150, 1, ENC_ASCII|ENC_BIG_ENDIAN);
779 conversation_data->server_port=pinfo->destport;
780 copy_address_shallow(&conversation_data->server_addr, &pinfo->dst);
782 break;
783 case TS2T_LOGINREPLY:
784 proto_tree_add_item(ts2_tree, hf_ts2_server_name, tvb, 20, 1, ENC_ASCII|ENC_BIG_ENDIAN);
785 proto_tree_add_item(ts2_tree, hf_ts2_platform_string, tvb, 50, 1, ENC_ASCII|ENC_BIG_ENDIAN);
786 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 80, 9, ENC_NA);
787 proto_tree_add_item(ts2_tree, hf_ts2_badlogin, tvb, 89, 3, ENC_LITTLE_ENDIAN);
788 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 92, 80, ENC_NA);
789 proto_tree_add_item(ts2_tree, hf_ts2_sessionkey, tvb, 172, 4, ENC_LITTLE_ENDIAN);
790 proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 178, 3, ENC_NA);
791 proto_tree_add_item(ts2_tree, hf_ts2_server_welcome_message, tvb, 180, 1, ENC_ASCII|ENC_BIG_ENDIAN);
792 break;
794 break;
795 case TS2C_ACK:
796 /* Ignore the type for ACK, it's always zero and clashes with CELP_5_1 */
798 proto_tree_add_item(ts2_tree, hf_ts2_seqnum, tvb, 12, 4, ENC_LITTLE_ENDIAN);
799 break;
800 case TS2C_STANDARD:
801 ts2_standard_dissect(tvb, pinfo, ts2_tree, conversation_data);
802 break;
804 } /* if (tree) */
805 return tvb_captured_length(tvb);
810 /* 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
811 * Returns true if the calculated CRC32 matches the passed CRC32.
812 * */
813 static void ts2_add_checked_crc32(proto_tree *tree, int hf_item, int hf_item_status, expert_field* ei_item, tvbuff_t *tvb, packet_info *pinfo, uint16_t offset)
815 uint32_t zero = 0;
816 int len = tvb_reported_length_remaining(tvb, offset+4);
817 uint32_t ocrc32;
819 if (len<0)
820 return;
822 ocrc32 = crc32_ccitt_tvb(tvb, offset);
823 ocrc32 = crc32_ccitt_seed((uint8_t*)&zero, 4, 0xffffffff-ocrc32);
824 ocrc32 = crc32_ccitt_tvb_offset_seed(tvb, offset+4, (unsigned)len, 0xffffffff-ocrc32);
826 proto_tree_add_checksum(tree, tvb, offset, hf_item, hf_item_status, ei_item, pinfo, ocrc32, ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
830 * proto_register_ts2()
831 * */
832 void proto_register_ts2(void)
834 static hf_register_info hf[] = {
835 { &hf_ts2_class,
836 { "Class", "ts2.class",
837 FT_UINT16, BASE_HEX,
838 VALS(classnames), 0x0,
839 NULL, HFILL }
841 { &hf_ts2_type,
842 { "Type", "ts2.type",
843 FT_UINT16, BASE_HEX,
844 VALS(typenames), 0x0,
845 NULL, HFILL }
847 { &hf_ts2_clientid,
848 { "Client id", "ts2.clientid",
849 FT_UINT32, BASE_DEC,
850 NULL, 0x0,
851 NULL, HFILL }
853 { &hf_ts2_sessionkey,
854 { "Session Key", "ts2.sessionkey",
855 FT_UINT32, BASE_HEX,
856 NULL, 0x0,
857 NULL, HFILL }
859 { &hf_ts2_ackto,
860 { "Ping Reply To", "ts2.ping_ackto",
861 FT_UINT32, BASE_DEC,
862 NULL, 0x0,
863 NULL, HFILL }
865 { &hf_ts2_crc32,
866 { "CRC32 Checksum", "ts2.crc32",
867 FT_UINT32, BASE_HEX,
868 NULL, 0x0,
869 NULL, HFILL }
871 { &hf_ts2_crc32_status,
872 { "CRC32 Checksum Status", "ts2.crc32.status",
873 FT_UINT8, BASE_NONE,
874 VALS(proto_checksum_vals), 0x0,
875 NULL, HFILL }
877 { &hf_ts2_seqnum,
878 { "Sequence Number", "ts2.sequencenum",
879 FT_UINT32, BASE_DEC,
880 NULL, 0x0,
881 NULL, HFILL }
883 { &hf_ts2_protocol_string,
884 { "Protocol String", "ts2.protocolstring",
885 FT_UINT_STRING, BASE_NONE,
886 NULL, 0x0,
887 NULL, HFILL }
889 #if 0
890 { &hf_ts2_string,
891 { "String", "ts2.string",
892 FT_STRING, BASE_NONE,
893 NULL, 0x0,
894 NULL, HFILL }
896 #endif
897 { &hf_ts2_registeredlogin,
898 { "Registered Login", "ts2.registeredlogin",
899 FT_BOOLEAN, BASE_NONE,
900 NULL, 0x0,
901 NULL, HFILL }
903 { &hf_ts2_name,
904 { "Name", "ts2.name",
905 FT_UINT_STRING, BASE_NONE,
906 NULL, 0x0,
907 NULL, HFILL }
909 { &hf_ts2_password,
910 { "Password", "ts2.password",
911 FT_UINT_STRING, BASE_NONE,
912 NULL, 0x0,
913 NULL, HFILL }
915 { &hf_ts2_nick,
916 { "Nick", "ts2.nick",
917 FT_UINT_STRING, BASE_NONE,
918 NULL, 0x0,
919 NULL, HFILL }
921 { &hf_ts2_badlogin,
922 { "Bad Login", "ts2.badlogin",
923 FT_BOOLEAN, BASE_NONE,
924 NULL, 0x0,
925 NULL, HFILL }
927 { &hf_ts2_unknown,
928 { "Unknown", "ts2.unknown",
929 FT_BYTES, BASE_NONE,
930 NULL, 0x0,
931 NULL, HFILL }
933 { &hf_ts2_channel,
934 { "Channel", "ts2.channel",
935 FT_UINT_STRING, BASE_NONE,
936 NULL, 0x0,
937 NULL, HFILL }
939 { &hf_ts2_subchannel,
940 { "Sub-Channel", "ts2.subchannel",
941 FT_UINT_STRING, BASE_NONE,
942 NULL, 0x0,
943 NULL, HFILL }
945 { &hf_ts2_channelpassword,
946 { "Channel Password", "ts2.channelpassword",
947 FT_UINT_STRING, BASE_NONE,
948 NULL, 0x0,
949 NULL, HFILL }
951 { &hf_ts2_emptyspace,
952 { "Empty Space", "ts2.emptyspace",
953 FT_NONE, BASE_NONE,
954 NULL, 0x0,
955 NULL, HFILL }
957 { &hf_ts2_fragmentnumber,
958 { "Fragment Number", "ts2.fragmentnumber",
959 FT_UINT16, BASE_DEC,
960 NULL, 0x0,
961 NULL, HFILL }
963 { &hf_ts2_platform_string,
964 { "Platform String", "ts2.platformstring",
965 FT_UINT_STRING, BASE_NONE,
966 NULL, 0x0,
967 NULL, HFILL }
969 { &hf_ts2_server_name,
970 { "Server Name", "ts2.servername",
971 FT_UINT_STRING, BASE_NONE,
972 NULL, 0x0,
973 NULL, HFILL }
975 { &hf_ts2_server_welcome_message,
976 { "Server Welcome Message", "ts2.serverwelcomemessage",
977 FT_UINT_STRING, BASE_NONE,
978 NULL, 0x0,
979 NULL, HFILL }
981 { &hf_ts2_parent_channel_id,
982 { "Parent Channel ID", "ts2.parentchannelid",
983 FT_UINT32, BASE_HEX,
984 NULL, 0x0,
985 NULL, HFILL }
987 { &hf_ts2_codec,
988 { "Codec", "ts2.codec",
989 FT_UINT16, BASE_HEX,
990 VALS(codecnames), 0x0,
991 NULL, HFILL }
993 { &hf_ts2_channel_flags,
994 { "Channel Flags", "ts2.channelflags",
995 FT_UINT8, BASE_HEX,
996 NULL, 0x0,
997 NULL, HFILL }
999 { &hf_ts2_channel_id,
1000 { "Channel Id", "ts2.channelid",
1001 FT_UINT32, BASE_DEC,
1002 NULL, 0x0,
1003 NULL, HFILL }
1005 { &hf_ts2_channel_name,
1006 { "Channel Name", "ts2.channelname",
1007 FT_STRINGZ, BASE_NONE,
1008 NULL, 0x0,
1009 NULL, HFILL }
1011 { &hf_ts2_channel_topic,
1012 { "Channel Topic", "ts2.channeltopic",
1013 FT_STRINGZ, BASE_NONE,
1014 NULL, 0x0,
1015 NULL, HFILL }
1017 { &hf_ts2_channel_description,
1018 { "Channel Description", "ts2.channeldescription",
1019 FT_STRINGZ, BASE_NONE,
1020 NULL, 0x0,
1021 NULL, HFILL }
1023 { &hf_ts2_player_id,
1024 { "Player Id", "ts2.playerid",
1025 FT_UINT32, BASE_DEC,
1026 NULL, 0x0,
1027 NULL, HFILL }
1029 { &hf_ts2_player_status_flags,
1030 { "Player Status Flags", "ts2.playerstatusflags",
1031 FT_UINT16, BASE_DEC,
1032 NULL, 0x0,
1033 NULL, HFILL }
1035 { &hf_ts2_number_of_players,
1036 { "Number Of Players", "ts2.numberofplayers",
1037 FT_UINT32, BASE_DEC,
1038 NULL, 0x0,
1039 NULL, HFILL }
1041 { &hf_ts2_number_of_channels,
1042 { "Number Of Channels", "ts2.numberofchannels",
1043 FT_UINT32, BASE_DEC,
1044 NULL, 0x0,
1045 NULL, HFILL }
1047 { &hf_ts2_resend_count,
1048 { "Resend Count", "ts2.resendcount",
1049 FT_UINT16, BASE_DEC,
1050 NULL, 0x0,
1051 NULL, HFILL }
1053 { &hf_ts2_status_channelcommander,
1054 { "Channel Commander", "ts2.playerstatusflags.channelcommander",
1055 FT_BOOLEAN, 8,
1056 NULL, TS2_STATUS_CHANNELCOMMANDER,
1057 NULL, HFILL }
1059 { &hf_ts2_status_blockwhispers,
1060 { "Block Whispers", "ts2.playerstatusflags.blockwhispers",
1061 FT_BOOLEAN, 8,
1062 NULL, TS2_STATUS_BLOCKWHISPERS,
1063 NULL, HFILL }
1065 { &hf_ts2_status_away,
1066 { "Away", "ts2.playerstatusflags.away",
1067 FT_BOOLEAN, 8,
1068 NULL, TS2_STATUS_AWAY,
1069 NULL, HFILL }
1071 { &hf_ts2_status_mutemicrophone,
1072 { "Mute Microphone", "ts2.playerstatusflags.mutemicrophone",
1073 FT_BOOLEAN, 8,
1074 NULL, TS2_STATUS_MUTEMICROPHONE,
1075 NULL, HFILL }
1077 { &hf_ts2_status_mute,
1078 { "Mute", "ts2.playerstatusflags.mute",
1079 FT_BOOLEAN, 8,
1080 NULL, TS2_STATUS_MUTE,
1081 NULL, HFILL }
1083 { &hf_msg_fragments,
1084 {"Message fragments", "ts2.fragments",
1085 FT_NONE, BASE_NONE,
1086 NULL, 0x00,
1087 NULL, HFILL }
1089 { &hf_msg_fragment,
1090 {"Message fragment", "ts2.fragment",
1091 FT_FRAMENUM, BASE_NONE,
1092 NULL, 0x00,
1093 NULL, HFILL }
1095 { &hf_msg_fragment_overlap,
1096 {"Message fragment overlap", "ts2.fragment.overlap",
1097 FT_BOOLEAN, BASE_NONE,
1098 NULL, 0x0,
1099 NULL, HFILL }
1101 { &hf_msg_fragment_overlap_conflicts,
1102 {"Message fragment overlapping with conflicting data",
1103 "ts2.fragment.overlap.conflicts",
1104 FT_BOOLEAN, BASE_NONE,
1105 NULL, 0x0,
1106 NULL, HFILL }
1108 { &hf_msg_fragment_multiple_tails,
1109 {"Message has multiple tail fragments",
1110 "ts2.fragment.multiple_tails",
1111 FT_BOOLEAN, BASE_NONE,
1112 NULL, 0x0,
1113 NULL, HFILL }
1115 { &hf_msg_fragment_too_long_fragment,
1116 {"Message fragment too long", "ts2.fragment.too_long_fragment",
1117 FT_BOOLEAN, BASE_NONE,
1118 NULL, 0x0,
1119 NULL, HFILL }
1121 { &hf_msg_fragment_error,
1122 {"Message defragmentation error", "ts2.fragment.error",
1123 FT_FRAMENUM, BASE_NONE,
1124 NULL, 0x00,
1125 NULL, HFILL }
1127 { &hf_msg_fragment_count,
1128 {"Message fragment count", "ts2.fragment.count",
1129 FT_UINT32, BASE_DEC,
1130 NULL, 0x00,
1131 NULL, HFILL }
1133 { &hf_msg_reassembled_in,
1134 {"Reassembled in", "ts2.reassembled.in",
1135 FT_FRAMENUM, BASE_NONE,
1136 NULL, 0x00,
1137 NULL, HFILL }
1139 { &hf_msg_reassembled_length,
1140 {"Reassembled TeamSpeak2 length", "ts2.reassembled.length",
1141 FT_UINT32, BASE_DEC,
1142 NULL, 0x00,
1143 NULL, HFILL }
1145 { &hf_ts2_channel_unregistered,
1146 { "Unregistered", "ts2.channelflags.unregistered",
1147 FT_BOOLEAN, 8,
1148 NULL, 0x01,
1149 NULL, HFILL }
1151 { &hf_ts2_channel_moderated,
1152 { "Moderated", "ts2.channelflags.moderated",
1153 FT_BOOLEAN, 8,
1154 NULL, 0x02,
1155 NULL, HFILL }
1157 { &hf_ts2_channel_password,
1158 { "Has password", "ts2.channelflags.has_password",
1159 FT_BOOLEAN, 8,
1160 NULL, 0x04,
1161 NULL, HFILL }
1163 { &hf_ts2_channel_subchannels,
1164 { "Has subchannels", "ts2.channelflags.has_subchannels",
1165 FT_BOOLEAN, 8,
1166 NULL, 0x08,
1167 NULL, HFILL }
1169 { &hf_ts2_channel_default,
1170 { "Default", "ts2.channelflags.default",
1171 FT_BOOLEAN, 8,
1172 NULL, 0x10,
1173 NULL, HFILL }
1175 { &hf_ts2_channel_order,
1176 { "Channel order", "ts2.channelorder",
1177 FT_UINT16, BASE_DEC,
1178 NULL, 0x00,
1179 NULL, HFILL }
1181 { &hf_ts2_max_users,
1182 { "Max users", "ts2.maxusers",
1183 FT_UINT16, BASE_DEC,
1184 NULL, 0x00,
1185 NULL, HFILL }
1189 static int *ett[] = {
1190 &ett_ts2,
1191 &ett_msg_fragment,
1192 &ett_msg_fragments,
1193 &ett_ts2_channel_flags
1196 static ei_register_info ei[] = {
1197 { &ei_ts2_crc32, { "ts2.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
1200 expert_module_t* expert_ts2;
1202 /* Setup protocol subtree array */
1203 proto_ts2 = proto_register_protocol ("Teamspeak2 Protocol", "TeamSpeak2", "ts2");
1204 proto_register_field_array(proto_ts2, hf, array_length(hf));
1205 proto_register_subtree_array(ett, array_length(ett));
1206 ts2_handle = register_dissector("ts2", dissect_ts2, proto_ts2);
1207 expert_ts2 = expert_register_protocol(proto_ts2);
1208 expert_register_field_array(expert_ts2, ei, array_length(ei));
1210 reassembly_table_register(&msg_reassembly_table,
1211 &addresses_reassembly_table_functions);
1215 * proto_reg_handoff_ts2()
1216 * */
1217 void proto_reg_handoff_ts2(void)
1219 dissector_add_uint_with_preference("udp.port", TS2_PORT, ts2_handle);
1223 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1225 * Local variables:
1226 * c-basic-offset: 4
1227 * tab-width: 8
1228 * indent-tabs-mode: nil
1229 * End:
1231 * vi: set shiftwidth=4 tabstop=8 expandtab:
1232 * :indentSize=4:tabSize=8:noTabs=true: