HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-sametime.c
blobdba4821a0e56d00a4347f5b2dfa2dd7b556d1feb
1 /* packet-sametime.c
2 * Routines for SAMETIME dissection
3 * Copyright 2010, Toralf Foerster <toralf.foerster [AT] gmx.de>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <epan/packet.h>
29 #include <epan/wmem/wmem.h>
30 #include <epan/dissectors/packet-tcp.h>
31 #include <epan/prefs.h>
32 #include <epan/tap.h>
33 #include <epan/stats_tree.h>
35 #define DEFAULT_SAMETIME_PORT 1533
37 static int proto_sametime = -1;
38 static guint global_sametime_port = DEFAULT_SAMETIME_PORT;
39 static dissector_handle_t sametime_handle;
41 /*preferences*/
42 static gboolean global_sametime_show_length = FALSE;
43 static gboolean global_sametime_reassemble_packets = TRUE;
45 /*heart beat*/
46 static int hf_sametime_heartbeat = -1;
48 /*sametime message header*/
49 static int hf_sametime_message_length = -1;
50 static int hf_sametime_message_type = -1;
51 static int hf_sametime_message_options = -1;
52 static int hf_sametime_message_options_attribute = -1;
53 static int hf_sametime_message_options_encrypted = -1;
54 static int hf_sametime_message_channel = -1;
56 /*common types*/
57 static int hf_sametime_field_length = -1;
58 static int hf_sametime_field_text = -1;
59 static int hf_sametime_code = -1;
60 static int hf_sametime_login_type = -1;
61 static int hf_sametime_time = -1;
63 /*handshake*/
64 static int hf_sametime_handshake_major = -1;
65 static int hf_sametime_handshake_minor = -1;
66 static int hf_sametime_handshake_srvrcalc_addr = -1;
67 static int hf_sametime_handshake_loclcalc_addr = -1;
69 /*channel*/
70 static int hf_sametime_channel_service = -1;
71 static int hf_sametime_channel_id = -1;
72 static int hf_sametime_channel_send_type = -1;
73 static int hf_sametime_channel_awareness = -1;
75 /*user status*/
76 static int hf_sametime_user_status = -1;
78 /*location*/
79 static int hf_sametime_location_country = -1;
80 static int hf_sametime_location_postalcode = -1;
81 static int hf_sametime_location_province = -1;
82 static int hf_sametime_location_city = -1;
83 static int hf_sametime_location_phone = -1;
84 static int hf_sametime_location_name = -1;
85 static int hf_sametime_location_timezone = -1;
87 /*packet detail tree*/
88 static gint ett_sametime = -1;
89 static gint ett_sametime_options = -1;
91 /*statistics*/
92 static int sametime_tap = -1;
93 static const guint8* st_str_packet = "Sametime Message Count";
94 static const guint8* st_str_message_type = "Message Type";
95 static const guint8* st_str_send_type = "Send Type";
96 static const guint8* st_str_user_status = "User Status";
97 static int st_node_packet = -1;
98 static int st_node_message_type = -1;
99 static int st_node_send_type = -1;
100 static int st_node_user_status = -1;
102 typedef struct SametimeTap {
103 gint message_type;
104 gint send_type;
105 gint user_status;
106 } SametimeTap;
108 #define SAMETIME_MESSAGETYPE_HEARTBEAT 0x80
109 #define SAMETIME_MESSAGETYPE_HANDSHAKE 0x0000
111 #define SAMETIME_MESSAGETYPE_HANDSHAKE_ACK 0x8000
112 #define SAMETIME_MESSAGETYPE_HANDSHAKE_SYN 0x0025
113 #define SAMETIME_MESSAGETYPE_LOGIN 0x0001
114 #define SAMETIME_MESSAGETYPE_LOGIN_ACK 0x8001
115 #define SAMETIME_MESSAGETYPE_LOGIN_REDIRECT 0x0018
116 #define SAMETIME_MESSAGETYPE_LOGIN_CONTINUE 0x0016
118 #define SAMETIME_MESSAGETYPE_CHANNEL_CREATE 0x0002
119 #define SAMETIME_MESSAGETYPE_CHANNEL_DESTROY 0x0003
120 #define SAMETIME_MESSAGETYPE_CHANNEL_SEND 0x0004
121 #define SAMETIME_MESSAGETYPE_CHANNEL_ACCEPT 0x0006
123 #define SAMETIME_MESSAGETYPE_SET_USER_STATUS 0x0009
124 #define SAMETIME_MESSAGETYPE_SET_PRIVACY_LIST 0x000b
125 #define SAMETIME_MESSAGETYPE_SENSE_SERVICE 0x0011
126 #define SAMETIME_MESSAGETYPE_ADMIN 0x0019
127 #define SAMETIME_MESSAGETYPE_ANNOUNCE 0x0022
130 static const value_string messagetypenames[] = {
131 { SAMETIME_MESSAGETYPE_HEARTBEAT, "HEARTBEAT" },
133 { SAMETIME_MESSAGETYPE_HANDSHAKE, "HANDSHAKE" },
134 { SAMETIME_MESSAGETYPE_HANDSHAKE_SYN, "HANDSHAKE_SYN" },
135 { SAMETIME_MESSAGETYPE_HANDSHAKE_ACK, "HANDSHAKE_ACK" },
136 { SAMETIME_MESSAGETYPE_LOGIN, "LOGIN" },
137 { SAMETIME_MESSAGETYPE_LOGIN_ACK, "LOGIN_ACK" },
138 { SAMETIME_MESSAGETYPE_LOGIN_REDIRECT, "LOGIN_REDIRECT" },
139 { SAMETIME_MESSAGETYPE_LOGIN_CONTINUE, "LOGIN_CONTINUE" },
141 { SAMETIME_MESSAGETYPE_CHANNEL_CREATE, "CHANNEL_CREATE" },
142 { SAMETIME_MESSAGETYPE_CHANNEL_DESTROY, "CHANNEL_DESTROY" },
143 { SAMETIME_MESSAGETYPE_CHANNEL_SEND, "CHANNEL_SEND" },
144 { SAMETIME_MESSAGETYPE_CHANNEL_ACCEPT, "CHANNEL_ACCEPT" },
146 { SAMETIME_MESSAGETYPE_SET_USER_STATUS, "SET_USER_STATUS" },
147 { SAMETIME_MESSAGETYPE_SET_PRIVACY_LIST, "SET_PRIVACY_LIST" },
148 { SAMETIME_MESSAGETYPE_SENSE_SERVICE, "SENSE_SERVICE" },
149 { SAMETIME_MESSAGETYPE_ADMIN, "ADMIN" },
150 { SAMETIME_MESSAGETYPE_ANNOUNCE, "ANNOUNCE" },
152 { 0, NULL }
155 #define SAMETIME_MESSAGEOPTION_ENCRYPT 0x4000
156 #define SAMETIME_MESSAGEOPTION_HAS_ATTRIBS 0x8000
158 static const value_string optionnames[] = {
159 { 0x0, "" },
160 { SAMETIME_MESSAGEOPTION_ENCRYPT, "ENCRYPT" },
161 { SAMETIME_MESSAGEOPTION_HAS_ATTRIBS, "HAS_ATTRIBS" },
163 { 0, NULL }
166 static const value_string userstatusnames[] = {
167 { 0x0020, "ACTIVE" }, /* "I am available" */
168 { 0x0040, "IDLE" }, /* never seen in the wild, maybe non-pc :-) ? */
169 { 0x0060, "AWAY" }, /* "I am away from my computer now" */
170 { 0x0080, "BUSY" }, /* "Please do not disturb me" */
171 { 0x0008, "MEETING" }, /* "I am in a meeting" */
173 { 0, NULL }
176 #define SAMETIME_SENDTYPE_AWARE_ADD 0x0068
177 #define SAMETIME_SENDTYPE_OPT_DO_SET 0x00c9
178 #define SAMETIME_SENDTYPE_AWARE_SNAPSHOT 0x01f4
179 #define SAMETIME_SENDTYPE_AWARE_UPDATE 0x01f5
180 #define SAMETIME_SENDTYPE_OPT_GOT_SET 0x0259
182 static const value_string sendtypenames[] = {
183 { SAMETIME_SENDTYPE_AWARE_ADD, "AWARE_ADD" },
184 { 0x0069, "AWARE_REMOVE" },
185 { SAMETIME_SENDTYPE_OPT_DO_SET, "OPT_DO_SET" },
186 { 0x00cb, "OPT_WATCH" },
187 { SAMETIME_SENDTYPE_AWARE_SNAPSHOT, "AWARE_SNAPSHOT" },
188 { SAMETIME_SENDTYPE_AWARE_UPDATE, "AWARE_UPDATE" },
189 { SAMETIME_SENDTYPE_OPT_GOT_SET, "OPT_GOT_SET" },
190 { 0x025a, "?" },
191 { 0x025d, "OPT_DID_SET" },
193 { 0, NULL }
196 static const value_string awarenessnames[] = {
197 { 0x0002, "USER" },
198 { 0x0003, "GROUP" },
199 { 0x0008, "SERVER" },
200 { 0, NULL }
203 static const value_string codenames[] = {
204 { 0x00000011, "SERVICE_AWARE" },
205 { 0x00000015, "SERVICE_RESOLVE" },
206 { 0x00000018, "SERVICE_STORAGE" },
207 { 0x0000001a, "SERVICE_DIRECTORY" },
209 { 0x80000011, "ERR_USER_SKETCHY" },
210 { 0x80000015, "ERR_TOKEN_INVALID" },
211 { 0x80000018, "ERR_PORT_IN_USE" },
212 { 0x80000022, "ERR_CHANNEL_DESTROYED" },
214 { 0, NULL }
218 static int
219 add_text_item(tvbuff_t *tvb, proto_tree *tree, int offset, int hf)
221 guint16 length;
223 /* heuristic rule, string should start w/ valid character(s) */
224 if (! tvb_get_guint8(tvb, offset + 2))
225 return 0;
227 length = tvb_get_ntohs(tvb, offset);
228 if (length) {
229 /* the string length must not exceed the packet length */
230 if (length > tvb_reported_length_remaining(tvb, offset + 2))
231 return 0;
233 /* add string length only if preferences is set */
234 if (global_sametime_show_length)
235 proto_tree_add_item(tree, hf_sametime_field_length, tvb, offset, 2, ENC_BIG_ENDIAN);
237 /* add string */
238 proto_tree_add_string(tree, hf, tvb, offset + 2, length, tvb_get_string(wmem_packet_scope(), tvb, offset + 2, length));
241 return 2 + length;
245 static guint16
246 dissect_set_user_status(tvbuff_t *tvb, proto_tree *tree, int offset)
248 guint16 user_status;
250 user_status = tvb_get_ntohs(tvb, offset);
251 proto_item_append_text(tree, ", %s", val_to_str(user_status, userstatusnames, "0x%04x"));
252 proto_tree_add_item(tree, hf_sametime_user_status, tvb, offset, 2, ENC_BIG_ENDIAN);
253 offset += 2;
254 proto_tree_add_item(tree, hf_sametime_time, tvb, offset, 4, ENC_BIG_ENDIAN);
255 offset += 4;
256 add_text_item(tvb, tree, offset, hf_sametime_field_text);
258 return user_status;
262 static int
263 dissect_handshake(tvbuff_t *tvb, proto_tree *tree, int offset)
265 proto_tree_add_item(tree, hf_sametime_handshake_major, tvb, offset, 2, ENC_BIG_ENDIAN);
266 offset += 2;
267 proto_tree_add_item(tree, hf_sametime_handshake_minor, tvb, offset, 2, ENC_BIG_ENDIAN);
268 offset += 2;
269 offset += 4;
270 proto_tree_add_item(tree, hf_sametime_handshake_srvrcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
271 offset += 4;
272 proto_tree_add_item(tree, hf_sametime_login_type, tvb, offset, 2, ENC_BIG_ENDIAN);
273 offset += 2;
274 proto_tree_add_item(tree, hf_sametime_handshake_loclcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
275 offset += 4;
276 offset += 6;
277 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
278 offset += 8;
279 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
281 return offset;
285 static void
286 dissect_handshake_ack(tvbuff_t *tvb, proto_tree *tree, int offset)
288 proto_tree_add_item(tree, hf_sametime_handshake_major, tvb, offset, 2, ENC_BIG_ENDIAN);
289 offset += 2;
290 proto_tree_add_item(tree, hf_sametime_handshake_minor, tvb, offset, 2, ENC_BIG_ENDIAN);
291 offset += 2;
292 proto_tree_add_item(tree, hf_sametime_handshake_loclcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
293 offset += 4;
294 offset += 4;
295 offset += 4;
296 add_text_item(tvb, tree, offset, hf_sametime_field_text);
300 static void
301 dissect_login(tvbuff_t *tvb, proto_tree *tree, int offset)
303 offset += 2;
304 add_text_item(tvb, tree, offset, hf_sametime_field_text);
308 static void
309 dissect_login_redirect(tvbuff_t *tvb, proto_tree *tree, int offset)
311 offset += 2;
312 add_text_item(tvb, tree, offset, hf_sametime_field_text);
316 static void
317 dissect_login_ack(tvbuff_t *tvb, proto_tree *tree, int offset)
319 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
320 proto_tree_add_item(tree, hf_sametime_login_type, tvb, offset, 2, ENC_BIG_ENDIAN);
321 offset += 2;
322 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
323 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
324 offset += 3;
325 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
326 proto_tree_add_item(tree, hf_sametime_handshake_loclcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
327 offset += 4;
328 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
329 offset += 21;
330 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
331 add_text_item(tvb, tree, offset, hf_sametime_field_text);
335 static void
336 dissect_channel_create(tvbuff_t *tvb, proto_tree *tree, int offset)
338 offset += 4;
339 proto_tree_add_item(tree, hf_sametime_channel_id, tvb, offset, 4, ENC_BIG_ENDIAN);
340 offset += 4;
341 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
342 proto_tree_add_item(tree, hf_sametime_channel_service, tvb, offset, 4, ENC_BIG_ENDIAN);
343 offset += 4;
344 offset += 8;
345 add_text_item(tvb, tree, offset, hf_sametime_field_text);
349 static guint16
350 dissect_channel_send(tvbuff_t *tvb, proto_tree *tree, int offset)
352 guint16 send_type, awareness;
353 guint na;
355 send_type = tvb_get_ntohs(tvb, offset);
356 proto_item_append_text(tree, ", %s", val_to_str(send_type, sendtypenames, "0x%04x"));
357 proto_tree_add_item(tree, hf_sametime_channel_send_type, tvb, offset, 2, ENC_BIG_ENDIAN);
358 offset += 2;
360 switch (send_type) {
361 case SAMETIME_SENDTYPE_AWARE_ADD:
362 offset += 8;
363 awareness = tvb_get_ntohs(tvb, offset);
364 proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
365 proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
366 offset += 2;
367 add_text_item(tvb, tree, offset, hf_sametime_field_text);
369 break;
371 case SAMETIME_SENDTYPE_OPT_DO_SET:
372 offset += 20;
373 na = tvb_get_ntohl(tvb, offset);
374 offset += 4;
375 if (na == 0x33) {
376 offset += add_text_item(tvb, tree, offset, hf_sametime_location_country);
377 offset += add_text_item(tvb, tree, offset, hf_sametime_location_postalcode);
378 offset += add_text_item(tvb, tree, offset, hf_sametime_location_province);
379 offset += add_text_item(tvb, tree, offset, hf_sametime_location_city);
380 offset += add_text_item(tvb, tree, offset, hf_sametime_location_phone);
381 offset += 1;
382 offset += add_text_item(tvb, tree, offset, hf_sametime_location_name);
383 add_text_item(tvb, tree, offset, hf_sametime_location_timezone);
384 } else {
385 add_text_item(tvb, tree, offset, hf_sametime_field_text);
388 break;
390 case SAMETIME_SENDTYPE_OPT_GOT_SET:
391 offset += 8;
392 awareness = tvb_get_ntohs(tvb, offset);
393 proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
394 proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
395 offset += 2;
396 while (tvb_reported_length_remaining(tvb, offset) > 2) {
397 int n = add_text_item(tvb, tree, offset, hf_sametime_field_text);
398 offset += (n) ? n : 1;
401 break;
403 case SAMETIME_SENDTYPE_AWARE_SNAPSHOT:
404 offset += 12;
405 awareness = tvb_get_ntohs(tvb, offset);
406 proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
407 proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
408 offset += 2;
409 add_text_item(tvb, tree, offset, hf_sametime_field_text);
411 break;
413 case SAMETIME_SENDTYPE_AWARE_UPDATE:
414 offset += 4;
415 offset += 4;
416 awareness = tvb_get_ntohs(tvb, offset);
417 proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
418 proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
419 offset += 2;
420 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
421 offset += 4;
422 if (tvb_get_guint8(tvb, offset)) {
423 offset += 1;
424 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
425 dissect_set_user_status(tvb, tree, offset);
428 break;
430 case 0x0000:
431 offset += 14;
432 add_text_item(tvb, tree, offset, hf_sametime_field_text);
434 break;
436 case 0x0002:
437 offset += 8;
438 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
439 offset += 3;
440 add_text_item(tvb, tree, offset, hf_sametime_field_text);
442 break;
444 case 0x0005: /* XML */
445 if (26 <= tvb_reported_length_remaining(tvb, offset + 2)) {
446 offset += 26;
447 add_text_item(tvb, tree, offset, hf_sametime_field_text);
450 break;
452 case 0x0007:
453 offset += 8;
454 if (4 <= tvb_reported_length_remaining(tvb, offset + 2)) {
455 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
456 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
457 offset += 3;
458 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
459 add_text_item(tvb, tree, offset, hf_sametime_field_text);
462 break;
464 case 0x025a:
465 offset += 10;
466 add_text_item(tvb, tree, offset, hf_sametime_field_text);
468 break;
470 default:
471 break;
474 return send_type;
478 static void
479 dissect_channel_accept(tvbuff_t *tvb, proto_tree *tree, int offset)
481 offset += 34;
482 if (tvb_reported_length_remaining(tvb, offset + 2)) {
483 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
484 if (tvb_get_guint8(tvb, offset)) {
485 offset += 1;
486 offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
487 dissect_set_user_status(tvb, tree, offset);
493 static void
494 dissect_sense_service(tvbuff_t *tvb, proto_tree *tree, int offset)
496 guint32 code;
498 code = tvb_get_ntohl(tvb, offset);
499 proto_item_append_text(tree, ", %s", val_to_str(code, codenames, "0x%04x"));
500 proto_tree_add_item(tree, hf_sametime_code, tvb, offset, 4, ENC_BIG_ENDIAN);
505 here we really dissect the message(s)
507 static int
508 dissect_sametime_content(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
510 proto_tree *sametime_tree;
511 proto_item *ti;
512 static SametimeTap *sinfo;
513 gint message_type;
514 int packet_length, offset = 0;
516 /* we expect either 1 heartbeat byte (0x80) or a sametime message */
517 packet_length = tvb_reported_length_remaining(tvb, offset);
518 if (packet_length == 1) {
519 message_type = tvb_get_guint8(tvb, 0);
521 } else if (packet_length < 12) {
522 message_type = -1;
524 } else {
525 message_type = tvb_get_ntohs(tvb, 4);
528 /* add message type */
529 col_append_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, messagetypenames, "0x%04x"));
530 col_append_str(pinfo->cinfo, COL_INFO, " ");
532 /* message type statistic */
533 sinfo = wmem_new(wmem_packet_scope(), struct SametimeTap);
534 sinfo->message_type = message_type;
535 sinfo->send_type = -1;
536 sinfo->user_status = -1;
538 /* packet detail tree */
539 ti = proto_tree_add_item(tree, proto_sametime, tvb, offset, -1, ENC_NA);
540 sametime_tree = proto_item_add_subtree(ti, ett_sametime);
541 proto_item_append_text(sametime_tree, ", %s", val_to_str(message_type, messagetypenames, "0x%04x"));
543 /* dissect message */
544 if (message_type == SAMETIME_MESSAGETYPE_HEARTBEAT) {
545 proto_tree_add_item(sametime_tree, hf_sametime_heartbeat, tvb, offset, 1, ENC_BIG_ENDIAN);
547 } else if (message_type != -1) {
548 proto_tree *options_tree;
549 proto_item *op;
551 /* first 4 bytes gives the length of the sametime message */
552 if (global_sametime_show_length) {
553 proto_tree_add_item(sametime_tree, hf_sametime_message_length, tvb, offset, 4, ENC_BIG_ENDIAN);
555 offset += 4;
557 /* next 2 bytes gives the message type */
558 proto_tree_add_item(sametime_tree, hf_sametime_message_type, tvb, offset, 2, ENC_BIG_ENDIAN);
559 offset += 2;
561 /* next 2 bytes are the message options */
562 op = proto_tree_add_item(sametime_tree, hf_sametime_message_options, tvb, offset, 2, ENC_BIG_ENDIAN);
563 options_tree = proto_item_add_subtree(op, ett_sametime_options);
564 proto_tree_add_item(options_tree, hf_sametime_message_options_attribute, tvb, offset, 2, ENC_BIG_ENDIAN);
565 proto_tree_add_item(options_tree, hf_sametime_message_options_encrypted, tvb, offset, 2, ENC_BIG_ENDIAN);
566 offset += 2;
568 /* next 4 bytes contains the channel id */
569 proto_tree_add_item(sametime_tree, hf_sametime_message_channel, tvb, offset, 4, ENC_BIG_ENDIAN);
570 offset += 4;
572 switch (message_type)
574 case SAMETIME_MESSAGETYPE_HANDSHAKE:
575 dissect_handshake(tvb, sametime_tree, offset);
576 break;
578 case SAMETIME_MESSAGETYPE_HANDSHAKE_ACK:
579 dissect_handshake_ack(tvb, sametime_tree, offset);
580 break;
582 case SAMETIME_MESSAGETYPE_HANDSHAKE_SYN:
583 break;
585 case SAMETIME_MESSAGETYPE_LOGIN:
586 dissect_login(tvb, sametime_tree, offset);
587 break;
589 case SAMETIME_MESSAGETYPE_LOGIN_REDIRECT:
590 dissect_login_redirect(tvb, sametime_tree, offset);
591 break;
593 case SAMETIME_MESSAGETYPE_LOGIN_ACK:
594 dissect_login_ack(tvb, sametime_tree, offset);
595 break;
597 case SAMETIME_MESSAGETYPE_CHANNEL_CREATE:
598 dissect_channel_create(tvb, sametime_tree, offset);
599 break;
601 case SAMETIME_MESSAGETYPE_CHANNEL_SEND:
602 sinfo->send_type = dissect_channel_send(tvb, sametime_tree, offset);
603 break;
605 case SAMETIME_MESSAGETYPE_CHANNEL_ACCEPT:
606 dissect_channel_accept(tvb, sametime_tree, offset);
607 break;
609 case SAMETIME_MESSAGETYPE_SET_USER_STATUS:
610 sinfo->user_status = dissect_set_user_status(tvb, sametime_tree, offset);
611 break;
613 case SAMETIME_MESSAGETYPE_SENSE_SERVICE:
614 dissect_sense_service(tvb, sametime_tree, offset);
615 break;
617 default:
618 /* do not fill the statistics with useless data from encrypted packages */
619 sinfo->message_type = -1;
620 break;
624 tap_queue_packet(sametime_tap, pinfo, sinfo);
625 return tvb_length(tvb);
630 tick statistics
632 static int
633 sametime_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p)
635 struct SametimeTap *pi = (struct SametimeTap *)p;
637 tick_stat_node(st, st_str_packet, 0, FALSE);
638 if (pi->message_type != -1)
639 stats_tree_tick_pivot(st, st_node_message_type, val_to_str(pi->message_type, messagetypenames, "Unknown (0x%04x)"));
641 if (pi->send_type != -1)
642 stats_tree_tick_pivot(st, st_node_send_type, val_to_str(pi->send_type, sendtypenames, "Unknown (0x%04x)"));
644 if (pi->user_status != -1)
645 stats_tree_tick_pivot(st, st_node_user_status, val_to_str(pi->user_status, userstatusnames, "Unknown (0x%04x)"));
647 return 1;
652 init statistic
654 static void
655 sametime_stats_tree_init(stats_tree* st)
657 st_node_packet = stats_tree_create_node(st, st_str_packet, 0, TRUE);
658 st_node_message_type = stats_tree_create_pivot(st, st_str_message_type, st_node_packet);
659 st_node_send_type = stats_tree_create_pivot(st, st_str_send_type, st_node_packet);
660 st_node_user_status = stats_tree_create_pivot(st, st_str_user_status, st_node_packet);
665 length of the sametime message
667 static guint
668 get_sametime_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
670 /* XXX: Actually: the length of the tvb will always be 4 or greater at this point */
671 /* because tcp_dissect_pdus was called with 4 as a required "fixed length". */
672 /* But newer variants of this protocol with a full encrypted network stream */
673 /* may require a more sophisticated dissection logic here */
674 guint32 N = tvb_length_remaining(tvb, offset);
676 return (N < 4) ? N : tvb_get_ntohl(tvb, offset) + 4;
681 the dissector itself
683 static int
684 dissect_sametime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
686 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAMETIME");
687 col_clear(pinfo->cinfo,COL_INFO);
689 tcp_dissect_pdus(tvb, pinfo, tree, global_sametime_reassemble_packets, 4,
690 get_sametime_message_len, dissect_sametime_content, data);
691 return tvb_length(tvb);
695 void
696 proto_register_sametime(void)
698 static hf_register_info hf[] = {
699 /*tcp payload is one byte : SAMETIME_MESSAGETYPE_HEARTBEAT*/
700 { &hf_sametime_heartbeat,
701 { "heartbeat", "sametime.heartbeat",
702 FT_UINT8, BASE_HEX,
703 NULL, 0x0,
704 NULL, HFILL }
707 /*sametime message header*/
708 { &hf_sametime_message_length,
709 { "msg length", "sametime.message_length",
710 FT_UINT32, BASE_DEC,
711 NULL, 0,
712 NULL, HFILL }
714 { &hf_sametime_message_type,
715 { "msg type", "sametime.message_type",
716 FT_UINT16, BASE_HEX,
717 VALS(messagetypenames), 0x0,
718 NULL, HFILL }
720 { &hf_sametime_message_options,
721 { "msg options", "sametime.message_options",
722 FT_UINT16, BASE_HEX,
723 VALS(optionnames), 0x0,
724 NULL, HFILL }
726 { &hf_sametime_message_options_encrypted,
727 { "ENCRYPT", "sametime.message_options.encrypted",
728 FT_BOOLEAN, 16,
729 NULL, SAMETIME_MESSAGEOPTION_ENCRYPT,
730 NULL, HFILL }
732 { &hf_sametime_message_options_attribute,
733 { "HAS_ATTRIBS", "sametime.message_options.attribute",
734 FT_BOOLEAN, 16,
735 NULL, SAMETIME_MESSAGEOPTION_HAS_ATTRIBS,
736 NULL, HFILL }
738 { &hf_sametime_message_channel,
739 { "msg channel", "sametime.message_channel",
740 FT_UINT32, BASE_DEC,
741 NULL, 0,
742 NULL, HFILL }
745 /*common fields within various message types*/
746 { &hf_sametime_field_length,
747 { "length", "sametime.field_length",
748 FT_UINT16, BASE_DEC,
749 NULL, 0,
750 NULL, HFILL }
752 { &hf_sametime_field_text,
753 { "text", "sametime.field_text",
754 FT_STRING, BASE_NONE,
755 NULL, 0x0,
756 NULL, HFILL }
758 { &hf_sametime_code,
759 { "code", "sametime.code",
760 FT_UINT32, BASE_HEX,
761 VALS(codenames), 0x0,
762 NULL, HFILL }
764 { &hf_sametime_login_type,
765 { "login type", "sametime.login_type",
766 FT_UINT16, BASE_HEX,
767 NULL, 0x0,
768 NULL, HFILL }
770 { &hf_sametime_time,
771 { "time", "sametime.time",
772 FT_UINT32, BASE_DEC,
773 NULL, 0,
774 NULL, HFILL }
777 /*type handshake*/
778 { &hf_sametime_handshake_major,
779 { "major", "sametime.handshake.major",
780 FT_UINT16, BASE_HEX,
781 NULL, 0x0,
782 NULL, HFILL }
784 { &hf_sametime_handshake_minor,
785 { "minor", "sametime.handshake.minor",
786 FT_UINT16, BASE_HEX,
787 NULL, 0x0,
788 NULL, HFILL }
790 { &hf_sametime_handshake_srvrcalc_addr,
791 { "srvr", "sametime.handshake.srvrcalc_addr",
792 FT_IPv4, BASE_NONE,
793 NULL, 0x0,
794 NULL, HFILL }
796 { &hf_sametime_handshake_loclcalc_addr,
797 { "locl", "sametime.handshake.loclcalc_addr",
798 FT_IPv4, BASE_NONE,
799 NULL, 0x0,
800 NULL, HFILL }
803 /*type channel*/
804 { &hf_sametime_channel_service,
805 { "service id", "sametime.channel.service",
806 FT_UINT32, BASE_DEC,
807 NULL, 0,
808 NULL, HFILL }
810 { &hf_sametime_channel_id,
811 { "channel id", "sametime.channel.id",
812 FT_UINT32, BASE_DEC,
813 NULL, 0,
814 NULL, HFILL }
816 { &hf_sametime_channel_send_type,
817 { "send type", "sametime.channel.send_type",
818 FT_UINT16, BASE_HEX,
819 VALS(sendtypenames), 0,
820 NULL, HFILL }
822 { &hf_sametime_channel_awareness,
823 { "awareness", "sametime.channel.awareness",
824 FT_UINT16, BASE_HEX,
825 VALS(awarenessnames), 0x0,
826 NULL, HFILL }
829 /*type user status*/
830 { &hf_sametime_user_status,
831 { "user status", "sametime.user_status_type",
832 FT_UINT16, BASE_HEX,
833 VALS(userstatusnames), 0x0,
834 NULL, HFILL }
837 /*type location*/
838 { &hf_sametime_location_name,
839 { "name", "sametime.location.name",
840 FT_STRING, BASE_NONE,
841 NULL, 0x0,
842 NULL, HFILL }
844 { &hf_sametime_location_city,
845 { "city", "sametime.location.city",
846 FT_STRING, BASE_NONE,
847 NULL, 0x0,
848 NULL, HFILL }
850 { &hf_sametime_location_province,
851 { "province", "sametime.location.province",
852 FT_STRING, BASE_NONE,
853 NULL, 0x0,
854 NULL, HFILL }
856 { &hf_sametime_location_postalcode,
857 { "postal code", "sametime.location.postalcode",
858 FT_STRING, BASE_NONE,
859 NULL, 0x0,
860 NULL, HFILL }
862 { &hf_sametime_location_country,
863 { "country", "sametime.location.country",
864 FT_STRING, BASE_NONE,
865 NULL, 0x0,
866 NULL, HFILL }
868 { &hf_sametime_location_phone,
869 { "phone", "sametime.location.phone",
870 FT_STRING, BASE_NONE,
871 NULL, 0x0,
872 NULL, HFILL }
874 { &hf_sametime_location_timezone,
875 { "time zone", "sametime.location.timezone",
876 FT_STRING, BASE_NONE,
877 NULL, 0x0,
878 NULL, HFILL }
882 static gint *ett[] = {
883 &ett_sametime,
884 &ett_sametime_options
887 module_t *sametime_module;
889 proto_sametime = proto_register_protocol (
890 "Sametime Protocol", /* name */
891 "SAMETIME", /* short name */
892 "sametime" /* abbrev */
894 proto_register_field_array(proto_sametime, hf, array_length(hf));
895 proto_register_subtree_array(ett, array_length(ett));
897 sametime_tap = register_tap("sametime");
899 /* Preference setting */
900 sametime_module = prefs_register_protocol(proto_sametime, NULL);
901 prefs_register_bool_preference(sametime_module, "show_length",
902 "Show length",
903 "Show length of text field",
904 &global_sametime_show_length);
905 prefs_register_bool_preference(sametime_module, "reassemble",
906 "Reassemble","reassemble packets",
907 &global_sametime_reassemble_packets);
908 prefs_register_uint_preference(sametime_module, "tcp_port",
909 "SAMETIME port number",
910 "port number for sametime traffic",
911 10, &global_sametime_port);
916 create / register
918 void
919 proto_reg_handoff_sametime(void)
921 static gboolean initialized = FALSE;
922 static guint saved_sametime_tcp_port;
924 if (!initialized) {
925 sametime_handle = new_create_dissector_handle(dissect_sametime, proto_sametime);
926 stats_tree_register("sametime", "sametime", "Sametime/Messages", 0,
927 sametime_stats_tree_packet,
928 sametime_stats_tree_init, NULL );
929 initialized = TRUE;
930 } else {
931 dissector_delete_uint("tcp.port", saved_sametime_tcp_port, sametime_handle);
934 dissector_add_uint("tcp.port", global_sametime_port, sametime_handle);
935 saved_sametime_tcp_port = global_sametime_port;