/src/wireshark/epan/dissectors/packet-sametime.c
Line | Count | Source |
1 | | /* packet-sametime.c |
2 | | * Routines for SAMETIME dissection |
3 | | * Copyright 2010, Toralf Foerster <toralf.foerster [AT] gmx.de> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <epan/packet.h> |
15 | | #include <epan/prefs.h> |
16 | | #include <epan/stats_tree.h> |
17 | | #include "packet-tcp.h" |
18 | | |
19 | 15 | #define DEFAULT_SAMETIME_PORT 1533 /* Not IANA registered */ |
20 | | |
21 | | void proto_register_sametime(void); |
22 | | void proto_reg_handoff_sametime(void); |
23 | | |
24 | | static int proto_sametime; |
25 | | static dissector_handle_t sametime_handle; |
26 | | |
27 | | /*preferences*/ |
28 | | static bool global_sametime_show_length; |
29 | | static bool global_sametime_reassemble_packets = true; |
30 | | |
31 | | /*heart beat*/ |
32 | | static int hf_sametime_heartbeat; |
33 | | |
34 | | /*sametime message header*/ |
35 | | static int hf_sametime_message_length; |
36 | | static int hf_sametime_message_type; |
37 | | static int hf_sametime_message_options; |
38 | | static int hf_sametime_message_options_attribute; |
39 | | static int hf_sametime_message_options_encrypted; |
40 | | static int hf_sametime_message_channel; |
41 | | |
42 | | /*common types*/ |
43 | | static int hf_sametime_field_length; |
44 | | static int hf_sametime_field_text; |
45 | | static int hf_sametime_code; |
46 | | static int hf_sametime_login_type; |
47 | | static int hf_sametime_time; |
48 | | |
49 | | /*handshake*/ |
50 | | static int hf_sametime_handshake_major; |
51 | | static int hf_sametime_handshake_minor; |
52 | | static int hf_sametime_handshake_srvrcalc_addr; |
53 | | static int hf_sametime_handshake_loclcalc_addr; |
54 | | |
55 | | /*channel*/ |
56 | | static int hf_sametime_channel_service; |
57 | | static int hf_sametime_channel_id; |
58 | | static int hf_sametime_channel_send_type; |
59 | | static int hf_sametime_channel_awareness; |
60 | | |
61 | | /*user status*/ |
62 | | static int hf_sametime_user_status; |
63 | | |
64 | | /*location*/ |
65 | | static int hf_sametime_location_country; |
66 | | static int hf_sametime_location_postalcode; |
67 | | static int hf_sametime_location_province; |
68 | | static int hf_sametime_location_city; |
69 | | static int hf_sametime_location_phone; |
70 | | static int hf_sametime_location_name; |
71 | | static int hf_sametime_location_timezone; |
72 | | |
73 | | /*packet detail tree*/ |
74 | | static int ett_sametime; |
75 | | static int ett_sametime_options; |
76 | | |
77 | | /*statistics*/ |
78 | | static int sametime_tap; |
79 | | static const char* st_str_packet = "Sametime Message Count"; |
80 | | static const char* st_str_message_type = "Message Type"; |
81 | | static const char* st_str_send_type = "Send Type"; |
82 | | static const char* st_str_user_status = "User Status"; |
83 | | static int st_node_packet = -1; |
84 | | static int st_node_message_type = -1; |
85 | | static int st_node_send_type = -1; |
86 | | static int st_node_user_status = -1; |
87 | | |
88 | | typedef struct SametimeTap { |
89 | | int message_type; |
90 | | int send_type; |
91 | | int user_status; |
92 | | } SametimeTap; |
93 | | |
94 | 133 | #define SAMETIME_MESSAGETYPE_HEARTBEAT 0x80 |
95 | 14 | #define SAMETIME_MESSAGETYPE_HANDSHAKE 0x0000 |
96 | | |
97 | 0 | #define SAMETIME_MESSAGETYPE_HANDSHAKE_ACK 0x8000 |
98 | 0 | #define SAMETIME_MESSAGETYPE_HANDSHAKE_SYN 0x0025 |
99 | 3 | #define SAMETIME_MESSAGETYPE_LOGIN 0x0001 |
100 | 0 | #define SAMETIME_MESSAGETYPE_LOGIN_ACK 0x8001 |
101 | 0 | #define SAMETIME_MESSAGETYPE_LOGIN_REDIRECT 0x0018 |
102 | | #define SAMETIME_MESSAGETYPE_LOGIN_CONTINUE 0x0016 |
103 | | |
104 | 1 | #define SAMETIME_MESSAGETYPE_CHANNEL_CREATE 0x0002 |
105 | | #define SAMETIME_MESSAGETYPE_CHANNEL_DESTROY 0x0003 |
106 | 0 | #define SAMETIME_MESSAGETYPE_CHANNEL_SEND 0x0004 |
107 | 2 | #define SAMETIME_MESSAGETYPE_CHANNEL_ACCEPT 0x0006 |
108 | | |
109 | 0 | #define SAMETIME_MESSAGETYPE_SET_USER_STATUS 0x0009 |
110 | | #define SAMETIME_MESSAGETYPE_SET_PRIVACY_LIST 0x000b |
111 | 0 | #define SAMETIME_MESSAGETYPE_SENSE_SERVICE 0x0011 |
112 | | #define SAMETIME_MESSAGETYPE_ADMIN 0x0019 |
113 | | #define SAMETIME_MESSAGETYPE_ANNOUNCE 0x0022 |
114 | | |
115 | | |
116 | | static const value_string messagetypenames[] = { |
117 | | { SAMETIME_MESSAGETYPE_HEARTBEAT, "HEARTBEAT" }, |
118 | | |
119 | | { SAMETIME_MESSAGETYPE_HANDSHAKE, "HANDSHAKE" }, |
120 | | { SAMETIME_MESSAGETYPE_HANDSHAKE_SYN, "HANDSHAKE_SYN" }, |
121 | | { SAMETIME_MESSAGETYPE_HANDSHAKE_ACK, "HANDSHAKE_ACK" }, |
122 | | { SAMETIME_MESSAGETYPE_LOGIN, "LOGIN" }, |
123 | | { SAMETIME_MESSAGETYPE_LOGIN_ACK, "LOGIN_ACK" }, |
124 | | { SAMETIME_MESSAGETYPE_LOGIN_REDIRECT, "LOGIN_REDIRECT" }, |
125 | | { SAMETIME_MESSAGETYPE_LOGIN_CONTINUE, "LOGIN_CONTINUE" }, |
126 | | |
127 | | { SAMETIME_MESSAGETYPE_CHANNEL_CREATE, "CHANNEL_CREATE" }, |
128 | | { SAMETIME_MESSAGETYPE_CHANNEL_DESTROY, "CHANNEL_DESTROY" }, |
129 | | { SAMETIME_MESSAGETYPE_CHANNEL_SEND, "CHANNEL_SEND" }, |
130 | | { SAMETIME_MESSAGETYPE_CHANNEL_ACCEPT, "CHANNEL_ACCEPT" }, |
131 | | |
132 | | { SAMETIME_MESSAGETYPE_SET_USER_STATUS, "SET_USER_STATUS" }, |
133 | | { SAMETIME_MESSAGETYPE_SET_PRIVACY_LIST, "SET_PRIVACY_LIST" }, |
134 | | { SAMETIME_MESSAGETYPE_SENSE_SERVICE, "SENSE_SERVICE" }, |
135 | | { SAMETIME_MESSAGETYPE_ADMIN, "ADMIN" }, |
136 | | { SAMETIME_MESSAGETYPE_ANNOUNCE, "ANNOUNCE" }, |
137 | | |
138 | | { 0, NULL } |
139 | | }; |
140 | | |
141 | 15 | #define SAMETIME_MESSAGEOPTION_ENCRYPT 0x4000 |
142 | 15 | #define SAMETIME_MESSAGEOPTION_HAS_ATTRIBS 0x8000 |
143 | | |
144 | | static const value_string optionnames[] = { |
145 | | { 0x0, "" }, |
146 | | { SAMETIME_MESSAGEOPTION_ENCRYPT, "ENCRYPT" }, |
147 | | { SAMETIME_MESSAGEOPTION_HAS_ATTRIBS, "HAS_ATTRIBS" }, |
148 | | |
149 | | { 0, NULL } |
150 | | }; |
151 | | |
152 | | static const value_string userstatusnames[] = { |
153 | | { 0x0020, "ACTIVE" }, /* "I am available" */ |
154 | | { 0x0040, "IDLE" }, /* never seen in the wild, maybe non-pc :-) ? */ |
155 | | { 0x0060, "AWAY" }, /* "I am away from my computer now" */ |
156 | | { 0x0080, "BUSY" }, /* "Please do not disturb me" */ |
157 | | { 0x0008, "MEETING" }, /* "I am in a meeting" */ |
158 | | |
159 | | { 0, NULL } |
160 | | }; |
161 | | |
162 | 0 | #define SAMETIME_SENDTYPE_AWARE_ADD 0x0068 |
163 | 0 | #define SAMETIME_SENDTYPE_OPT_DO_SET 0x00c9 |
164 | 0 | #define SAMETIME_SENDTYPE_AWARE_SNAPSHOT 0x01f4 |
165 | 0 | #define SAMETIME_SENDTYPE_AWARE_UPDATE 0x01f5 |
166 | 0 | #define SAMETIME_SENDTYPE_OPT_GOT_SET 0x0259 |
167 | | |
168 | | static const value_string sendtypenames[] = { |
169 | | { SAMETIME_SENDTYPE_AWARE_ADD, "AWARE_ADD" }, |
170 | | { 0x0069, "AWARE_REMOVE" }, |
171 | | { SAMETIME_SENDTYPE_OPT_DO_SET, "OPT_DO_SET" }, |
172 | | { 0x00cb, "OPT_WATCH" }, |
173 | | { SAMETIME_SENDTYPE_AWARE_SNAPSHOT, "AWARE_SNAPSHOT" }, |
174 | | { SAMETIME_SENDTYPE_AWARE_UPDATE, "AWARE_UPDATE" }, |
175 | | { SAMETIME_SENDTYPE_OPT_GOT_SET, "OPT_GOT_SET" }, |
176 | | { 0x025a, "?" }, |
177 | | { 0x025d, "OPT_DID_SET" }, |
178 | | |
179 | | { 0, NULL } |
180 | | }; |
181 | | |
182 | | static const value_string awarenessnames[] = { |
183 | | { 0x0002, "USER" }, |
184 | | { 0x0003, "GROUP" }, |
185 | | { 0x0008, "SERVER" }, |
186 | | { 0, NULL } |
187 | | }; |
188 | | |
189 | | static const value_string codenames[] = { |
190 | | { 0x00000011, "SERVICE_AWARE" }, |
191 | | { 0x00000015, "SERVICE_RESOLVE" }, |
192 | | { 0x00000018, "SERVICE_STORAGE" }, |
193 | | { 0x0000001a, "SERVICE_DIRECTORY" }, |
194 | | |
195 | | { 0x80000011, "ERR_USER_SKETCHY" }, |
196 | | { 0x80000015, "ERR_TOKEN_INVALID" }, |
197 | | { 0x80000018, "ERR_PORT_IN_USE" }, |
198 | | { 0x80000022, "ERR_CHANNEL_DESTROYED" }, |
199 | | |
200 | | { 0, NULL } |
201 | | }; |
202 | | |
203 | | |
204 | | static int |
205 | | add_text_item(tvbuff_t *tvb, proto_tree *tree, int offset, int hf) |
206 | 25 | { |
207 | 25 | uint16_t length; |
208 | | |
209 | | /* heuristic rule, string should start w/ valid character(s) */ |
210 | 25 | if (! tvb_get_uint8(tvb, offset + 2)) |
211 | 13 | return 0; |
212 | | |
213 | 12 | length = tvb_get_ntohs(tvb, offset); |
214 | 12 | if (length) { |
215 | | /* the string length must not exceed the packet length */ |
216 | 7 | if (length > tvb_reported_length_remaining(tvb, offset + 2)) |
217 | 3 | return 0; |
218 | | |
219 | | /* add string length only if preferences is set */ |
220 | 4 | if (global_sametime_show_length) |
221 | 0 | proto_tree_add_item(tree, hf_sametime_field_length, tvb, offset, 2, ENC_BIG_ENDIAN); |
222 | | |
223 | | /* add string */ |
224 | 4 | proto_tree_add_item(tree, hf, tvb, offset + 2, length, ENC_ASCII|ENC_NA); |
225 | 4 | } |
226 | | |
227 | 9 | return 2 + length; |
228 | 12 | } |
229 | | |
230 | | |
231 | | static uint16_t |
232 | | dissect_set_user_status(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset) |
233 | 0 | { |
234 | 0 | uint16_t user_status; |
235 | |
|
236 | 0 | user_status = tvb_get_ntohs(tvb, offset); |
237 | 0 | proto_item_append_text(tree, ", %s", val_to_str(pinfo->pool, user_status, userstatusnames, "0x%04x")); |
238 | 0 | proto_tree_add_item(tree, hf_sametime_user_status, tvb, offset, 2, ENC_BIG_ENDIAN); |
239 | 0 | offset += 2; |
240 | 0 | proto_tree_add_item(tree, hf_sametime_time, tvb, offset, 4, ENC_BIG_ENDIAN); |
241 | 0 | offset += 4; |
242 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
243 | |
|
244 | 0 | return user_status; |
245 | 0 | } |
246 | | |
247 | | |
248 | | static int |
249 | | dissect_handshake(tvbuff_t *tvb, proto_tree *tree, int offset) |
250 | 14 | { |
251 | 14 | proto_tree_add_item(tree, hf_sametime_handshake_major, tvb, offset, 2, ENC_BIG_ENDIAN); |
252 | 14 | offset += 2; |
253 | 14 | proto_tree_add_item(tree, hf_sametime_handshake_minor, tvb, offset, 2, ENC_BIG_ENDIAN); |
254 | 14 | offset += 2; |
255 | 14 | offset += 4; |
256 | 14 | proto_tree_add_item(tree, hf_sametime_handshake_srvrcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN); |
257 | 14 | offset += 4; |
258 | 14 | proto_tree_add_item(tree, hf_sametime_login_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
259 | 14 | offset += 2; |
260 | 14 | proto_tree_add_item(tree, hf_sametime_handshake_loclcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN); |
261 | 14 | offset += 4; |
262 | 14 | offset += 6; |
263 | 14 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
264 | 14 | offset += 8; |
265 | 14 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
266 | | |
267 | 14 | return offset; |
268 | 14 | } |
269 | | |
270 | | |
271 | | static void |
272 | | dissect_handshake_ack(tvbuff_t *tvb, proto_tree *tree, int offset) |
273 | 0 | { |
274 | 0 | proto_tree_add_item(tree, hf_sametime_handshake_major, tvb, offset, 2, ENC_BIG_ENDIAN); |
275 | 0 | offset += 2; |
276 | 0 | proto_tree_add_item(tree, hf_sametime_handshake_minor, tvb, offset, 2, ENC_BIG_ENDIAN); |
277 | 0 | offset += 2; |
278 | 0 | proto_tree_add_item(tree, hf_sametime_handshake_loclcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN); |
279 | 0 | offset += 4; |
280 | 0 | offset += 4; |
281 | 0 | offset += 4; |
282 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
283 | 0 | } |
284 | | |
285 | | |
286 | | static void |
287 | | dissect_login(tvbuff_t *tvb, proto_tree *tree, int offset) |
288 | 3 | { |
289 | 3 | offset += 2; |
290 | 3 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
291 | 3 | } |
292 | | |
293 | | |
294 | | static void |
295 | | dissect_login_redirect(tvbuff_t *tvb, proto_tree *tree, int offset) |
296 | 0 | { |
297 | 0 | offset += 2; |
298 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
299 | 0 | } |
300 | | |
301 | | |
302 | | static void |
303 | | dissect_login_ack(tvbuff_t *tvb, proto_tree *tree, int offset) |
304 | 0 | { |
305 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
306 | 0 | proto_tree_add_item(tree, hf_sametime_login_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
307 | 0 | offset += 2; |
308 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
309 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
310 | 0 | offset += 3; |
311 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
312 | 0 | proto_tree_add_item(tree, hf_sametime_handshake_loclcalc_addr, tvb, offset, 4, ENC_BIG_ENDIAN); |
313 | 0 | offset += 4; |
314 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
315 | 0 | offset += 21; |
316 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
317 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
318 | 0 | } |
319 | | |
320 | | |
321 | | static void |
322 | | dissect_channel_create(tvbuff_t *tvb, proto_tree *tree, int offset) |
323 | 1 | { |
324 | 1 | offset += 4; |
325 | 1 | proto_tree_add_item(tree, hf_sametime_channel_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
326 | 1 | offset += 4; |
327 | 1 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
328 | 1 | proto_tree_add_item(tree, hf_sametime_channel_service, tvb, offset, 4, ENC_BIG_ENDIAN); |
329 | 1 | offset += 4; |
330 | 1 | offset += 8; |
331 | 1 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
332 | 1 | } |
333 | | |
334 | | |
335 | | static uint16_t |
336 | | dissect_channel_send(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset) |
337 | 0 | { |
338 | 0 | uint16_t send_type, awareness; |
339 | 0 | unsigned na; |
340 | |
|
341 | 0 | send_type = tvb_get_ntohs(tvb, offset); |
342 | 0 | proto_item_append_text(tree, ", %s", val_to_str(pinfo->pool, send_type, sendtypenames, "0x%04x")); |
343 | 0 | proto_tree_add_item(tree, hf_sametime_channel_send_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
344 | 0 | offset += 2; |
345 | |
|
346 | 0 | switch (send_type) { |
347 | 0 | case SAMETIME_SENDTYPE_AWARE_ADD: |
348 | 0 | offset += 8; |
349 | 0 | awareness = tvb_get_ntohs(tvb, offset); |
350 | 0 | proto_item_append_text(tree, ", %s", val_to_str(pinfo->pool, awareness, awarenessnames, "0x%04x")); |
351 | 0 | proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN); |
352 | 0 | offset += 2; |
353 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
354 | |
|
355 | 0 | break; |
356 | | |
357 | 0 | case SAMETIME_SENDTYPE_OPT_DO_SET: |
358 | 0 | offset += 20; |
359 | 0 | na = tvb_get_ntohl(tvb, offset); |
360 | 0 | offset += 4; |
361 | 0 | if (na == 0x33) { |
362 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_location_country); |
363 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_location_postalcode); |
364 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_location_province); |
365 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_location_city); |
366 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_location_phone); |
367 | 0 | offset += 1; |
368 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_location_name); |
369 | 0 | add_text_item(tvb, tree, offset, hf_sametime_location_timezone); |
370 | 0 | } else { |
371 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
372 | 0 | } |
373 | |
|
374 | 0 | break; |
375 | | |
376 | 0 | case SAMETIME_SENDTYPE_OPT_GOT_SET: |
377 | 0 | offset += 8; |
378 | 0 | awareness = tvb_get_ntohs(tvb, offset); |
379 | 0 | proto_item_append_text(tree, ", %s", val_to_str(pinfo->pool, awareness, awarenessnames, "0x%04x")); |
380 | 0 | proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN); |
381 | 0 | offset += 2; |
382 | 0 | while (tvb_reported_length_remaining(tvb, offset) > 2) { |
383 | 0 | int n = add_text_item(tvb, tree, offset, hf_sametime_field_text); |
384 | 0 | offset += (n) ? n : 1; |
385 | 0 | } |
386 | |
|
387 | 0 | break; |
388 | | |
389 | 0 | case SAMETIME_SENDTYPE_AWARE_SNAPSHOT: |
390 | 0 | offset += 12; |
391 | 0 | awareness = tvb_get_ntohs(tvb, offset); |
392 | 0 | proto_item_append_text(tree, ", %s", val_to_str(pinfo->pool, awareness, awarenessnames, "0x%04x")); |
393 | 0 | proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN); |
394 | 0 | offset += 2; |
395 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
396 | |
|
397 | 0 | break; |
398 | | |
399 | 0 | case SAMETIME_SENDTYPE_AWARE_UPDATE: |
400 | 0 | offset += 4; |
401 | 0 | offset += 4; |
402 | 0 | awareness = tvb_get_ntohs(tvb, offset); |
403 | 0 | proto_item_append_text(tree, ", %s", val_to_str(pinfo->pool, awareness, awarenessnames, "0x%04x")); |
404 | 0 | proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN); |
405 | 0 | offset += 2; |
406 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
407 | 0 | offset += 4; |
408 | 0 | if (tvb_get_uint8(tvb, offset)) { |
409 | 0 | offset += 1; |
410 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
411 | 0 | dissect_set_user_status(tvb, pinfo, tree, offset); |
412 | 0 | } |
413 | |
|
414 | 0 | break; |
415 | | |
416 | 0 | case 0x0000: |
417 | 0 | offset += 14; |
418 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
419 | |
|
420 | 0 | break; |
421 | | |
422 | 0 | case 0x0002: |
423 | 0 | offset += 8; |
424 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
425 | 0 | offset += 3; |
426 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
427 | |
|
428 | 0 | break; |
429 | | |
430 | 0 | case 0x0005: /* XML */ |
431 | 0 | if (26 <= tvb_reported_length_remaining(tvb, offset + 2)) { |
432 | 0 | offset += 26; |
433 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
434 | 0 | } |
435 | |
|
436 | 0 | break; |
437 | | |
438 | 0 | case 0x0007: |
439 | 0 | offset += 8; |
440 | 0 | if (4 <= tvb_reported_length_remaining(tvb, offset + 2)) { |
441 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
442 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
443 | 0 | offset += 3; |
444 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
445 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
446 | 0 | } |
447 | |
|
448 | 0 | break; |
449 | | |
450 | 0 | case 0x025a: |
451 | 0 | offset += 10; |
452 | 0 | add_text_item(tvb, tree, offset, hf_sametime_field_text); |
453 | |
|
454 | 0 | break; |
455 | | |
456 | 0 | default: |
457 | 0 | break; |
458 | 0 | } |
459 | | |
460 | 0 | return send_type; |
461 | 0 | } |
462 | | |
463 | | |
464 | | static void |
465 | | dissect_channel_accept(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset) |
466 | 2 | { |
467 | 2 | offset += 34; |
468 | 2 | if (tvb_reported_length_remaining(tvb, offset + 2)) { |
469 | 1 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
470 | 1 | if (tvb_get_uint8(tvb, offset)) { |
471 | 0 | offset += 1; |
472 | 0 | offset += add_text_item(tvb, tree, offset, hf_sametime_field_text); |
473 | 0 | dissect_set_user_status(tvb, pinfo, tree, offset); |
474 | 0 | } |
475 | 1 | } |
476 | 2 | } |
477 | | |
478 | | |
479 | | static void |
480 | | dissect_sense_service(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset) |
481 | 0 | { |
482 | 0 | uint32_t code; |
483 | |
|
484 | 0 | code = tvb_get_ntohl(tvb, offset); |
485 | 0 | proto_item_append_text(tree, ", %s", val_to_str(pinfo->pool, code, codenames, "0x%04x")); |
486 | 0 | proto_tree_add_item(tree, hf_sametime_code, tvb, offset, 4, ENC_BIG_ENDIAN); |
487 | 0 | } |
488 | | |
489 | | |
490 | | /* |
491 | | here we really dissect the message(s) |
492 | | */ |
493 | | static int |
494 | | dissect_sametime_content(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
495 | 133 | { |
496 | 133 | proto_tree *sametime_tree; |
497 | 133 | proto_item *ti; |
498 | 133 | static SametimeTap *sinfo; |
499 | 133 | int message_type; |
500 | 133 | int packet_length, offset = 0; |
501 | | |
502 | | /* we expect either 1 heartbeat byte (0x80) or a sametime message */ |
503 | 133 | packet_length = tvb_reported_length_remaining(tvb, offset); |
504 | 133 | if (packet_length == 1) { |
505 | 0 | message_type = tvb_get_uint8(tvb, 0); |
506 | |
|
507 | 133 | } else if (packet_length < 12) { |
508 | 100 | message_type = -1; |
509 | | |
510 | 100 | } else { |
511 | 33 | message_type = tvb_get_ntohs(tvb, 4); |
512 | 33 | } |
513 | | |
514 | | /* add message type */ |
515 | 133 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, message_type, messagetypenames, "0x%04x")); |
516 | 133 | col_append_str(pinfo->cinfo, COL_INFO, " "); |
517 | | |
518 | | /* message type statistic */ |
519 | 133 | sinfo = wmem_new(pinfo->pool, struct SametimeTap); |
520 | 133 | sinfo->message_type = message_type; |
521 | 133 | sinfo->send_type = -1; |
522 | 133 | sinfo->user_status = -1; |
523 | | |
524 | | /* packet detail tree */ |
525 | 133 | ti = proto_tree_add_item(tree, proto_sametime, tvb, offset, -1, ENC_NA); |
526 | 133 | sametime_tree = proto_item_add_subtree(ti, ett_sametime); |
527 | 133 | proto_item_append_text(sametime_tree, ", %s", val_to_str(pinfo->pool, message_type, messagetypenames, "0x%04x")); |
528 | | |
529 | | /* dissect message */ |
530 | 133 | if (message_type == SAMETIME_MESSAGETYPE_HEARTBEAT) { |
531 | 0 | proto_tree_add_item(sametime_tree, hf_sametime_heartbeat, tvb, offset, 1, ENC_BIG_ENDIAN); |
532 | |
|
533 | 133 | } else if (message_type != -1) { |
534 | 32 | proto_tree *options_tree; |
535 | 32 | proto_item *op; |
536 | | |
537 | | /* first 4 bytes gives the length of the sametime message */ |
538 | 32 | if (global_sametime_show_length) { |
539 | 0 | proto_tree_add_item(sametime_tree, hf_sametime_message_length, tvb, offset, 4, ENC_BIG_ENDIAN); |
540 | 0 | } |
541 | 32 | offset += 4; |
542 | | |
543 | | /* next 2 bytes gives the message type */ |
544 | 32 | proto_tree_add_item(sametime_tree, hf_sametime_message_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
545 | 32 | offset += 2; |
546 | | |
547 | | /* next 2 bytes are the message options */ |
548 | 32 | op = proto_tree_add_item(sametime_tree, hf_sametime_message_options, tvb, offset, 2, ENC_BIG_ENDIAN); |
549 | 32 | options_tree = proto_item_add_subtree(op, ett_sametime_options); |
550 | 32 | proto_tree_add_item(options_tree, hf_sametime_message_options_attribute, tvb, offset, 2, ENC_BIG_ENDIAN); |
551 | 32 | proto_tree_add_item(options_tree, hf_sametime_message_options_encrypted, tvb, offset, 2, ENC_BIG_ENDIAN); |
552 | 32 | offset += 2; |
553 | | |
554 | | /* next 4 bytes contains the channel id */ |
555 | 32 | proto_tree_add_item(sametime_tree, hf_sametime_message_channel, tvb, offset, 4, ENC_BIG_ENDIAN); |
556 | 32 | offset += 4; |
557 | | |
558 | 32 | switch (message_type) |
559 | 32 | { |
560 | 14 | case SAMETIME_MESSAGETYPE_HANDSHAKE: |
561 | 14 | dissect_handshake(tvb, sametime_tree, offset); |
562 | 14 | break; |
563 | | |
564 | 0 | case SAMETIME_MESSAGETYPE_HANDSHAKE_ACK: |
565 | 0 | dissect_handshake_ack(tvb, sametime_tree, offset); |
566 | 0 | break; |
567 | | |
568 | 0 | case SAMETIME_MESSAGETYPE_HANDSHAKE_SYN: |
569 | 0 | break; |
570 | | |
571 | 3 | case SAMETIME_MESSAGETYPE_LOGIN: |
572 | 3 | dissect_login(tvb, sametime_tree, offset); |
573 | 3 | break; |
574 | | |
575 | 0 | case SAMETIME_MESSAGETYPE_LOGIN_REDIRECT: |
576 | 0 | dissect_login_redirect(tvb, sametime_tree, offset); |
577 | 0 | break; |
578 | | |
579 | 0 | case SAMETIME_MESSAGETYPE_LOGIN_ACK: |
580 | 0 | dissect_login_ack(tvb, sametime_tree, offset); |
581 | 0 | break; |
582 | | |
583 | 1 | case SAMETIME_MESSAGETYPE_CHANNEL_CREATE: |
584 | 1 | dissect_channel_create(tvb, sametime_tree, offset); |
585 | 1 | break; |
586 | | |
587 | 0 | case SAMETIME_MESSAGETYPE_CHANNEL_SEND: |
588 | 0 | sinfo->send_type = dissect_channel_send(tvb, pinfo, sametime_tree, offset); |
589 | 0 | break; |
590 | | |
591 | 2 | case SAMETIME_MESSAGETYPE_CHANNEL_ACCEPT: |
592 | 2 | dissect_channel_accept(tvb, pinfo, sametime_tree, offset); |
593 | 2 | break; |
594 | | |
595 | 0 | case SAMETIME_MESSAGETYPE_SET_USER_STATUS: |
596 | 0 | sinfo->user_status = dissect_set_user_status(tvb, pinfo, sametime_tree, offset); |
597 | 0 | break; |
598 | | |
599 | 0 | case SAMETIME_MESSAGETYPE_SENSE_SERVICE: |
600 | 0 | dissect_sense_service(tvb, pinfo ,sametime_tree, offset); |
601 | 0 | break; |
602 | | |
603 | 12 | default: |
604 | | /* do not fill the statistics with useless data from encrypted packages */ |
605 | 12 | sinfo->message_type = -1; |
606 | 12 | break; |
607 | 32 | } |
608 | 32 | } |
609 | | |
610 | 125 | tap_queue_packet(sametime_tap, pinfo, sinfo); |
611 | 125 | return tvb_captured_length(tvb); |
612 | 133 | } |
613 | | |
614 | | |
615 | | /* |
616 | | tick statistics |
617 | | */ |
618 | | static tap_packet_status |
619 | | sametime_stats_tree_packet(stats_tree* st, packet_info* pinfo _U_, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_) |
620 | 0 | { |
621 | 0 | const struct SametimeTap *pi = (const struct SametimeTap *)p; |
622 | |
|
623 | 0 | tick_stat_node(st, st_str_packet, 0, false); |
624 | 0 | if (pi->message_type != -1) |
625 | 0 | stats_tree_tick_pivot(st, st_node_message_type, val_to_str(pinfo->pool, pi->message_type, messagetypenames, "Unknown (0x%04x)")); |
626 | |
|
627 | 0 | if (pi->send_type != -1) |
628 | 0 | stats_tree_tick_pivot(st, st_node_send_type, val_to_str(pinfo->pool, pi->send_type, sendtypenames, "Unknown (0x%04x)")); |
629 | |
|
630 | 0 | if (pi->user_status != -1) |
631 | 0 | stats_tree_tick_pivot(st, st_node_user_status, val_to_str(pinfo->pool, pi->user_status, userstatusnames, "Unknown (0x%04x)")); |
632 | |
|
633 | 0 | return TAP_PACKET_REDRAW; |
634 | 0 | } |
635 | | |
636 | | |
637 | | /* |
638 | | init statistic |
639 | | */ |
640 | | static void |
641 | | sametime_stats_tree_init(stats_tree* st) |
642 | 0 | { |
643 | 0 | st_node_packet = stats_tree_create_node(st, st_str_packet, 0, STAT_DT_INT, true); |
644 | 0 | st_node_message_type = stats_tree_create_pivot(st, st_str_message_type, st_node_packet); |
645 | 0 | st_node_send_type = stats_tree_create_pivot(st, st_str_send_type, st_node_packet); |
646 | 0 | st_node_user_status = stats_tree_create_pivot(st, st_str_user_status, st_node_packet); |
647 | 0 | } |
648 | | |
649 | | |
650 | | /* |
651 | | length of the sametime message |
652 | | */ |
653 | | static unsigned |
654 | | get_sametime_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, |
655 | | int offset, void *data _U_) |
656 | 133 | { |
657 | | /* XXX: Actually: the length of the tvb will always be 4 or greater at this point */ |
658 | | /* because tcp_dissect_pdus was called with 4 as a required "fixed length". */ |
659 | | /* But newer variants of this protocol with a full encrypted network stream */ |
660 | | /* may require a more sophisticated dissection logic here */ |
661 | 133 | uint32_t N = tvb_captured_length_remaining(tvb, offset); |
662 | | |
663 | 133 | return (N < 4) ? N : tvb_get_ntohl(tvb, offset) + 4; |
664 | 133 | } |
665 | | |
666 | | |
667 | | /* |
668 | | the dissector itself |
669 | | */ |
670 | | static int |
671 | | dissect_sametime(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
672 | 24 | { |
673 | 24 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAMETIME"); |
674 | 24 | col_clear(pinfo->cinfo,COL_INFO); |
675 | | |
676 | 24 | tcp_dissect_pdus(tvb, pinfo, tree, global_sametime_reassemble_packets, 4, |
677 | 24 | get_sametime_message_len, dissect_sametime_content, data); |
678 | 24 | return tvb_captured_length(tvb); |
679 | 24 | } |
680 | | |
681 | | |
682 | | void |
683 | | proto_register_sametime(void) |
684 | 15 | { |
685 | 15 | static hf_register_info hf[] = { |
686 | | /*tcp payload is one byte : SAMETIME_MESSAGETYPE_HEARTBEAT*/ |
687 | 15 | { &hf_sametime_heartbeat, |
688 | 15 | { "heartbeat", "sametime.heartbeat", |
689 | 15 | FT_UINT8, BASE_HEX, |
690 | 15 | NULL, 0x0, |
691 | 15 | NULL, HFILL } |
692 | 15 | }, |
693 | | |
694 | | /*sametime message header*/ |
695 | 15 | { &hf_sametime_message_length, |
696 | 15 | { "msg length", "sametime.message_length", |
697 | 15 | FT_UINT32, BASE_DEC, |
698 | 15 | NULL, 0, |
699 | 15 | NULL, HFILL } |
700 | 15 | }, |
701 | 15 | { &hf_sametime_message_type, |
702 | 15 | { "msg type", "sametime.message_type", |
703 | 15 | FT_UINT16, BASE_HEX, |
704 | 15 | VALS(messagetypenames), 0x0, |
705 | 15 | NULL, HFILL } |
706 | 15 | }, |
707 | 15 | { &hf_sametime_message_options, |
708 | 15 | { "msg options", "sametime.message_options", |
709 | 15 | FT_UINT16, BASE_HEX, |
710 | 15 | VALS(optionnames), 0x0, |
711 | 15 | NULL, HFILL } |
712 | 15 | }, |
713 | 15 | { &hf_sametime_message_options_encrypted, |
714 | 15 | { "ENCRYPT", "sametime.message_options.encrypted", |
715 | 15 | FT_BOOLEAN, 16, |
716 | 15 | NULL, SAMETIME_MESSAGEOPTION_ENCRYPT, |
717 | 15 | NULL, HFILL } |
718 | 15 | }, |
719 | 15 | { &hf_sametime_message_options_attribute, |
720 | 15 | { "HAS_ATTRIBS", "sametime.message_options.attribute", |
721 | 15 | FT_BOOLEAN, 16, |
722 | 15 | NULL, SAMETIME_MESSAGEOPTION_HAS_ATTRIBS, |
723 | 15 | NULL, HFILL } |
724 | 15 | }, |
725 | 15 | { &hf_sametime_message_channel, |
726 | 15 | { "msg channel", "sametime.message_channel", |
727 | 15 | FT_UINT32, BASE_DEC, |
728 | 15 | NULL, 0, |
729 | 15 | NULL, HFILL } |
730 | 15 | }, |
731 | | |
732 | | /*common fields within various message types*/ |
733 | 15 | { &hf_sametime_field_length, |
734 | 15 | { "length", "sametime.field_length", |
735 | 15 | FT_UINT16, BASE_DEC, |
736 | 15 | NULL, 0, |
737 | 15 | NULL, HFILL } |
738 | 15 | }, |
739 | 15 | { &hf_sametime_field_text, |
740 | 15 | { "text", "sametime.field_text", |
741 | 15 | FT_STRING, BASE_NONE, |
742 | 15 | NULL, 0x0, |
743 | 15 | NULL, HFILL } |
744 | 15 | }, |
745 | 15 | { &hf_sametime_code, |
746 | 15 | { "code", "sametime.code", |
747 | 15 | FT_UINT32, BASE_HEX, |
748 | 15 | VALS(codenames), 0x0, |
749 | 15 | NULL, HFILL } |
750 | 15 | }, |
751 | 15 | { &hf_sametime_login_type, |
752 | 15 | { "login type", "sametime.login_type", |
753 | 15 | FT_UINT16, BASE_HEX, |
754 | 15 | NULL, 0x0, |
755 | 15 | NULL, HFILL } |
756 | 15 | }, |
757 | 15 | { &hf_sametime_time, |
758 | 15 | { "time", "sametime.time", |
759 | 15 | FT_UINT32, BASE_DEC, |
760 | 15 | NULL, 0, |
761 | 15 | NULL, HFILL } |
762 | 15 | }, |
763 | | |
764 | | /*type handshake*/ |
765 | 15 | { &hf_sametime_handshake_major, |
766 | 15 | { "major", "sametime.handshake.major", |
767 | 15 | FT_UINT16, BASE_HEX, |
768 | 15 | NULL, 0x0, |
769 | 15 | NULL, HFILL } |
770 | 15 | }, |
771 | 15 | { &hf_sametime_handshake_minor, |
772 | 15 | { "minor", "sametime.handshake.minor", |
773 | 15 | FT_UINT16, BASE_HEX, |
774 | 15 | NULL, 0x0, |
775 | 15 | NULL, HFILL } |
776 | 15 | }, |
777 | 15 | { &hf_sametime_handshake_srvrcalc_addr, |
778 | 15 | { "srvr", "sametime.handshake.srvrcalc_addr", |
779 | 15 | FT_IPv4, BASE_NONE, |
780 | 15 | NULL, 0x0, |
781 | 15 | NULL, HFILL } |
782 | 15 | }, |
783 | 15 | { &hf_sametime_handshake_loclcalc_addr, |
784 | 15 | { "locl", "sametime.handshake.loclcalc_addr", |
785 | 15 | FT_IPv4, BASE_NONE, |
786 | 15 | NULL, 0x0, |
787 | 15 | NULL, HFILL } |
788 | 15 | }, |
789 | | |
790 | | /*type channel*/ |
791 | 15 | { &hf_sametime_channel_service, |
792 | 15 | { "service id", "sametime.channel.service", |
793 | 15 | FT_UINT32, BASE_DEC, |
794 | 15 | NULL, 0, |
795 | 15 | NULL, HFILL } |
796 | 15 | }, |
797 | 15 | { &hf_sametime_channel_id, |
798 | 15 | { "channel id", "sametime.channel.id", |
799 | 15 | FT_UINT32, BASE_DEC, |
800 | 15 | NULL, 0, |
801 | 15 | NULL, HFILL } |
802 | 15 | }, |
803 | 15 | { &hf_sametime_channel_send_type, |
804 | 15 | { "send type", "sametime.channel.send_type", |
805 | 15 | FT_UINT16, BASE_HEX, |
806 | 15 | VALS(sendtypenames), 0, |
807 | 15 | NULL, HFILL } |
808 | 15 | }, |
809 | 15 | { &hf_sametime_channel_awareness, |
810 | 15 | { "awareness", "sametime.channel.awareness", |
811 | 15 | FT_UINT16, BASE_HEX, |
812 | 15 | VALS(awarenessnames), 0x0, |
813 | 15 | NULL, HFILL } |
814 | 15 | }, |
815 | | |
816 | | /*type user status*/ |
817 | 15 | { &hf_sametime_user_status, |
818 | 15 | { "user status", "sametime.user_status_type", |
819 | 15 | FT_UINT16, BASE_HEX, |
820 | 15 | VALS(userstatusnames), 0x0, |
821 | 15 | NULL, HFILL } |
822 | 15 | }, |
823 | | |
824 | | /*type location*/ |
825 | 15 | { &hf_sametime_location_name, |
826 | 15 | { "name", "sametime.location.name", |
827 | 15 | FT_STRING, BASE_NONE, |
828 | 15 | NULL, 0x0, |
829 | 15 | NULL, HFILL } |
830 | 15 | }, |
831 | 15 | { &hf_sametime_location_city, |
832 | 15 | { "city", "sametime.location.city", |
833 | 15 | FT_STRING, BASE_NONE, |
834 | 15 | NULL, 0x0, |
835 | 15 | NULL, HFILL } |
836 | 15 | }, |
837 | 15 | { &hf_sametime_location_province, |
838 | 15 | { "province", "sametime.location.province", |
839 | 15 | FT_STRING, BASE_NONE, |
840 | 15 | NULL, 0x0, |
841 | 15 | NULL, HFILL } |
842 | 15 | }, |
843 | 15 | { &hf_sametime_location_postalcode, |
844 | 15 | { "postal code", "sametime.location.postalcode", |
845 | 15 | FT_STRING, BASE_NONE, |
846 | 15 | NULL, 0x0, |
847 | 15 | NULL, HFILL } |
848 | 15 | }, |
849 | 15 | { &hf_sametime_location_country, |
850 | 15 | { "country", "sametime.location.country", |
851 | 15 | FT_STRING, BASE_NONE, |
852 | 15 | NULL, 0x0, |
853 | 15 | NULL, HFILL } |
854 | 15 | }, |
855 | 15 | { &hf_sametime_location_phone, |
856 | 15 | { "phone", "sametime.location.phone", |
857 | 15 | FT_STRING, BASE_NONE, |
858 | 15 | NULL, 0x0, |
859 | 15 | NULL, HFILL } |
860 | 15 | }, |
861 | 15 | { &hf_sametime_location_timezone, |
862 | 15 | { "time zone", "sametime.location.timezone", |
863 | 15 | FT_STRING, BASE_NONE, |
864 | 15 | NULL, 0x0, |
865 | 15 | NULL, HFILL } |
866 | 15 | }, |
867 | 15 | }; |
868 | | |
869 | 15 | static int *ett[] = { |
870 | 15 | &ett_sametime, |
871 | 15 | &ett_sametime_options |
872 | 15 | }; |
873 | | |
874 | 15 | module_t *sametime_module; |
875 | | |
876 | 15 | proto_sametime = proto_register_protocol ("Sametime Protocol", "SAMETIME", "sametime"); |
877 | 15 | proto_register_field_array(proto_sametime, hf, array_length(hf)); |
878 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
879 | | |
880 | 15 | sametime_handle = register_dissector("sametime", dissect_sametime, proto_sametime); |
881 | | |
882 | 15 | sametime_tap = register_tap("sametime"); |
883 | | |
884 | | /* Preference setting */ |
885 | 15 | sametime_module = prefs_register_protocol(proto_sametime, NULL); |
886 | 15 | prefs_register_bool_preference(sametime_module, "show_length", |
887 | 15 | "Show length", |
888 | 15 | "Show length of text field", |
889 | 15 | &global_sametime_show_length); |
890 | 15 | prefs_register_bool_preference(sametime_module, "reassemble", |
891 | 15 | "Reassemble","reassemble packets", |
892 | 15 | &global_sametime_reassemble_packets); |
893 | 15 | } |
894 | | |
895 | | |
896 | | /* |
897 | | create / register |
898 | | */ |
899 | | void |
900 | | proto_reg_handoff_sametime(void) |
901 | 15 | { |
902 | 15 | dissector_add_uint_with_preference("tcp.port", DEFAULT_SAMETIME_PORT, sametime_handle); |
903 | | |
904 | 15 | stats_tree_register("sametime", "sametime", "Sametime" STATS_TREE_MENU_SEPARATOR "Messages", 0, |
905 | 15 | sametime_stats_tree_packet, |
906 | 15 | sametime_stats_tree_init, NULL ); |
907 | | |
908 | 15 | } |
909 | | |
910 | | |
911 | | /* |
912 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
913 | | * |
914 | | * Local variables: |
915 | | * c-basic-offset: 4 |
916 | | * tab-width: 8 |
917 | | * indent-tabs-mode: nil |
918 | | * End: |
919 | | * |
920 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
921 | | * :indentSize=4:tabSize=8:noTabs=true: |
922 | | */ |