2 * Routines for Gadu-Gadu dissection
3 * Copyright 2011,2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
7 * Protocol documentation available at http://toxygen.net/libgadu/protocol/
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #define NEW_PROTO_TREE_API
34 #include <epan/packet.h>
35 #include <epan/prefs.h>
36 #include <epan/wmem/wmem.h>
38 #include <epan/dissectors/packet-tcp.h>
40 #define TCP_PORT_GADU_GADU 8074 /* assigned by IANA */
42 /* desegmentation of Gadu-Gadu over TCP */
43 static gboolean gadu_gadu_desegment = TRUE;
45 static dissector_handle_t gadu_gadu_handle;
47 static int ett_gadu_gadu = -1;
48 static int ett_gadu_gadu_contact = -1;
50 #define GG_ERA_OMNIX_MASK 0x04000000
51 #define GG_HAS_AUDIO_MASK 0x40000000
53 #define GG_WELCOME 0x01
54 #define GG_STATUS 0x02
55 #define GG_LOGIN_OK 0x03
56 #define GG_SEND_MSG_ACK 0x05
59 #define GG_LOGIN_FAILED 0x09
60 #define GG_RECV_MSG 0x0a
61 #define GG_DISCONNECTING 0x0b
62 #define GG_NOTIFY_REPLY 0x0c
63 #define GG_DISCONNECT_ACK 0x0d
64 #define GG_PUBDIR50_REPLY 0x0e
65 #define GG_STATUS60 0x0f
66 #define GG_USERLIST_REPLY 0x10
67 #define GG_NOTIFY_REPLY60 0x11
68 #define GG_NEED_EMAIL 0x14
69 #define GG_LOGIN_HASH_TYPE_INVALID 0x16
70 #define GG_STATUS77 0x17
71 #define GG_NOTIFY_REPLY77 0x18
72 #define GG_DCC7_INFO 0x1f
73 #define GG_DCC7_NEW 0x20
74 #define GG_DCC7_ACCEPT 0x21
75 #define GG_DCC7_REJECT 0x22
76 #define GG_DCC7_ID_REPLY 0x23
77 #define GG_DCC7_ID_ABORTED 0x25
78 #define GG_XML_EVENT 0x27
79 #define GG_STATUS80BETA 0x2a
80 #define GG_NOTIFY_REPLY80BETA 0x2b
81 #define GG_XML_ACTION 0x2c
82 #define GG_RECV_MSG80 0x2e
83 #define GG_USERLIST_REPLY80 0x30
84 #define GG_LOGIN_OK80 0x35
85 #define GG_STATUS80 0x36
86 #define GG_NOTIFY_REPLY80 0x37
87 #define GG_USERLIST100_REPLY 0x41
88 #define GG_LOGIN80_FAILED 0x43
89 #define GG_USER_DATA 0x44
90 #define GG_TYPING_NOTIFY 0x59
91 #define GG_OWN_MESSAGE 0x5A
92 #define GG_OWN_RESOURCE_INFO 0x5B
93 #define GG_USERLIST100_VERSION 0x5C
96 #define GG_TYPE_VS(x) { x, #x }
98 /* original (GG_*) names likes in documentation (http://toxygen.net/libgadu/protocol/#ch1.16) */
99 static const value_string gadu_gadu_packets_type_recv[] = {
100 GG_TYPE_VS(GG_WELCOME),
101 GG_TYPE_VS(GG_STATUS),
102 GG_TYPE_VS(GG_LOGIN_OK),
103 GG_TYPE_VS(GG_SEND_MSG_ACK),
106 GG_TYPE_VS(GG_LOGIN_FAILED),
107 GG_TYPE_VS(GG_RECV_MSG),
108 GG_TYPE_VS(GG_DISCONNECTING),
109 GG_TYPE_VS(GG_NOTIFY_REPLY),
110 GG_TYPE_VS(GG_DISCONNECT_ACK),
111 GG_TYPE_VS(GG_PUBDIR50_REPLY),
112 GG_TYPE_VS(GG_STATUS60),
113 GG_TYPE_VS(GG_USERLIST_REPLY),
114 GG_TYPE_VS(GG_NOTIFY_REPLY60),
115 GG_TYPE_VS(GG_NEED_EMAIL),
116 GG_TYPE_VS(GG_LOGIN_HASH_TYPE_INVALID),
117 GG_TYPE_VS(GG_STATUS77),
118 GG_TYPE_VS(GG_NOTIFY_REPLY77),
119 GG_TYPE_VS(GG_DCC7_INFO),
120 GG_TYPE_VS(GG_DCC7_NEW),
121 GG_TYPE_VS(GG_DCC7_ACCEPT),
122 GG_TYPE_VS(GG_DCC7_REJECT),
123 GG_TYPE_VS(GG_DCC7_ID_REPLY),
124 GG_TYPE_VS(GG_DCC7_ID_ABORTED),
125 GG_TYPE_VS(GG_XML_EVENT),
126 GG_TYPE_VS(GG_STATUS80BETA),
127 GG_TYPE_VS(GG_NOTIFY_REPLY80BETA),
128 GG_TYPE_VS(GG_XML_ACTION),
129 GG_TYPE_VS(GG_RECV_MSG80),
130 GG_TYPE_VS(GG_USERLIST_REPLY80),
131 GG_TYPE_VS(GG_LOGIN_OK80),
132 GG_TYPE_VS(GG_STATUS80),
133 GG_TYPE_VS(GG_NOTIFY_REPLY80),
134 GG_TYPE_VS(GG_USERLIST100_REPLY),
135 GG_TYPE_VS(GG_LOGIN80_FAILED),
136 GG_TYPE_VS(GG_USER_DATA),
137 GG_TYPE_VS(GG_TYPING_NOTIFY),
138 GG_TYPE_VS(GG_OWN_MESSAGE),
139 GG_TYPE_VS(GG_OWN_RESOURCE_INFO),
140 GG_TYPE_VS(GG_USERLIST100_VERSION),
144 #define GG_NEW_STATUS 0x02
147 #define GG_SEND_MSG 0x0b
148 #define GG_LOGIN 0x0c
149 #define GG_ADD_NOTIFY 0x0d
150 #define GG_REMOVE_NOTIFY 0x0e
151 #define GG_NOTIFY_FIRST 0x0f
152 #define GG_NOTIFY_LAST 0x10
153 #define GG_LIST_EMPTY 0x12
154 #define GG_LOGIN_EXT 0x13
155 #define GG_PUBDIR50_REQUEST 0x14
156 #define GG_LOGIN60 0x15
157 #define GG_USERLIST_REQUEST 0x16
158 #define GG_LOGIN70 0x19
159 #define GG_DCC7_INFO 0x1f
160 #define GG_DCC7_NEW 0x20
161 #define GG_DCC7_ACCEPT 0x21
162 #define GG_DCC7_REJECT 0x22
163 #define GG_DCC7_ID_REQUEST 0x23
164 #define GG_DCC7_ID_DUNNO1 0x24
165 #define GG_DCC7_ID_ABORT 0x25
166 #define GG_NEW_STATUS80BETA 0x28
167 #define GG_LOGIN80BETA 0x29
168 #define GG_SEND_MSG80 0x2d
169 #define GG_USERLIST_REQUEST80 0x2f
170 #define GG_LOGIN80 0x31
171 #define GG_NEW_STATUS80 0x38
172 #define GG_USERLIST100_REQUEST 0x40
173 #define GG_RECV_MSG_ACK 0x46
174 #define GG_TYPING_NOTIFY 0x59
175 #define GG_OWN_DISCONNECT 0x62
176 #define GG_NEW_STATUS105 0x63
177 #define GG_NOTIFY105 0x78
178 #define GG_ADD_NOTIFY105 0x7b
179 #define GG_REMOVE_NOTIFY105 0x7c
180 #define GG_LOGIN105 0x83
182 static const value_string gadu_gadu_packets_type_send[] = {
183 GG_TYPE_VS(GG_NEW_STATUS),
186 GG_TYPE_VS(GG_SEND_MSG),
187 GG_TYPE_VS(GG_LOGIN),
188 GG_TYPE_VS(GG_ADD_NOTIFY),
189 GG_TYPE_VS(GG_REMOVE_NOTIFY),
190 GG_TYPE_VS(GG_NOTIFY_FIRST),
191 GG_TYPE_VS(GG_NOTIFY_LAST),
192 GG_TYPE_VS(GG_LIST_EMPTY),
193 GG_TYPE_VS(GG_LOGIN_EXT),
194 GG_TYPE_VS(GG_PUBDIR50_REQUEST),
195 GG_TYPE_VS(GG_LOGIN60),
196 GG_TYPE_VS(GG_USERLIST_REQUEST),
197 GG_TYPE_VS(GG_LOGIN70),
198 GG_TYPE_VS(GG_DCC7_INFO),
199 GG_TYPE_VS(GG_DCC7_NEW),
200 GG_TYPE_VS(GG_DCC7_ACCEPT),
201 GG_TYPE_VS(GG_DCC7_REJECT),
202 GG_TYPE_VS(GG_DCC7_ID_REQUEST),
203 GG_TYPE_VS(GG_DCC7_ID_DUNNO1),
204 GG_TYPE_VS(GG_DCC7_ID_ABORT),
205 GG_TYPE_VS(GG_NEW_STATUS80BETA),
206 GG_TYPE_VS(GG_LOGIN80BETA),
207 GG_TYPE_VS(GG_SEND_MSG80),
208 GG_TYPE_VS(GG_USERLIST_REQUEST80),
209 GG_TYPE_VS(GG_LOGIN80),
210 GG_TYPE_VS(GG_NEW_STATUS80),
211 GG_TYPE_VS(GG_USERLIST100_REQUEST),
212 GG_TYPE_VS(GG_RECV_MSG_ACK),
213 GG_TYPE_VS(GG_TYPING_NOTIFY),
214 GG_TYPE_VS(GG_OWN_DISCONNECT),
215 GG_TYPE_VS(GG_NEW_STATUS105),
216 GG_TYPE_VS(GG_NOTIFY105),
217 GG_TYPE_VS(GG_ADD_NOTIFY105),
218 GG_TYPE_VS(GG_REMOVE_NOTIFY105),
219 GG_TYPE_VS(GG_LOGIN105),
223 static const value_string gadu_gadu_msg_ack_status_vals[] = {
224 { 0x01, "Message blocked" },
225 { 0x02, "Message delivered" },
226 { 0x03, "Message queued" },
227 { 0x04, "Message not delivered (queue full)" },
228 { 0x06, "CTCP Message not delivered" },
232 #define GG_STATUS_NOT_AVAIL 0x01
233 #define GG_STATUS_NOT_AVAIL_DESCR 0x15
234 #define GG_STATUS_FFC 0x17
235 #define GG_STATUS_FFC_DESCR 0x18
236 #define GG_STATUS_AVAIL 0x02
237 #define GG_STATUS_AVAIL_DESCR 0x04
238 #define GG_STATUS_BUSY 0x03
239 #define GG_STATUS_BUSY_DESCR 0x05
240 #define GG_STATUS_DND 0x21
241 #define GG_STATUS_DND_DESCR 0x22
242 #define GG_STATUS_INVISIBLE 0x14
243 #define GG_STATUS_INVISIBLE_DESCR 0x16
244 #define GG_STATUS_BLOCKED 0x06
246 #define GG_LOGIN_HASH_GG32 0x01
247 #define GG_LOGIN_HASH_SHA1 0x02
249 static const value_string gadu_gadu_hash_type_vals[] = {
250 { GG_LOGIN_HASH_GG32, "GG32 hash" },
251 { GG_LOGIN_HASH_SHA1, "SHA1 hash" },
255 #define GG_USERLIST_PUT 0x00
256 #define GG_USERLIST_PUT_MORE 0x01
257 #define GG_USERLIST_GET 0x02
259 static const value_string gadu_gadu_userlist_request_type_vals[] = {
260 { GG_USERLIST_PUT, "Userlist put" },
261 { GG_USERLIST_PUT_MORE, "Userlist put (more)" },
262 { GG_USERLIST_GET, "Userlist get" },
266 #define GG_USERLIST_PUT_REPLY 0x00
267 #define GG_USERLIST_PUT_MORE_REPLY 0x02
268 #define GG_USERLIST_GET_REPLY 0x06
269 #define GG_USERLIST_GET_MORE_REPLY 0x04
271 static const value_string gadu_gadu_userlist_reply_type_vals[] = {
272 { GG_USERLIST_PUT_REPLY, "Userlist put" },
273 { GG_USERLIST_PUT_MORE_REPLY, "Userlist put (more)" },
274 { GG_USERLIST_GET_REPLY, "Userlist get" },
275 { GG_USERLIST_GET_MORE_REPLY, "Userlist get (more)" },
279 #define GG_USERLIST100_FORMAT_TYPE_NONE 0x00
280 #define GG_USERLIST100_FORMAT_TYPE_GG70 0x01
281 #define GG_USERLIST100_FORMAT_TYPE_GG100 0x02
283 static const value_string gadu_gadu_userlist_request_format_vals[] = {
284 { GG_USERLIST100_FORMAT_TYPE_NONE, "None" },
285 { GG_USERLIST100_FORMAT_TYPE_GG70, "Classic (7.0)" },
286 { GG_USERLIST100_FORMAT_TYPE_GG100, "XML (10.0)" },
290 /* XXX, add compatible libgadu versions? */
291 static const value_string gadu_gadu_version_vals[] = {
292 { 0x2e, "Gadu-Gadu 8.0 (build 8283)" },
293 { 0x2d, "Gadu-Gadu 8.0 (build 4881)" },
294 { 0x2a, "Gadu-Gadu 7.7 (build 3315)" },
295 { 0x29, "Gadu-Gadu 7.6 (build 1688)" },
296 { 0x28, "Gadu-Gadu 7.5.0 (build 2201)" },
297 { 0x27, "Gadu-Gadu 7.0 (build 22)" },
298 { 0x26, "Gadu-Gadu 7.0 (build 20)" },
299 { 0x25, "Gadu-Gadu 7.0 (build 1)" },
300 { 0x24, "Gadu-Gadu 6.1 (build 155) or 7.6 (build 1359)" },
301 { 0x22, "Gadu-Gadu 6.0 (build 140)" },
302 { 0x21, "Gadu-Gadu 6.0 (build 133)" },
303 { 0x20, "Gadu-Gadu 6.0" },
304 { 0x1e, "Gadu-Gadu 5.7 beta (build 121)" },
305 { 0x1c, "Gadu_Gadu 5.7 beta" },
306 { 0x1b, "Gadu-Gadu 5.0.5" },
307 { 0x19, "Gadu-Gadu 5.0.3" },
308 { 0x18, "Gadu-Gadu 5.0.1, 5.0.0, 4.9.3" },
309 { 0x17, "Gadu-Gadu 4.9.2" },
310 { 0x16, "Gadu-Gadu 4.9.1" },
311 { 0x15, "Gadu-Gadu 4.8.9" },
312 { 0x14, "Gadu-Gadu 4.8.3, 4.8.1" },
313 { 0x11, "Gadu-Gadu 4.6.10, 4.6.1" },
314 { 0x10, "Gadu-Gadu 4.5.22, 4.5.21, 4.5.19, 4.5.17, 4.5.15" },
315 { 0x0f, "Gadu-Gadu 4.5.12" },
316 { 0x0b, "Gadu-Gadu 4.0.30, 4.0.29, 4.0.28, 4.0.25" },
320 static const value_string gadu_gadu_dcc_type_vals[] = {
321 { 1, "Voice transmission" },
322 { 4, "File transmission" },
326 static const value_string gadu_gadu_typing_notify_type_vals[] = {
327 { 1, "Typing started" },
328 { 0, "Typing stopped" },
332 static const value_string gadu_gadu_pubdir_type_vals[] = {
333 { 1, "Public directory write" },
334 { 2, "Public directory read" },
335 { 3, "Public directory search" },
339 static header_field_info *hfi_gadu_gadu = NULL;
341 #define GADU_GADU_HFI_INIT HFI_INIT(proto_gadu_gadu)
344 static header_field_info hfi_gadu_gadu_header_type_recv GADU_GADU_HFI_INIT =
345 { "Packet Type", "gadu-gadu.recv", FT_UINT32, BASE_HEX, VALS(gadu_gadu_packets_type_recv), 0x0, "Packet Type (recv)", HFILL };
347 static header_field_info hfi_gadu_gadu_header_type_send GADU_GADU_HFI_INIT =
348 { "Packet Type", "gadu-gadu.send", FT_UINT32, BASE_HEX, VALS(gadu_gadu_packets_type_send), 0x0, "Packet Type (send)", HFILL };
350 static header_field_info hfi_gadu_gadu_header_length GADU_GADU_HFI_INIT =
351 { "Packet Length", "gadu-gadu.len", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL };
353 /* Login common (gadu-gadu.login.*) */
354 static header_field_info hfi_gadu_gadu_login_uin GADU_GADU_HFI_INIT =
355 { "Client UIN", "gadu-gadu.login.uin", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
357 static header_field_info hfi_gadu_gadu_login_hash_type GADU_GADU_HFI_INIT =
358 { "Login hash type", "gadu-gadu.login.hash_type", FT_UINT8, BASE_HEX, gadu_gadu_hash_type_vals, 0x00, NULL, HFILL };
360 static header_field_info hfi_gadu_gadu_login_hash GADU_GADU_HFI_INIT =
361 { "Login hash", "gadu-gadu.login.hash", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL };
363 static header_field_info hfi_gadu_gadu_login_status GADU_GADU_HFI_INIT =
364 { "Client status", "gadu-gadu.login.status", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL };
366 static header_field_info hfi_gadu_gadu_login_protocol GADU_GADU_HFI_INIT =
367 { "Client protocol", "gadu-gadu.login.protocol", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL };
369 static header_field_info hfi_gadu_gadu_login_version GADU_GADU_HFI_INIT =
370 { "Client version", "gadu-gadu.login.version", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
372 static header_field_info hfi_gadu_gadu_login_local_ip GADU_GADU_HFI_INIT =
373 { "Client local IP", "gadu-gadu.login.local_ip", FT_IPv4, BASE_NONE, NULL, 0x00, NULL, HFILL };
375 static header_field_info hfi_gadu_gadu_login_local_port GADU_GADU_HFI_INIT =
376 { "Client local port", "gadu-gadu.login.local_port", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL };
378 /* GG_LOGIN80 (gadu-gadu.login80.*) */
379 static header_field_info hfi_gadu_gadu_login80_lang GADU_GADU_HFI_INIT =
380 { "Client language", "gadu-gadu.login80.lang", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
382 /* Contacts details (gadu-gadu.user_data.*) */
383 static header_field_info hfi_gadu_gadu_userdata_uin GADU_GADU_HFI_INIT =
384 { "UIN", "gadu-gadu.user_data.uin", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
386 static header_field_info hfi_gadu_gadu_userdata_attr_name GADU_GADU_HFI_INIT =
387 { "Attribute name", "gadu-gadu.user_data.attr_name", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
389 static header_field_info hfi_gadu_gadu_userdata_attr_type GADU_GADU_HFI_INIT =
390 { "Attribute type", "gadu-gadu.user_data.attr_type", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL };
392 static header_field_info hfi_gadu_gadu_userdata_attr_value GADU_GADU_HFI_INIT =
393 { "Attribute value", "gadu-gadu.user_data.attr_val", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
395 /* Typing notify (gadu-gadu.typing_notify.*) */
396 static header_field_info hfi_gadu_gadu_typing_notify_type GADU_GADU_HFI_INIT =
397 { "Typing notify type", "gadu-gadu.typing_notify.type", FT_UINT16, BASE_HEX, gadu_gadu_typing_notify_type_vals, 0x00, NULL, HFILL };
399 static header_field_info hfi_gadu_gadu_typing_notify_uin GADU_GADU_HFI_INIT =
400 { "Typing notify recipient", "gadu-gadu.typing_notify.uin", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
402 /* Message common (gadu-gadu.msg.*) */
403 static header_field_info hfi_gadu_gadu_msg_uin GADU_GADU_HFI_INIT =
404 { "Message sender or recipient", "gadu-gadu.msg.uin", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
406 static header_field_info hfi_gadu_gadu_msg_sender GADU_GADU_HFI_INIT =
407 { "Message sender", "gadu-gadu.msg.sender", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
409 static header_field_info hfi_gadu_gadu_msg_recipient GADU_GADU_HFI_INIT =
410 { "Message recipient", "gadu-gadu.msg.recipient", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
412 static header_field_info hfi_gadu_gadu_msg_seq GADU_GADU_HFI_INIT =
413 { "Message sequence number", "gadu-gadu.msg.seq", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
415 static header_field_info hfi_gadu_gadu_msg_time GADU_GADU_HFI_INIT =
416 { "Message time", "gadu-gadu.msg.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL };
418 static header_field_info hfi_gadu_gadu_msg_class GADU_GADU_HFI_INIT =
419 { "Message class", "gadu-gadu.msg.class", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL };
421 static header_field_info hfi_gadu_gadu_msg_text GADU_GADU_HFI_INIT =
422 { "Message text", "gadu-gadu.msg.text", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL };
424 /* GG_RECV_MSG80, GG_SEND_MSG80 (gadu-gadu.msg80.*) */
425 static header_field_info hfi_gadu_gadu_msg80_offset_plain GADU_GADU_HFI_INIT =
426 { "Message plaintext offset", "gadu-gadu.msg80.offset_plain", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
428 static header_field_info hfi_gadu_gadu_msg80_offset_attr GADU_GADU_HFI_INIT =
429 { "Message attribute offset", "gadu-gadu.msg80.offset_attributes", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
431 /* GG_SEND_MSG_ACK (gadu-gadu.msg_ack.*) */
432 static header_field_info hfi_gadu_gadu_msg_ack_status GADU_GADU_HFI_INIT =
433 { "Message status", "gadu-gadu.msg_ack.status", FT_UINT32, BASE_HEX, gadu_gadu_msg_ack_status_vals, 0x00, NULL, HFILL };
435 static header_field_info hfi_gadu_gadu_msg_ack_recipient GADU_GADU_HFI_INIT =
436 { "Message recipient", "gadu-gadu.msg_ack.recipient", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
438 static header_field_info hfi_gadu_gadu_msg_ack_seq GADU_GADU_HFI_INIT =
439 { "Message sequence number", "gadu-gadu.msg_ack.seq", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
441 /* Status common (gadu-gadu.status.*) */
442 static header_field_info hfi_gadu_gadu_status_uin GADU_GADU_HFI_INIT =
443 { "UIN", "gadu-gadu.status.uin", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
445 static header_field_info hfi_gadu_gadu_status_status GADU_GADU_HFI_INIT =
446 { "Status", "gadu-gadu.status.status", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL };
448 static header_field_info hfi_gadu_gadu_status_ip GADU_GADU_HFI_INIT =
449 { "IP", "gadu-gadu.status.remote_ip", FT_IPv4, BASE_NONE, NULL, 0x00, NULL, HFILL };
451 static header_field_info hfi_gadu_gadu_status_port GADU_GADU_HFI_INIT =
452 { "Port", "gadu-gadu.status.remote_port", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL };
454 static header_field_info hfi_gadu_gadu_status_version GADU_GADU_HFI_INIT =
455 { "Version", "gadu-gadu.status.version", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL };
457 static header_field_info hfi_gadu_gadu_status_img_size GADU_GADU_HFI_INIT =
458 { "Image size", "gadu-gadu.status.image_size", FT_UINT8, BASE_DEC, NULL, 0x00, "Maximum image size in KB", HFILL };
460 static header_field_info hfi_gadu_gadu_status_descr GADU_GADU_HFI_INIT =
461 { "Description", "gadu-gadu.status.description", FT_STRINGZ, BASE_NONE, NULL, 0x00, NULL, HFILL };
463 /* Direct Connection (gadu-gadu.dcc.*) */
464 static header_field_info hfi_dcc_type GADU_GADU_HFI_INIT =
465 { "Direct connection type", "gadu-gadu.dcc.type", FT_UINT32, BASE_HEX, gadu_gadu_dcc_type_vals, 0x00, NULL, HFILL };
467 static header_field_info hfi_dcc_id GADU_GADU_HFI_INIT =
468 { "Direct connection id", "gadu-gadu.dcc.id", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL };
470 static header_field_info hfi_dcc_uin_to GADU_GADU_HFI_INIT =
471 { "Direct connection UIN target", "gadu-gadu.dcc.uin_to", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
473 static header_field_info hfi_dcc_uin_from GADU_GADU_HFI_INIT =
474 { "Direct connection UIN initiator", "gadu-gadu.dcc.uin_from", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
476 static header_field_info hfi_dcc_filename GADU_GADU_HFI_INIT =
477 { "Direct connection filename", "gadu-gadu.dcc.filename", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
479 /* New status (setting status) common (gadu-gadu.new_status.*) */
480 static header_field_info hfi_gadu_gadu_new_status_status GADU_GADU_HFI_INIT =
481 { "Status", "gadu-gadu.new_status.status", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL };
483 static header_field_info hfi_gadu_gadu_new_status_desc GADU_GADU_HFI_INIT =
484 { "Description", "gadu-gadu.new_status.description", FT_STRINGZ, BASE_NONE, NULL, 0x00, NULL, HFILL };
486 /* Userlist (gadu-gadu.userlist.*) */
487 static header_field_info hfi_gadu_gadu_userlist_request_type GADU_GADU_HFI_INIT =
488 { "Request type", "gadu-gadu.userlist.request_type", FT_UINT32, BASE_HEX, gadu_gadu_userlist_request_type_vals, 0x00, NULL, HFILL };
490 static header_field_info hfi_gadu_gadu_userlist_version GADU_GADU_HFI_INIT =
491 { "Userlist version", "gadu-gadu.userlist.version", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
493 static header_field_info hfi_gadu_gadu_userlist_format GADU_GADU_HFI_INIT =
494 { "Userlist format", "gadu-gadu.userlist.format", FT_UINT8, BASE_HEX, gadu_gadu_userlist_request_format_vals, 0x00, NULL, HFILL };
496 static header_field_info hfi_gadu_gadu_userlist_reply_type GADU_GADU_HFI_INIT =
497 { "Reply type", "gadu-gadu.userlist.reply_type", FT_UINT32, BASE_HEX, gadu_gadu_userlist_reply_type_vals, 0x00, NULL, HFILL };
499 /* Public Directory (gadu-gadu.pubdir.*) */
500 static header_field_info hfi_gadu_gadu_pubdir_request_type GADU_GADU_HFI_INIT =
501 { "Request type", "gadu-gadu.pubdir.request_type", FT_UINT8, BASE_HEX, gadu_gadu_pubdir_type_vals, 0x00, NULL, HFILL };
503 static header_field_info hfi_gadu_gadu_pubdir_request_seq GADU_GADU_HFI_INIT =
504 { "Request sequence", "gadu-gadu.pubdir.request_seq", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL };
506 static header_field_info hfi_gadu_gadu_pubdir_request_str GADU_GADU_HFI_INIT =
507 { "Request string", "gadu-gadu.pubdir.request_str", FT_STRINGZ, BASE_NONE, NULL, 0x00, NULL, HFILL };
509 static header_field_info hfi_gadu_gadu_pubdir_reply_type GADU_GADU_HFI_INIT =
510 { "Reply type", "gadu-gadu.pubdir.reply_type", FT_UINT8, BASE_HEX, gadu_gadu_pubdir_type_vals, 0x00, NULL, HFILL };
512 static header_field_info hfi_gadu_gadu_pubdir_reply_seq GADU_GADU_HFI_INIT =
513 { "Reply sequence", "gadu-gadu.pubdir.reply_seq", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL };
515 static header_field_info hfi_gadu_gadu_pubdir_reply_str GADU_GADU_HFI_INIT =
516 { "Reply string", "gadu-gadu.pubdir.request_str", FT_STRINGZ, BASE_NONE, NULL, 0x00, NULL, HFILL };
518 /* Contact (notify) common (gadu-gadu.contact.*) */
519 static header_field_info hfi_gadu_gadu_contact_uin GADU_GADU_HFI_INIT =
520 { "UIN", "gadu-gadu.contact.uin", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
522 static header_field_info hfi_gadu_gadu_contact_uin_str GADU_GADU_HFI_INIT =
523 { "UIN", "gadu-gadu.contact.uin_str", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
525 static header_field_info hfi_gadu_gadu_contact_type GADU_GADU_HFI_INIT =
526 { "Type", "gadu-gadu.contact.type", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL };
529 static header_field_info hfi_gadu_gadu_welcome_seed GADU_GADU_HFI_INIT =
530 { "Seed", "gadu-gadu.welcome.seed", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL };
532 /* Not dissected data */
533 static header_field_info hfi_gadu_gadu_data GADU_GADU_HFI_INIT =
534 { "Packet Data", "gadu-gadu.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL };
537 static dissector_handle_t xml_handle;
539 struct gadu_gadu_conv_data {
540 guint32 uin; /* uin from login packet */
543 static struct gadu_gadu_conv_data *
544 gadu_gadu_create_conversation(packet_info *pinfo, guint32 uin)
546 conversation_t *conv;
547 struct gadu_gadu_conv_data *gg_conv;
549 conv = find_or_create_conversation(pinfo);
550 gg_conv = (struct gadu_gadu_conv_data *)conversation_get_proto_data(conv, hfi_gadu_gadu->id);
552 gg_conv = wmem_new(wmem_file_scope(), struct gadu_gadu_conv_data);
555 conversation_add_proto_data(conv, hfi_gadu_gadu->id, gg_conv);
557 /* assert(gg_conv->uin == uin); */
561 static struct gadu_gadu_conv_data *
562 gadu_gadu_get_conversation_data(packet_info *pinfo)
564 conversation_t *conv;
566 conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
568 return (struct gadu_gadu_conv_data *)conversation_get_proto_data(conv, hfi_gadu_gadu->id);
573 gadu_gadu_status_has_descr(int status)
576 (status == GG_STATUS_NOT_AVAIL_DESCR) ||
577 (status == GG_STATUS_FFC_DESCR) ||
578 (status == GG_STATUS_AVAIL_DESCR) ||
579 (status == GG_STATUS_BUSY_DESCR) ||
580 (status == GG_STATUS_DND_DESCR) ||
581 (status == GG_STATUS_INVISIBLE_DESCR);
585 dissect_gadu_gadu_stringz_cp1250(tvbuff_t *tvb, const header_field_info *hfi, proto_tree *tree, const int offset)
590 /* XXX, new code is throwing exception if string is not NUL terminated */
591 str = (const char *) tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_NA | ENC_WINDOWS_1250);
593 proto_tree_add_unicode_string(tree, hfi->id, tvb, offset, len, str);
599 dissect_gadu_gadu_uint32_string_utf8(tvbuff_t *tvb, const header_field_info *hfi, proto_tree *tree, int offset)
601 const int org_offset = offset;
606 len = tvb_get_letohl(tvb, offset);
610 /* proto_item_fill_label() is broken for UTF-8 strings.
611 * It's using internally format_text() which doesn't support UTF-8
613 /* proto_tree_add_item(tree, hfindex, tvb, offset, len, ENC_UTF_8|ENC_NA); */
616 str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_UTF_8|ENC_NA);
623 proto_tree_add_unicode_string(tree, hfi->id, tvb, org_offset, offset - org_offset, str);
629 dissect_gadu_gadu_disconnecting(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
631 col_set_str(pinfo->cinfo, COL_INFO, "Disconnecting");
640 dissect_gadu_gadu_disconnect_ack(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
642 col_set_str(pinfo->cinfo, COL_INFO, "Disconnect acknowledge (< 10.0)");
650 _tvb_memcpy_reverse(tvbuff_t *tvb, void *target, gint offset, size_t length)
652 guint8 *t = (guint8 *) target;
656 t[length] = tvb_get_guint8(tvb, offset);
663 dissect_gadu_gadu_login_protocol(tvbuff_t *tvb, proto_tree *tree, int offset)
669 protocol = tvb_get_letohl(tvb, offset) & 0xff;
670 proto_tree_add_item(tree, &hfi_gadu_gadu_login_protocol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
671 ti = proto_tree_add_string(tree, &hfi_gadu_gadu_login_version, tvb, offset, 4, val_to_str(protocol, gadu_gadu_version_vals, "Unknown (0x%x)"));
672 PROTO_ITEM_SET_GENERATED(ti);
679 dissect_gadu_gadu_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
686 col_set_str(pinfo->cinfo, COL_INFO, "Login request (< 6.0)");
688 uin = tvb_get_letohl(tvb, offset);
689 gadu_gadu_create_conversation(pinfo, uin);
691 proto_tree_add_uint(tree, &hfi_gadu_gadu_login_uin, tvb, offset, 4, uin);
694 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_login_hash_type, tvb, 0, 0, GG_LOGIN_HASH_GG32);
695 PROTO_ITEM_SET_GENERATED(ti);
697 /* hash is 32-bit number written in LE */
698 _tvb_memcpy_reverse(tvb, hash, offset, 4);
699 proto_tree_add_bytes_format_value(tree, hfi_gadu_gadu_login_hash.id, tvb, offset, 4, hash, "0x%.8x", tvb_get_letohl(tvb, offset));
702 proto_tree_add_item(tree, &hfi_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
705 offset = dissect_gadu_gadu_login_protocol(tvb, tree, offset);
707 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
710 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
717 dissect_gadu_gadu_login_hash(tvbuff_t *tvb, proto_tree *tree, int offset)
724 hash_type = tvb_get_guint8(tvb, offset);
725 proto_tree_add_item(tree, &hfi_gadu_gadu_login_hash_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
729 case GG_LOGIN_HASH_GG32:
730 /* hash is 32-bit number written in LE */
731 _tvb_memcpy_reverse(tvb, hash, offset, 4);
732 proto_tree_add_bytes_format_value(tree, hfi_gadu_gadu_login_hash.id, tvb, offset, 4, hash, "0x%.8x", tvb_get_letohl(tvb, offset));
733 for (i = 4; i < 64; i++) {
734 if (tvb_get_guint8(tvb, offset+i)) {
735 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset + 4, 64-4, ENC_NA);
741 case GG_LOGIN_HASH_SHA1:
742 proto_tree_add_item(tree, &hfi_gadu_gadu_login_hash, tvb, offset, 20, ENC_NA);
743 for (i = 20; i < 64; i++) {
744 if (tvb_get_guint8(tvb, offset+i)) {
745 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset + 20, 64-20, ENC_NA);
752 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 64, ENC_NA);
761 dissect_gadu_gadu_login70(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
765 col_set_str(pinfo->cinfo, COL_INFO, "Login request (7.0)");
767 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
768 gadu_gadu_create_conversation(pinfo, uin);
770 proto_tree_add_uint(tree, &hfi_gadu_gadu_login_uin, tvb, offset, 4, uin);
773 offset = dissect_gadu_gadu_login_hash(tvb, tree, offset);
775 proto_tree_add_item(tree, &hfi_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
778 offset = dissect_gadu_gadu_login_protocol(tvb, tree, offset);
780 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
783 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
786 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
789 /* XXX packet not fully dissected */
795 dissect_gadu_gadu_login80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
799 col_set_str(pinfo->cinfo, COL_INFO, "Login request (8.0)");
801 uin = tvb_get_letohl(tvb, offset);
802 gadu_gadu_create_conversation(pinfo, uin);
804 proto_tree_add_item(tree, &hfi_gadu_gadu_login_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
807 proto_tree_add_item(tree, &hfi_gadu_gadu_login80_lang, tvb, offset, 2, ENC_ASCII | ENC_NA);
810 offset = dissect_gadu_gadu_login_hash(tvb, tree, offset);
812 proto_tree_add_item(tree, &hfi_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
815 /* XXX packet not fully dissected */
821 dissect_gadu_gadu_login_ok(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
823 col_set_str(pinfo->cinfo, COL_INFO, "Login success (< 8.0)");
825 /* not empty packet, but content unknown */
831 dissect_gadu_gadu_login_failed(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
833 col_set_str(pinfo->cinfo, COL_INFO, "Login fail (< 8.0)");
841 dissect_gadu_gadu_login_ok80(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
843 col_set_str(pinfo->cinfo, COL_INFO, "Login success (8.0)");
845 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA); /* 01 00 00 00 */
852 dissect_gadu_gadu_login80_failed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
854 col_set_str(pinfo->cinfo, COL_INFO, "Login fail (8.0)");
856 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA); /* 01 00 00 00 */
863 dissect_gadu_gadu_user_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
867 col_set_str(pinfo->cinfo, COL_INFO, "Contact details");
869 /* XXX, add subtrees */
873 users_num = tvb_get_letohl(tvb, offset);
876 while (users_num--) {
879 proto_tree_add_item(tree, &hfi_gadu_gadu_userdata_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
882 attr_num = tvb_get_letohl(tvb, offset);
886 guint32 name_size, val_size;
889 name_size = tvb_get_letohl(tvb, offset);
892 name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, name_size, ENC_ASCII | ENC_NA);
893 proto_tree_add_string(tree, &hfi_gadu_gadu_userdata_attr_name, tvb, offset - 4, 4 + name_size, name);
896 proto_tree_add_item(tree, &hfi_gadu_gadu_userdata_attr_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
899 val_size = tvb_get_letohl(tvb, offset);
902 val = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, val_size, ENC_ASCII | ENC_NA);
903 proto_tree_add_string(tree, &hfi_gadu_gadu_userdata_attr_value, tvb, offset - 4, 4 + val_size, val);
912 dissect_gadu_gadu_typing_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
914 col_set_str(pinfo->cinfo, COL_INFO, "Typing notify");
916 /* XXX, when type > 1, it's length not type ! */
917 proto_tree_add_item(tree, &hfi_gadu_gadu_typing_notify_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
920 proto_tree_add_item(tree, &hfi_gadu_gadu_typing_notify_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
927 dissect_gadu_gadu_msg_attr(tvbuff_t *tvb _U_, proto_tree *tree _U_, int offset)
935 dissect_gadu_gadu_recv_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
937 struct gadu_gadu_conv_data *conv;
940 col_set_str(pinfo->cinfo, COL_INFO, "Receive message (< 8.0)");
942 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
943 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_recipient, tvb, 0, 0, conv->uin);
944 PROTO_ITEM_SET_GENERATED(ti);
946 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
947 PROTO_ITEM_SET_GENERATED(ti);
948 PROTO_ITEM_SET_HIDDEN(ti);
951 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
952 PROTO_ITEM_SET_HIDDEN(ti);
953 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_sender, tvb, offset, 4, ENC_LITTLE_ENDIAN);
956 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
959 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
962 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
965 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_msg_text, tree, offset);
967 offset = dissect_gadu_gadu_msg_attr(tvb, tree, offset);
973 dissect_gadu_gadu_send_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
975 struct gadu_gadu_conv_data *conv;
978 col_set_str(pinfo->cinfo, COL_INFO, "Send message (< 8.0)");
980 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
981 PROTO_ITEM_SET_HIDDEN(ti);
982 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
985 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
986 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_sender, tvb, 0, 0, conv->uin);
987 PROTO_ITEM_SET_GENERATED(ti);
989 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
990 PROTO_ITEM_SET_GENERATED(ti);
991 PROTO_ITEM_SET_HIDDEN(ti);
994 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
997 ti = proto_tree_add_time(tree, &hfi_gadu_gadu_msg_time, tvb, 0, 0, &(pinfo->fd->abs_ts));
998 PROTO_ITEM_SET_GENERATED(ti);
1000 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1003 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_msg_text, tree, offset);
1005 offset = dissect_gadu_gadu_msg_attr(tvb, tree, offset);
1011 dissect_gadu_gadu_recv_msg80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1013 struct gadu_gadu_conv_data *conv;
1016 col_set_str(pinfo->cinfo, COL_INFO, "Receive message (8.0)");
1018 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
1019 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_recipient, tvb, 0, 0, conv->uin);
1020 PROTO_ITEM_SET_GENERATED(ti);
1022 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
1023 PROTO_ITEM_SET_GENERATED(ti);
1024 PROTO_ITEM_SET_HIDDEN(ti);
1027 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1028 PROTO_ITEM_SET_HIDDEN(ti);
1029 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_sender, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1032 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1035 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1038 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1041 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_plain, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1044 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_attr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1047 /* XXX packet not fully dissected */
1053 dissect_gadu_gadu_send_msg80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1055 struct gadu_gadu_conv_data *conv;
1058 col_set_str(pinfo->cinfo, COL_INFO, "Send message (8.0)");
1060 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1061 PROTO_ITEM_SET_HIDDEN(ti);
1062 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1065 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
1066 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_sender, tvb, 0, 0, conv->uin);
1067 PROTO_ITEM_SET_GENERATED(ti);
1069 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
1070 PROTO_ITEM_SET_GENERATED(ti);
1071 PROTO_ITEM_SET_HIDDEN(ti);
1074 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1077 ti = proto_tree_add_time(tree, &hfi_gadu_gadu_msg_time, tvb, 0, 0, &(pinfo->fd->abs_ts));
1078 PROTO_ITEM_SET_GENERATED(ti);
1080 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1083 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_plain, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1086 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_attr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1089 /* XXX packet not fully dissected */
1095 dissect_gadu_gadu_send_msg_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1097 col_set_str(pinfo->cinfo, COL_INFO, "Message acknowledge (server)");
1099 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1102 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1105 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1112 dissect_gadu_gadu_recv_msg_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1114 col_set_str(pinfo->cinfo, COL_INFO, "Message acknowledge (client)");
1116 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1123 dissect_gadu_gadu_status60(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1128 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (6.0)");
1130 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
1131 proto_tree_add_uint(tree, &hfi_gadu_gadu_status_uin, tvb, offset, 4, uin);
1134 status = tvb_get_guint8(tvb, offset);
1135 proto_tree_add_item(tree, &hfi_gadu_gadu_status_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1138 proto_tree_add_item(tree, &hfi_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1141 proto_tree_add_item(tree, &hfi_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1144 proto_tree_add_item(tree, &hfi_gadu_gadu_status_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1147 proto_tree_add_item(tree, &hfi_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1150 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
1153 if (gadu_gadu_status_has_descr(status))
1154 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1160 dissect_gadu_gadu_status77(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1165 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (7.7)");
1167 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
1168 proto_tree_add_uint(tree, &hfi_gadu_gadu_status_uin, tvb, offset, 4, uin);
1171 status = tvb_get_guint8(tvb, offset);
1172 proto_tree_add_item(tree, &hfi_gadu_gadu_status_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1175 proto_tree_add_item(tree, &hfi_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1178 proto_tree_add_item(tree, &hfi_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1181 proto_tree_add_item(tree, &hfi_gadu_gadu_status_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1184 proto_tree_add_item(tree, &hfi_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1187 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
1190 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1193 if (gadu_gadu_status_has_descr(status))
1194 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1200 dissect_gadu_gadu_status80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1202 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (8.0)");
1204 proto_tree_add_item(tree, &hfi_gadu_gadu_status_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1207 proto_tree_add_item(tree, &hfi_gadu_gadu_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1210 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1213 proto_tree_add_item(tree, &hfi_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1216 proto_tree_add_item(tree, &hfi_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1219 proto_tree_add_item(tree, &hfi_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1222 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA);
1225 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1228 offset = dissect_gadu_gadu_uint32_string_utf8(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1234 dissect_gadu_gadu_notify_reply80(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1236 col_set_str(pinfo->cinfo, COL_INFO, "Receive status list (8.0)");
1238 /* XXX packet not fully dissected */
1244 dissect_gadu_gadu_new_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1248 col_set_str(pinfo->cinfo, COL_INFO, "New status (< 8.0)");
1250 status = tvb_get_letohl(tvb, offset);
1251 proto_tree_add_item(tree, &hfi_gadu_gadu_new_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1254 if (gadu_gadu_status_has_descr(status & 0xff))
1255 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1261 dissect_gadu_gadu_new_status80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1263 col_set_str(pinfo->cinfo, COL_INFO, "New status (8.0)");
1265 proto_tree_add_item(tree, &hfi_gadu_gadu_new_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1268 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1271 offset = dissect_gadu_gadu_uint32_string_utf8(tvb, &hfi_gadu_gadu_new_status_desc, tree, offset);
1277 dissect_gadu_gadu_list_empty(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1279 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (empty)");
1287 dissect_gadu_gadu_add_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1289 col_set_str(pinfo->cinfo, COL_INFO, "Notify list add");
1291 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1294 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1301 dissect_gadu_gadu_notify105_common(tvbuff_t *tvb, proto_tree *tree, int offset, char **puin)
1306 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* unknown 00 */
1309 uin_len = tvb_get_guint8(tvb, offset);
1311 uin = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, uin_len, ENC_ASCII | ENC_NA);
1312 proto_tree_add_string(tree, &hfi_gadu_gadu_contact_uin_str, tvb, offset - 1, 1 + uin_len, uin);
1317 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1324 dissect_gadu_gadu_add_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1326 col_set_str(pinfo->cinfo, COL_INFO, "Notify list add (10.5)");
1328 return dissect_gadu_gadu_notify105_common(tvb, tree, offset, NULL);
1332 dissect_gadu_gadu_remove_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1334 col_set_str(pinfo->cinfo, COL_INFO, "Notify list remove");
1336 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1339 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1346 dissect_gadu_gadu_remove_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1348 col_set_str(pinfo->cinfo, COL_INFO, "Notify list remove (10.5)");
1350 return dissect_gadu_gadu_notify105_common(tvb, tree, offset, NULL);
1354 dissect_gadu_gadu_notify_common(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1356 proto_tree *contact_tree;
1359 while (tvb_reported_length_remaining(tvb, offset) >= 4+1) {
1360 guint32 uin = tvb_get_letohl(tvb, offset);
1362 ti = proto_tree_add_text(tree, tvb, offset, 5, "Contact: %u", uin);
1363 contact_tree = proto_item_add_subtree(ti, ett_gadu_gadu_contact);
1365 proto_tree_add_item(contact_tree, &hfi_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1368 proto_tree_add_item(contact_tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1376 dissect_gadu_gadu_notify_first(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1378 col_set_str(pinfo->cinfo, COL_INFO, "Notify list");
1380 return dissect_gadu_gadu_notify_common(tvb, pinfo, tree, offset);
1384 dissect_gadu_gadu_notify_last(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1386 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (last)");
1388 return dissect_gadu_gadu_notify_common(tvb, pinfo, tree, offset);
1392 dissect_gadu_gadu_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1394 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (10.5)");
1396 while (tvb_reported_length_remaining(tvb, offset) >= 2) {
1397 const int org_offset = offset;
1399 proto_tree *contact_tree;
1404 ti = proto_tree_add_text(tree, tvb, offset, 0, "Contact: ");
1405 contact_tree = proto_item_add_subtree(ti, ett_gadu_gadu_contact);
1407 offset = dissect_gadu_gadu_notify105_common(tvb, contact_tree, offset, &uin);
1408 proto_item_append_text(ti, "%s", uin);
1410 proto_item_set_len(ti, offset - org_offset);
1417 dissect_gadu_gadu_ping(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1419 col_set_str(pinfo->cinfo, COL_INFO, "Ping");
1427 dissect_gadu_gadu_welcome(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1429 col_set_str(pinfo->cinfo, COL_INFO, "Welcome");
1431 proto_tree_add_item(tree, &hfi_gadu_gadu_welcome_seed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1438 dissect_gadu_gadu_userlist_xml_compressed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1440 int remain = tvb_reported_length_remaining(tvb, offset);
1441 tvbuff_t *uncomp_tvb;
1446 if ((uncomp_tvb = tvb_child_uncompress(tvb, tvb, offset, remain))) {
1447 proto_tree_add_text(tree, tvb, offset, remain, "Userlist XML data: [Decompression succeeded]");
1449 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed userlist");
1451 /* XXX add DTD (pinfo->match_string) */
1452 call_dissector_only(xml_handle, uncomp_tvb, pinfo, tree, NULL);
1454 proto_tree_add_text(tree, tvb, offset, remain, "Userlist XML data: [Error: Decompression failed] (or no libz)");
1462 dissect_gadu_gadu_userlist_request80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1467 col_set_str(pinfo->cinfo, COL_INFO, "Userlist request (8.0)");
1469 type = tvb_get_guint8(tvb, offset);
1470 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1473 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_userlist_format, tvb, 0, 0, GG_USERLIST100_FORMAT_TYPE_GG100);
1474 PROTO_ITEM_SET_GENERATED(ti);
1477 case GG_USERLIST_PUT:
1478 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1486 dissect_gadu_gadu_userlist_request100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1488 guint8 type, format;
1490 col_set_str(pinfo->cinfo, COL_INFO, "Userlist request (10.0)");
1492 type = tvb_get_guint8(tvb, offset);
1493 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1496 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1499 format = tvb_get_guint8(tvb, offset);
1500 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1503 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 01 */
1507 case GG_USERLIST_PUT:
1508 if (format == GG_USERLIST100_FORMAT_TYPE_GG100)
1509 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1517 dissect_gadu_gadu_userlist_reply80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1521 col_set_str(pinfo->cinfo, COL_INFO, "Userlist reply (8.0)");
1523 type = tvb_get_guint8(tvb, offset);
1524 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1528 case GG_USERLIST_GET_REPLY:
1529 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1537 dissect_gadu_gadu_userlist_reply100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1539 guint8 type, format;
1541 col_set_str(pinfo->cinfo, COL_INFO, "Userlist reply (10.0)");
1543 type = tvb_get_guint8(tvb, offset);
1544 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1547 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1550 format = tvb_get_guint8(tvb, offset);
1551 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1554 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 01 */
1558 case GG_USERLIST_GET_REPLY:
1559 if (format == GG_USERLIST100_FORMAT_TYPE_GG100)
1560 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1568 dissect_gadu_gadu_userlist_version100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1570 col_set_str(pinfo->cinfo, COL_INFO, "Userlist version (10.0)");
1572 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1579 dissect_gadu_gadu_dcc7_id_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1581 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection id request");
1583 proto_tree_add_item(tree, &hfi_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1590 dissect_gadu_gadu_dcc7_id_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1592 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection id reply");
1594 proto_tree_add_item(tree, &hfi_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1597 proto_tree_add_item(tree, &hfi_dcc_id, tvb, offset, 8, ENC_NA);
1604 dissect_gadu_gadu_dcc7_new(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1606 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection new");
1608 proto_tree_add_item(tree, &hfi_dcc_id, tvb, offset, 8, ENC_NA);
1611 proto_tree_add_item(tree, &hfi_dcc_uin_from, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1614 proto_tree_add_item(tree, &hfi_dcc_uin_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1617 proto_tree_add_item(tree, &hfi_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1620 proto_tree_add_item(tree, &hfi_dcc_filename, tvb, offset, 255, ENC_ASCII | ENC_NA);
1627 dissect_gadu_gadu_dcc7_id_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1629 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection abort");
1631 proto_tree_add_item(tree, &hfi_dcc_id, tvb, offset, 8, ENC_NA);
1634 proto_tree_add_item(tree, &hfi_dcc_uin_from, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1637 proto_tree_add_item(tree, &hfi_dcc_uin_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1644 dissect_gadu_gadu_pubdir50_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1648 col_set_str(pinfo->cinfo, COL_INFO, "Public directory request");
1650 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1653 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_request_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1655 /* XXX, link request sequence with reply sequence */
1657 while ((pos = tvb_find_guint8(tvb, offset, -1, '\0')) > 0) {
1658 /* XXX, display it better, field=value */
1659 dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_pubdir_request_str, tree, offset);
1667 dissect_gadu_gadu_pubdir50_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1671 col_set_str(pinfo->cinfo, COL_INFO, "Public directory reply");
1673 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1676 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_reply_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1678 /* XXX, link reply sequence with request sequence */
1680 while ((pos = tvb_find_guint8(tvb, offset, -1, '\0')) > 0) {
1681 /* XXX, display it better, field=value */
1682 dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_pubdir_reply_str, tree, offset);
1690 dissect_gadu_gadu_xml_action(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1695 col_set_str(pinfo->cinfo, COL_INFO, "XML action message");
1697 xml_tvb = tvb_new_subset_remaining(tvb, offset);
1699 /* XXX add DTD (pinfo->match_string) */
1700 ret = call_dissector_only(xml_handle, xml_tvb, pinfo, tree, NULL);
1702 return offset + ret;
1706 dissect_gadu_gadu_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1708 proto_tree *gadu_gadu_tree = NULL;
1713 col_clear(pinfo->cinfo, COL_INFO); /* XXX, remove, add separator when multiple PDU */
1716 proto_item *ti = proto_tree_add_item(tree, hfi_gadu_gadu, tvb, 0, -1, ENC_NA);
1717 gadu_gadu_tree = proto_item_add_subtree(ti, ett_gadu_gadu);
1720 pkt_type = tvb_get_letohl(tvb, offset);
1721 proto_tree_add_item(gadu_gadu_tree, (pinfo->p2p_dir == P2P_DIR_RECV) ? &hfi_gadu_gadu_header_type_recv : &hfi_gadu_gadu_header_type_send, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1723 proto_tree_add_item(gadu_gadu_tree, &hfi_gadu_gadu_header_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1726 if (pinfo->p2p_dir == P2P_DIR_RECV) {
1728 case GG_DISCONNECTING:
1729 offset = dissect_gadu_gadu_disconnecting(tvb, pinfo, gadu_gadu_tree, offset);
1732 case GG_DISCONNECT_ACK:
1733 offset = dissect_gadu_gadu_disconnect_ack(tvb, pinfo, gadu_gadu_tree, offset);
1737 offset = dissect_gadu_gadu_login_ok(tvb, pinfo, gadu_gadu_tree, offset);
1741 offset = dissect_gadu_gadu_login_ok80(tvb, pinfo, gadu_gadu_tree, offset);
1744 case GG_LOGIN_FAILED:
1745 offset = dissect_gadu_gadu_login_failed(tvb, pinfo, gadu_gadu_tree, offset);
1748 case GG_LOGIN80_FAILED:
1749 offset = dissect_gadu_gadu_login80_failed(tvb, pinfo, gadu_gadu_tree, offset);
1753 offset = dissect_gadu_gadu_user_data(tvb, pinfo, gadu_gadu_tree, offset);
1756 case GG_TYPING_NOTIFY:
1757 offset = dissect_gadu_gadu_typing_notify(tvb, pinfo, gadu_gadu_tree, offset);
1761 offset = dissect_gadu_gadu_recv_msg(tvb, pinfo, gadu_gadu_tree, offset);
1765 offset = dissect_gadu_gadu_recv_msg80(tvb, pinfo, gadu_gadu_tree, offset);
1768 case GG_SEND_MSG_ACK:
1769 /* GG_SEND_MSG_ACK is received by client */
1770 offset = dissect_gadu_gadu_send_msg_ack(tvb, pinfo, gadu_gadu_tree, offset);
1774 offset = dissect_gadu_gadu_status60(tvb, pinfo, gadu_gadu_tree, offset);
1778 offset = dissect_gadu_gadu_status77(tvb, pinfo, gadu_gadu_tree, offset);
1782 offset = dissect_gadu_gadu_status80(tvb, pinfo, gadu_gadu_tree, offset);
1785 case GG_NOTIFY_REPLY80:
1786 offset = dissect_gadu_gadu_notify_reply80(tvb, pinfo, gadu_gadu_tree, offset);
1789 case GG_DCC7_ID_REPLY:
1790 offset = dissect_gadu_gadu_dcc7_id_reply(tvb, pinfo, gadu_gadu_tree, offset);
1794 offset = dissect_gadu_gadu_welcome(tvb, pinfo, gadu_gadu_tree, offset);
1797 case GG_USERLIST_REPLY80:
1798 offset = dissect_gadu_gadu_userlist_reply80(tvb, pinfo, gadu_gadu_tree, offset);
1801 case GG_USERLIST100_REPLY:
1802 offset = dissect_gadu_gadu_userlist_reply100(tvb, pinfo, gadu_gadu_tree, offset);
1805 case GG_USERLIST100_VERSION:
1806 offset = dissect_gadu_gadu_userlist_version100(tvb, pinfo, gadu_gadu_tree, offset);
1809 case GG_PUBDIR50_REPLY:
1810 offset = dissect_gadu_gadu_pubdir50_reply(tvb, pinfo, gadu_gadu_tree, offset);
1814 offset = dissect_gadu_gadu_xml_action(tvb, pinfo, gadu_gadu_tree, offset);
1820 case GG_NOTIFY_REPLY:
1821 case GG_USERLIST_REPLY:
1822 case GG_NOTIFY_REPLY60:
1824 case GG_LOGIN_HASH_TYPE_INVALID:
1825 case GG_NOTIFY_REPLY77:
1828 case GG_DCC7_ACCEPT:
1829 case GG_DCC7_REJECT:
1830 case GG_DCC7_ID_ABORTED:
1832 case GG_STATUS80BETA:
1833 case GG_NOTIFY_REPLY80BETA:
1834 case GG_OWN_MESSAGE:
1835 case GG_OWN_RESOURCE_INFO:
1838 const char *pkt_name = try_val_to_str(pkt_type, gadu_gadu_packets_type_recv);
1841 col_set_str(pinfo->cinfo, COL_INFO, pkt_name);
1843 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown recv packet: %.2x", pkt_type);
1851 offset = dissect_gadu_gadu_login(tvb, pinfo, gadu_gadu_tree, offset);
1855 offset = dissect_gadu_gadu_login70(tvb, pinfo, gadu_gadu_tree, offset);
1859 offset = dissect_gadu_gadu_login80(tvb, pinfo, gadu_gadu_tree, offset);
1863 offset = dissect_gadu_gadu_list_empty(tvb, pinfo, gadu_gadu_tree, offset);
1866 case GG_NOTIFY_FIRST:
1867 offset = dissect_gadu_gadu_notify_first(tvb, pinfo, gadu_gadu_tree, offset);
1870 case GG_NOTIFY_LAST:
1871 offset = dissect_gadu_gadu_notify_last(tvb, pinfo, gadu_gadu_tree, offset);
1875 offset = dissect_gadu_gadu_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1879 offset = dissect_gadu_gadu_add_notify(tvb, pinfo, gadu_gadu_tree, offset);
1882 case GG_ADD_NOTIFY105:
1883 offset = dissect_gadu_gadu_add_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1886 case GG_REMOVE_NOTIFY:
1887 offset = dissect_gadu_gadu_remove_notify(tvb, pinfo, gadu_gadu_tree, offset);
1890 case GG_REMOVE_NOTIFY105:
1891 offset = dissect_gadu_gadu_remove_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1895 offset = dissect_gadu_gadu_ping(tvb, pinfo, gadu_gadu_tree, offset);
1898 case GG_TYPING_NOTIFY:
1899 offset = dissect_gadu_gadu_typing_notify(tvb, pinfo, gadu_gadu_tree, offset);
1903 offset = dissect_gadu_gadu_send_msg(tvb, pinfo, gadu_gadu_tree, offset);
1907 offset = dissect_gadu_gadu_send_msg80(tvb, pinfo, gadu_gadu_tree, offset);
1910 case GG_RECV_MSG_ACK:
1911 /* GG_RECV_MSG_ACK is send by client */
1912 offset = dissect_gadu_gadu_recv_msg_ack(tvb, pinfo, gadu_gadu_tree, offset);
1916 offset = dissect_gadu_gadu_new_status(tvb, pinfo, gadu_gadu_tree, offset);
1919 case GG_NEW_STATUS80:
1920 offset = dissect_gadu_gadu_new_status80(tvb, pinfo, gadu_gadu_tree, offset);
1923 case GG_DCC7_ID_REQUEST:
1924 offset = dissect_gadu_gadu_dcc7_id_request(tvb, pinfo, gadu_gadu_tree, offset);
1928 offset = dissect_gadu_gadu_dcc7_new(tvb, pinfo, gadu_gadu_tree, offset);
1931 case GG_DCC7_ID_ABORT:
1932 offset = dissect_gadu_gadu_dcc7_id_abort(tvb, pinfo, gadu_gadu_tree, offset);
1935 case GG_USERLIST_REQUEST80:
1936 offset = dissect_gadu_gadu_userlist_request80(tvb, pinfo, gadu_gadu_tree, offset);
1939 case GG_USERLIST100_REQUEST:
1940 offset = dissect_gadu_gadu_userlist_request100(tvb, pinfo, gadu_gadu_tree, offset);
1943 case GG_PUBDIR50_REQUEST:
1944 offset = dissect_gadu_gadu_pubdir50_request(tvb, pinfo, gadu_gadu_tree, offset);
1950 case GG_USERLIST_REQUEST:
1952 case GG_DCC7_ACCEPT:
1953 case GG_DCC7_REJECT:
1954 case GG_DCC7_ID_DUNNO1:
1955 case GG_NEW_STATUS80BETA:
1956 case GG_LOGIN80BETA:
1957 case GG_OWN_DISCONNECT:
1958 case GG_NEW_STATUS105:
1962 const char *pkt_name = try_val_to_str(pkt_type, gadu_gadu_packets_type_send);
1965 col_set_str(pinfo->cinfo, COL_INFO, pkt_name);
1967 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown send packet: %.2x", pkt_type);
1973 /* for now display rest of data as FT_BYTES. */
1974 if (tvb_reported_length_remaining(tvb, offset) > 0) {
1975 proto_tree_add_item(gadu_gadu_tree, &hfi_gadu_gadu_data, tvb, offset, -1, ENC_NA);
1978 return tvb_length(tvb);
1982 get_gadu_gadu_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1984 guint32 len = tvb_get_letohl(tvb, offset + 4);
1990 dissect_gadu_gadu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1992 if (pinfo->srcport == pinfo->match_uint && pinfo->destport != pinfo->match_uint)
1993 pinfo->p2p_dir = P2P_DIR_RECV;
1994 else if (pinfo->srcport != pinfo->match_uint && pinfo->destport == pinfo->match_uint)
1995 pinfo->p2p_dir = P2P_DIR_SENT;
1999 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gadu-Gadu");
2000 col_clear(pinfo->cinfo, COL_INFO);
2002 tcp_dissect_pdus(tvb, pinfo, tree, gadu_gadu_desegment, 8, get_gadu_gadu_pdu_len, dissect_gadu_gadu_pdu, data);
2003 return tvb_length(tvb);
2007 proto_register_gadu_gadu(void)
2009 #ifndef HAVE_HFI_SECTION_INIT
2010 static header_field_info *hfi[] = {
2012 &hfi_gadu_gadu_header_type_recv,
2013 &hfi_gadu_gadu_header_type_send,
2014 &hfi_gadu_gadu_header_length,
2016 &hfi_gadu_gadu_login_uin,
2017 &hfi_gadu_gadu_login_hash_type,
2018 &hfi_gadu_gadu_login_hash,
2019 &hfi_gadu_gadu_login_status,
2020 &hfi_gadu_gadu_login_protocol,
2021 &hfi_gadu_gadu_login_version,
2022 &hfi_gadu_gadu_login_local_ip,
2023 &hfi_gadu_gadu_login_local_port,
2025 &hfi_gadu_gadu_login80_lang,
2026 /* Contacts details */
2027 &hfi_gadu_gadu_userdata_uin,
2028 &hfi_gadu_gadu_userdata_attr_name,
2029 &hfi_gadu_gadu_userdata_attr_type,
2030 &hfi_gadu_gadu_userdata_attr_value,
2031 &hfi_gadu_gadu_typing_notify_type,
2032 &hfi_gadu_gadu_typing_notify_uin,
2033 /* Message common */
2034 &hfi_gadu_gadu_msg_uin,
2035 &hfi_gadu_gadu_msg_sender,
2036 &hfi_gadu_gadu_msg_recipient,
2037 &hfi_gadu_gadu_msg_seq,
2038 &hfi_gadu_gadu_msg_time,
2039 &hfi_gadu_gadu_msg_class,
2040 &hfi_gadu_gadu_msg_text,
2041 /* GG_RECV_MSG80, GG_SEND_MSG80 */
2042 &hfi_gadu_gadu_msg80_offset_plain,
2043 &hfi_gadu_gadu_msg80_offset_attr,
2044 /* Contact (notify) common */
2045 &hfi_gadu_gadu_contact_uin,
2046 &hfi_gadu_gadu_contact_uin_str,
2047 &hfi_gadu_gadu_contact_type,
2049 &hfi_gadu_gadu_status_uin,
2050 &hfi_gadu_gadu_status_status,
2051 &hfi_gadu_gadu_status_ip,
2052 &hfi_gadu_gadu_status_port,
2053 &hfi_gadu_gadu_status_version,
2054 &hfi_gadu_gadu_status_img_size,
2055 &hfi_gadu_gadu_status_descr,
2056 /* New status (setting status) common */
2057 &hfi_gadu_gadu_new_status_status,
2058 &hfi_gadu_gadu_new_status_desc,
2060 &hfi_gadu_gadu_userlist_request_type,
2061 &hfi_gadu_gadu_userlist_version,
2062 &hfi_gadu_gadu_userlist_format,
2063 &hfi_gadu_gadu_userlist_reply_type,
2064 /* Direct Connection */
2070 /* Public Directory */
2071 &hfi_gadu_gadu_pubdir_request_type,
2072 &hfi_gadu_gadu_pubdir_request_seq,
2073 &hfi_gadu_gadu_pubdir_request_str,
2074 &hfi_gadu_gadu_pubdir_reply_type,
2075 &hfi_gadu_gadu_pubdir_reply_seq,
2076 &hfi_gadu_gadu_pubdir_reply_str,
2078 &hfi_gadu_gadu_welcome_seed,
2079 /* GG_SEND_MSG_ACK */
2080 &hfi_gadu_gadu_msg_ack_status,
2081 &hfi_gadu_gadu_msg_ack_recipient,
2082 &hfi_gadu_gadu_msg_ack_seq,
2083 /* Not dissected data */
2084 &hfi_gadu_gadu_data,
2086 #endif /* HAVE_HFI_SECTION_INIT */
2088 static gint *ett[] = {
2090 &ett_gadu_gadu_contact
2093 module_t *gadu_gadu_module;
2095 int proto_gadu_gadu;
2097 proto_gadu_gadu = proto_register_protocol("Gadu-Gadu Protocol", "Gadu-Gadu", "gadu-gadu");
2098 hfi_gadu_gadu = proto_registrar_get_nth(proto_gadu_gadu);
2100 gadu_gadu_module = prefs_register_protocol(proto_gadu_gadu, NULL);
2101 prefs_register_bool_preference(gadu_gadu_module, "desegment",
2102 "Reassemble Gadu-Gadu messages spanning multiple TCP segments",
2103 "Whether the Gadu-Gadu dissector should reassemble messages spanning multiple TCP segments."
2104 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2105 &gadu_gadu_desegment);
2107 proto_register_fields(proto_gadu_gadu, hfi, array_length(hfi));
2108 proto_register_subtree_array(ett, array_length(ett));
2110 gadu_gadu_handle = new_create_dissector_handle(dissect_gadu_gadu, proto_gadu_gadu);
2114 proto_reg_handoff_gadu_gadu(void)
2116 dissector_add_uint("tcp.port", TCP_PORT_GADU_GADU, gadu_gadu_handle);
2118 xml_handle = find_dissector("xml");