MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-gadu-gadu.c
blobebf688cb84f4bea3bb75729c5159276c00291e06
1 /* packet-gadu-gadu.c
2 * Routines for Gadu-Gadu dissection
3 * Copyright 2011,2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
5 * $Id$
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
30 #include "config.h"
32 #include <glib.h>
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
57 #define GG_PONG 0x07
58 #define GG_PING 0x08
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),
104 GG_TYPE_VS(GG_PONG),
105 GG_TYPE_VS(GG_PING),
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),
141 { 0, NULL }
144 #define GG_NEW_STATUS 0x02
145 #define GG_PONG 0x07
146 #define GG_PING 0x08
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),
184 GG_TYPE_VS(GG_PONG),
185 GG_TYPE_VS(GG_PING),
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),
220 { 0, NULL }
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" },
229 { 0, NULL }
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" },
252 { 0, NULL }
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" },
263 { 0, NULL }
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)" },
276 { 0, NULL }
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)" },
287 { 0, NULL }
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" },
317 { 0, NULL }
320 static const value_string gadu_gadu_dcc_type_vals[] = {
321 { 1, "Voice transmission" },
322 { 4, "File transmission" },
323 { 0, NULL }
326 static const value_string gadu_gadu_typing_notify_type_vals[] = {
327 { 1, "Typing started" },
328 { 0, "Typing stopped" },
329 { 0, NULL }
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" },
336 { 0, NULL }
339 static header_field_info *hfi_gadu_gadu = NULL;
341 #define GADU_GADU_HFI_INIT HFI_INIT(proto_gadu_gadu)
343 /* Header */
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 };
528 /* GG_WELCOME */
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);
551 if (!gg_conv) {
552 gg_conv = wmem_new(wmem_file_scope(), struct gadu_gadu_conv_data);
553 gg_conv->uin = uin;
555 conversation_add_proto_data(conv, hfi_gadu_gadu->id, gg_conv);
557 /* assert(gg_conv->uin == uin); */
558 return gg_conv;
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);
567 if (conv)
568 return (struct gadu_gadu_conv_data *)conversation_get_proto_data(conv, hfi_gadu_gadu->id);
569 return NULL;
572 static gboolean
573 gadu_gadu_status_has_descr(int status)
575 return
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);
584 static int
585 dissect_gadu_gadu_stringz_cp1250(tvbuff_t *tvb, const header_field_info *hfi, proto_tree *tree, int offset)
587 static const gunichar2 table_cp1250[] = {
588 0x20ac, 0xFFFD, 0x201a, 0xFFFD, 0x201e, 0x2026, 0x2020, 0x2021, /* 0x80 - */
589 0xFFFD, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179, /* - 0x8F */
590 0xFFFD, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 0x90 - */
591 0xFFFD, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a, /* - 0x9F */
592 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, /* 0xA0 - */
593 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b, /* - 0xAF */
594 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, /* 0xB0 - */
595 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c, /* - 0xBF */
596 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* 0xC0 - */
597 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* - 0xCF */
598 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* 0xD0 - */
599 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* - 0xDF */
600 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* 0xE0 - */
601 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* - 0xEF */
602 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* 0xF0 - */
603 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* - 0xFF */
606 const int org_offset = offset;
608 wmem_strbuf_t *str;
609 guint8 ch;
610 gint len;
612 len = tvb_reported_length_remaining(tvb, offset);
614 str = wmem_strbuf_new(wmem_packet_scope(), "");
616 while ((len > 0) && (ch = tvb_get_guint8(tvb, offset))) {
617 if (ch < 0x80)
618 wmem_strbuf_append_c(str, ch);
619 else
620 wmem_strbuf_append_unichar(str, table_cp1250[ch-0x80]);
621 offset++;
622 len--;
624 if (len > 0)
625 offset++; /* NUL */
627 proto_tree_add_unicode_string(tree, hfi->id, tvb, org_offset, offset - org_offset, wmem_strbuf_get_str(str));
629 return offset;
632 static int
633 dissect_gadu_gadu_uint32_string_utf8(tvbuff_t *tvb, const header_field_info *hfi, proto_tree *tree, int offset)
635 const int org_offset = offset;
637 const char *str;
638 guint32 len;
640 len = tvb_get_letohl(tvb, offset);
641 offset += 4;
643 if (len > 0) {
644 /* proto_item_fill_label() is broken for UTF-8 strings.
645 * It's using internally format_text() which doesn't support UTF-8
647 /* proto_tree_add_item(tree, hfindex, tvb, offset, len, ENC_UTF_8|ENC_NA); */
649 /* Use workaround */
650 str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_UTF_8|ENC_NA);
652 } else
653 str = "";
655 offset += len;
657 proto_tree_add_unicode_string(tree, hfi->id, tvb, org_offset, offset - org_offset, str);
658 return offset;
662 static int
663 dissect_gadu_gadu_disconnecting(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
665 col_set_str(pinfo->cinfo, COL_INFO, "Disconnecting");
667 /* empty packet */
669 return offset;
673 static int
674 dissect_gadu_gadu_disconnect_ack(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
676 col_set_str(pinfo->cinfo, COL_INFO, "Disconnect acknowledge (< 10.0)");
678 /* empty packet */
680 return offset;
683 static void *
684 _tvb_memcpy_reverse(tvbuff_t *tvb, void *target, gint offset, size_t length)
686 guint8 *t = (guint8 *) target;
688 while (length > 0) {
689 length--;
690 t[length] = tvb_get_guint8(tvb, offset);
691 offset++;
693 return target;
696 static int
697 dissect_gadu_gadu_login_protocol(tvbuff_t *tvb, proto_tree *tree, int offset)
699 proto_item *ti;
701 guint32 protocol;
703 protocol = tvb_get_letohl(tvb, offset) & 0xff;
704 proto_tree_add_item(tree, &hfi_gadu_gadu_login_protocol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
705 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)"));
706 PROTO_ITEM_SET_GENERATED(ti);
707 offset += 4;
709 return offset;
712 static int
713 dissect_gadu_gadu_login(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
715 proto_item *ti;
717 guint32 uin;
718 guint8 hash[4];
720 col_set_str(pinfo->cinfo, COL_INFO, "Login request (< 6.0)");
722 uin = tvb_get_letohl(tvb, offset);
723 gadu_gadu_create_conversation(pinfo, uin);
725 proto_tree_add_uint(tree, &hfi_gadu_gadu_login_uin, tvb, offset, 4, uin);
726 offset += 4;
728 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_login_hash_type, tvb, 0, 0, GG_LOGIN_HASH_GG32);
729 PROTO_ITEM_SET_GENERATED(ti);
731 /* hash is 32-bit number written in LE */
732 _tvb_memcpy_reverse(tvb, hash, offset, 4);
733 proto_tree_add_bytes_format_value(tree, hfi_gadu_gadu_login_hash.id, tvb, offset, 4, hash, "0x%.8x", tvb_get_letohl(tvb, offset));
734 offset += 4;
736 proto_tree_add_item(tree, &hfi_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
737 offset += 4;
739 offset = dissect_gadu_gadu_login_protocol(tvb, tree, offset);
741 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
742 offset += 4;
744 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
745 offset += 2;
747 return offset;
750 static int
751 dissect_gadu_gadu_login_hash(tvbuff_t *tvb, proto_tree *tree, int offset)
753 guint8 hash_type;
755 guint8 hash[4];
756 int i;
758 hash_type = tvb_get_guint8(tvb, offset);
759 proto_tree_add_item(tree, &hfi_gadu_gadu_login_hash_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
760 offset += 1;
762 switch (hash_type) {
763 case GG_LOGIN_HASH_GG32:
764 /* hash is 32-bit number written in LE */
765 _tvb_memcpy_reverse(tvb, hash, offset, 4);
766 proto_tree_add_bytes_format_value(tree, hfi_gadu_gadu_login_hash.id, tvb, offset, 4, hash, "0x%.8x", tvb_get_letohl(tvb, offset));
767 for (i = 4; i < 64; i++) {
768 if (tvb_get_guint8(tvb, offset+i)) {
769 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset + 4, 64-4, ENC_NA);
770 break;
773 break;
775 case GG_LOGIN_HASH_SHA1:
776 proto_tree_add_item(tree, &hfi_gadu_gadu_login_hash, tvb, offset, 20, ENC_NA);
777 for (i = 20; i < 64; i++) {
778 if (tvb_get_guint8(tvb, offset+i)) {
779 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset + 20, 64-20, ENC_NA);
780 break;
783 break;
785 default:
786 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 64, ENC_NA);
787 break;
789 offset += 64;
791 return offset;
794 static int
795 dissect_gadu_gadu_login70(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
797 guint32 uin;
799 col_set_str(pinfo->cinfo, COL_INFO, "Login request (7.0)");
801 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
802 gadu_gadu_create_conversation(pinfo, uin);
804 proto_tree_add_uint(tree, &hfi_gadu_gadu_login_uin, tvb, offset, 4, uin);
805 offset += 4;
807 offset = dissect_gadu_gadu_login_hash(tvb, tree, offset);
809 proto_tree_add_item(tree, &hfi_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
810 offset += 4;
812 offset = dissect_gadu_gadu_login_protocol(tvb, tree, offset);
814 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
815 offset += 1;
817 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
818 offset += 4;
820 proto_tree_add_item(tree, &hfi_gadu_gadu_login_local_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
821 offset += 2;
823 /* XXX packet not fully dissected */
825 return offset;
828 static int
829 dissect_gadu_gadu_login80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
831 guint32 uin;
833 col_set_str(pinfo->cinfo, COL_INFO, "Login request (8.0)");
835 uin = tvb_get_letohl(tvb, offset);
836 gadu_gadu_create_conversation(pinfo, uin);
838 proto_tree_add_item(tree, &hfi_gadu_gadu_login_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
839 offset += 4;
841 proto_tree_add_item(tree, &hfi_gadu_gadu_login80_lang, tvb, offset, 2, ENC_ASCII | ENC_NA);
842 offset += 2;
844 offset = dissect_gadu_gadu_login_hash(tvb, tree, offset);
846 proto_tree_add_item(tree, &hfi_gadu_gadu_login_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
847 offset += 4;
849 /* XXX packet not fully dissected */
851 return offset;
854 static int
855 dissect_gadu_gadu_login_ok(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
857 col_set_str(pinfo->cinfo, COL_INFO, "Login success (< 8.0)");
859 /* not empty packet, but content unknown */
861 return offset;
864 static int
865 dissect_gadu_gadu_login_failed(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
867 col_set_str(pinfo->cinfo, COL_INFO, "Login fail (< 8.0)");
869 /* empty packet */
871 return offset;
874 static int
875 dissect_gadu_gadu_login_ok80(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
877 col_set_str(pinfo->cinfo, COL_INFO, "Login success (8.0)");
879 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA); /* 01 00 00 00 */
880 offset += 4;
882 return offset;
885 static int
886 dissect_gadu_gadu_login80_failed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
888 col_set_str(pinfo->cinfo, COL_INFO, "Login fail (8.0)");
890 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA); /* 01 00 00 00 */
891 offset += 4;
893 return offset;
896 static int
897 dissect_gadu_gadu_user_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
899 guint32 users_num;
901 col_set_str(pinfo->cinfo, COL_INFO, "Contact details");
903 /* XXX, add subtrees */
905 offset += 4;
907 users_num = tvb_get_letohl(tvb, offset);
908 offset += 4;
910 while (users_num--) {
911 guint32 attr_num;
913 proto_tree_add_item(tree, &hfi_gadu_gadu_userdata_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
914 offset += 4;
916 attr_num = tvb_get_letohl(tvb, offset);
917 offset += 4;
919 while (attr_num--) {
920 guint32 name_size, val_size;
921 char *name, *val;
922 /* name */
923 name_size = tvb_get_letohl(tvb, offset);
924 offset += 4;
926 name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, name_size, ENC_ASCII | ENC_NA);
927 proto_tree_add_string(tree, &hfi_gadu_gadu_userdata_attr_name, tvb, offset - 4, 4 + name_size, name);
928 offset += name_size;
929 /* type */
930 proto_tree_add_item(tree, &hfi_gadu_gadu_userdata_attr_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
931 offset += 4;
932 /* value */
933 val_size = tvb_get_letohl(tvb, offset);
934 offset += 4;
936 val = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, val_size, ENC_ASCII | ENC_NA);
937 proto_tree_add_string(tree, &hfi_gadu_gadu_userdata_attr_value, tvb, offset - 4, 4 + val_size, val);
938 offset += val_size;
942 return offset;
945 static int
946 dissect_gadu_gadu_typing_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
948 col_set_str(pinfo->cinfo, COL_INFO, "Typing notify");
950 /* XXX, when type > 1, it's length not type ! */
951 proto_tree_add_item(tree, &hfi_gadu_gadu_typing_notify_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
952 offset += 2;
954 proto_tree_add_item(tree, &hfi_gadu_gadu_typing_notify_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
955 offset += 4;
957 return offset;
960 static int
961 dissect_gadu_gadu_msg_attr(tvbuff_t *tvb _U_, proto_tree *tree _U_, int offset)
963 /* XXX, stub */
965 return offset;
968 static int
969 dissect_gadu_gadu_recv_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
971 struct gadu_gadu_conv_data *conv;
972 proto_item *ti;
974 col_set_str(pinfo->cinfo, COL_INFO, "Receive message (< 8.0)");
976 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
977 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_recipient, tvb, 0, 0, conv->uin);
978 PROTO_ITEM_SET_GENERATED(ti);
980 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
981 PROTO_ITEM_SET_GENERATED(ti);
982 PROTO_ITEM_SET_HIDDEN(ti);
985 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
986 PROTO_ITEM_SET_HIDDEN(ti);
987 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_sender, tvb, offset, 4, ENC_LITTLE_ENDIAN);
988 offset += 4;
990 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
991 offset += 4;
993 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
994 offset += 4;
996 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
997 offset += 4;
999 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_msg_text, tree, offset);
1001 offset = dissect_gadu_gadu_msg_attr(tvb, tree, offset);
1003 return offset;
1006 static int
1007 dissect_gadu_gadu_send_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1009 struct gadu_gadu_conv_data *conv;
1010 proto_item *ti;
1012 col_set_str(pinfo->cinfo, COL_INFO, "Send message (< 8.0)");
1014 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1015 PROTO_ITEM_SET_HIDDEN(ti);
1016 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1017 offset += 4;
1019 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
1020 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_sender, tvb, 0, 0, conv->uin);
1021 PROTO_ITEM_SET_GENERATED(ti);
1023 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
1024 PROTO_ITEM_SET_GENERATED(ti);
1025 PROTO_ITEM_SET_HIDDEN(ti);
1028 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1029 offset += 4;
1031 ti = proto_tree_add_time(tree, &hfi_gadu_gadu_msg_time, tvb, 0, 0, &(pinfo->fd->abs_ts));
1032 PROTO_ITEM_SET_GENERATED(ti);
1034 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1035 offset += 4;
1037 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_msg_text, tree, offset);
1039 offset = dissect_gadu_gadu_msg_attr(tvb, tree, offset);
1041 return offset;
1044 static int
1045 dissect_gadu_gadu_recv_msg80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1047 struct gadu_gadu_conv_data *conv;
1048 proto_item *ti;
1050 col_set_str(pinfo->cinfo, COL_INFO, "Receive message (8.0)");
1052 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
1053 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_recipient, tvb, 0, 0, conv->uin);
1054 PROTO_ITEM_SET_GENERATED(ti);
1056 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
1057 PROTO_ITEM_SET_GENERATED(ti);
1058 PROTO_ITEM_SET_HIDDEN(ti);
1061 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1062 PROTO_ITEM_SET_HIDDEN(ti);
1063 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_sender, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1064 offset += 4;
1066 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1067 offset += 4;
1069 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_time, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1070 offset += 4;
1072 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1073 offset += 4;
1075 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_plain, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1076 offset += 4;
1078 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_attr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1079 offset += 4;
1081 /* XXX packet not fully dissected */
1083 return offset;
1086 static int
1087 dissect_gadu_gadu_send_msg80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1089 struct gadu_gadu_conv_data *conv;
1090 proto_item *ti;
1092 col_set_str(pinfo->cinfo, COL_INFO, "Send message (8.0)");
1094 ti = proto_tree_add_item(tree, &hfi_gadu_gadu_msg_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1095 PROTO_ITEM_SET_HIDDEN(ti);
1096 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1097 offset += 4;
1099 if ((conv = gadu_gadu_get_conversation_data(pinfo))) {
1100 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_sender, tvb, 0, 0, conv->uin);
1101 PROTO_ITEM_SET_GENERATED(ti);
1103 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_msg_uin, tvb, 0, 0, conv->uin);
1104 PROTO_ITEM_SET_GENERATED(ti);
1105 PROTO_ITEM_SET_HIDDEN(ti);
1108 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1109 offset += 4;
1111 ti = proto_tree_add_time(tree, &hfi_gadu_gadu_msg_time, tvb, 0, 0, &(pinfo->fd->abs_ts));
1112 PROTO_ITEM_SET_GENERATED(ti);
1114 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_class, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1115 offset += 4;
1117 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_plain, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1118 offset += 4;
1120 proto_tree_add_item(tree, &hfi_gadu_gadu_msg80_offset_attr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1121 offset += 4;
1123 /* XXX packet not fully dissected */
1125 return offset;
1128 static int
1129 dissect_gadu_gadu_send_msg_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1131 col_set_str(pinfo->cinfo, COL_INFO, "Message acknowledge (server)");
1133 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1134 offset += 4;
1136 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_recipient, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1137 offset += 4;
1139 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1140 offset += 4;
1142 return offset;
1145 static int
1146 dissect_gadu_gadu_recv_msg_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1148 col_set_str(pinfo->cinfo, COL_INFO, "Message acknowledge (client)");
1150 proto_tree_add_item(tree, &hfi_gadu_gadu_msg_ack_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1151 offset += 4;
1153 return offset;
1156 static int
1157 dissect_gadu_gadu_status60(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1159 guint32 uin;
1160 guint8 status;
1162 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (6.0)");
1164 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
1165 proto_tree_add_uint(tree, &hfi_gadu_gadu_status_uin, tvb, offset, 4, uin);
1166 offset += 4;
1168 status = tvb_get_guint8(tvb, offset);
1169 proto_tree_add_item(tree, &hfi_gadu_gadu_status_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1170 offset += 1;
1172 proto_tree_add_item(tree, &hfi_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1173 offset += 4;
1175 proto_tree_add_item(tree, &hfi_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1176 offset += 2;
1178 proto_tree_add_item(tree, &hfi_gadu_gadu_status_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1179 offset += 1;
1181 proto_tree_add_item(tree, &hfi_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1182 offset += 1;
1184 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
1185 offset += 1;
1187 if (gadu_gadu_status_has_descr(status))
1188 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1190 return offset;
1193 static int
1194 dissect_gadu_gadu_status77(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1196 guint32 uin;
1197 guint8 status;
1199 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (7.7)");
1201 uin = tvb_get_letohl(tvb, offset) & ~(GG_ERA_OMNIX_MASK | GG_HAS_AUDIO_MASK);
1202 proto_tree_add_uint(tree, &hfi_gadu_gadu_status_uin, tvb, offset, 4, uin);
1203 offset += 4;
1205 status = tvb_get_guint8(tvb, offset);
1206 proto_tree_add_item(tree, &hfi_gadu_gadu_status_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1207 offset += 1;
1209 proto_tree_add_item(tree, &hfi_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1210 offset += 4;
1212 proto_tree_add_item(tree, &hfi_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1213 offset += 2;
1215 proto_tree_add_item(tree, &hfi_gadu_gadu_status_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1216 offset += 1;
1218 proto_tree_add_item(tree, &hfi_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1219 offset += 1;
1221 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 00 */
1222 offset += 1;
1224 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1225 offset += 4;
1227 if (gadu_gadu_status_has_descr(status))
1228 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1230 return offset;
1233 static int
1234 dissect_gadu_gadu_status80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1236 col_set_str(pinfo->cinfo, COL_INFO, "Receive status (8.0)");
1238 proto_tree_add_item(tree, &hfi_gadu_gadu_status_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1239 offset += 4;
1241 proto_tree_add_item(tree, &hfi_gadu_gadu_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1242 offset += 4;
1244 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1245 offset += 4;
1247 proto_tree_add_item(tree, &hfi_gadu_gadu_status_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1248 offset += 4;
1250 proto_tree_add_item(tree, &hfi_gadu_gadu_status_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1251 offset += 2;
1253 proto_tree_add_item(tree, &hfi_gadu_gadu_status_img_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1254 offset += 1;
1256 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA);
1257 offset += 1;
1259 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1260 offset += 4;
1262 offset = dissect_gadu_gadu_uint32_string_utf8(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1264 return offset;
1267 static int
1268 dissect_gadu_gadu_notify_reply80(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1270 col_set_str(pinfo->cinfo, COL_INFO, "Receive status list (8.0)");
1272 /* XXX packet not fully dissected */
1274 return offset;
1277 static int
1278 dissect_gadu_gadu_new_status(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1280 guint32 status;
1282 col_set_str(pinfo->cinfo, COL_INFO, "New status (< 8.0)");
1284 status = tvb_get_letohl(tvb, offset);
1285 proto_tree_add_item(tree, &hfi_gadu_gadu_new_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1286 offset += 4;
1288 if (gadu_gadu_status_has_descr(status & 0xff))
1289 offset = dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_status_descr, tree, offset);
1291 return offset;
1294 static int
1295 dissect_gadu_gadu_new_status80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1297 col_set_str(pinfo->cinfo, COL_INFO, "New status (8.0)");
1299 proto_tree_add_item(tree, &hfi_gadu_gadu_new_status_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1300 offset += 4;
1302 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 4, ENC_NA);
1303 offset += 4;
1305 offset = dissect_gadu_gadu_uint32_string_utf8(tvb, &hfi_gadu_gadu_new_status_desc, tree, offset);
1307 return offset;
1310 static int
1311 dissect_gadu_gadu_list_empty(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1313 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (empty)");
1315 /* empty packet */
1317 return offset;
1320 static int
1321 dissect_gadu_gadu_add_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1323 col_set_str(pinfo->cinfo, COL_INFO, "Notify list add");
1325 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1326 offset += 4;
1328 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1329 offset += 1;
1331 return offset;
1334 static int
1335 dissect_gadu_gadu_notify105_common(tvbuff_t *tvb, proto_tree *tree, int offset, char **puin)
1337 guint16 uin_len;
1338 char *uin;
1340 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* unknown 00 */
1341 offset += 1;
1343 uin_len = tvb_get_guint8(tvb, offset);
1344 offset += 1;
1345 uin = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, uin_len, ENC_ASCII | ENC_NA);
1346 proto_tree_add_string(tree, &hfi_gadu_gadu_contact_uin_str, tvb, offset - 1, 1 + uin_len, uin);
1347 offset += uin_len;
1348 if (puin)
1349 *puin = uin;
1351 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1352 offset += 1;
1354 return offset;
1357 static int
1358 dissect_gadu_gadu_add_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1360 col_set_str(pinfo->cinfo, COL_INFO, "Notify list add (10.5)");
1362 return dissect_gadu_gadu_notify105_common(tvb, tree, offset, NULL);
1365 static int
1366 dissect_gadu_gadu_remove_notify(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1368 col_set_str(pinfo->cinfo, COL_INFO, "Notify list remove");
1370 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1371 offset += 4;
1373 proto_tree_add_item(tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1374 offset += 1;
1376 return offset;
1379 static int
1380 dissect_gadu_gadu_remove_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1382 col_set_str(pinfo->cinfo, COL_INFO, "Notify list remove (10.5)");
1384 return dissect_gadu_gadu_notify105_common(tvb, tree, offset, NULL);
1387 static int
1388 dissect_gadu_gadu_notify_common(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1390 proto_tree *contact_tree;
1391 proto_item *ti;
1393 while (tvb_reported_length_remaining(tvb, offset) >= 4+1) {
1394 guint32 uin = tvb_get_letohl(tvb, offset);
1396 ti = proto_tree_add_text(tree, tvb, offset, 5, "Contact: %u", uin);
1397 contact_tree = proto_item_add_subtree(ti, ett_gadu_gadu_contact);
1399 proto_tree_add_item(contact_tree, &hfi_gadu_gadu_contact_uin, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1400 offset += 4;
1402 proto_tree_add_item(contact_tree, &hfi_gadu_gadu_contact_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1403 offset += 1;
1406 return offset;
1409 static int
1410 dissect_gadu_gadu_notify_first(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1412 col_set_str(pinfo->cinfo, COL_INFO, "Notify list");
1414 return dissect_gadu_gadu_notify_common(tvb, pinfo, tree, offset);
1417 static int
1418 dissect_gadu_gadu_notify_last(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1420 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (last)");
1422 return dissect_gadu_gadu_notify_common(tvb, pinfo, tree, offset);
1425 static int
1426 dissect_gadu_gadu_notify105(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1428 col_set_str(pinfo->cinfo, COL_INFO, "Notify list (10.5)");
1430 while (tvb_reported_length_remaining(tvb, offset) >= 2) {
1431 const int org_offset = offset;
1433 proto_tree *contact_tree;
1434 proto_item *ti;
1436 char *uin;
1438 ti = proto_tree_add_text(tree, tvb, offset, 0, "Contact: ");
1439 contact_tree = proto_item_add_subtree(ti, ett_gadu_gadu_contact);
1441 offset = dissect_gadu_gadu_notify105_common(tvb, contact_tree, offset, &uin);
1442 proto_item_append_text(ti, "%s", uin);
1444 proto_item_set_len(ti, offset - org_offset);
1447 return offset;
1450 static int
1451 dissect_gadu_gadu_ping(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, int offset)
1453 col_set_str(pinfo->cinfo, COL_INFO, "Ping");
1455 /* empty packet */
1457 return offset;
1460 static int
1461 dissect_gadu_gadu_welcome(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1463 col_set_str(pinfo->cinfo, COL_INFO, "Welcome");
1465 proto_tree_add_item(tree, &hfi_gadu_gadu_welcome_seed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1466 offset += 4;
1468 return offset;
1471 static int
1472 dissect_gadu_gadu_userlist_xml_compressed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1474 int remain = tvb_reported_length_remaining(tvb, offset);
1475 tvbuff_t *uncomp_tvb;
1477 if (remain <= 0)
1478 return offset;
1480 if ((uncomp_tvb = tvb_child_uncompress(tvb, tvb, offset, remain))) {
1481 proto_tree_add_text(tree, tvb, offset, remain, "Userlist XML data: [Decompression succeeded]");
1483 add_new_data_source(pinfo, uncomp_tvb, "Uncompressed userlist");
1485 /* XXX add DTD (pinfo->match_string) */
1486 call_dissector_only(xml_handle, uncomp_tvb, pinfo, tree, NULL);
1487 } else
1488 proto_tree_add_text(tree, tvb, offset, remain, "Userlist XML data: [Error: Decompression failed] (or no libz)");
1490 offset += remain;
1492 return offset;
1495 static int
1496 dissect_gadu_gadu_userlist_request80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1498 guint8 type;
1499 proto_item *ti;
1501 col_set_str(pinfo->cinfo, COL_INFO, "Userlist request (8.0)");
1503 type = tvb_get_guint8(tvb, offset);
1504 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1505 offset += 1;
1507 ti = proto_tree_add_uint(tree, &hfi_gadu_gadu_userlist_format, tvb, 0, 0, GG_USERLIST100_FORMAT_TYPE_GG100);
1508 PROTO_ITEM_SET_GENERATED(ti);
1510 switch (type) {
1511 case GG_USERLIST_PUT:
1512 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1513 break;
1516 return offset;
1519 static int
1520 dissect_gadu_gadu_userlist_request100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1522 guint8 type, format;
1524 col_set_str(pinfo->cinfo, COL_INFO, "Userlist request (10.0)");
1526 type = tvb_get_guint8(tvb, offset);
1527 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1528 offset += 1;
1530 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1531 offset += 4;
1533 format = tvb_get_guint8(tvb, offset);
1534 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1535 offset += 1;
1537 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 01 */
1538 offset += 1;
1540 switch (type) {
1541 case GG_USERLIST_PUT:
1542 if (format == GG_USERLIST100_FORMAT_TYPE_GG100)
1543 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1544 break;
1547 return offset;
1550 static int
1551 dissect_gadu_gadu_userlist_reply80(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1553 guint8 type;
1555 col_set_str(pinfo->cinfo, COL_INFO, "Userlist reply (8.0)");
1557 type = tvb_get_guint8(tvb, offset);
1558 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1559 offset += 1;
1561 switch (type) {
1562 case GG_USERLIST_GET_REPLY:
1563 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1564 break;
1567 return offset;
1570 static int
1571 dissect_gadu_gadu_userlist_reply100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1573 guint8 type, format;
1575 col_set_str(pinfo->cinfo, COL_INFO, "Userlist reply (10.0)");
1577 type = tvb_get_guint8(tvb, offset);
1578 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1579 offset += 1;
1581 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1582 offset += 4;
1584 format = tvb_get_guint8(tvb, offset);
1585 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_format, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1586 offset += 1;
1588 proto_tree_add_item(tree, &hfi_gadu_gadu_data, tvb, offset, 1, ENC_NA); /* 01 */
1589 offset += 1;
1591 switch (type) {
1592 case GG_USERLIST_GET_REPLY:
1593 if (format == GG_USERLIST100_FORMAT_TYPE_GG100)
1594 offset = dissect_gadu_gadu_userlist_xml_compressed(tvb, pinfo, tree, offset);
1595 break;
1598 return offset;
1601 static int
1602 dissect_gadu_gadu_userlist_version100(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1604 col_set_str(pinfo->cinfo, COL_INFO, "Userlist version (10.0)");
1606 proto_tree_add_item(tree, &hfi_gadu_gadu_userlist_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1607 offset += 4;
1609 return offset;
1612 static int
1613 dissect_gadu_gadu_dcc7_id_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1615 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection id request");
1617 proto_tree_add_item(tree, &hfi_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1618 offset += 4;
1620 return offset;
1623 static int
1624 dissect_gadu_gadu_dcc7_id_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1626 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection id reply");
1628 proto_tree_add_item(tree, &hfi_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1629 offset += 4;
1631 proto_tree_add_item(tree, &hfi_dcc_id, tvb, offset, 8, ENC_NA);
1632 offset += 8;
1634 return offset;
1637 static int
1638 dissect_gadu_gadu_dcc7_new(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1640 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection new");
1642 proto_tree_add_item(tree, &hfi_dcc_id, tvb, offset, 8, ENC_NA);
1643 offset += 8;
1645 proto_tree_add_item(tree, &hfi_dcc_uin_from, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1646 offset += 4;
1648 proto_tree_add_item(tree, &hfi_dcc_uin_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1649 offset += 4;
1651 proto_tree_add_item(tree, &hfi_dcc_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1652 offset += 4;
1654 proto_tree_add_item(tree, &hfi_dcc_filename, tvb, offset, 255, ENC_ASCII | ENC_NA);
1655 offset += 255;
1657 return offset;
1660 static int
1661 dissect_gadu_gadu_dcc7_id_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1663 col_set_str(pinfo->cinfo, COL_INFO, "Direct connection abort");
1665 proto_tree_add_item(tree, &hfi_dcc_id, tvb, offset, 8, ENC_NA);
1666 offset += 8;
1668 proto_tree_add_item(tree, &hfi_dcc_uin_from, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1669 offset += 4;
1671 proto_tree_add_item(tree, &hfi_dcc_uin_to, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1672 offset += 4;
1674 return offset;
1677 static int
1678 dissect_gadu_gadu_pubdir50_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1680 int pos;
1682 col_set_str(pinfo->cinfo, COL_INFO, "Public directory request");
1684 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_request_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1685 offset += 1;
1687 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_request_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1688 offset += 4;
1689 /* XXX, link request sequence with reply sequence */
1691 while ((pos = tvb_find_guint8(tvb, offset, -1, '\0')) > 0) {
1692 /* XXX, display it better, field=value */
1693 dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_pubdir_request_str, tree, offset);
1694 offset = pos + 1;
1697 return offset;
1700 static int
1701 dissect_gadu_gadu_pubdir50_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1703 int pos;
1705 col_set_str(pinfo->cinfo, COL_INFO, "Public directory reply");
1707 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_reply_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1708 offset += 1;
1710 proto_tree_add_item(tree, &hfi_gadu_gadu_pubdir_reply_seq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1711 offset += 4;
1712 /* XXX, link reply sequence with request sequence */
1714 while ((pos = tvb_find_guint8(tvb, offset, -1, '\0')) > 0) {
1715 /* XXX, display it better, field=value */
1716 dissect_gadu_gadu_stringz_cp1250(tvb, &hfi_gadu_gadu_pubdir_reply_str, tree, offset);
1717 offset = pos + 1;
1720 return offset;
1723 static int
1724 dissect_gadu_gadu_xml_action(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1726 tvbuff_t *xml_tvb;
1727 int ret;
1729 col_set_str(pinfo->cinfo, COL_INFO, "XML action message");
1731 xml_tvb = tvb_new_subset_remaining(tvb, offset);
1733 /* XXX add DTD (pinfo->match_string) */
1734 ret = call_dissector_only(xml_handle, xml_tvb, pinfo, tree, NULL);
1736 return offset + ret;
1739 static int
1740 dissect_gadu_gadu_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1742 proto_tree *gadu_gadu_tree = NULL;
1744 int offset = 0;
1745 guint32 pkt_type;
1747 col_clear(pinfo->cinfo, COL_INFO); /* XXX, remove, add separator when multiple PDU */
1749 if (tree) {
1750 proto_item *ti = proto_tree_add_item(tree, hfi_gadu_gadu, tvb, 0, -1, ENC_NA);
1751 gadu_gadu_tree = proto_item_add_subtree(ti, ett_gadu_gadu);
1754 pkt_type = tvb_get_letohl(tvb, offset);
1755 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);
1756 offset += 4;
1757 proto_tree_add_item(gadu_gadu_tree, &hfi_gadu_gadu_header_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1758 offset += 4;
1760 if (pinfo->p2p_dir == P2P_DIR_RECV) {
1761 switch (pkt_type) {
1762 case GG_DISCONNECTING:
1763 offset = dissect_gadu_gadu_disconnecting(tvb, pinfo, gadu_gadu_tree, offset);
1764 break;
1766 case GG_DISCONNECT_ACK:
1767 offset = dissect_gadu_gadu_disconnect_ack(tvb, pinfo, gadu_gadu_tree, offset);
1768 break;
1770 case GG_LOGIN_OK:
1771 offset = dissect_gadu_gadu_login_ok(tvb, pinfo, gadu_gadu_tree, offset);
1772 break;
1774 case GG_LOGIN_OK80:
1775 offset = dissect_gadu_gadu_login_ok80(tvb, pinfo, gadu_gadu_tree, offset);
1776 break;
1778 case GG_LOGIN_FAILED:
1779 offset = dissect_gadu_gadu_login_failed(tvb, pinfo, gadu_gadu_tree, offset);
1780 break;
1782 case GG_LOGIN80_FAILED:
1783 offset = dissect_gadu_gadu_login80_failed(tvb, pinfo, gadu_gadu_tree, offset);
1784 break;
1786 case GG_USER_DATA:
1787 offset = dissect_gadu_gadu_user_data(tvb, pinfo, gadu_gadu_tree, offset);
1788 break;
1790 case GG_TYPING_NOTIFY:
1791 offset = dissect_gadu_gadu_typing_notify(tvb, pinfo, gadu_gadu_tree, offset);
1792 break;
1794 case GG_RECV_MSG:
1795 offset = dissect_gadu_gadu_recv_msg(tvb, pinfo, gadu_gadu_tree, offset);
1796 break;
1798 case GG_RECV_MSG80:
1799 offset = dissect_gadu_gadu_recv_msg80(tvb, pinfo, gadu_gadu_tree, offset);
1800 break;
1802 case GG_SEND_MSG_ACK:
1803 /* GG_SEND_MSG_ACK is received by client */
1804 offset = dissect_gadu_gadu_send_msg_ack(tvb, pinfo, gadu_gadu_tree, offset);
1805 break;
1807 case GG_STATUS60:
1808 offset = dissect_gadu_gadu_status60(tvb, pinfo, gadu_gadu_tree, offset);
1809 break;
1811 case GG_STATUS77:
1812 offset = dissect_gadu_gadu_status77(tvb, pinfo, gadu_gadu_tree, offset);
1813 break;
1815 case GG_STATUS80:
1816 offset = dissect_gadu_gadu_status80(tvb, pinfo, gadu_gadu_tree, offset);
1817 break;
1819 case GG_NOTIFY_REPLY80:
1820 offset = dissect_gadu_gadu_notify_reply80(tvb, pinfo, gadu_gadu_tree, offset);
1821 break;
1823 case GG_DCC7_ID_REPLY:
1824 offset = dissect_gadu_gadu_dcc7_id_reply(tvb, pinfo, gadu_gadu_tree, offset);
1825 break;
1827 case GG_WELCOME:
1828 offset = dissect_gadu_gadu_welcome(tvb, pinfo, gadu_gadu_tree, offset);
1829 break;
1831 case GG_USERLIST_REPLY80:
1832 offset = dissect_gadu_gadu_userlist_reply80(tvb, pinfo, gadu_gadu_tree, offset);
1833 break;
1835 case GG_USERLIST100_REPLY:
1836 offset = dissect_gadu_gadu_userlist_reply100(tvb, pinfo, gadu_gadu_tree, offset);
1837 break;
1839 case GG_USERLIST100_VERSION:
1840 offset = dissect_gadu_gadu_userlist_version100(tvb, pinfo, gadu_gadu_tree, offset);
1841 break;
1843 case GG_PUBDIR50_REPLY:
1844 offset = dissect_gadu_gadu_pubdir50_reply(tvb, pinfo, gadu_gadu_tree, offset);
1845 break;
1847 case GG_XML_ACTION:
1848 offset = dissect_gadu_gadu_xml_action(tvb, pinfo, gadu_gadu_tree, offset);
1849 break;
1851 case GG_STATUS:
1852 case GG_PONG:
1853 case GG_PING:
1854 case GG_NOTIFY_REPLY:
1855 case GG_USERLIST_REPLY:
1856 case GG_NOTIFY_REPLY60:
1857 case GG_NEED_EMAIL:
1858 case GG_LOGIN_HASH_TYPE_INVALID:
1859 case GG_NOTIFY_REPLY77:
1860 case GG_DCC7_INFO:
1861 case GG_DCC7_NEW:
1862 case GG_DCC7_ACCEPT:
1863 case GG_DCC7_REJECT:
1864 case GG_DCC7_ID_ABORTED:
1865 case GG_XML_EVENT:
1866 case GG_STATUS80BETA:
1867 case GG_NOTIFY_REPLY80BETA:
1868 case GG_OWN_MESSAGE:
1869 case GG_OWN_RESOURCE_INFO:
1870 default:
1872 const char *pkt_name = try_val_to_str(pkt_type, gadu_gadu_packets_type_recv);
1874 if (pkt_name)
1875 col_set_str(pinfo->cinfo, COL_INFO, pkt_name);
1876 else
1877 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown recv packet: %.2x", pkt_type);
1878 break;
1882 } else {
1883 switch (pkt_type) {
1884 case GG_LOGIN:
1885 offset = dissect_gadu_gadu_login(tvb, pinfo, gadu_gadu_tree, offset);
1886 break;
1888 case GG_LOGIN70:
1889 offset = dissect_gadu_gadu_login70(tvb, pinfo, gadu_gadu_tree, offset);
1890 break;
1892 case GG_LOGIN80:
1893 offset = dissect_gadu_gadu_login80(tvb, pinfo, gadu_gadu_tree, offset);
1894 break;
1896 case GG_LIST_EMPTY:
1897 offset = dissect_gadu_gadu_list_empty(tvb, pinfo, gadu_gadu_tree, offset);
1898 break;
1900 case GG_NOTIFY_FIRST:
1901 offset = dissect_gadu_gadu_notify_first(tvb, pinfo, gadu_gadu_tree, offset);
1902 break;
1904 case GG_NOTIFY_LAST:
1905 offset = dissect_gadu_gadu_notify_last(tvb, pinfo, gadu_gadu_tree, offset);
1906 break;
1908 case GG_NOTIFY105:
1909 offset = dissect_gadu_gadu_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1910 break;
1912 case GG_ADD_NOTIFY:
1913 offset = dissect_gadu_gadu_add_notify(tvb, pinfo, gadu_gadu_tree, offset);
1914 break;
1916 case GG_ADD_NOTIFY105:
1917 offset = dissect_gadu_gadu_add_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1918 break;
1920 case GG_REMOVE_NOTIFY:
1921 offset = dissect_gadu_gadu_remove_notify(tvb, pinfo, gadu_gadu_tree, offset);
1922 break;
1924 case GG_REMOVE_NOTIFY105:
1925 offset = dissect_gadu_gadu_remove_notify105(tvb, pinfo, gadu_gadu_tree, offset);
1926 break;
1928 case GG_PING:
1929 offset = dissect_gadu_gadu_ping(tvb, pinfo, gadu_gadu_tree, offset);
1930 break;
1932 case GG_TYPING_NOTIFY:
1933 offset = dissect_gadu_gadu_typing_notify(tvb, pinfo, gadu_gadu_tree, offset);
1934 break;
1936 case GG_SEND_MSG:
1937 offset = dissect_gadu_gadu_send_msg(tvb, pinfo, gadu_gadu_tree, offset);
1938 break;
1940 case GG_SEND_MSG80:
1941 offset = dissect_gadu_gadu_send_msg80(tvb, pinfo, gadu_gadu_tree, offset);
1942 break;
1944 case GG_RECV_MSG_ACK:
1945 /* GG_RECV_MSG_ACK is send by client */
1946 offset = dissect_gadu_gadu_recv_msg_ack(tvb, pinfo, gadu_gadu_tree, offset);
1947 break;
1949 case GG_NEW_STATUS:
1950 offset = dissect_gadu_gadu_new_status(tvb, pinfo, gadu_gadu_tree, offset);
1951 break;
1953 case GG_NEW_STATUS80:
1954 offset = dissect_gadu_gadu_new_status80(tvb, pinfo, gadu_gadu_tree, offset);
1955 break;
1957 case GG_DCC7_ID_REQUEST:
1958 offset = dissect_gadu_gadu_dcc7_id_request(tvb, pinfo, gadu_gadu_tree, offset);
1959 break;
1961 case GG_DCC7_NEW:
1962 offset = dissect_gadu_gadu_dcc7_new(tvb, pinfo, gadu_gadu_tree, offset);
1963 break;
1965 case GG_DCC7_ID_ABORT:
1966 offset = dissect_gadu_gadu_dcc7_id_abort(tvb, pinfo, gadu_gadu_tree, offset);
1967 break;
1969 case GG_USERLIST_REQUEST80:
1970 offset = dissect_gadu_gadu_userlist_request80(tvb, pinfo, gadu_gadu_tree, offset);
1971 break;
1973 case GG_USERLIST100_REQUEST:
1974 offset = dissect_gadu_gadu_userlist_request100(tvb, pinfo, gadu_gadu_tree, offset);
1975 break;
1977 case GG_PUBDIR50_REQUEST:
1978 offset = dissect_gadu_gadu_pubdir50_request(tvb, pinfo, gadu_gadu_tree, offset);
1979 break;
1981 case GG_PONG:
1982 case GG_LOGIN_EXT:
1983 case GG_LOGIN60:
1984 case GG_USERLIST_REQUEST:
1985 case GG_DCC7_INFO:
1986 case GG_DCC7_ACCEPT:
1987 case GG_DCC7_REJECT:
1988 case GG_DCC7_ID_DUNNO1:
1989 case GG_NEW_STATUS80BETA:
1990 case GG_LOGIN80BETA:
1991 case GG_OWN_DISCONNECT:
1992 case GG_NEW_STATUS105:
1993 case GG_LOGIN105:
1994 default:
1996 const char *pkt_name = try_val_to_str(pkt_type, gadu_gadu_packets_type_send);
1998 if (pkt_name)
1999 col_set_str(pinfo->cinfo, COL_INFO, pkt_name);
2000 else
2001 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown send packet: %.2x", pkt_type);
2002 break;
2007 /* for now display rest of data as FT_BYTES. */
2008 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2009 proto_tree_add_item(gadu_gadu_tree, &hfi_gadu_gadu_data, tvb, offset, -1, ENC_NA);
2012 return tvb_length(tvb);
2015 static guint
2016 get_gadu_gadu_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
2018 guint32 len = tvb_get_letohl(tvb, offset + 4);
2020 return len + 8;
2023 static int
2024 dissect_gadu_gadu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2026 if (pinfo->srcport == pinfo->match_uint && pinfo->destport != pinfo->match_uint)
2027 pinfo->p2p_dir = P2P_DIR_RECV;
2028 else if (pinfo->srcport != pinfo->match_uint && pinfo->destport == pinfo->match_uint)
2029 pinfo->p2p_dir = P2P_DIR_SENT;
2030 else
2031 return 0;
2033 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gadu-Gadu");
2034 col_clear(pinfo->cinfo, COL_INFO);
2036 tcp_dissect_pdus(tvb, pinfo, tree, gadu_gadu_desegment, 8, get_gadu_gadu_pdu_len, dissect_gadu_gadu_pdu, data);
2037 return tvb_length(tvb);
2040 void
2041 proto_register_gadu_gadu(void)
2043 #ifndef HAVE_HFI_SECTION_INIT
2044 static header_field_info *hfi[] = {
2045 /* Header */
2046 &hfi_gadu_gadu_header_type_recv,
2047 &hfi_gadu_gadu_header_type_send,
2048 &hfi_gadu_gadu_header_length,
2049 /* Login common */
2050 &hfi_gadu_gadu_login_uin,
2051 &hfi_gadu_gadu_login_hash_type,
2052 &hfi_gadu_gadu_login_hash,
2053 &hfi_gadu_gadu_login_status,
2054 &hfi_gadu_gadu_login_protocol,
2055 &hfi_gadu_gadu_login_version,
2056 &hfi_gadu_gadu_login_local_ip,
2057 &hfi_gadu_gadu_login_local_port,
2058 /* GG_LOGIN80 */
2059 &hfi_gadu_gadu_login80_lang,
2060 /* Contacts details */
2061 &hfi_gadu_gadu_userdata_uin,
2062 &hfi_gadu_gadu_userdata_attr_name,
2063 &hfi_gadu_gadu_userdata_attr_type,
2064 &hfi_gadu_gadu_userdata_attr_value,
2065 &hfi_gadu_gadu_typing_notify_type,
2066 &hfi_gadu_gadu_typing_notify_uin,
2067 /* Message common */
2068 &hfi_gadu_gadu_msg_uin,
2069 &hfi_gadu_gadu_msg_sender,
2070 &hfi_gadu_gadu_msg_recipient,
2071 &hfi_gadu_gadu_msg_seq,
2072 &hfi_gadu_gadu_msg_time,
2073 &hfi_gadu_gadu_msg_class,
2074 &hfi_gadu_gadu_msg_text,
2075 /* GG_RECV_MSG80, GG_SEND_MSG80 */
2076 &hfi_gadu_gadu_msg80_offset_plain,
2077 &hfi_gadu_gadu_msg80_offset_attr,
2078 /* Contact (notify) common */
2079 &hfi_gadu_gadu_contact_uin,
2080 &hfi_gadu_gadu_contact_uin_str,
2081 &hfi_gadu_gadu_contact_type,
2082 /* Status common */
2083 &hfi_gadu_gadu_status_uin,
2084 &hfi_gadu_gadu_status_status,
2085 &hfi_gadu_gadu_status_ip,
2086 &hfi_gadu_gadu_status_port,
2087 &hfi_gadu_gadu_status_version,
2088 &hfi_gadu_gadu_status_img_size,
2089 &hfi_gadu_gadu_status_descr,
2090 /* New status (setting status) common */
2091 &hfi_gadu_gadu_new_status_status,
2092 &hfi_gadu_gadu_new_status_desc,
2093 /* Userlist */
2094 &hfi_gadu_gadu_userlist_request_type,
2095 &hfi_gadu_gadu_userlist_version,
2096 &hfi_gadu_gadu_userlist_format,
2097 &hfi_gadu_gadu_userlist_reply_type,
2098 /* Direct Connection */
2099 &hfi_dcc_type,
2100 &hfi_dcc_id,
2101 &hfi_dcc_uin_to,
2102 &hfi_dcc_uin_from,
2103 &hfi_dcc_filename,
2104 /* Public Directory */
2105 &hfi_gadu_gadu_pubdir_request_type,
2106 &hfi_gadu_gadu_pubdir_request_seq,
2107 &hfi_gadu_gadu_pubdir_request_str,
2108 &hfi_gadu_gadu_pubdir_reply_type,
2109 &hfi_gadu_gadu_pubdir_reply_seq,
2110 &hfi_gadu_gadu_pubdir_reply_str,
2111 /* GG_WELCOME */
2112 &hfi_gadu_gadu_welcome_seed,
2113 /* GG_SEND_MSG_ACK */
2114 &hfi_gadu_gadu_msg_ack_status,
2115 &hfi_gadu_gadu_msg_ack_recipient,
2116 &hfi_gadu_gadu_msg_ack_seq,
2117 /* Not dissected data */
2118 &hfi_gadu_gadu_data,
2120 #endif /* HAVE_HFI_SECTION_INIT */
2122 static gint *ett[] = {
2123 &ett_gadu_gadu,
2124 &ett_gadu_gadu_contact
2127 module_t *gadu_gadu_module;
2129 int proto_gadu_gadu;
2131 proto_gadu_gadu = proto_register_protocol("Gadu-Gadu Protocol", "Gadu-Gadu", "gadu-gadu");
2132 hfi_gadu_gadu = proto_registrar_get_nth(proto_gadu_gadu);
2134 gadu_gadu_module = prefs_register_protocol(proto_gadu_gadu, NULL);
2135 prefs_register_bool_preference(gadu_gadu_module, "desegment",
2136 "Reassemble Gadu-Gadu messages spanning multiple TCP segments",
2137 "Whether the Gadu-Gadu dissector should reassemble messages spanning multiple TCP segments."
2138 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2139 &gadu_gadu_desegment);
2141 proto_register_fields(proto_gadu_gadu, hfi, array_length(hfi));
2142 proto_register_subtree_array(ett, array_length(ett));
2144 gadu_gadu_handle = new_create_dissector_handle(dissect_gadu_gadu, proto_gadu_gadu);
2147 void
2148 proto_reg_handoff_gadu_gadu(void)
2150 dissector_add_uint("tcp.port", TCP_PORT_GADU_GADU, gadu_gadu_handle);
2152 xml_handle = find_dissector("xml");