Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-gadu-gadu.c
blob33968d4125c989d084cae2689d70777e40bae72c
1 /* packet-gadu-gadu.c
2 * Routines for Gadu-Gadu dissection
3 * Copyright 2011,2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
5 * Protocol documentation available at http://toxygen.net/libgadu/protocol/
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include "packet-tcp.h"
19 void proto_register_gadu_gadu(void);
20 void proto_reg_handoff_gadu_gadu(void);
22 #define TCP_PORT_GADU_GADU 8074 /* assigned by IANA */
24 /* desegmentation of Gadu-Gadu over TCP */
25 static bool gadu_gadu_desegment = true;
27 static dissector_handle_t gadu_gadu_handle;
29 static int proto_gadu_gadu;
31 static int hf_dcc_filename;
32 static int hf_dcc_id;
33 static int hf_dcc_type;
34 static int hf_dcc_uin_from;
35 static int hf_dcc_uin_to;
36 static int hf_gadu_gadu_contact_type;
37 static int hf_gadu_gadu_contact_uin;
38 static int hf_gadu_gadu_contact_uin_str;
39 static int hf_gadu_gadu_data;
40 static int hf_gadu_gadu_header_length;
41 static int hf_gadu_gadu_header_type_recv;
42 static int hf_gadu_gadu_header_type_send;
43 static int hf_gadu_gadu_login80_lang;
44 static int hf_gadu_gadu_login_hash;
45 static int hf_gadu_gadu_login_hash_type;
46 static int hf_gadu_gadu_login_local_ip;
47 static int hf_gadu_gadu_login_local_port;
48 static int hf_gadu_gadu_login_protocol;
49 static int hf_gadu_gadu_login_status;
50 static int hf_gadu_gadu_login_uin;
51 static int hf_gadu_gadu_login_version;
52 static int hf_gadu_gadu_msg80_offset_attr;
53 static int hf_gadu_gadu_msg80_offset_plain;
54 static int hf_gadu_gadu_msg_ack_recipient;
55 static int hf_gadu_gadu_msg_ack_seq;
56 static int hf_gadu_gadu_msg_ack_status;
57 static int hf_gadu_gadu_msg_class;
58 static int hf_gadu_gadu_msg_recipient;
59 static int hf_gadu_gadu_msg_sender;
60 static int hf_gadu_gadu_msg_seq;
61 static int hf_gadu_gadu_msg_text;
62 static int hf_gadu_gadu_msg_time;
63 static int hf_gadu_gadu_msg_uin;
64 static int hf_gadu_gadu_new_status_desc;
65 static int hf_gadu_gadu_new_status_status;
66 static int hf_gadu_gadu_pubdir_reply_seq;
67 static int hf_gadu_gadu_pubdir_reply_str;
68 static int hf_gadu_gadu_pubdir_reply_type;
69 static int hf_gadu_gadu_pubdir_request_seq;
70 static int hf_gadu_gadu_pubdir_request_str;
71 static int hf_gadu_gadu_pubdir_request_type;
72 static int hf_gadu_gadu_status_descr;
73 static int hf_gadu_gadu_status_img_size;
74 static int hf_gadu_gadu_status_ip;
75 static int hf_gadu_gadu_status_port;
76 static int hf_gadu_gadu_status_status;
77 static int hf_gadu_gadu_status_uin;
78 static int hf_gadu_gadu_status_version;
79 static int hf_gadu_gadu_typing_notify_type;
80 static int hf_gadu_gadu_typing_notify_uin;
81 static int hf_gadu_gadu_userdata_attr_name;
82 static int hf_gadu_gadu_userdata_attr_type;
83 static int hf_gadu_gadu_userdata_attr_value;
84 static int hf_gadu_gadu_userdata_uin;
85 static int hf_gadu_gadu_userlist;
86 static int hf_gadu_gadu_userlist_format;
87 static int hf_gadu_gadu_userlist_reply_type;
88 static int hf_gadu_gadu_userlist_request_type;
89 static int hf_gadu_gadu_userlist_version;
90 static int hf_gadu_gadu_welcome_seed;
92 static int ett_gadu_gadu;
93 static int ett_gadu_gadu_contact;
95 #define GG_ERA_OMNIX_MASK 0x04000000
96 #define GG_HAS_AUDIO_MASK 0x40000000
98 #define GG_WELCOME 0x01
99 #define GG_STATUS 0x02
100 #define GG_LOGIN_OK 0x03
101 #define GG_SEND_MSG_ACK 0x05
102 #define GG_PONG 0x07
103 #define GG_PING 0x08
104 #define GG_LOGIN_FAILED 0x09
105 #define GG_RECV_MSG 0x0a
106 #define GG_DISCONNECTING 0x0b
107 #define GG_NOTIFY_REPLY 0x0c
108 #define GG_DISCONNECT_ACK 0x0d
109 #define GG_PUBDIR50_REPLY 0x0e
110 #define GG_STATUS60 0x0f
111 #define GG_USERLIST_REPLY 0x10
112 #define GG_NOTIFY_REPLY60 0x11
113 #define GG_NEED_EMAIL 0x14
114 #define GG_LOGIN_HASH_TYPE_INVALID 0x16
115 #define GG_STATUS77 0x17
116 #define GG_NOTIFY_REPLY77 0x18
117 #define GG_DCC7_INFO 0x1f
118 #define GG_DCC7_NEW 0x20
119 #define GG_DCC7_ACCEPT 0x21
120 #define GG_DCC7_REJECT 0x22
121 #define GG_DCC7_ID_REPLY 0x23
122 #define GG_DCC7_ID_ABORTED 0x25
123 #define GG_XML_EVENT 0x27
124 #define GG_STATUS80BETA 0x2a
125 #define GG_NOTIFY_REPLY80BETA 0x2b
126 #define GG_XML_ACTION 0x2c
127 #define GG_RECV_MSG80 0x2e
128 #define GG_USERLIST_REPLY80 0x30
129 #define GG_LOGIN_OK80 0x35
130 #define GG_STATUS80 0x36
131 #define GG_NOTIFY_REPLY80 0x37
132 #define GG_USERLIST100_REPLY 0x41
133 #define GG_LOGIN80_FAILED 0x43
134 #define GG_USER_DATA 0x44
135 #define GG_TYPING_NOTIFY 0x59
136 #define GG_OWN_MESSAGE 0x5A
137 #define GG_OWN_RESOURCE_INFO 0x5B
138 #define GG_USERLIST100_VERSION 0x5C
141 #define GG_TYPE_VS(x) { x, #x }
143 /* original (GG_*) names likes in documentation (http://toxygen.net/libgadu/protocol/#ch1.16) */
144 static const value_string gadu_gadu_packets_type_recv[] = {
145 GG_TYPE_VS(GG_WELCOME),
146 GG_TYPE_VS(GG_STATUS),
147 GG_TYPE_VS(GG_LOGIN_OK),
148 GG_TYPE_VS(GG_SEND_MSG_ACK),
149 GG_TYPE_VS(GG_PONG),
150 GG_TYPE_VS(GG_PING),
151 GG_TYPE_VS(GG_LOGIN_FAILED),
152 GG_TYPE_VS(GG_RECV_MSG),
153 GG_TYPE_VS(GG_DISCONNECTING),
154 GG_TYPE_VS(GG_NOTIFY_REPLY),
155 GG_TYPE_VS(GG_DISCONNECT_ACK),
156 GG_TYPE_VS(GG_PUBDIR50_REPLY),
157 GG_TYPE_VS(GG_STATUS60),
158 GG_TYPE_VS(GG_USERLIST_REPLY),
159 GG_TYPE_VS(GG_NOTIFY_REPLY60),
160 GG_TYPE_VS(GG_NEED_EMAIL),
161 GG_TYPE_VS(GG_LOGIN_HASH_TYPE_INVALID),
162 GG_TYPE_VS(GG_STATUS77),
163 GG_TYPE_VS(GG_NOTIFY_REPLY77),
164 GG_TYPE_VS(GG_DCC7_INFO),
165 GG_TYPE_VS(GG_DCC7_NEW),
166 GG_TYPE_VS(GG_DCC7_ACCEPT),
167 GG_TYPE_VS(GG_DCC7_REJECT),
168 GG_TYPE_VS(GG_DCC7_ID_REPLY),
169 GG_TYPE_VS(GG_DCC7_ID_ABORTED),
170 GG_TYPE_VS(GG_XML_EVENT),
171 GG_TYPE_VS(GG_STATUS80BETA),
172 GG_TYPE_VS(GG_NOTIFY_REPLY80BETA),
173 GG_TYPE_VS(GG_XML_ACTION),
174 GG_TYPE_VS(GG_RECV_MSG80),
175 GG_TYPE_VS(GG_USERLIST_REPLY80),
176 GG_TYPE_VS(GG_LOGIN_OK80),
177 GG_TYPE_VS(GG_STATUS80),
178 GG_TYPE_VS(GG_NOTIFY_REPLY80),
179 GG_TYPE_VS(GG_USERLIST100_REPLY),
180 GG_TYPE_VS(GG_LOGIN80_FAILED),
181 GG_TYPE_VS(GG_USER_DATA),
182 GG_TYPE_VS(GG_TYPING_NOTIFY),
183 GG_TYPE_VS(GG_OWN_MESSAGE),
184 GG_TYPE_VS(GG_OWN_RESOURCE_INFO),
185 GG_TYPE_VS(GG_USERLIST100_VERSION),
186 { 0, NULL }
189 #define GG_NEW_STATUS 0x02
190 #define GG_PONG 0x07
191 #define GG_PING 0x08
192 #define GG_SEND_MSG 0x0b
193 #define GG_LOGIN 0x0c
194 #define GG_ADD_NOTIFY 0x0d
195 #define GG_REMOVE_NOTIFY 0x0e
196 #define GG_NOTIFY_FIRST 0x0f
197 #define GG_NOTIFY_LAST 0x10
198 #define GG_LIST_EMPTY 0x12
199 #define GG_LOGIN_EXT 0x13
200 #define GG_PUBDIR50_REQUEST 0x14
201 #define GG_LOGIN60 0x15
202 #define GG_USERLIST_REQUEST 0x16
203 #define GG_LOGIN70 0x19
204 #define GG_DCC7_INFO 0x1f
205 #define GG_DCC7_NEW 0x20
206 #define GG_DCC7_ACCEPT 0x21
207 #define GG_DCC7_REJECT 0x22
208 #define GG_DCC7_ID_REQUEST 0x23
209 #define GG_DCC7_ID_DUNNO1 0x24
210 #define GG_DCC7_ID_ABORT 0x25
211 #define GG_NEW_STATUS80BETA 0x28
212 #define GG_LOGIN80BETA 0x29
213 #define GG_SEND_MSG80 0x2d
214 #define GG_USERLIST_REQUEST80 0x2f
215 #define GG_LOGIN80 0x31
216 #define GG_NEW_STATUS80 0x38
217 #define GG_USERLIST100_REQUEST 0x40
218 #define GG_RECV_MSG_ACK 0x46
219 #define GG_TYPING_NOTIFY 0x59
220 #define GG_OWN_DISCONNECT 0x62
221 #define GG_NEW_STATUS105 0x63
222 #define GG_NOTIFY105 0x78
223 #define GG_ADD_NOTIFY105 0x7b
224 #define GG_REMOVE_NOTIFY105 0x7c
225 #define GG_LOGIN105 0x83
227 static const value_string gadu_gadu_packets_type_send[] = {
228 GG_TYPE_VS(GG_NEW_STATUS),
229 GG_TYPE_VS(GG_PONG),
230 GG_TYPE_VS(GG_PING),
231 GG_TYPE_VS(GG_SEND_MSG),
232 GG_TYPE_VS(GG_LOGIN),
233 GG_TYPE_VS(GG_ADD_NOTIFY),
234 GG_TYPE_VS(GG_REMOVE_NOTIFY),
235 GG_TYPE_VS(GG_NOTIFY_FIRST),
236 GG_TYPE_VS(GG_NOTIFY_LAST),
237 GG_TYPE_VS(GG_LIST_EMPTY),
238 GG_TYPE_VS(GG_LOGIN_EXT),
239 GG_TYPE_VS(GG_PUBDIR50_REQUEST),
240 GG_TYPE_VS(GG_LOGIN60),
241 GG_TYPE_VS(GG_USERLIST_REQUEST),
242 GG_TYPE_VS(GG_LOGIN70),
243 GG_TYPE_VS(GG_DCC7_INFO),
244 GG_TYPE_VS(GG_DCC7_NEW),
245 GG_TYPE_VS(GG_DCC7_ACCEPT),
246 GG_TYPE_VS(GG_DCC7_REJECT),
247 GG_TYPE_VS(GG_DCC7_ID_REQUEST),
248 GG_TYPE_VS(GG_DCC7_ID_DUNNO1),
249 GG_TYPE_VS(GG_DCC7_ID_ABORT),
250 GG_TYPE_VS(GG_NEW_STATUS80BETA),
251 GG_TYPE_VS(GG_LOGIN80BETA),
252 GG_TYPE_VS(GG_SEND_MSG80),
253 GG_TYPE_VS(GG_USERLIST_REQUEST80),
254 GG_TYPE_VS(GG_LOGIN80),
255 GG_TYPE_VS(GG_NEW_STATUS80),
256 GG_TYPE_VS(GG_USERLIST100_REQUEST),
257 GG_TYPE_VS(GG_RECV_MSG_ACK),
258 GG_TYPE_VS(GG_TYPING_NOTIFY),
259 GG_TYPE_VS(GG_OWN_DISCONNECT),
260 GG_TYPE_VS(GG_NEW_STATUS105),
261 GG_TYPE_VS(GG_NOTIFY105),
262 GG_TYPE_VS(GG_ADD_NOTIFY105),
263 GG_TYPE_VS(GG_REMOVE_NOTIFY105),
264 GG_TYPE_VS(GG_LOGIN105),
265 { 0, NULL }
268 static const value_string gadu_gadu_msg_ack_status_vals[] = {
269 { 0x01, "Message blocked" },
270 { 0x02, "Message delivered" },
271 { 0x03, "Message queued" },
272 { 0x04, "Message not delivered (queue full)" },
273 { 0x06, "CTCP Message not delivered" },
274 { 0, NULL }
277 #define GG_STATUS_NOT_AVAIL 0x01
278 #define GG_STATUS_NOT_AVAIL_DESCR 0x15
279 #define GG_STATUS_FFC 0x17
280 #define GG_STATUS_FFC_DESCR 0x18
281 #define GG_STATUS_AVAIL 0x02
282 #define GG_STATUS_AVAIL_DESCR 0x04
283 #define GG_STATUS_BUSY 0x03
284 #define GG_STATUS_BUSY_DESCR 0x05
285 #define GG_STATUS_DND 0x21
286 #define GG_STATUS_DND_DESCR 0x22
287 #define GG_STATUS_INVISIBLE 0x14
288 #define GG_STATUS_INVISIBLE_DESCR 0x16
289 #define GG_STATUS_BLOCKED 0x06
291 #define GG_LOGIN_HASH_GG32 0x01
292 #define GG_LOGIN_HASH_SHA1 0x02
294 static const value_string gadu_gadu_hash_type_vals[] = {
295 { GG_LOGIN_HASH_GG32, "GG32 hash" },
296 { GG_LOGIN_HASH_SHA1, "SHA1 hash" },
297 { 0, NULL }
300 #define GG_USERLIST_PUT 0x00
301 #define GG_USERLIST_PUT_MORE 0x01
302 #define GG_USERLIST_GET 0x02
304 static const value_string gadu_gadu_userlist_request_type_vals[] = {
305 { GG_USERLIST_PUT, "Userlist put" },
306 { GG_USERLIST_PUT_MORE, "Userlist put (more)" },
307 { GG_USERLIST_GET, "Userlist get" },
308 { 0, NULL }
311 #define GG_USERLIST_PUT_REPLY 0x00
312 #define GG_USERLIST_PUT_MORE_REPLY 0x02
313 #define GG_USERLIST_GET_REPLY 0x06
314 #define GG_USERLIST_GET_MORE_REPLY 0x04
316 static const value_string gadu_gadu_userlist_reply_type_vals[] = {
317 { GG_USERLIST_PUT_REPLY, "Userlist put" },
318 { GG_USERLIST_PUT_MORE_REPLY, "Userlist put (more)" },
319 { GG_USERLIST_GET_REPLY, "Userlist get" },
320 { GG_USERLIST_GET_MORE_REPLY, "Userlist get (more)" },
321 { 0, NULL }
324 #define GG_USERLIST100_FORMAT_TYPE_NONE 0x00
325 #define GG_USERLIST100_FORMAT_TYPE_GG70 0x01
326 #define GG_USERLIST100_FORMAT_TYPE_GG100 0x02
328 static const value_string gadu_gadu_userlist_request_format_vals[] = {
329 { GG_USERLIST100_FORMAT_TYPE_NONE, "None" },
330 { GG_USERLIST100_FORMAT_TYPE_GG70, "Classic (7.0)" },
331 { GG_USERLIST100_FORMAT_TYPE_GG100, "XML (10.0)" },
332 { 0, NULL }
335 /* XXX, add compatible libgadu versions? */
336 static const value_string gadu_gadu_version_vals[] = {
337 { 0x2e, "Gadu-Gadu 8.0 (build 8283)" },
338 { 0x2d, "Gadu-Gadu 8.0 (build 4881)" },
339 { 0x2a, "Gadu-Gadu 7.7 (build 3315)" },
340 { 0x29, "Gadu-Gadu 7.6 (build 1688)" },
341 { 0x28, "Gadu-Gadu 7.5.0 (build 2201)" },
342 { 0x27, "Gadu-Gadu 7.0 (build 22)" },
343 { 0x26, "Gadu-Gadu 7.0 (build 20)" },
344 { 0x25, "Gadu-Gadu 7.0 (build 1)" },
345 { 0x24, "Gadu-Gadu 6.1 (build 155) or 7.6 (build 1359)" },
346 { 0x22, "Gadu-Gadu 6.0 (build 140)" },
347 { 0x21, "Gadu-Gadu 6.0 (build 133)" },
348 { 0x20, "Gadu-Gadu 6.0" },
349 { 0x1e, "Gadu-Gadu 5.7 beta (build 121)" },
350 { 0x1c, "Gadu_Gadu 5.7 beta" },
351 { 0x1b, "Gadu-Gadu 5.0.5" },
352 { 0x19, "Gadu-Gadu 5.0.3" },
353 { 0x18, "Gadu-Gadu 5.0.1, 5.0.0, 4.9.3" },
354 { 0x17, "Gadu-Gadu 4.9.2" },
355 { 0x16, "Gadu-Gadu 4.9.1" },
356 { 0x15, "Gadu-Gadu 4.8.9" },
357 { 0x14, "Gadu-Gadu 4.8.3, 4.8.1" },
358 { 0x11, "Gadu-Gadu 4.6.10, 4.6.1" },
359 { 0x10, "Gadu-Gadu 4.5.22, 4.5.21, 4.5.19, 4.5.17, 4.5.15" },
360 { 0x0f, "Gadu-Gadu 4.5.12" },
361 { 0x0b, "Gadu-Gadu 4.0.30, 4.0.29, 4.0.28, 4.0.25" },
362 { 0, NULL }
365 static const value_string gadu_gadu_dcc_type_vals[] = {
366 { 1, "Voice transmission" },
367 { 4, "File transmission" },
368 { 0, NULL }
371 static const value_string gadu_gadu_typing_notify_type_vals[] = {
372 { 1, "Typing started" },
373 { 0, "Typing stopped" },
374 { 0, NULL }
377 static const value_string gadu_gadu_pubdir_type_vals[] = {
378 { 1, "Public directory write" },
379 { 2, "Public directory read" },
380 { 3, "Public directory search" },
381 { 0, NULL }
384 static dissector_handle_t xml_handle;
386 struct gadu_gadu_conv_data {
387 uint32_t uin; /* uin from login packet */
390 static struct gadu_gadu_conv_data *
391 gadu_gadu_create_conversation(packet_info *pinfo, uint32_t uin)
393 conversation_t *conv;
394 struct gadu_gadu_conv_data *gg_conv;
396 conv = find_or_create_conversation(pinfo);
397 gg_conv = (struct gadu_gadu_conv_data *)conversation_get_proto_data(conv, proto_gadu_gadu);
398 if (!gg_conv) {
399 gg_conv = wmem_new(wmem_file_scope(), struct gadu_gadu_conv_data);
400 gg_conv->uin = uin;
402 conversation_add_proto_data(conv, proto_gadu_gadu, gg_conv);
404 /* assert(gg_conv->uin == uin); */
405 return gg_conv;
408 static struct gadu_gadu_conv_data *
409 gadu_gadu_get_conversation_data(packet_info *pinfo)
411 conversation_t *conv;
413 conv = find_conversation_pinfo(pinfo, 0);
414 if (conv)
415 return (struct gadu_gadu_conv_data *)conversation_get_proto_data(conv, proto_gadu_gadu);
416 return NULL;
419 static bool
420 gadu_gadu_status_has_descr(int status)
422 return
423 (status == GG_STATUS_NOT_AVAIL_DESCR) ||
424 (status == GG_STATUS_FFC_DESCR) ||
425 (status == GG_STATUS_AVAIL_DESCR) ||
426 (status == GG_STATUS_BUSY_DESCR) ||
427 (status == GG_STATUS_DND_DESCR) ||
428 (status == GG_STATUS_INVISIBLE_DESCR);
431 /* like tvb_strsize() but return maximum length instead of throwing exception */
432 static int
433 gadu_gadu_strsize(tvbuff_t *tvb, const int abs_offset)
435 int nul_offset;
437 nul_offset = tvb_find_uint8(tvb, abs_offset, -1, 0);
438 if (nul_offset == -1)
439 nul_offset = tvb_captured_length(tvb) - 1;
441 return (nul_offset - abs_offset) + 1;
444 static int
445 dissect_gadu_gadu_stringz_cp1250(tvbuff_t *tvb, int hfindex, proto_tree *tree, const int offset)
447 int len = gadu_gadu_strsize(tvb, offset);
449 proto_tree_add_item(tree, hfindex, tvb, offset, len, ENC_WINDOWS_1250 | ENC_NA);
451 return offset + len;
454 static int
455 dissect_gadu_gadu_uint32_string_utf8(tvbuff_t *tvb, int hfindex, proto_tree *tree, int offset)
457 const int org_offset = offset;
459 uint32_t len;
461 len = tvb_get_letohl(tvb, offset);
462 offset += 4;
464 offset += len;
466 proto_tree_add_item(tree, hfindex, tvb, org_offset, offset - org_offset, ENC_UTF_8 | ENC_NA);
468 return offset;
472 static int
473 dissect_gadu_gadu_disconnecting(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
475 col_set_str(pinfo->cinfo, COL_INFO, "Disconnecting");
477 /* empty packet */
479 return offset;
483 static int
484 dissect_gadu_gadu_disconnect_ack(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
486 col_set_str(pinfo->cinfo, COL_INFO, "Disconnect acknowledge (< 10.0)");
488 /* empty packet */
490 return offset;
493 static void *
494 _tvb_memcpy_reverse(tvbuff_t *tvb, void *target, int offset, size_t length)
496 uint8_t *t = (uint8_t *) target;
498 while (length > 0) {
499 length--;
500 t[length] = tvb_get_uint8(tvb, offset);
501 offset++;
503 return target;
506 static int
507 dissect_gadu_gadu_login_protocol(tvbuff_t *tvb, proto_tree *tree, int offset)
509 proto_item *ti;
511 uint32_t protocol;
513 protocol = tvb_get_letohl(tvb, offset) & 0xff;
514 proto_tree_add_item(tree, hf_gadu_gadu_login_protocol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
515 ti = proto_tree_add_string(tree, hf_gadu_gadu_login_version, tvb, offset, 4, val_to_str(protocol, gadu_gadu_version_vals, "Unknown (0x%x)"));
516 proto_item_set_generated(ti);
517 offset += 4;
519 return offset;
522 static int
523 dissect_gadu_gadu_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
525 proto_item *ti;
527 uint32_t uin;
528 uint8_t hash[4];
530 col_set_str(pinfo->cinfo, COL_INFO, "Login request (< 6.0)");
532 uin = tvb_get_letohl(tvb, offset);
533 gadu_gadu_create_conversation(pinfo, uin);
535 proto_tree_add_uint(tree, hf_gadu_gadu_login_uin, tvb, offset, 4, uin);
536 offset += 4;
538 ti = proto_tree_add_uint(tree, hf_gadu_gadu_login_hash_type, tvb, 0, 0, GG_LOGIN_HASH_GG32);
539 proto_item_set_generated(ti);
541 /* hash is 32-bit number written in LE */
542 _tvb_memcpy_reverse(tvb, hash, offset, 4);
543 proto_tree_add_bytes_format_value(tree, hf_gadu_gadu_login_hash, tvb, offset, 4, hash, "0x%.8x", tvb_get_letohl(tvb, offset));
544 offset += 4;
546 proto_tree_add_item(tree, hf_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
547 offset += 4;
549 offset = dissect_gadu_gadu_login_protocol(tvb, tree, offset);
551 proto_tree_add_item(tree, hf_gadu_gadu_login_local_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
552 offset += 4;
554 proto_tree_add_item(tree, hf_gadu_gadu_login_local_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
555 offset += 2;
557 return offset;
560 static int
561 dissect_gadu_gadu_login_hash(tvbuff_t *tvb, proto_tree *tree, int offset)
563 uint8_t hash_type;
565 uint8_t hash[4];
566 int i;
568 hash_type = tvb_get_uint8(tvb, offset);
569 proto_tree_add_item(tree, hf_gadu_gadu_login_hash_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
570 offset += 1;
572 switch (hash_type) {
573 case GG_LOGIN_HASH_GG32:
574 /* hash is 32-bit number written in LE */
575 _tvb_memcpy_reverse(tvb, hash, offset, 4);
576 proto_tree_add_bytes_format_value(tree, hf_gadu_gadu_login_hash, tvb, offset, 4, hash, "0x%.8x", tvb_get_letohl(tvb, offset));
577 for (i = 4; i < 64; i++) {
578 if (tvb_get_uint8(tvb, offset+i)) {
579 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset + 4, 64-4, ENC_NA);
580 break;
583 break;
585 case GG_LOGIN_HASH_SHA1:
586 proto_tree_add_item(tree, hf_gadu_gadu_login_hash, tvb, offset, 20, ENC_NA);
587 for (i = 20; i < 64; i++) {
588 if (tvb_get_uint8(tvb, offset+i)) {
589 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset + 20, 64-20, ENC_NA);
590 break;
593 break;
595 default:
596 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 64, ENC_NA);
597 break;
599 offset += 64;
601 return offset;
604 static int
605 dissect_gadu_gadu_login70(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
607 uint32_t uin;
609 col_set_str(pinfo->cinfo, COL_INFO, "Login request (7.0)");
611 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
612 gadu_gadu_create_conversation(pinfo, uin);
614 proto_tree_add_uint(tree, hf_gadu_gadu_login_uin, tvb, offset, 4, uin);
615 offset += 4;
617 offset = dissect_gadu_gadu_login_hash(tvb, tree, offset);
619 proto_tree_add_item(tree, hf_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
620 offset += 4;
622 offset = dissect_gadu_gadu_login_protocol(tvb, tree, offset);
624 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
625 offset += 1;
627 proto_tree_add_item(tree, hf_gadu_gadu_login_local_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
628 offset += 4;
630 proto_tree_add_item(tree, hf_gadu_gadu_login_local_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
631 offset += 2;
633 /* XXX packet not fully dissected */
635 return offset;
638 static int
639 dissect_gadu_gadu_login80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
641 uint32_t uin;
643 col_set_str(pinfo->cinfo, COL_INFO, "Login request (8.0)");
645 uin = tvb_get_letohl(tvb, offset);
646 gadu_gadu_create_conversation(pinfo, uin);
648 proto_tree_add_item(tree, hf_gadu_gadu_login_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
649 offset += 4;
651 proto_tree_add_item(tree, hf_gadu_gadu_login80_lang, tvb, offset, 2, ENC_ASCII | ENC_NA);
652 offset += 2;
654 offset = dissect_gadu_gadu_login_hash(tvb, tree, offset);
656 proto_tree_add_item(tree, hf_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
657 offset += 4;
659 /* XXX packet not fully dissected */
661 return offset;
664 static int
665 dissect_gadu_gadu_login_ok(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
667 col_set_str(pinfo->cinfo, COL_INFO, "Login success (< 8.0)");
669 /* not empty packet, but content unknown */
671 return offset;
674 static int
675 dissect_gadu_gadu_login_failed(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
677 col_set_str(pinfo->cinfo, COL_INFO, "Login fail (< 8.0)");
679 /* empty packet */
681 return offset;
684 static int
685 dissect_gadu_gadu_login_ok80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
687 col_set_str(pinfo->cinfo, COL_INFO, "Login success (8.0)");
689 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 4, ENC_NA); /* 01 00 00 00 */
690 offset += 4;
692 return offset;
695 static int
696 dissect_gadu_gadu_login80_failed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
698 col_set_str(pinfo->cinfo, COL_INFO, "Login fail (8.0)");
700 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 4, ENC_NA); /* 01 00 00 00 */
701 offset += 4;
703 return offset;
706 static int
707 dissect_gadu_gadu_user_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
709 uint32_t users_num;
711 col_set_str(pinfo->cinfo, COL_INFO, "Contact details");
713 /* XXX, add subtrees */
715 offset += 4;
717 users_num = tvb_get_letohl(tvb, offset);
718 offset += 4;
720 while (users_num--) {
721 uint32_t attr_num;
723 proto_tree_add_item(tree, hf_gadu_gadu_userdata_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
724 offset += 4;
726 attr_num = tvb_get_letohl(tvb, offset);
727 offset += 4;
729 while (attr_num--) {
730 uint32_t name_size, val_size;
731 char *name, *val;
732 /* name */
733 name_size = tvb_get_letohl(tvb, offset);
734 offset += 4;
736 name = tvb_get_string_enc(pinfo->pool, tvb, offset, name_size, ENC_ASCII | ENC_NA);
737 proto_tree_add_string(tree, hf_gadu_gadu_userdata_attr_name, tvb, offset - 4, 4 + name_size, name);
738 offset += name_size;
739 /* type */
740 proto_tree_add_item(tree, hf_gadu_gadu_userdata_attr_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
741 offset += 4;
742 /* value */
743 val_size = tvb_get_letohl(tvb, offset);
744 offset += 4;
746 val = tvb_get_string_enc(pinfo->pool, tvb, offset, val_size, ENC_ASCII | ENC_NA);
747 proto_tree_add_string(tree, hf_gadu_gadu_userdata_attr_value, tvb, offset - 4, 4 + val_size, val);
748 offset += val_size;
752 return offset;
755 static int
756 dissect_gadu_gadu_typing_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
758 col_set_str(pinfo->cinfo, COL_INFO, "Typing notify");
760 /* XXX, when type > 1, it's length not type ! */
761 proto_tree_add_item(tree, hf_gadu_gadu_typing_notify_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
762 offset += 2;
764 proto_tree_add_item(tree, hf_gadu_gadu_typing_notify_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
765 offset += 4;
767 return offset;
770 static int
771 dissect_gadu_gadu_msg_attr(tvbuff_t *tvb _U_, proto_tree *tree _U_, int offset)
773 /* XXX, stub */
775 return offset;
778 static int
779 dissect_gadu_gadu_recv_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
781 struct gadu_gadu_conv_data *conv;
782 proto_item *ti;
784 col_set_str(pinfo->cinfo, COL_INFO, "Receive message (< 8.0)");
786 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
787 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_recipient, tvb, 0, 0, conv->uin);
788 proto_item_set_generated(ti);
790 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
791 proto_item_set_generated(ti);
792 proto_item_set_hidden(ti);
795 ti = proto_tree_add_item(tree, hf_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
796 proto_item_set_hidden(ti);
797 proto_tree_add_item(tree, hf_gadu_gadu_msg_sender, tvb, offset, 4, ENC_LITTLE_ENDIAN);
798 offset += 4;
800 proto_tree_add_item(tree, hf_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
801 offset += 4;
803 proto_tree_add_item(tree, hf_gadu_gadu_msg_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
804 offset += 4;
806 proto_tree_add_item(tree, hf_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
807 offset += 4;
809 offset = dissect_gadu_gadu_stringz_cp1250(tvb, hf_gadu_gadu_msg_text, tree, offset);
811 offset = dissect_gadu_gadu_msg_attr(tvb, tree, offset);
813 return offset;
816 static int
817 dissect_gadu_gadu_send_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
819 struct gadu_gadu_conv_data *conv;
820 proto_item *ti;
822 col_set_str(pinfo->cinfo, COL_INFO, "Send message (< 8.0)");
824 ti = proto_tree_add_item(tree, hf_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
825 proto_item_set_hidden(ti);
826 proto_tree_add_item(tree, hf_gadu_gadu_msg_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
827 offset += 4;
829 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
830 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_sender, tvb, 0, 0, conv->uin);
831 proto_item_set_generated(ti);
833 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
834 proto_item_set_generated(ti);
835 proto_item_set_hidden(ti);
838 proto_tree_add_item(tree, hf_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
839 offset += 4;
841 ti = proto_tree_add_time(tree, hf_gadu_gadu_msg_time, tvb, 0, 0, &(pinfo->abs_ts));
842 proto_item_set_generated(ti);
844 proto_tree_add_item(tree, hf_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
845 offset += 4;
847 offset = dissect_gadu_gadu_stringz_cp1250(tvb, hf_gadu_gadu_msg_text, tree, offset);
849 offset = dissect_gadu_gadu_msg_attr(tvb, tree, offset);
851 return offset;
854 static int
855 dissect_gadu_gadu_recv_msg80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
857 struct gadu_gadu_conv_data *conv;
858 proto_item *ti;
860 col_set_str(pinfo->cinfo, COL_INFO, "Receive message (8.0)");
862 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
863 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_recipient, tvb, 0, 0, conv->uin);
864 proto_item_set_generated(ti);
866 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
867 proto_item_set_generated(ti);
868 proto_item_set_hidden(ti);
871 ti = proto_tree_add_item(tree, hf_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
872 proto_item_set_hidden(ti);
873 proto_tree_add_item(tree, hf_gadu_gadu_msg_sender, tvb, offset, 4, ENC_LITTLE_ENDIAN);
874 offset += 4;
876 proto_tree_add_item(tree, hf_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
877 offset += 4;
879 proto_tree_add_item(tree, hf_gadu_gadu_msg_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
880 offset += 4;
882 proto_tree_add_item(tree, hf_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
883 offset += 4;
885 proto_tree_add_item(tree, hf_gadu_gadu_msg80_offset_plain, tvb, offset, 4, ENC_LITTLE_ENDIAN);
886 offset += 4;
888 proto_tree_add_item(tree, hf_gadu_gadu_msg80_offset_attr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
889 offset += 4;
891 /* XXX packet not fully dissected */
893 return offset;
896 static int
897 dissect_gadu_gadu_send_msg80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
899 struct gadu_gadu_conv_data *conv;
900 proto_item *ti;
902 col_set_str(pinfo->cinfo, COL_INFO, "Send message (8.0)");
904 ti = proto_tree_add_item(tree, hf_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
905 proto_item_set_hidden(ti);
906 proto_tree_add_item(tree, hf_gadu_gadu_msg_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
907 offset += 4;
909 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
910 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_sender, tvb, 0, 0, conv->uin);
911 proto_item_set_generated(ti);
913 ti = proto_tree_add_uint(tree, hf_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
914 proto_item_set_generated(ti);
915 proto_item_set_hidden(ti);
918 proto_tree_add_item(tree, hf_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
919 offset += 4;
921 ti = proto_tree_add_time(tree, hf_gadu_gadu_msg_time, tvb, 0, 0, &(pinfo->abs_ts));
922 proto_item_set_generated(ti);
924 proto_tree_add_item(tree, hf_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
925 offset += 4;
927 proto_tree_add_item(tree, hf_gadu_gadu_msg80_offset_plain, tvb, offset, 4, ENC_LITTLE_ENDIAN);
928 offset += 4;
930 proto_tree_add_item(tree, hf_gadu_gadu_msg80_offset_attr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
931 offset += 4;
933 /* XXX packet not fully dissected */
935 return offset;
938 static int
939 dissect_gadu_gadu_send_msg_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
941 col_set_str(pinfo->cinfo, COL_INFO, "Message acknowledge (server)");
943 proto_tree_add_item(tree, hf_gadu_gadu_msg_ack_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
944 offset += 4;
946 proto_tree_add_item(tree, hf_gadu_gadu_msg_ack_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
947 offset += 4;
949 proto_tree_add_item(tree, hf_gadu_gadu_msg_ack_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
950 offset += 4;
952 return offset;
955 static int
956 dissect_gadu_gadu_recv_msg_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
958 col_set_str(pinfo->cinfo, COL_INFO, "Message acknowledge (client)");
960 proto_tree_add_item(tree, hf_gadu_gadu_msg_ack_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
961 offset += 4;
963 return offset;
966 static int
967 dissect_gadu_gadu_status60(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
969 uint32_t uin;
970 uint8_t status;
972 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (6.0)");
974 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
975 proto_tree_add_uint(tree, hf_gadu_gadu_status_uin, tvb, offset, 4, uin);
976 offset += 4;
978 status = tvb_get_uint8(tvb, offset);
979 proto_tree_add_item(tree, hf_gadu_gadu_status_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
980 offset += 1;
982 proto_tree_add_item(tree, hf_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
983 offset += 4;
985 proto_tree_add_item(tree, hf_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
986 offset += 2;
988 proto_tree_add_item(tree, hf_gadu_gadu_status_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
989 offset += 1;
991 proto_tree_add_item(tree, hf_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
992 offset += 1;
994 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
995 offset += 1;
997 if (gadu_gadu_status_has_descr(status))
998 offset = dissect_gadu_gadu_stringz_cp1250(tvb, hf_gadu_gadu_status_descr, tree, offset);
1000 return offset;
1003 static int
1004 dissect_gadu_gadu_status77(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1006 uint32_t uin;
1007 uint8_t status;
1009 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (7.7)");
1011 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
1012 proto_tree_add_uint(tree, hf_gadu_gadu_status_uin, tvb, offset, 4, uin);
1013 offset += 4;
1015 status = tvb_get_uint8(tvb, offset);
1016 proto_tree_add_item(tree, hf_gadu_gadu_status_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1017 offset += 1;
1019 proto_tree_add_item(tree, hf_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1020 offset += 4;
1022 proto_tree_add_item(tree, hf_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1023 offset += 2;
1025 proto_tree_add_item(tree, hf_gadu_gadu_status_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1026 offset += 1;
1028 proto_tree_add_item(tree, hf_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1029 offset += 1;
1031 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
1032 offset += 1;
1034 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1035 offset += 4;
1037 if (gadu_gadu_status_has_descr(status))
1038 offset = dissect_gadu_gadu_stringz_cp1250(tvb, hf_gadu_gadu_status_descr, tree, offset);
1040 return offset;
1043 static int
1044 dissect_gadu_gadu_status80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1046 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (8.0)");
1048 proto_tree_add_item(tree, hf_gadu_gadu_status_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1049 offset += 4;
1051 proto_tree_add_item(tree, hf_gadu_gadu_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1052 offset += 4;
1054 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1055 offset += 4;
1057 proto_tree_add_item(tree, hf_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1058 offset += 4;
1060 proto_tree_add_item(tree, hf_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1061 offset += 2;
1063 proto_tree_add_item(tree, hf_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1064 offset += 1;
1066 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 1, ENC_NA);
1067 offset += 1;
1069 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1070 offset += 4;
1072 offset = dissect_gadu_gadu_uint32_string_utf8(tvb, hf_gadu_gadu_status_descr, tree, offset);
1074 return offset;
1077 static int
1078 dissect_gadu_gadu_notify_reply80(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1080 col_set_str(pinfo->cinfo, COL_INFO, "Receive status list (8.0)");
1082 /* XXX packet not fully dissected */
1084 return offset;
1087 static int
1088 dissect_gadu_gadu_new_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1090 uint32_t status;
1092 col_set_str(pinfo->cinfo, COL_INFO, "New status (< 8.0)");
1094 status = tvb_get_letohl(tvb, offset);
1095 proto_tree_add_item(tree, hf_gadu_gadu_new_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1096 offset += 4;
1098 if (gadu_gadu_status_has_descr(status & 0xff))
1099 offset = dissect_gadu_gadu_stringz_cp1250(tvb, hf_gadu_gadu_status_descr, tree, offset);
1101 return offset;
1104 static int
1105 dissect_gadu_gadu_new_status80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1107 col_set_str(pinfo->cinfo, COL_INFO, "New status (8.0)");
1109 proto_tree_add_item(tree, hf_gadu_gadu_new_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1110 offset += 4;
1112 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1113 offset += 4;
1115 offset = dissect_gadu_gadu_uint32_string_utf8(tvb, hf_gadu_gadu_new_status_desc, tree, offset);
1117 return offset;
1120 static int
1121 dissect_gadu_gadu_list_empty(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1123 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (empty)");
1125 /* empty packet */
1127 return offset;
1130 static int
1131 dissect_gadu_gadu_add_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1133 col_set_str(pinfo->cinfo, COL_INFO, "Notify list add");
1135 proto_tree_add_item(tree, hf_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1136 offset += 4;
1138 proto_tree_add_item(tree, hf_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1139 offset += 1;
1141 return offset;
1144 static int
1145 dissect_gadu_gadu_notify105_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, char **puin)
1147 uint16_t uin_len;
1148 char *uin;
1150 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* unknown 00 */
1151 offset += 1;
1153 uin_len = tvb_get_uint8(tvb, offset);
1154 offset += 1;
1155 uin = tvb_get_string_enc(pinfo->pool, tvb, offset, uin_len, ENC_ASCII | ENC_NA);
1156 proto_tree_add_string(tree, hf_gadu_gadu_contact_uin_str, tvb, offset - 1, 1 + uin_len, uin);
1157 offset += uin_len;
1158 if (puin)
1159 *puin = uin;
1161 proto_tree_add_item(tree, hf_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1162 offset += 1;
1164 return offset;
1167 static int
1168 dissect_gadu_gadu_add_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1170 col_set_str(pinfo->cinfo, COL_INFO, "Notify list add (10.5)");
1172 return dissect_gadu_gadu_notify105_common(tvb, pinfo, tree, offset, NULL);
1175 static int
1176 dissect_gadu_gadu_remove_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1178 col_set_str(pinfo->cinfo, COL_INFO, "Notify list remove");
1180 proto_tree_add_item(tree, hf_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1181 offset += 4;
1183 proto_tree_add_item(tree, hf_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1184 offset += 1;
1186 return offset;
1189 static int
1190 dissect_gadu_gadu_remove_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1192 col_set_str(pinfo->cinfo, COL_INFO, "Notify list remove (10.5)");
1194 return dissect_gadu_gadu_notify105_common(tvb, pinfo, tree, offset, NULL);
1197 static int
1198 dissect_gadu_gadu_notify_common(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1200 proto_tree *contact_tree;
1202 while (tvb_reported_length_remaining(tvb, offset) >= 4+1) {
1203 uint32_t uin = tvb_get_letohl(tvb, offset);
1205 contact_tree = proto_tree_add_subtree_format(tree, tvb, offset, 5,
1206 ett_gadu_gadu_contact, NULL, "Contact: %u", uin);
1208 proto_tree_add_item(contact_tree, hf_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1209 offset += 4;
1211 proto_tree_add_item(contact_tree, hf_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1212 offset += 1;
1215 return offset;
1218 static int
1219 dissect_gadu_gadu_notify_first(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1221 col_set_str(pinfo->cinfo, COL_INFO, "Notify list");
1223 return dissect_gadu_gadu_notify_common(tvb, pinfo, tree, offset);
1226 static int
1227 dissect_gadu_gadu_notify_last(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1229 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (last)");
1231 return dissect_gadu_gadu_notify_common(tvb, pinfo, tree, offset);
1234 static int
1235 dissect_gadu_gadu_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1237 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (10.5)");
1239 while (tvb_reported_length_remaining(tvb, offset) >= 2) {
1240 const int org_offset = offset;
1242 proto_tree *contact_tree;
1243 proto_item *ti;
1245 char *uin;
1247 contact_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_gadu_gadu_contact, &ti, "Contact: ");
1249 offset = dissect_gadu_gadu_notify105_common(tvb, pinfo, contact_tree, offset, &uin);
1250 proto_item_append_text(ti, "%s", uin);
1252 proto_item_set_len(ti, offset - org_offset);
1255 return offset;
1258 static int
1259 dissect_gadu_gadu_ping(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1261 col_set_str(pinfo->cinfo, COL_INFO, "Ping");
1263 /* empty packet */
1265 return offset;
1268 static int
1269 dissect_gadu_gadu_welcome(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1271 col_set_str(pinfo->cinfo, COL_INFO, "Welcome");
1273 proto_tree_add_item(tree, hf_gadu_gadu_welcome_seed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1274 offset += 4;
1276 return offset;
1279 static int
1280 dissect_gadu_gadu_userlist_xml_compressed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1282 int remain = tvb_reported_length_remaining(tvb, offset);
1283 tvbuff_t *uncomp_tvb;
1285 if (remain <= 0)
1286 return offset;
1288 if ((uncomp_tvb = tvb_child_uncompress_zlib(tvb, tvb, offset, remain))) {
1289 proto_tree_add_bytes_format_value(tree, hf_gadu_gadu_userlist, tvb, offset, remain, NULL, "%s", "[Decompression succeeded]");
1291 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed userlist");
1293 /* XXX add DTD (pinfo->match_string) */
1294 call_dissector_only(xml_handle, uncomp_tvb, pinfo, tree, NULL);
1295 } else
1296 proto_tree_add_bytes_format_value(tree, hf_gadu_gadu_userlist, tvb, offset, remain, NULL, "%s", "[Error: Decompression failed] (or no zlib)");
1298 offset += remain;
1300 return offset;
1303 static int
1304 dissect_gadu_gadu_userlist_request80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1306 uint8_t type;
1307 proto_item *ti;
1309 col_set_str(pinfo->cinfo, COL_INFO, "Userlist request (8.0)");
1311 type = tvb_get_uint8(tvb, offset);
1312 proto_tree_add_item(tree, hf_gadu_gadu_userlist_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1313 offset += 1;
1315 ti = proto_tree_add_uint(tree, hf_gadu_gadu_userlist_format, tvb, 0, 0, GG_USERLIST100_FORMAT_TYPE_GG100);
1316 proto_item_set_generated(ti);
1318 switch (type) {
1319 case GG_USERLIST_PUT:
1320 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1321 break;
1324 return offset;
1327 static int
1328 dissect_gadu_gadu_userlist_request100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1330 uint8_t type, format;
1332 col_set_str(pinfo->cinfo, COL_INFO, "Userlist request (10.0)");
1334 type = tvb_get_uint8(tvb, offset);
1335 proto_tree_add_item(tree, hf_gadu_gadu_userlist_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1336 offset += 1;
1338 proto_tree_add_item(tree, hf_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1339 offset += 4;
1341 format = tvb_get_uint8(tvb, offset);
1342 proto_tree_add_item(tree, hf_gadu_gadu_userlist_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1343 offset += 1;
1345 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 01 */
1346 offset += 1;
1348 switch (type) {
1349 case GG_USERLIST_PUT:
1350 if (format == GG_USERLIST100_FORMAT_TYPE_GG100)
1351 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1352 break;
1355 return offset;
1358 static int
1359 dissect_gadu_gadu_userlist_reply80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1361 uint8_t type;
1363 col_set_str(pinfo->cinfo, COL_INFO, "Userlist reply (8.0)");
1365 type = tvb_get_uint8(tvb, offset);
1366 proto_tree_add_item(tree, hf_gadu_gadu_userlist_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1367 offset += 1;
1369 switch (type) {
1370 case GG_USERLIST_GET_REPLY:
1371 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1372 break;
1375 return offset;
1378 static int
1379 dissect_gadu_gadu_userlist_reply100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1381 uint8_t type, format;
1383 col_set_str(pinfo->cinfo, COL_INFO, "Userlist reply (10.0)");
1385 type = tvb_get_uint8(tvb, offset);
1386 proto_tree_add_item(tree, hf_gadu_gadu_userlist_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1387 offset += 1;
1389 proto_tree_add_item(tree, hf_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1390 offset += 4;
1392 format = tvb_get_uint8(tvb, offset);
1393 proto_tree_add_item(tree, hf_gadu_gadu_userlist_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1394 offset += 1;
1396 proto_tree_add_item(tree, hf_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 01 */
1397 offset += 1;
1399 switch (type) {
1400 case GG_USERLIST_GET_REPLY:
1401 if (format == GG_USERLIST100_FORMAT_TYPE_GG100)
1402 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1403 break;
1406 return offset;
1409 static int
1410 dissect_gadu_gadu_userlist_version100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1412 col_set_str(pinfo->cinfo, COL_INFO, "Userlist version (10.0)");
1414 proto_tree_add_item(tree, hf_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1415 offset += 4;
1417 return offset;
1420 static int
1421 dissect_gadu_gadu_dcc7_id_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1423 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection id request");
1425 proto_tree_add_item(tree, hf_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1426 offset += 4;
1428 return offset;
1431 static int
1432 dissect_gadu_gadu_dcc7_id_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1434 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection id reply");
1436 proto_tree_add_item(tree, hf_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1437 offset += 4;
1439 proto_tree_add_item(tree, hf_dcc_id, tvb, offset, 8, ENC_NA);
1440 offset += 8;
1442 return offset;
1445 static int
1446 dissect_gadu_gadu_dcc7_new(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1448 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection new");
1450 proto_tree_add_item(tree, hf_dcc_id, tvb, offset, 8, ENC_NA);
1451 offset += 8;
1453 proto_tree_add_item(tree, hf_dcc_uin_from, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1454 offset += 4;
1456 proto_tree_add_item(tree, hf_dcc_uin_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1457 offset += 4;
1459 proto_tree_add_item(tree, hf_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1460 offset += 4;
1462 proto_tree_add_item(tree, hf_dcc_filename, tvb, offset, 255, ENC_ASCII | ENC_NA);
1463 offset += 255;
1465 return offset;
1468 static int
1469 dissect_gadu_gadu_dcc7_id_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1471 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection abort");
1473 proto_tree_add_item(tree, hf_dcc_id, tvb, offset, 8, ENC_NA);
1474 offset += 8;
1476 proto_tree_add_item(tree, hf_dcc_uin_from, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1477 offset += 4;
1479 proto_tree_add_item(tree, hf_dcc_uin_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1480 offset += 4;
1482 return offset;
1485 static int
1486 dissect_gadu_gadu_pubdir50_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1488 int pos;
1490 col_set_str(pinfo->cinfo, COL_INFO, "Public directory request");
1492 proto_tree_add_item(tree, hf_gadu_gadu_pubdir_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1493 offset += 1;
1495 proto_tree_add_item(tree, hf_gadu_gadu_pubdir_request_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1496 offset += 4;
1497 /* XXX, link request sequence with reply sequence */
1499 while ((pos = tvb_find_uint8(tvb, offset, -1, '\0')) > 0) {
1500 /* XXX, display it better, field=value */
1501 proto_tree_add_item(tree, hf_gadu_gadu_pubdir_request_str, tvb, offset, (pos - offset) + 1, ENC_NA | ENC_WINDOWS_1250);
1502 offset = pos + 1;
1505 return offset;
1508 static int
1509 dissect_gadu_gadu_pubdir50_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1511 int pos;
1513 col_set_str(pinfo->cinfo, COL_INFO, "Public directory reply");
1515 proto_tree_add_item(tree, hf_gadu_gadu_pubdir_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1516 offset += 1;
1518 proto_tree_add_item(tree, hf_gadu_gadu_pubdir_reply_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1519 offset += 4;
1520 /* XXX, link reply sequence with request sequence */
1522 while ((pos = tvb_find_uint8(tvb, offset, -1, '\0')) > 0) {
1523 /* XXX, display it better, field=value */
1524 proto_tree_add_item(tree, hf_gadu_gadu_pubdir_reply_str, tvb, offset, (pos - offset) + 1, ENC_NA | ENC_WINDOWS_1250);
1525 offset = pos + 1;
1528 return offset;
1531 static int
1532 dissect_gadu_gadu_xml_action(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1534 tvbuff_t *xml_tvb;
1535 int ret;
1537 col_set_str(pinfo->cinfo, COL_INFO, "XML action message");
1539 xml_tvb = tvb_new_subset_remaining(tvb, offset);
1541 /* XXX add DTD (pinfo->match_string) */
1542 ret = call_dissector_only(xml_handle, xml_tvb, pinfo, tree, NULL);
1544 return offset + ret;
1547 static int
1548 dissect_gadu_gadu_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1550 proto_tree *gadu_gadu_tree = NULL;
1552 int offset = 0;
1553 uint32_t pkt_type;
1555 col_clear(pinfo->cinfo, COL_INFO); /* XXX, remove, add separator when multiple PDU */
1557 if (tree) {
1558 proto_item *ti = proto_tree_add_item(tree, proto_gadu_gadu, tvb, 0, -1, ENC_NA);
1559 gadu_gadu_tree = proto_item_add_subtree(ti, ett_gadu_gadu);
1562 pkt_type = tvb_get_letohl(tvb, offset);
1563 proto_tree_add_item(gadu_gadu_tree, (pinfo->p2p_dir == P2P_DIR_RECV) ? hf_gadu_gadu_header_type_recv : hf_gadu_gadu_header_type_send, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1564 offset += 4;
1565 proto_tree_add_item(gadu_gadu_tree, hf_gadu_gadu_header_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1566 offset += 4;
1568 if (pinfo->p2p_dir == P2P_DIR_RECV) {
1569 switch (pkt_type) {
1570 case GG_DISCONNECTING:
1571 offset = dissect_gadu_gadu_disconnecting(tvb, pinfo, gadu_gadu_tree, offset);
1572 break;
1574 case GG_DISCONNECT_ACK:
1575 offset = dissect_gadu_gadu_disconnect_ack(tvb, pinfo, gadu_gadu_tree, offset);
1576 break;
1578 case GG_LOGIN_OK:
1579 offset = dissect_gadu_gadu_login_ok(tvb, pinfo, gadu_gadu_tree, offset);
1580 break;
1582 case GG_LOGIN_OK80:
1583 offset = dissect_gadu_gadu_login_ok80(tvb, pinfo, gadu_gadu_tree, offset);
1584 break;
1586 case GG_LOGIN_FAILED:
1587 offset = dissect_gadu_gadu_login_failed(tvb, pinfo, gadu_gadu_tree, offset);
1588 break;
1590 case GG_LOGIN80_FAILED:
1591 offset = dissect_gadu_gadu_login80_failed(tvb, pinfo, gadu_gadu_tree, offset);
1592 break;
1594 case GG_USER_DATA:
1595 offset = dissect_gadu_gadu_user_data(tvb, pinfo, gadu_gadu_tree, offset);
1596 break;
1598 case GG_TYPING_NOTIFY:
1599 offset = dissect_gadu_gadu_typing_notify(tvb, pinfo, gadu_gadu_tree, offset);
1600 break;
1602 case GG_RECV_MSG:
1603 offset = dissect_gadu_gadu_recv_msg(tvb, pinfo, gadu_gadu_tree, offset);
1604 break;
1606 case GG_RECV_MSG80:
1607 offset = dissect_gadu_gadu_recv_msg80(tvb, pinfo, gadu_gadu_tree, offset);
1608 break;
1610 case GG_SEND_MSG_ACK:
1611 /* GG_SEND_MSG_ACK is received by client */
1612 offset = dissect_gadu_gadu_send_msg_ack(tvb, pinfo, gadu_gadu_tree, offset);
1613 break;
1615 case GG_STATUS60:
1616 offset = dissect_gadu_gadu_status60(tvb, pinfo, gadu_gadu_tree, offset);
1617 break;
1619 case GG_STATUS77:
1620 offset = dissect_gadu_gadu_status77(tvb, pinfo, gadu_gadu_tree, offset);
1621 break;
1623 case GG_STATUS80:
1624 offset = dissect_gadu_gadu_status80(tvb, pinfo, gadu_gadu_tree, offset);
1625 break;
1627 case GG_NOTIFY_REPLY80:
1628 offset = dissect_gadu_gadu_notify_reply80(tvb, pinfo, gadu_gadu_tree, offset);
1629 break;
1631 case GG_DCC7_ID_REPLY:
1632 offset = dissect_gadu_gadu_dcc7_id_reply(tvb, pinfo, gadu_gadu_tree, offset);
1633 break;
1635 case GG_WELCOME:
1636 offset = dissect_gadu_gadu_welcome(tvb, pinfo, gadu_gadu_tree, offset);
1637 break;
1639 case GG_USERLIST_REPLY80:
1640 offset = dissect_gadu_gadu_userlist_reply80(tvb, pinfo, gadu_gadu_tree, offset);
1641 break;
1643 case GG_USERLIST100_REPLY:
1644 offset = dissect_gadu_gadu_userlist_reply100(tvb, pinfo, gadu_gadu_tree, offset);
1645 break;
1647 case GG_USERLIST100_VERSION:
1648 offset = dissect_gadu_gadu_userlist_version100(tvb, pinfo, gadu_gadu_tree, offset);
1649 break;
1651 case GG_PUBDIR50_REPLY:
1652 offset = dissect_gadu_gadu_pubdir50_reply(tvb, pinfo, gadu_gadu_tree, offset);
1653 break;
1655 case GG_XML_ACTION:
1656 offset = dissect_gadu_gadu_xml_action(tvb, pinfo, gadu_gadu_tree, offset);
1657 break;
1659 case GG_STATUS:
1660 case GG_PONG:
1661 case GG_PING:
1662 case GG_NOTIFY_REPLY:
1663 case GG_USERLIST_REPLY:
1664 case GG_NOTIFY_REPLY60:
1665 case GG_NEED_EMAIL:
1666 case GG_LOGIN_HASH_TYPE_INVALID:
1667 case GG_NOTIFY_REPLY77:
1668 case GG_DCC7_INFO:
1669 case GG_DCC7_NEW:
1670 case GG_DCC7_ACCEPT:
1671 case GG_DCC7_REJECT:
1672 case GG_DCC7_ID_ABORTED:
1673 case GG_XML_EVENT:
1674 case GG_STATUS80BETA:
1675 case GG_NOTIFY_REPLY80BETA:
1676 case GG_OWN_MESSAGE:
1677 case GG_OWN_RESOURCE_INFO:
1678 default:
1680 const char *pkt_name = try_val_to_str(pkt_type, gadu_gadu_packets_type_recv);
1682 if (pkt_name)
1683 col_set_str(pinfo->cinfo, COL_INFO, pkt_name);
1684 else
1685 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown recv packet: %.2x", pkt_type);
1686 break;
1690 } else {
1691 switch (pkt_type) {
1692 case GG_LOGIN:
1693 offset = dissect_gadu_gadu_login(tvb, pinfo, gadu_gadu_tree, offset);
1694 break;
1696 case GG_LOGIN70:
1697 offset = dissect_gadu_gadu_login70(tvb, pinfo, gadu_gadu_tree, offset);
1698 break;
1700 case GG_LOGIN80:
1701 offset = dissect_gadu_gadu_login80(tvb, pinfo, gadu_gadu_tree, offset);
1702 break;
1704 case GG_LIST_EMPTY:
1705 offset = dissect_gadu_gadu_list_empty(tvb, pinfo, gadu_gadu_tree, offset);
1706 break;
1708 case GG_NOTIFY_FIRST:
1709 offset = dissect_gadu_gadu_notify_first(tvb, pinfo, gadu_gadu_tree, offset);
1710 break;
1712 case GG_NOTIFY_LAST:
1713 offset = dissect_gadu_gadu_notify_last(tvb, pinfo, gadu_gadu_tree, offset);
1714 break;
1716 case GG_NOTIFY105:
1717 offset = dissect_gadu_gadu_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1718 break;
1720 case GG_ADD_NOTIFY:
1721 offset = dissect_gadu_gadu_add_notify(tvb, pinfo, gadu_gadu_tree, offset);
1722 break;
1724 case GG_ADD_NOTIFY105:
1725 offset = dissect_gadu_gadu_add_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1726 break;
1728 case GG_REMOVE_NOTIFY:
1729 offset = dissect_gadu_gadu_remove_notify(tvb, pinfo, gadu_gadu_tree, offset);
1730 break;
1732 case GG_REMOVE_NOTIFY105:
1733 offset = dissect_gadu_gadu_remove_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1734 break;
1736 case GG_PING:
1737 offset = dissect_gadu_gadu_ping(tvb, pinfo, gadu_gadu_tree, offset);
1738 break;
1740 case GG_TYPING_NOTIFY:
1741 offset = dissect_gadu_gadu_typing_notify(tvb, pinfo, gadu_gadu_tree, offset);
1742 break;
1744 case GG_SEND_MSG:
1745 offset = dissect_gadu_gadu_send_msg(tvb, pinfo, gadu_gadu_tree, offset);
1746 break;
1748 case GG_SEND_MSG80:
1749 offset = dissect_gadu_gadu_send_msg80(tvb, pinfo, gadu_gadu_tree, offset);
1750 break;
1752 case GG_RECV_MSG_ACK:
1753 /* GG_RECV_MSG_ACK is send by client */
1754 offset = dissect_gadu_gadu_recv_msg_ack(tvb, pinfo, gadu_gadu_tree, offset);
1755 break;
1757 case GG_NEW_STATUS:
1758 offset = dissect_gadu_gadu_new_status(tvb, pinfo, gadu_gadu_tree, offset);
1759 break;
1761 case GG_NEW_STATUS80:
1762 offset = dissect_gadu_gadu_new_status80(tvb, pinfo, gadu_gadu_tree, offset);
1763 break;
1765 case GG_DCC7_ID_REQUEST:
1766 offset = dissect_gadu_gadu_dcc7_id_request(tvb, pinfo, gadu_gadu_tree, offset);
1767 break;
1769 case GG_DCC7_NEW:
1770 offset = dissect_gadu_gadu_dcc7_new(tvb, pinfo, gadu_gadu_tree, offset);
1771 break;
1773 case GG_DCC7_ID_ABORT:
1774 offset = dissect_gadu_gadu_dcc7_id_abort(tvb, pinfo, gadu_gadu_tree, offset);
1775 break;
1777 case GG_USERLIST_REQUEST80:
1778 offset = dissect_gadu_gadu_userlist_request80(tvb, pinfo, gadu_gadu_tree, offset);
1779 break;
1781 case GG_USERLIST100_REQUEST:
1782 offset = dissect_gadu_gadu_userlist_request100(tvb, pinfo, gadu_gadu_tree, offset);
1783 break;
1785 case GG_PUBDIR50_REQUEST:
1786 offset = dissect_gadu_gadu_pubdir50_request(tvb, pinfo, gadu_gadu_tree, offset);
1787 break;
1789 case GG_PONG:
1790 case GG_LOGIN_EXT:
1791 case GG_LOGIN60:
1792 case GG_USERLIST_REQUEST:
1793 case GG_DCC7_INFO:
1794 case GG_DCC7_ACCEPT:
1795 case GG_DCC7_REJECT:
1796 case GG_DCC7_ID_DUNNO1:
1797 case GG_NEW_STATUS80BETA:
1798 case GG_LOGIN80BETA:
1799 case GG_OWN_DISCONNECT:
1800 case GG_NEW_STATUS105:
1801 case GG_LOGIN105:
1802 default:
1804 const char *pkt_name = try_val_to_str(pkt_type, gadu_gadu_packets_type_send);
1806 if (pkt_name)
1807 col_set_str(pinfo->cinfo, COL_INFO, pkt_name);
1808 else
1809 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown send packet: %.2x", pkt_type);
1810 break;
1815 /* for now display rest of data as FT_BYTES. */
1816 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1817 proto_tree_add_item(gadu_gadu_tree, hf_gadu_gadu_data, tvb, offset, -1, ENC_NA);
1820 return tvb_captured_length(tvb);
1823 static unsigned
1824 get_gadu_gadu_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1825 int offset, void *data _U_)
1827 uint32_t len = tvb_get_letohl(tvb, offset + 4);
1829 return len + 8;
1832 static int
1833 dissect_gadu_gadu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1835 if (pinfo->srcport == pinfo->match_uint && pinfo->destport != pinfo->match_uint)
1836 pinfo->p2p_dir = P2P_DIR_RECV;
1837 else if (pinfo->srcport != pinfo->match_uint && pinfo->destport == pinfo->match_uint)
1838 pinfo->p2p_dir = P2P_DIR_SENT;
1839 else
1840 return 0;
1842 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gadu-Gadu");
1843 col_clear(pinfo->cinfo, COL_INFO);
1845 tcp_dissect_pdus(tvb, pinfo, tree, gadu_gadu_desegment, 8, get_gadu_gadu_pdu_len, dissect_gadu_gadu_pdu, data);
1846 return tvb_captured_length(tvb);
1849 void
1850 proto_register_gadu_gadu(void)
1852 static hf_register_info hf[] = {
1853 { &hf_gadu_gadu_header_type_recv,
1854 { "Packet Type", "gadu-gadu.recv",
1855 FT_UINT32, BASE_HEX, VALS(gadu_gadu_packets_type_recv), 0x0,
1856 "Packet Type (recv)", HFILL }
1858 { &hf_gadu_gadu_header_type_send,
1859 { "Packet Type", "gadu-gadu.send",
1860 FT_UINT32, BASE_HEX, VALS(gadu_gadu_packets_type_send), 0x0,
1861 "Packet Type (send)", HFILL }
1863 { &hf_gadu_gadu_header_length,
1864 { "Packet Length", "gadu-gadu.len",
1865 FT_UINT32, BASE_DEC, NULL, 0x0,
1866 NULL, HFILL }
1868 { &hf_gadu_gadu_login_uin,
1869 { "Client UIN", "gadu-gadu.login.uin",
1870 FT_UINT32, BASE_DEC, NULL, 0x00,
1871 NULL, HFILL }
1873 { &hf_gadu_gadu_login_hash_type,
1874 { "Login hash type", "gadu-gadu.login.hash_type",
1875 FT_UINT8, BASE_HEX, VALS(gadu_gadu_hash_type_vals), 0x00,
1876 NULL, HFILL }
1878 { &hf_gadu_gadu_login_hash,
1879 { "Login hash", "gadu-gadu.login.hash",
1880 FT_BYTES, BASE_NONE, NULL, 0x00,
1881 NULL, HFILL }
1883 { &hf_gadu_gadu_login_status,
1884 { "Client status", "gadu-gadu.login.status",
1885 FT_UINT32, BASE_HEX, NULL, 0x00,
1886 NULL, HFILL }
1888 { &hf_gadu_gadu_login_protocol,
1889 { "Client protocol", "gadu-gadu.login.protocol",
1890 FT_UINT32, BASE_HEX, NULL, 0x00,
1891 NULL, HFILL }
1893 { &hf_gadu_gadu_login_version,
1894 { "Client version", "gadu-gadu.login.version",
1895 FT_STRING, BASE_NONE, NULL, 0x00,
1896 NULL, HFILL }
1898 { &hf_gadu_gadu_login_local_ip,
1899 { "Client local IP", "gadu-gadu.login.local_ip",
1900 FT_IPv4, BASE_NONE, NULL, 0x00,
1901 NULL, HFILL }
1903 { &hf_gadu_gadu_login_local_port,
1904 { "Client local port", "gadu-gadu.login.local_port",
1905 FT_UINT16, BASE_DEC, NULL, 0x00,
1906 NULL, HFILL }
1908 { &hf_gadu_gadu_login80_lang,
1909 { "Client language", "gadu-gadu.login80.lang",
1910 FT_STRING, BASE_NONE, NULL, 0x00,
1911 NULL, HFILL }
1913 { &hf_gadu_gadu_userdata_uin,
1914 { "UIN", "gadu-gadu.user_data.uin",
1915 FT_UINT32, BASE_DEC, NULL, 0x00,
1916 NULL, HFILL }
1918 { &hf_gadu_gadu_userdata_attr_name,
1919 { "Attribute name", "gadu-gadu.user_data.attr_name",
1920 FT_STRING, BASE_NONE, NULL, 0x00,
1921 NULL, HFILL }
1923 { &hf_gadu_gadu_userdata_attr_type,
1924 { "Attribute type", "gadu-gadu.user_data.attr_type",
1925 FT_UINT32, BASE_HEX, NULL, 0x00,
1926 NULL, HFILL }
1928 { &hf_gadu_gadu_userdata_attr_value,
1929 { "Attribute value", "gadu-gadu.user_data.attr_val",
1930 FT_STRING, BASE_NONE, NULL, 0x00,
1931 NULL, HFILL }
1933 { &hf_gadu_gadu_typing_notify_type,
1934 { "Typing notify type", "gadu-gadu.typing_notify.type",
1935 FT_UINT16, BASE_HEX, VALS(gadu_gadu_typing_notify_type_vals), 0x00,
1936 NULL, HFILL }
1938 { &hf_gadu_gadu_typing_notify_uin,
1939 { "Typing notify recipient", "gadu-gadu.typing_notify.uin",
1940 FT_UINT32, BASE_DEC, NULL, 0x00,
1941 NULL, HFILL }
1943 { &hf_gadu_gadu_msg_uin,
1944 { "Message sender or recipient", "gadu-gadu.msg.uin",
1945 FT_UINT32, BASE_DEC, NULL, 0x00,
1946 NULL, HFILL }
1948 { &hf_gadu_gadu_msg_sender,
1949 { "Message sender", "gadu-gadu.msg.sender",
1950 FT_UINT32, BASE_DEC, NULL, 0x00,
1951 NULL, HFILL }
1953 { &hf_gadu_gadu_msg_recipient,
1954 { "Message recipient", "gadu-gadu.msg.recipient",
1955 FT_UINT32, BASE_DEC, NULL, 0x00,
1956 NULL, HFILL }
1958 { &hf_gadu_gadu_msg_seq,
1959 { "Message sequence number", "gadu-gadu.msg.seq",
1960 FT_UINT32, BASE_DEC, NULL, 0x00,
1961 NULL, HFILL }
1963 { &hf_gadu_gadu_msg_time,
1964 { "Message time", "gadu-gadu.msg.time",
1965 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
1966 NULL, HFILL }
1968 { &hf_gadu_gadu_msg_class,
1969 { "Message class", "gadu-gadu.msg.class",
1970 FT_UINT32, BASE_HEX, NULL, 0x0,
1971 NULL, HFILL }
1973 { &hf_gadu_gadu_msg_text,
1974 { "Message text", "gadu-gadu.msg.text",
1975 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1976 NULL, HFILL }
1978 { &hf_gadu_gadu_msg80_offset_plain,
1979 { "Message plaintext offset", "gadu-gadu.msg80.offset_plain",
1980 FT_UINT32, BASE_DEC, NULL, 0x00,
1981 NULL, HFILL }
1983 { &hf_gadu_gadu_msg80_offset_attr,
1984 { "Message attribute offset", "gadu-gadu.msg80.offset_attributes",
1985 FT_UINT32, BASE_DEC, NULL, 0x00,
1986 NULL, HFILL }
1988 { &hf_gadu_gadu_msg_ack_status,
1989 { "Message status", "gadu-gadu.msg_ack.status",
1990 FT_UINT32, BASE_HEX, VALS(gadu_gadu_msg_ack_status_vals), 0x00,
1991 NULL, HFILL }
1993 { &hf_gadu_gadu_msg_ack_recipient,
1994 { "Message recipient", "gadu-gadu.msg_ack.recipient",
1995 FT_UINT32, BASE_DEC, NULL, 0x00,
1996 NULL, HFILL }
1998 { &hf_gadu_gadu_msg_ack_seq,
1999 { "Message sequence number", "gadu-gadu.msg_ack.seq",
2000 FT_UINT32, BASE_DEC, NULL, 0x00,
2001 NULL, HFILL }
2003 { &hf_gadu_gadu_status_uin,
2004 { "UIN", "gadu-gadu.status.uin",
2005 FT_UINT32, BASE_DEC, NULL, 0x00,
2006 NULL, HFILL }
2008 { &hf_gadu_gadu_status_status,
2009 { "Status", "gadu-gadu.status.status",
2010 FT_UINT32, BASE_HEX, NULL, 0x00,
2011 NULL, HFILL }
2013 { &hf_gadu_gadu_status_ip,
2014 { "IP", "gadu-gadu.status.remote_ip",
2015 FT_IPv4, BASE_NONE, NULL, 0x00,
2016 NULL, HFILL }
2018 { &hf_gadu_gadu_status_port,
2019 { "Port", "gadu-gadu.status.remote_port",
2020 FT_UINT16, BASE_DEC, NULL, 0x00,
2021 NULL, HFILL }
2023 { &hf_gadu_gadu_status_version,
2024 { "Version", "gadu-gadu.status.version",
2025 FT_UINT8, BASE_HEX, NULL, 0x00,
2026 NULL, HFILL }
2028 { &hf_gadu_gadu_status_img_size,
2029 { "Image size", "gadu-gadu.status.image_size",
2030 FT_UINT8, BASE_DEC, NULL, 0x00,
2031 "Maximum image size in KB", HFILL }
2033 { &hf_gadu_gadu_status_descr,
2034 { "Description", "gadu-gadu.status.description",
2035 FT_STRINGZ, BASE_NONE, NULL, 0x00,
2036 NULL, HFILL }
2038 { &hf_dcc_type,
2039 { "Direct connection type", "gadu-gadu.dcc.type",
2040 FT_UINT32, BASE_HEX, VALS(gadu_gadu_dcc_type_vals), 0x00,
2041 NULL, HFILL }
2043 { &hf_dcc_id,
2044 { "Direct connection id", "gadu-gadu.dcc.id",
2045 FT_BYTES, BASE_NONE, NULL, 0x00,
2046 NULL, HFILL }
2048 { &hf_dcc_uin_to,
2049 { "Direct connection UIN target", "gadu-gadu.dcc.uin_to",
2050 FT_UINT32, BASE_DEC, NULL, 0x00,
2051 NULL, HFILL }
2053 { &hf_dcc_uin_from,
2054 { "Direct connection UIN initiator", "gadu-gadu.dcc.uin_from",
2055 FT_UINT32, BASE_DEC, NULL, 0x00,
2056 NULL, HFILL }
2058 { &hf_dcc_filename,
2059 { "Direct connection filename", "gadu-gadu.dcc.filename",
2060 FT_STRING, BASE_NONE, NULL, 0x00,
2061 NULL, HFILL }
2063 { &hf_gadu_gadu_new_status_status,
2064 { "Status", "gadu-gadu.new_status.status",
2065 FT_UINT32, BASE_HEX, NULL, 0x00,
2066 NULL, HFILL }
2068 { &hf_gadu_gadu_new_status_desc,
2069 { "Description", "gadu-gadu.new_status.description",
2070 FT_STRINGZ, BASE_NONE, NULL, 0x00,
2071 NULL, HFILL }
2073 { &hf_gadu_gadu_userlist_request_type,
2074 { "Request type", "gadu-gadu.userlist.request_type",
2075 FT_UINT32, BASE_HEX, VALS(gadu_gadu_userlist_request_type_vals), 0x00,
2076 NULL, HFILL }
2078 { &hf_gadu_gadu_userlist_version,
2079 { "Userlist version", "gadu-gadu.userlist.version",
2080 FT_UINT32, BASE_DEC, NULL, 0x00,
2081 NULL, HFILL }
2083 { &hf_gadu_gadu_userlist_format,
2084 { "Userlist format", "gadu-gadu.userlist.format",
2085 FT_UINT8, BASE_HEX, VALS(gadu_gadu_userlist_request_format_vals), 0x00,
2086 NULL, HFILL }
2088 { &hf_gadu_gadu_userlist_reply_type,
2089 { "Reply type", "gadu-gadu.userlist.reply_type",
2090 FT_UINT32, BASE_HEX, VALS(gadu_gadu_userlist_reply_type_vals), 0x00,
2091 NULL, HFILL }
2093 { &hf_gadu_gadu_userlist,
2094 { "Userlist XML data", "gadu-gadu.userlist",
2095 FT_BYTES, BASE_NONE, NULL, 0x00,
2096 NULL, HFILL }
2098 { &hf_gadu_gadu_pubdir_request_type,
2099 { "Request type", "gadu-gadu.pubdir.request_type",
2100 FT_UINT8, BASE_HEX, VALS(gadu_gadu_pubdir_type_vals), 0x00,
2101 NULL, HFILL }
2103 { &hf_gadu_gadu_pubdir_request_seq,
2104 { "Request sequence", "gadu-gadu.pubdir.request_seq",
2105 FT_UINT32, BASE_HEX, NULL, 0x00,
2106 NULL, HFILL }
2108 { &hf_gadu_gadu_pubdir_request_str,
2109 { "Request string", "gadu-gadu.pubdir.request_str",
2110 FT_STRINGZ, BASE_NONE, NULL, 0x00,
2111 NULL, HFILL }
2113 { &hf_gadu_gadu_pubdir_reply_type,
2114 { "Reply type", "gadu-gadu.pubdir.reply_type",
2115 FT_UINT8, BASE_HEX, VALS(gadu_gadu_pubdir_type_vals), 0x00,
2116 NULL, HFILL }
2118 { &hf_gadu_gadu_pubdir_reply_seq,
2119 { "Reply sequence", "gadu-gadu.pubdir.reply_seq",
2120 FT_UINT32, BASE_HEX, NULL, 0x00,
2121 NULL, HFILL }
2123 { &hf_gadu_gadu_pubdir_reply_str,
2124 { "Reply string", "gadu-gadu.pubdir.reply_str",
2125 FT_STRINGZ, BASE_NONE, NULL, 0x00,
2126 NULL, HFILL }
2128 { &hf_gadu_gadu_contact_uin,
2129 { "UIN", "gadu-gadu.contact.uin",
2130 FT_UINT32, BASE_DEC, NULL, 0x00,
2131 NULL, HFILL }
2133 { &hf_gadu_gadu_contact_uin_str,
2134 { "UIN", "gadu-gadu.contact.uin_str",
2135 FT_STRING, BASE_NONE, NULL, 0x00,
2136 NULL, HFILL }
2138 { &hf_gadu_gadu_contact_type,
2139 { "Type", "gadu-gadu.contact.type",
2140 FT_UINT8, BASE_HEX, NULL, 0x00,
2141 NULL, HFILL }
2143 { &hf_gadu_gadu_welcome_seed,
2144 { "Seed", "gadu-gadu.welcome.seed",
2145 FT_UINT32, BASE_HEX, NULL, 0x0,
2146 NULL, HFILL }
2148 { &hf_gadu_gadu_data,
2149 { "Packet Data", "gadu-gadu.data",
2150 FT_BYTES, BASE_NONE, NULL, 0x0,
2151 NULL, HFILL }
2155 static int *ett[] = {
2156 &ett_gadu_gadu,
2157 &ett_gadu_gadu_contact
2160 module_t *gadu_gadu_module;
2162 proto_gadu_gadu = proto_register_protocol("Gadu-Gadu Protocol", "Gadu-Gadu", "gadu-gadu");
2164 gadu_gadu_module = prefs_register_protocol(proto_gadu_gadu, NULL);
2165 prefs_register_bool_preference(gadu_gadu_module, "desegment",
2166 "Reassemble Gadu-Gadu messages spanning multiple TCP segments",
2167 "Whether the Gadu-Gadu dissector should reassemble messages spanning multiple TCP segments."
2168 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2169 &gadu_gadu_desegment);
2171 proto_register_field_array(proto_gadu_gadu, hf, array_length(hf));
2172 proto_register_subtree_array(ett, array_length(ett));
2174 gadu_gadu_handle = register_dissector("gadugadu", dissect_gadu_gadu, proto_gadu_gadu);
2177 void
2178 proto_reg_handoff_gadu_gadu(void)
2180 dissector_add_uint_with_preference("tcp.port", TCP_PORT_GADU_GADU, gadu_gadu_handle);
2182 xml_handle = find_dissector_add_dependency("xml", proto_gadu_gadu);
2186 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2188 * Local variables:
2189 * c-basic-offset: 8
2190 * tab-width: 8
2191 * indent-tabs-mode: t
2192 * End:
2194 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2195 * :indentSize=8:tabSize=8:noTabs=false: