1 /* packet-slsk.c
2 * Routines for SoulSeek Protocol dissection
3 * Copyright 2003, Christian Wagner <Christian.Wagner@stud.uni-karlsruhe.de>
4 * Institute of Telematics - University of Karlsruhe
5 * part of this work supported by
6 * Deutsche Forschungsgemeinschaft (DFG) Grant Number FU448/1
7 *
8 * SoulSeek Protocol dissector based on protocol descriptions from SoleSeek Project:
9 * http://cvs.sourceforge.net/viewcvs.py/soleseek/SoleSeek/doc/protocol.html?rev=HEAD
10 * Updated for SoulSeek client version 151
11 *
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
15 *
16 * SPDX-License-Identifier: GPL-2.0-or-later
17 */
18
19 #include "config.h"
20
21
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/strutil.h>
25 #include <epan/expert.h>
26 #include "packet-tcp.h"
27
28 void proto_register_slsk(void);
29 void proto_reg_handoff_slsk(void);
Atom(Index resnr,std::string md_atom_name,Index atom_id,Eigen::Vector3d pos,std::string type)30
31 /* Initialize the protocol and registered fields */
32 static int proto_slsk = -1;
33
34 static int hf_slsk_integer = -1;
35 static int hf_slsk_string = -1;
36 static int hf_slsk_byte = -1;
37 static int hf_slsk_message_length = -1;
38 static int hf_slsk_message_code = -1;
39 static int hf_slsk_embedded_message_type = -1;
40 static int hf_slsk_client_ip = -1;
41 /* static int hf_slsk_server_ip = -1; */
42 static int hf_slsk_directory_name = -1;
43 static int hf_slsk_username = -1;
44 static int hf_slsk_password = -1;
45 static int hf_slsk_version = -1;
46 static int hf_slsk_login_successful = -1;
47 static int hf_slsk_login_message = -1;
48 static int hf_slsk_port = -1;
49 static int hf_slsk_ip = -1;
50 static int hf_slsk_user_exists = -1;
51 static int hf_slsk_status_code = -1;
52 static int hf_slsk_room = -1;
53 static int hf_slsk_chat_message = -1;
54 static int hf_slsk_users_in_room = -1;
55 static int hf_slsk_token = -1;
56 static int hf_slsk_connection_type = -1;
57 static int hf_slsk_chat_message_id = -1;
58 static int hf_slsk_timestamp = -1;
59 static int hf_slsk_search_text = -1;
60 static int hf_slsk_folder_count = -1;
61 static int hf_slsk_file_count = -1;
62 static int hf_slsk_average_speed = -1;
63 static int hf_slsk_download_number = -1;
64 static int hf_slsk_files = -1;
65 static int hf_slsk_directories = -1;
66 static int hf_slsk_slotsfull = -1;
67 static int hf_slsk_place_in_queue = -1;
Atom(Index atom_id,std::string element,Eigen::Vector3d pos)68 static int hf_slsk_number_of_rooms = -1;
69 static int hf_slsk_filename = -1;
70 static int hf_slsk_filename_ext = -1;
GetElementFromString(const std::string & MDName)71 static int hf_slsk_directory = -1;
72 static int hf_slsk_size = -1;
73 /* static int hf_slsk_checksum = -1; */
74 static int hf_slsk_code = -1;
75 static int hf_slsk_number_of_users = -1;
76 static int hf_slsk_number_of_days = -1;
77 static int hf_slsk_transfer_direction = -1;
78 static int hf_slsk_user_description = -1;
79 static int hf_slsk_picture_exists = -1;
80 static int hf_slsk_picture = -1;
81 /* static int hf_slsk_user_uploads = -1; */
Rotate(const Eigen::Matrix3d & R,const Eigen::Vector3d & refPos)82 static int hf_slsk_total_uploads = -1;
83 static int hf_slsk_queued_uploads = -1;
84 static int hf_slsk_slots_available = -1;
85 static int hf_slsk_allowed = -1;
86 static int hf_slsk_compr_packet = -1;
87 static int hf_slsk_parent_min_speed = -1;
SetupCptTable(CptTable & table)88 static int hf_slsk_parent_speed_connection_ratio = -1;
89 static int hf_slsk_seconds_parent_inactivity_before_disconnect = -1;
90 static int hf_slsk_seconds_server_inactivity_before_disconnect = -1;
91 static int hf_slsk_nodes_in_cache_before_disconnect = -1;
92 static int hf_slsk_seconds_before_ping_children = -1;
93 static int hf_slsk_recommendation = -1;
94 static int hf_slsk_user = -1;
95 static int hf_slsk_ranking = -1;
96 static int hf_slsk_compressed_packet_length = -1;
97 static int hf_slsk_uncompressed_packet_length = -1;
WriteData(data & d) const98 static int hf_slsk_num_directories = -1;
99 static int hf_slsk_upload_speed = -1;
100 static int hf_slsk_in_queue = -1;
101 static int hf_slsk_num_slotsfull_records = -1;
102 static int hf_slsk_num_recommendations = -1;
103 static int hf_slsk_num_files = -1;
104 static int hf_slsk_num_strings = -1;
105 static int hf_slsk_file_code = -1;
106 static int hf_slsk_file_size1 = -1;
107 static int hf_slsk_file_size2 = -1;
ReadData(const data & d)108 static int hf_slsk_file_num_attributes = -1;
109 static int hf_slsk_file_attribute_type = -1;
110 static int hf_slsk_file_attribute_value = -1;
111 static int hf_slsk_free_upload_slots = -1;
112 static int hf_slsk_bytes = -1;
113 static int hf_slsk_same_recommendation = -1;
114 static int hf_slsk_number_of_priv_users = -1;
115 static int hf_slsk_num_parent_address = -1;
116
117 /* Initialize the subtree pointers */
118 static gint ett_slsk = -1;
119 static gint ett_slsk_compr_packet = -1;
120 static gint ett_slsk_directory = -1;
121 static gint ett_slsk_file = -1;
122 static gint ett_slsk_file_attribute = -1;
123 static gint ett_slsk_user = -1;
124 static gint ett_slsk_recommendation = -1;
125 static gint ett_slsk_room = -1;
126 static gint ett_slsk_string = -1;
127
128 static expert_field ei_slsk_unknown_data = EI_INIT;
129 static expert_field ei_slsk_zlib_decompression_failed = EI_INIT;
130 static expert_field ei_slsk_decompression_failed = EI_INIT;
131
132 #define SLSK_TCP_PORT_RANGE "2234,2240,5534"
133
134
135 /* desegmentation of SoulSeek Message over TCP */
136 static gboolean slsk_desegment = TRUE;
137 #ifdef HAVE_ZLIB
138 static gboolean slsk_decompress = TRUE;
139 #else
140 static gboolean slsk_decompress = FALSE;
141 #endif
142
143 static const value_string slsk_tcp_msgs[] = {
144 { 1, "Login"},
145 { 2, "Set Wait Port"},
146 { 3, "Get Peer Address"},
147 { 4, "Get Shared File List"},
148 { 5, "User Exists / Shared File List"},
149 { 7, "Get User Status"},
150 { 9, "File Search Result"},
151 { 13, "Say ChatRoom"},
152 { 14, "Join Room"},
153 { 15, "Leave Room / User Info Request"},
154 { 16, "User Joined Room / User Info Reply"},
155 { 17, "User Left Room"},
156 { 18, "Connect To Peer"},
157 { 22, "Message User"},
158 { 23, "Message User Ack"},
159 { 26, "File Search"},
160 { 28, "Set Status"},
161 { 32, "Ping"},
162 { 34, "Update Upload Speed"},
163 { 35, "Shared Files & Folders"},
164 { 36, "Get User Stats / Folder Contents Request"},
165 { 37, "Folder Contents Response"},
166 { 40, "Queued Downloads / Transfer Request"},
167 { 41, "Transfer Response"},
168 { 42, "Placehold Upload"},
169 { 43, "Queue Upload"},
170 { 44, "Place In Queue"},
171 { 46, "Upload Failed"},
172 { 50, "Queue Failed / Own Recommendation"},
173 { 51, "Add Things I like / Place In Queue Request"},
174 { 52, "Remove Things I like"},
175 { 54, "Get Recommendations"},
176 { 55, "Type 55"},
177 { 56, "Get Global Rankings"},
178 { 57, "Get User Recommendations"},
179 { 58, "Admin Command"},
180 { 60, "Place In Line Response"},
181 { 62, "Room Added"},
182 { 63, "Room Removed"},
183 { 64, "Room List"},
184 { 65, "Exact File Search"},
185 { 66, "Admin Message"},
186 { 67, "Global User List"},
187 { 68, "Tunneled Message"},
188 { 69, "Privileged User List"},
189 { 71, "Get Parent List"},
190 { 73, "Type 73"},
191 { 83, "Parent Min Speed"},
192 { 84, "Parent Speed Connection Ratio"},
193 { 86, "Parent Inactivity Before Disconnect"},
194 { 87, "Server Inactivity Before Disconnect"},
195 { 88, "Nodes In Cache Before Disconnect"},
196 { 90, "Seconds Before Ping Children"},
197 { 91, "Add To Privileged"},
198 { 92, "Check Privileges"},
199 { 93, "Embedded Message"},
200 { 100, "Become Parent"},
201 { 102, "Random Parent Addresses"},
202 { 103, "Send Wishlist Entry"},
203 { 104, "Type 104"},
204 { 110, "Get Similar Users"},
205 { 111, "Get Recommendations for Item"},
206 { 112, "Get Similar Users for Item"},
207 { 1001, "Can't Connect To Peer"},
208 { 0, NULL }
209 };
210
211 static const value_string slsk_status_codes[] = {
212 { -1, "Unknown"},
213 { 0, "Offline"},
214 { 1, "Away"},
215 { 2, "Online"},
216 { 0, NULL }
217 };
218
219 static const value_string slsk_transfer_direction[] = {
220 { 0, "Download"},
221 { 1, "Upload"},
222 { 0, NULL }
223 };
224
225 static const value_string slsk_yes_no[] = {
226 { 0, "No"},
227 { 1, "Yes"},
228 { 0, NULL }
229 };
230
231 static const value_string slsk_attr_type[] = {
232 { 0, "Bitrate"},
233 { 1, "Length"},
234 { 2, "VBR"},
235 { 0, NULL }
236 };
237
238 static const char* connection_type(char con_type[]) {
239 if (strlen(con_type) != 1) return "Unknown";
240 if (con_type[0] == 'D') return "Distributed Search";
241 if (con_type[0] == 'P') return "Peer Connection"; /* "File Search Result / User Info Request / Get Shared File List" */
242 if (con_type[0] == 'F') return "File Transfer";
243 return "Unknown";
244 }
245
246 static gboolean check_slsk_format(tvbuff_t *tvb, int offset, const char format[]){
247
248 /*
249 * Returns TRUE if tvbuff beginning at offset matches a certain format
250 * The format is given by an array of characters standing for a special field type
251 * i - integer (4 bytes)
252 * b - byte (1 byte)
253 * s - string (string_length + 4 bytes)
254 *
255 * * - can be used at the end of a format to ignore any following bytes
256 */
257
258 switch ( format[0] ) {
259 case 'i':
260 if (tvb_captured_length_remaining(tvb, offset) < 4) return FALSE;
261 offset += 4;
262 break;
263 case 'b':
264 if (tvb_captured_length_remaining(tvb, offset) < 1) return FALSE;
265 offset += 1;
266 break;
267 case 's':
268 if (tvb_captured_length_remaining(tvb, offset) < 4) return FALSE;
269 if (tvb_captured_length_remaining(tvb, offset) < (int)tvb_get_letohl(tvb, offset)+4) return FALSE;
270 offset += tvb_get_letohl(tvb, offset)+4;
271 break;
272 case '*':
273 return TRUE;
274 default:
275 return FALSE;
276 }
277
278 if (format[1] == '\0' ) {
279 if (tvb_captured_length_remaining(tvb, offset) > 0) /* Checks for additional bytes at the end */
280 return FALSE;
281 return TRUE;
282 }
283 return check_slsk_format(tvb, offset, &format[1]);
284
285 }
286
287 static const char* get_message_type(tvbuff_t *tvb) {
288 /*
289 * Checks if the Message Code is known.
290 * If unknown checks if the Message Code is stored in a byte.
291 * Returns the Message Type.
292 */
293 int msg_code = tvb_get_letohl(tvb, 4);
294 const gchar *message_type = try_val_to_str(msg_code, slsk_tcp_msgs);
295 if (message_type == NULL) {
296 if (check_slsk_format(tvb, 4, "bisis"))
297 message_type = "Distributed Search";
298 else if (check_slsk_format(tvb, 4, "bssi"))
299 message_type = "Peer Init";
300 else if (check_slsk_format(tvb, 4, "bi"))
301 message_type = "Pierce Fw";
302 else
303 message_type = "Unknown";
304 }
305 return message_type;
306 }
307
308 static guint get_slsk_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
309 int offset, void *data _U_)
310 {
311 guint32 msg_len;
312 msg_len = tvb_get_letohl(tvb, offset);
313 /* That length doesn't include the length field itself; add that in. */
314 msg_len += 4;
315 return msg_len;
316 }
317
318 /* Code to actually dissect the packets */
319
320 static int dissect_slsk_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
321 {
322
323 /* Set up structures needed to add the protocol subtree and manage it */
324 proto_item *ti, *ti_len, *ti_subtree, *ti_subtree2;
325 proto_tree *slsk_tree, *subtree, *subtree2, *subtree3;
326
327 int offset = 0, i, j;
328 guint32 msg_len, msg_code;
329 guint8 *str;
330 int str_len, start_offset, start_offset2;
331
332 int comprlen = 0, uncomprlen = 0, uncompr_tvb_offset = 0;
333 int i2 = 0, j2 = 0;
334 int i3 = 0, j3 = 0;
335
336 /* Make entries in Protocol column and Info column on summary display */
337 col_set_str(pinfo->cinfo, COL_PROTOCOL, "slsk");
338
339 /* This field shows up as the "Info" column in the display */
340
341 col_set_str(pinfo->cinfo, COL_INFO, "SoulSeek Message");
342
343 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", get_message_type(tvb));
344
345 /* create display subtree for the protocol */
346 ti = proto_tree_add_item(tree, proto_slsk, tvb, 0, -1, ENC_NA);
347 slsk_tree = proto_item_add_subtree(ti, ett_slsk);
348
349 /* Continue adding tree items to process the packet here */
350
351 ti_len = proto_tree_add_item_ret_uint(slsk_tree, hf_slsk_message_length, tvb, offset, 4, ENC_LITTLE_ENDIAN, &msg_len);
352 offset += 4;
353 msg_code = tvb_get_letohl(tvb, offset);
354
355 switch (msg_code) {
356
357 case 1:
358 if (check_slsk_format(tvb, offset, "issi")) {
359 /* Client-to-Server */
360 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
361 "Login (Code: %02d)", msg_code);
362 offset += 4;
363 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
364 offset += str_len;
365 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_password, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
366 offset += str_len;
367 proto_tree_add_item(slsk_tree, hf_slsk_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
368 offset += 4;
369 }
370 else if (check_slsk_format(tvb, offset, "ibs") || check_slsk_format(tvb, offset, "ibsi")) {
371 /* Server-to-Client */
372 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
373 "Login Reply (Code: %02d)", msg_code);
374 offset += 4;
375 i=tvb_get_guint8(tvb, offset);
376 proto_tree_add_item(slsk_tree, hf_slsk_login_successful, tvb, offset, 1, ENC_NA);
377 offset += 1;
378 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_login_message, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
379 offset += str_len;
380 if (i == 1){
381 proto_tree_add_item(slsk_tree, hf_slsk_client_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
382 offset += 4;
383 }
384 }
385 break;
386
387 case 2:
388 if (check_slsk_format(tvb, offset, "ii")) {
389 /* Client-to-Server */
390 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
391 "Set Wait Port (Code: %02d)", msg_code);
392 offset += 4;
393 proto_tree_add_item(slsk_tree, hf_slsk_port, tvb, offset, 4, ENC_LITTLE_ENDIAN);
394 offset += 4;
395 }
396 break;
397
398 case 3:
399 if (check_slsk_format(tvb, offset, "isii")) {
400 /* Server-to-Client */
401 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
402 "Get Peer Address Reply (Code: %02d)", msg_code);
403 offset += 4;
404 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
405 offset += str_len;
406 proto_tree_add_item(slsk_tree, hf_slsk_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
407 offset += 4;
408 proto_tree_add_item(slsk_tree, hf_slsk_port, tvb, offset, 4, ENC_LITTLE_ENDIAN);
409 offset += 4;
410 }
411 else if (check_slsk_format(tvb, offset, "is")) {
412 /* Client-to-Server */
413 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
414 "Get Peer Address (Code: %02d)", msg_code);
415 offset += 4;
416 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
417 offset += str_len;
418 }
419 break;
420
421 case 4:
422 if (check_slsk_format(tvb, offset, "i")) {
423 /* Client-to-Client */
424 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
425 "Get Shared File List (Code: %02d)", msg_code);
426 offset += 4;
427 }
428 break;
429
430 case 5:
431 if (check_slsk_format(tvb, offset, "isb")) {
432 /* Server-to-Client */
433 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
434 "User Exists Reply (Code: %02d)", msg_code);
435 offset += 4;
436 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
437 offset += str_len;
438 proto_tree_add_item(slsk_tree, hf_slsk_user_exists, tvb, offset, 1, ENC_NA);
439 offset += 1;
440 }
441 else if (check_slsk_format(tvb, offset, "is")) {
442 /* Client-to-Server */
443 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
444 "User Exists Request (Code: %02d)", msg_code);
445 offset += 4;
446 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
447 offset += str_len;
448 }
449 else if (check_slsk_format(tvb, offset, "i*")) {
450 /* Client-to-Client */
451 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
452 "Shared File List (Code: %02d)", msg_code);
453 offset += 4;
454
455 /* [zlib compressed] */
456 comprlen = tvb_captured_length_remaining(tvb, offset);
457
458 if (slsk_decompress == TRUE){
459
460 tvbuff_t *uncompr_tvb = tvb_child_uncompress(tvb, tvb, offset, comprlen);
461
462 if (uncompr_tvb == NULL) {
463 proto_tree_add_expert(slsk_tree, pinfo, &ei_slsk_zlib_decompression_failed, tvb, offset, -1);
464 offset += tvb_captured_length_remaining(tvb, offset);
465 } else {
466
467 proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, ENC_NA);
468 proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
469 proto_item_set_generated(ti2);
470
471 ti = proto_tree_add_uint(slsk_tree, hf_slsk_compressed_packet_length, tvb, offset, 0, comprlen);
472 proto_item_set_generated(ti);
473 uncomprlen = tvb_reported_length_remaining(uncompr_tvb, 0);
474 ti = proto_tree_add_uint(slsk_tree, hf_slsk_uncompressed_packet_length, tvb, offset, 0, uncomprlen);
475 proto_item_set_generated(ti);
476
477 add_new_data_source(pinfo, uncompr_tvb, "Uncompressed SoulSeek data");
478 uncompr_tvb_offset = 0;
479 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "i*")) {
480 proto_tree_add_item_ret_int(slsk_compr_packet_tree, hf_slsk_num_directories, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j);
481 uncompr_tvb_offset += 4;
482 for (i = 0; i < j; i++) {
483 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "si*")) {
484 start_offset = uncompr_tvb_offset;
485 subtree = proto_tree_add_subtree_format(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset, 1, ett_slsk_directory, &ti_subtree, "Directory #%d", i+1);
486 proto_tree_add_item_ret_length(subtree, hf_slsk_directory_name, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
487 uncompr_tvb_offset += str_len;
488 proto_tree_add_item_ret_int(subtree, hf_slsk_num_files, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j2);
489 uncompr_tvb_offset += 4;
490 for (i2 = 0; i2 < j2; i2++) {
491 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
492 start_offset2 = uncompr_tvb_offset;
493 subtree2 = proto_tree_add_subtree_format(subtree, uncompr_tvb, uncompr_tvb_offset, 1, ett_slsk_file, &ti_subtree2, "File #%d", i2+1);
494 proto_tree_add_item(subtree2, hf_slsk_file_code, uncompr_tvb, uncompr_tvb_offset, 1, ENC_NA);
495 uncompr_tvb_offset += 1;
496 proto_tree_add_item_ret_length(subtree2, hf_slsk_filename, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
497 uncompr_tvb_offset += str_len;
498 proto_tree_add_item(subtree2, hf_slsk_file_size1, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
499 uncompr_tvb_offset += 4;
500 proto_tree_add_item(subtree2, hf_slsk_file_size2, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
501 uncompr_tvb_offset += 4;
502 proto_tree_add_item_ret_length(subtree2, hf_slsk_filename_ext, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
503 uncompr_tvb_offset += str_len;
504 proto_tree_add_item_ret_int(subtree2, hf_slsk_file_num_attributes, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j3);
505 uncompr_tvb_offset += 4;
506 for (i3 = 0; i3 < j3; i3++) {
507 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
508 subtree3 = proto_tree_add_subtree_format(subtree2, uncompr_tvb, uncompr_tvb_offset, 8, ett_slsk_file_attribute, NULL, "Attribute #%d", i3+1);
509 proto_tree_add_item(subtree3, hf_slsk_file_attribute_type, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
510 uncompr_tvb_offset += 4;
511 proto_tree_add_item(subtree3, hf_slsk_file_attribute_value, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
512 uncompr_tvb_offset += 4;
513 } else {
514 break; /* invalid format */
515 }
516 }
517 proto_item_set_len(ti_subtree2, uncompr_tvb_offset-start_offset2);
518 } else {
519 break; /* invalid format */
520 }
521 }
522 proto_item_set_len(ti_subtree, uncompr_tvb_offset-start_offset);
523 } else {
524 break; /* invalid format */
525 }
526 }
527 }
528 }
529 }else {
530 ti = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, ENC_NA);
531 proto_item_set_generated(ti);
532 ti = proto_tree_add_uint(slsk_tree, hf_slsk_compressed_packet_length, tvb, offset, 0, comprlen);
533 proto_item_set_generated(ti);
534 offset += tvb_captured_length_remaining(tvb, offset);
535 }
536 }
537 break;
538
539 case 7:
540 if (check_slsk_format(tvb, offset, "isi")) {
541 /* Server-to-Client */
542 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
543 "Get User Status Reply (Code: %02d)", msg_code);
544 offset += 4;
545 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
546 offset += str_len;
547 proto_tree_add_item(slsk_tree, hf_slsk_status_code, tvb, offset, 4, ENC_LITTLE_ENDIAN);
548 offset += 4;
549 }
550 else if (check_slsk_format(tvb, offset, "is")) {
551 /* Client-to-Server */
552 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
553 "Get User Status (Code: %02d)", msg_code);
554 offset += 4;
555 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
556 offset += str_len;
557 }
558 break;
559
560 case 9:
561 if (check_slsk_format(tvb, offset, "i*")) {
562 /* Client-to-Client */
563 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
564 "File Search Result (Code: %02d)", msg_code);
565 offset += 4;
566
567 /* [zlib compressed] */
568 comprlen = tvb_captured_length_remaining(tvb, offset);
569
570 if (slsk_decompress == TRUE){
571
572 tvbuff_t *uncompr_tvb = tvb_child_uncompress(tvb, tvb, offset, comprlen);
573
574 if (uncompr_tvb == NULL) {
575 ti = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA);
576 proto_item_set_generated(ti);
577 offset += tvb_captured_length_remaining(tvb, offset);
578 expert_add_info(pinfo, ti, &ei_slsk_decompression_failed);
579 } else {
580
581 proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, ENC_NA);
582 proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
583 proto_item_set_generated(ti2);
584
585 ti = proto_tree_add_uint(slsk_tree, hf_slsk_compressed_packet_length, tvb, offset, 0, comprlen);
586 proto_item_set_generated(ti);
587 uncomprlen = tvb_captured_length_remaining(uncompr_tvb, 0);
588 ti = proto_tree_add_uint(slsk_tree, hf_slsk_uncompressed_packet_length, tvb, offset, 0, uncomprlen);
589 proto_item_set_generated(ti);
590
591 add_new_data_source(pinfo, uncompr_tvb, "Uncompressed SoulSeek data");
592 uncompr_tvb_offset = 0;
593 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "sii*")) {
594 proto_tree_add_item_ret_length(slsk_compr_packet_tree, hf_slsk_username, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_NA, &str_len);
595 uncompr_tvb_offset += str_len;
596 proto_tree_add_item(slsk_compr_packet_tree, hf_slsk_token, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
597 uncompr_tvb_offset += 4;
598 proto_tree_add_item_ret_int(slsk_compr_packet_tree, hf_slsk_num_files, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j);
599 uncompr_tvb_offset += 4;
600 for (i = 0; i < j; i++) {
601 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
602 start_offset2 = uncompr_tvb_offset;
603 subtree2 = proto_tree_add_subtree_format(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset, 1, ett_slsk_file, &ti_subtree2, "File #%d", i+1);
604 proto_tree_add_item(subtree2, hf_slsk_file_code, uncompr_tvb, uncompr_tvb_offset, 1, ENC_NA);
605 uncompr_tvb_offset += 1;
606 proto_tree_add_item_ret_length(subtree2, hf_slsk_filename, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
607 uncompr_tvb_offset += str_len;
608 proto_tree_add_item(subtree2, hf_slsk_file_size1, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
609 uncompr_tvb_offset += 4;
610 proto_tree_add_item(subtree2, hf_slsk_file_size2, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
611 uncompr_tvb_offset += 4;
612 proto_tree_add_item_ret_length(subtree2, hf_slsk_filename_ext, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
613 uncompr_tvb_offset += str_len;
614 proto_tree_add_item_ret_int(subtree2, hf_slsk_file_num_attributes, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j2);
615 uncompr_tvb_offset += 4;
616 for (i2 = 0; i2 < j2; i2++) {
617 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
618 subtree3 = proto_tree_add_subtree_format(subtree2, uncompr_tvb, uncompr_tvb_offset, 8, ett_slsk_file_attribute, NULL, "Attribute #%d", i2+1);
619 proto_tree_add_item(subtree3, hf_slsk_file_attribute_type, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
620 uncompr_tvb_offset += 4;
621 proto_tree_add_item(subtree3, hf_slsk_file_attribute_value, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
622 uncompr_tvb_offset += 4;
623 } else {
624 break; /* invalid format */
625 }
626 }
627 proto_item_set_len(ti_subtree2, uncompr_tvb_offset-start_offset2);
628 } else {
629 break; /* invalid format */
630 }
631 }
632
633 proto_tree_add_item(slsk_compr_packet_tree, hf_slsk_free_upload_slots, uncompr_tvb, uncompr_tvb_offset, 1, ENC_LITTLE_ENDIAN);
634 uncompr_tvb_offset += 1;
635 proto_tree_add_item(slsk_compr_packet_tree, hf_slsk_upload_speed, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
636 uncompr_tvb_offset += 4;
637 proto_tree_add_item(slsk_compr_packet_tree, hf_slsk_in_queue, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
638 }
639 }
640 }else {
641 ti = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, ENC_NA);
642 proto_item_set_generated(ti);
643 ti = proto_tree_add_uint(slsk_tree, hf_slsk_compressed_packet_length, tvb, offset, 0, comprlen);
644 proto_item_set_generated(ti);
645 offset += tvb_captured_length_remaining(tvb, offset);
646 }
647 }
648 break;
649
650 case 13:
651 if (check_slsk_format(tvb, offset, "isss")) {
652 /* Server-to-Client */
653 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
654 "Say ChatRoom (Code: %02d)", msg_code);
655 offset += 4;
656 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
657 offset += str_len;
658 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
659 offset += str_len;
660 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_chat_message, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
661 offset += str_len;
662 }
663 else if (check_slsk_format(tvb, offset, "iss")) {
664 /* Client-to-Server */
665 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
666 "Say ChatRoom (Code: %02d)", msg_code);
667 offset += 4;
668 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
669 offset += str_len;
670 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_chat_message, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
671 offset += str_len;
672 }
673 break;
674
675 case 14:
676 if (check_slsk_format(tvb, offset, "is")) {
677 /* Client-to-Server */
678 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
679 "Join/Add Room (Code: %02d)", msg_code);
680 offset += 4;
681 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
682 offset += str_len;
683 }
684 else if (check_slsk_format(tvb, offset, "isi*")) {
685 /* Server-to-Client */
686 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
687 "Join Room User List (Code: %02d)", msg_code);
688 offset += 4;
689 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
690 offset += str_len;
691 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
692 offset += 4;
693 if (j > tvb_reported_length_remaining(tvb, offset))
694 break;
695 for (i = 0; i < j; i++) {
696 if (check_slsk_format(tvb, offset, "s*")) {
697 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_user, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
698 offset += str_len;
699 } else {
700 break; /* invalid format */
701 }
702 }
703 if (check_slsk_format(tvb, offset, "i*")) {
704 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
705 offset += 4;
706 if (j > tvb_reported_length_remaining(tvb, offset))
707 break;
708 for (i = 0; i < j; i++) {
709 if (check_slsk_format(tvb, offset, "i*")) {
710 proto_tree_add_item(slsk_tree, hf_slsk_status_code, tvb, offset, 4, ENC_LITTLE_ENDIAN);
711 offset += 4;
712 } else {
713 break; /* invalid format */
714 }
715 }
716 }
717 if (check_slsk_format(tvb, offset, "i*")) {
718 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
719 offset += 4;
720 if (j > tvb_reported_length_remaining(tvb, offset))
721 break;
722 for (i = 0; i < j; i++) {
723 if (check_slsk_format(tvb, offset, "iiiii*")) {
724 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 20, ett_slsk_user, NULL, "User #%d", i+1);
725 proto_tree_add_item(subtree, hf_slsk_average_speed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
726 offset += 4;
727 proto_tree_add_item(subtree, hf_slsk_download_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
728 offset += 4;
729 proto_tree_add_item(subtree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
730 offset += 4;
731 proto_tree_add_item(subtree, hf_slsk_files, tvb, offset, 4, ENC_LITTLE_ENDIAN);
732 offset += 4;
733 proto_tree_add_item(subtree, hf_slsk_directories, tvb, offset, 4, ENC_LITTLE_ENDIAN);
734 offset += 4;
735 } else {
736 break; /* invalid format */
737 }
738 }
739 }
740 if (check_slsk_format(tvb, offset, "i*")) {
741 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_slotsfull_records, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
742 offset += 4;
743 if (j > tvb_reported_length_remaining(tvb, offset))
744 break;
745 for (i = 0; i < j; i++) {
746 if (check_slsk_format(tvb, offset, "i*")) {
747 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 4, ett_slsk_user, NULL, "User #%d", i+1);
748 proto_tree_add_item(subtree, hf_slsk_slotsfull, tvb, offset, 4, ENC_LITTLE_ENDIAN);
749 offset += 4;
750 } else {
751 break; /* invalid format */
752 }
753 }
754 }
755 }
756 break;
757
758 case 15:
759 if (check_slsk_format(tvb, offset, "is")) {
760 /* Client-to-Server & Server-to-Client */
761 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
762 "Leave Room (Code: %02d)", msg_code);
763 offset += 4;
764 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
765 offset += str_len;
766 }
767 else if (check_slsk_format(tvb, offset, "i")) {
768 /* Client-to-Client */
769 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
770 "User Info Request (Code: %02d)", msg_code);
771 offset += 4;
772 }
773 break;
774
775 case 16:
776 if (check_slsk_format(tvb, offset, "issiiiiiii")) {
777 /* Server-to-Client */
778 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
779 "User Joined Room (Code: %02d)", msg_code);
780 offset += 4;
781 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
782 offset += str_len;
783 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
784 offset += str_len;
785 proto_tree_add_item(slsk_tree, hf_slsk_total_uploads, tvb, offset, 4, ENC_LITTLE_ENDIAN);
786 offset += 4;
787 proto_tree_add_item(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
788 offset += 4;
789 proto_tree_add_item(slsk_tree, hf_slsk_download_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
790 offset += 4;
791 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
792 offset += 4;
793 proto_tree_add_item(slsk_tree, hf_slsk_files, tvb, offset, 4, ENC_LITTLE_ENDIAN);
794 offset += 4;
795 proto_tree_add_item(slsk_tree, hf_slsk_directories, tvb, offset, 4, ENC_LITTLE_ENDIAN);
796 offset += 4;
797 proto_tree_add_item(slsk_tree, hf_slsk_slotsfull, tvb, offset, 4, ENC_LITTLE_ENDIAN);
798 offset += 4;
799 }
800 else if (check_slsk_format(tvb, offset, "isbiib") || check_slsk_format(tvb, offset, "isbsiib")) {
801 /* Client-to-Client */
802 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
803 "User Info Reply (Code: %02d)", msg_code);
804 offset += 4;
805 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_user_description, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
806 offset += str_len;
807 proto_tree_add_item(slsk_tree, hf_slsk_picture_exists, tvb, offset, 1, ENC_NA);
808 offset += 1;
809 if ( tvb_get_guint8(tvb, offset -1 ) == 1 ) {
810 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_picture, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
811 offset += str_len;
812 }
813 proto_tree_add_item(slsk_tree, hf_slsk_total_uploads, tvb, offset, 4, ENC_LITTLE_ENDIAN);
814 offset += 4;
815 proto_tree_add_item(slsk_tree, hf_slsk_queued_uploads, tvb, offset, 4, ENC_LITTLE_ENDIAN);
816 offset += 4;
817 proto_tree_add_item(slsk_tree, hf_slsk_slots_available, tvb, offset, 1, ENC_NA);
818 offset += 1;
819 }
820 break;
821
822 case 17:
823 if (check_slsk_format(tvb, offset, "iss")) {
824 /* Server-to-Client */
825 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
826 "User Left Room (Code: %02d)", msg_code);
827 offset += 4;
828 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
829 offset += str_len;
830 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
831 offset += str_len;
832 }
833 break;
834
835 case 18:
836 if (check_slsk_format(tvb, offset, "iiss")) {
837 /* Client-to-Server */
838 guint32 len;
839
840 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
841 "Connect To Peer (Code: %02d)", msg_code);
842 offset += 4;
843 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
844 offset += 4;
845 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
846 offset += str_len;
847 len = tvb_get_letohl(tvb, offset);
848 str = tvb_get_string_enc(pinfo->pool, tvb, offset+4, len, ENC_ASCII);
849 proto_tree_add_string_format_value(slsk_tree, hf_slsk_connection_type, tvb, offset, 4+len, str,
850 "%s (Char: %s)", connection_type(str),
851 format_text(pinfo->pool, str, len));
852 offset += 4+len;
853 }
854 else if (check_slsk_format(tvb, offset, "issiii")) {
855 /* Server-to-Client */
856 guint32 len;
857
858 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
859 "Connect To Peer (Code: %02d)", msg_code);
860 offset += 4;
861 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
862 offset += str_len;
863 len = tvb_get_letohl(tvb, offset);
864 str = tvb_get_string_enc(pinfo->pool, tvb, offset+4, len, ENC_ASCII);
865 proto_tree_add_string_format_value(slsk_tree, hf_slsk_connection_type, tvb, offset, 4+len, str,
866 "%s (Char: %s)", connection_type(str),
867 format_text(pinfo->pool, str, len));
868 offset += 4+len;
869 proto_tree_add_item(slsk_tree, hf_slsk_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
870 offset += 4;
871 proto_tree_add_item(slsk_tree, hf_slsk_port, tvb, offset, 4, ENC_LITTLE_ENDIAN);
872 offset += 4;
873 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
874 offset += 4;
875 }
876 break;
877
878 case 22:
879 if (check_slsk_format(tvb, offset, "iss")) {
880 /* Client-to-Server */
881 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
882 "Message User Send (Code: %02d)", msg_code);
883 offset += 4;
884 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
885 offset += str_len;
886 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_chat_message, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
887 offset += str_len;
888 }
889 else if (check_slsk_format(tvb, offset, "iiiss")) {
890 /* Server-to-Client */
891 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
892 "Message User Receive (Code: %02d)", msg_code);
893 offset += 4;
894 proto_tree_add_item(slsk_tree, hf_slsk_chat_message_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
895 offset += 4;
896 proto_tree_add_item(slsk_tree, hf_slsk_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN);
897 offset += 4;
898 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
899 offset += str_len;
900 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_chat_message, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
901 offset += str_len;
902 }
903 break;
904
905 case 23:
906 if (check_slsk_format(tvb, offset, "ii")) {
907 /* Client-to-Server */
908 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
909 "Message User Receive Ack (Code: %02d)", msg_code);
910 offset += 4;
911 proto_tree_add_item(slsk_tree, hf_slsk_chat_message_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
912 offset += 4;
913 }
914 break;
915
916 case 26:
917 if (check_slsk_format(tvb, offset, "iis")) {
918 /* Client-to-Server */
919 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
920 "File Search (Code: %02d)", msg_code);
921 offset += 4;
922 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
923 offset += 4;
924 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_search_text, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
925 offset += str_len;
926 }
927 break;
928
929 case 28:
930 if (check_slsk_format(tvb, offset, "ii")) {
931 /* Client-to-Server */
932 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
933 "Set Status (Code: %02d)", msg_code);
934 offset += 4;
935 proto_tree_add_item(slsk_tree, hf_slsk_status_code, tvb, offset, 4, ENC_LITTLE_ENDIAN);
936 offset += 4;
937 }
938 break;
939
940 case 32:
941 if (check_slsk_format(tvb, offset, "i")) {
942 /* Client-to-Server */
943 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
944 "Ping (Code: %02d)", msg_code);
945 offset += 4;
946 }
947 break;
948
949 case 34:
950 if (check_slsk_format(tvb, offset, "isi")) {
951 /* Client-to-Server */
952 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
953 "Update Upload Speed (Code: %02d)", msg_code);
954 offset += 4;
955 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
956 offset += str_len;
957 proto_tree_add_item(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
958 offset += 4;
959 }
960 break;
961
962 case 35:
963 if (check_slsk_format(tvb, offset, "iii")) {
964 /* Client-to-Server */
965 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
966 "Shared Files & Folders (Code: %02d)", msg_code);
967 offset += 4;
968 proto_tree_add_item(slsk_tree, hf_slsk_folder_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
969 offset += 4;
970 proto_tree_add_item(slsk_tree, hf_slsk_file_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
971 offset += 4;
972 }
973 break;
974
975 case 36:
976 if (check_slsk_format(tvb, offset, "isiiiii")) {
977 /* Server-to-Client */
978 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
979 "Get User Stats Reply (Code: %02d)", msg_code);
980 offset += 4;
981 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
982 offset += str_len;
983 proto_tree_add_item(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
984 offset += 4;
985 proto_tree_add_item(slsk_tree, hf_slsk_download_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
986 offset += 4;
987 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
988 offset += 4;
989 proto_tree_add_item(slsk_tree, hf_slsk_files, tvb, offset, 4, ENC_LITTLE_ENDIAN);
990 offset += 4;
991 proto_tree_add_item(slsk_tree, hf_slsk_directories, tvb, offset, 4, ENC_LITTLE_ENDIAN);
992 offset += 4;
993 }
994 else if (check_slsk_format(tvb, offset, "is")) {
995 /* Client-to-Client */
996 /* Client-to-Server: send after login successful */
997 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
998 "Get User Stats (Code: %02d)", msg_code);
999 offset += 4;
1000 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1001 offset += str_len;
1002 }
1003 else if (check_slsk_format(tvb, offset, "iis")) {
1004 /* Client-to-Client */
1005 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1006 "Folder Contents Request (Code: %02d)", msg_code);
1007 offset += 4;
1008 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1009 offset += 4;
1010 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_directory, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1011 offset += str_len;
1012 }
1013 break;
1014
1015 case 37:
1016 if (check_slsk_format(tvb, offset, "i*")) {
1017 /* Client-to-Client */
1018 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1019 "Folder Contents Response (Code: %02d)", msg_code);
1020 offset += 4;
1021
1022 /* [zlib compressed] */
1023 comprlen = tvb_captured_length_remaining(tvb, offset);
1024
1025 if (slsk_decompress == TRUE){
1026
1027 tvbuff_t *uncompr_tvb = tvb_child_uncompress(tvb, tvb, offset, comprlen);
1028
1029 if (uncompr_tvb == NULL) {
1030 proto_tree_add_expert(slsk_tree, pinfo, &ei_slsk_zlib_decompression_failed, tvb, offset, -1);
1031 offset += tvb_captured_length_remaining(tvb, offset);
1032 } else {
1033
1034 proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, ENC_NA);
1035 proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
1036 proto_item_set_generated(ti2);
1037
1038 ti = proto_tree_add_uint(slsk_tree, hf_slsk_compressed_packet_length, tvb, offset, 0, comprlen);
1039 proto_item_set_generated(ti);
1040 uncomprlen = tvb_captured_length_remaining(uncompr_tvb, 0);
1041 ti = proto_tree_add_uint(slsk_tree, hf_slsk_uncompressed_packet_length, tvb, offset, 0, uncomprlen);
1042 proto_item_set_generated(ti);
1043 add_new_data_source(pinfo, uncompr_tvb, "Uncompressed SoulSeek data");
1044
1045 uncompr_tvb_offset = 0;
1046 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "isi*")) {
1047 guint32 len;
1048
1049 proto_tree_add_item(slsk_compr_packet_tree, hf_slsk_token, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
1050 uncompr_tvb_offset += 4;
1051 proto_tree_add_item_ret_length(slsk_compr_packet_tree, hf_slsk_directory_name, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &len);
1052 uncompr_tvb_offset += len;
1053
1054 proto_tree_add_item_ret_int(slsk_compr_packet_tree, hf_slsk_num_directories, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j);
1055 uncompr_tvb_offset += 4;
1056 for (i = 0; i < j; i++) {
1057 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "si*")) {
1058 start_offset = uncompr_tvb_offset;
1059 subtree = proto_tree_add_subtree_format(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset, 1, ett_slsk_directory, &ti_subtree, "Directory #%d", i+1);
1060 proto_tree_add_item_ret_length(subtree, hf_slsk_directory_name, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1061 uncompr_tvb_offset += str_len;
1062 proto_tree_add_item_ret_int(subtree, hf_slsk_num_files, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j2);
1063 uncompr_tvb_offset += 4;
1064 for (i2 = 0; i2 < j2; i2++) {
1065 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
1066 start_offset2 = uncompr_tvb_offset;
1067 subtree2 = proto_tree_add_subtree_format(subtree, uncompr_tvb, uncompr_tvb_offset, 1, ett_slsk_file, &ti_subtree2, "File #%d", i2+1);
1068 proto_tree_add_item(subtree2, hf_slsk_file_code, uncompr_tvb, uncompr_tvb_offset, 1, ENC_NA);
1069 uncompr_tvb_offset += 1;
1070 proto_tree_add_item_ret_length(subtree2, hf_slsk_filename, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1071 uncompr_tvb_offset += str_len;
1072 proto_tree_add_item(subtree2, hf_slsk_file_size1, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
1073 uncompr_tvb_offset += 4;
1074 proto_tree_add_item(subtree2, hf_slsk_file_size2, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
1075 uncompr_tvb_offset += 4;
1076 proto_tree_add_item_ret_length(subtree2, hf_slsk_filename_ext, uncompr_tvb, uncompr_tvb_offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1077 uncompr_tvb_offset += str_len;
1078 proto_tree_add_item_ret_int(subtree2, hf_slsk_file_num_attributes, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN, &j3);
1079 uncompr_tvb_offset += 4;
1080 for (i3 = 0; i3 < j3; i3++) {
1081 if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
1082 subtree3 = proto_tree_add_subtree_format(subtree2, uncompr_tvb, uncompr_tvb_offset, 8, ett_slsk_file_attribute, NULL, "Attribute #%d", i3+1);
1083 proto_tree_add_item(subtree3, hf_slsk_file_attribute_type, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
1084 uncompr_tvb_offset += 4;
1085 proto_tree_add_item(subtree3, hf_slsk_file_attribute_value, uncompr_tvb, uncompr_tvb_offset, 4, ENC_LITTLE_ENDIAN);
1086 uncompr_tvb_offset += 4;
1087 } else {
1088 break; /* invalid format */
1089 }
1090 }
1091 proto_item_set_len(ti_subtree2, uncompr_tvb_offset-start_offset2);
1092 } else {
1093 break; /* invalid format */
1094 }
1095 }
1096 proto_item_set_len(ti_subtree, uncompr_tvb_offset-start_offset);
1097 } else {
1098 break; /* invalid format */
1099 }
1100 }
1101 }
1102 }
1103 }else {
1104 ti = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, ENC_NA);
1105 proto_item_set_generated(ti);
1106 ti = proto_tree_add_uint(slsk_tree, hf_slsk_compressed_packet_length, tvb, offset, 0, comprlen);
1107 proto_item_set_generated(ti);
1108 offset += tvb_captured_length_remaining(tvb, offset);
1109 }
1110 }
1111 break;
1112
1113 case 40:
1114 if (check_slsk_format(tvb, offset, "isi")) {
1115 /* Server-to-Client */
1116 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1117 "Queued Downloads (Code: %02d)", msg_code);
1118 offset += 4;
1119 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1120 offset += str_len;
1121 proto_tree_add_item(slsk_tree, hf_slsk_slotsfull, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1122 offset += 4;
1123 }
1124 else if (check_slsk_format(tvb, offset, "iiis") || check_slsk_format(tvb, offset, "iiisii")) {
1125 /* Client-to-Client */
1126 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1127 "Transfer Request (Code: %02d)", msg_code);
1128 offset += 4;
1129 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_transfer_direction, tvb, offset, 4, ENC_LITTLE_ENDIAN, &i);
1130 offset += 4;
1131 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1132 offset += 4;
1133 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1134 offset += str_len;
1135 if (i == 1){
1136 proto_tree_add_item(slsk_tree, hf_slsk_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1137 offset += 4;
1138 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1139 offset += 4;
1140 }
1141 }
1142
1143 break;
1144
1145 case 41:
1146 if (check_slsk_format(tvb, offset, "iibs") || check_slsk_format(tvb, offset, "iibii") || check_slsk_format(tvb, offset, "iib")) {
1147 /* Client-to-Client */
1148 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1149 "Transfer Response (Code: %02d)", msg_code);
1150 offset += 4;
1151 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1152 offset += 4;
1153 i = tvb_get_guint8(tvb, offset);
1154 proto_tree_add_item(slsk_tree, hf_slsk_allowed, tvb, offset, 1, ENC_NA);
1155 offset += 1;
1156 if ( i == 1 ) {
1157 if ( tvb_reported_length_remaining(tvb, offset) == 8 ) {
1158 proto_tree_add_item(slsk_tree, hf_slsk_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1159 offset += 4;
1160 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1161 offset += 4;
1162 }
1163 } else {
1164 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_string, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1165 offset += str_len;
1166 }
1167 }
1168 break;
1169
1170 case 42:
1171 if (check_slsk_format(tvb, offset, "is")) {
1172 /* Client-to-Client */
1173 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1174 "Placehold Upload (Code: %02d)", msg_code);
1175 offset += 4;
1176 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1177 offset += str_len;
1178 }
1179 break;
1180
1181 case 43:
1182 if (check_slsk_format(tvb, offset, "is")) {
1183 /* Client-to-Client */
1184 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1185 "Queue Upload (Code: %02d)", msg_code);
1186 offset += 4;
1187 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1188 offset += str_len;
1189 }
1190 break;
1191
1192 case 44:
1193 if (check_slsk_format(tvb, offset, "isi")) {
1194 /* Client-to-Client */
1195 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1196 "Place In Queue (Code: %02d)", msg_code);
1197 offset += 4;
1198 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1199 offset += str_len;
1200 proto_tree_add_item(slsk_tree, hf_slsk_place_in_queue, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1201 offset += 4;
1202 }
1203 break;
1204
1205 case 46:
1206 if (check_slsk_format(tvb, offset, "is")) {
1207 /* Client-to-Client */
1208 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1209 "Upload Failed (Code: %02d)", msg_code);
1210 offset += 4;
1211 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1212 offset += str_len;
1213 }
1214 break;
1215
1216 case 50:
1217 if (check_slsk_format(tvb, offset, "is")) {
1218 /* Client-to-Server */
1219 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1220 "Make Own Recommendation (Code: %02d)", msg_code);
1221 offset += 4;
1222 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1223 offset += str_len;
1224 }
1225 else if (check_slsk_format(tvb, offset, "isi")) {
1226 /* Client-to-Server */
1227 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1228 "Remove Own Recommendation (Code: %02d)", msg_code);
1229 offset += 4;
1230 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1231 offset += str_len;
1232 proto_tree_add_item(slsk_tree, hf_slsk_ranking, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1233 offset += 4;
1234 }
1235 else if (check_slsk_format(tvb, offset, "iss")) {
1236 /* Client-to-Client */
1237 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1238 "Queue Failed (Code: %02d)", msg_code);
1239 offset += 4;
1240 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1241 offset += str_len;
1242 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_string, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1243 offset += str_len;
1244 }
1245 break;
1246
1247 case 51:
1248 if (check_slsk_format(tvb, offset, "is")) {
1249 /* Client-to-Server: "Add Things I like" */
1250 /* Client-to-Client: "Place In Queue Request" */
1251 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1252 "Add Things I like / Place In Queue Request (Code: %02d)", msg_code);
1253 offset += 4;
1254 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1255 offset += str_len;
1256 }
1257 break;
1258
1259 case 52:
1260 if (check_slsk_format(tvb, offset, "is")) {
1261 /* Client-to-Server */
1262 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1263 "Remove Things I like (Code: %02d)", msg_code);
1264 offset += 4;
1265 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1266 offset += str_len;
1267 }
1268 break;
1269
1270 case 54:
1271 if (check_slsk_format(tvb, offset, "i")) {
1272 /* Client-to-Server */
1273 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1274 "Get Recommendations (Code: %02d)", msg_code);
1275 offset += 4;
1276 }
1277 else if (check_slsk_format(tvb, offset, "ii*")) {
1278 /* Server-to-Client */
1279 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1280 "Get Recommendations Reply (Code: %02d)", msg_code);
1281 offset += 4;
1282 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_recommendations, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1283 offset += 4;
1284 if (j > tvb_reported_length_remaining(tvb, offset))
1285 break;
1286 for (i = 0; i < j; i++) {
1287 if (check_slsk_format(tvb, offset, "si*")) {
1288 start_offset = offset;
1289 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 1, ett_slsk_recommendation, &ti_subtree, "Recommendation #%d", i+1);
1290 proto_tree_add_item_ret_length(subtree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1291 offset += str_len;
1292 proto_tree_add_item(subtree, hf_slsk_ranking, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1293 offset += 4;
1294 proto_item_set_len(ti_subtree, offset-start_offset);
1295 } else {
1296 break; /* invalid format */
1297 }
1298 }
1299 }
1300 break;
1301
1302 case 55:
1303 if (check_slsk_format(tvb, offset, "i")) {
1304 /* Client-to-Server */
1305 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1306 "Type 55 (Code: %02d)", msg_code);
1307 offset += 4;
1308 }
1309 break;
1310
1311 case 56:
1312 if (check_slsk_format(tvb, offset, "i")) {
1313 /* Client-to-Server */
1314 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1315 "Get Global Rankings (Code: %02d)", msg_code);
1316 offset += 4;
1317 }
1318 else if (check_slsk_format(tvb, offset, "ii*")) {
1319 /* Server-to-Client */
1320 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1321 "Get Global Rankings Reply (Code: %02d)", msg_code);
1322 offset += 4;
1323 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_recommendations, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1324 offset += 4;
1325 if (j > tvb_reported_length_remaining(tvb, offset))
1326 break;
1327 for (i = 0; i < j; i++) {
1328 if (check_slsk_format(tvb, offset, "si*")) {
1329 start_offset = offset;
1330 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 1, ett_slsk_recommendation, &ti_subtree, "Recommendation #%d", i+1);
1331 proto_tree_add_item_ret_length(subtree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1332 offset += str_len;
1333 proto_tree_add_item(subtree, hf_slsk_ranking, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1334 offset += 4;
1335 proto_item_set_len(ti_subtree, offset-start_offset);
1336 } else {
1337 break; /* invalid format */
1338 }
1339 }
1340 }
1341 break;
1342
1343 case 57:
1344 if (check_slsk_format(tvb, offset, "is")) {
1345 /* Client-to-Server */
1346 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1347 "Get User Recommendations (Code: %02d)", msg_code);
1348 offset += 4;
1349 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1350 offset += str_len;
1351 }
1352 else if (check_slsk_format(tvb, offset, "isi*")) {
1353 /* Server-to-Client */
1354 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1355 "Get User Recommendations Reply (Code: %02d)", msg_code);
1356 offset += 4;
1357 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1358 offset += str_len;
1359 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_recommendations, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1360 offset += 4;
1361 if (j > tvb_reported_length_remaining(tvb, offset))
1362 break;
1363 for (i = 0; i < j; i++) {
1364 if (check_slsk_format(tvb, offset, "s*")) {
1365 start_offset = offset;
1366 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 1, ett_slsk_recommendation, &ti_subtree, "Recommendation #%d", i+1);
1367 proto_tree_add_item_ret_length(subtree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1368 offset += str_len;
1369 proto_item_set_len(ti_subtree, offset-start_offset);
1370 } else {
1371 break; /* invalid format */
1372 }
1373 }
1374 }
1375 break;
1376
1377 case 58:
1378 if (check_slsk_format(tvb, offset, "isi*")) {
1379 /* Client-to-Server */
1380 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1381 "Admin Command (Code: %02d)", msg_code);
1382 offset += 4;
1383 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_string, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1384 offset += str_len;
1385 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_strings, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1386 offset += 4;
1387 if (j > tvb_reported_length_remaining(tvb, offset))
1388 break;
1389 for (i = 0; i < j; i++) {
1390 if (check_slsk_format(tvb, offset, "s*")) {
1391 start_offset = offset;
1392 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 1, ett_slsk_string, &ti_subtree, "String #%d", i+1);
1393 proto_tree_add_item_ret_length(subtree, hf_slsk_string, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1394 offset += str_len;
1395 proto_item_set_len(ti_subtree, offset-start_offset);
1396 } else {
1397 break; /* invalid format */
1398 }
1399 }
1400 }
1401 break;
1402
1403 case 60:
1404 if (check_slsk_format(tvb, offset, "isii")) {
1405 /* Client-to-Server & Server-to-Client */
1406 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1407 "Place In Line Response (Code: %02d)", msg_code);
1408 offset += 4;
1409 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1410 offset += str_len;
1411 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1412 offset += 4;
1413 proto_tree_add_item(slsk_tree, hf_slsk_place_in_queue, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1414 offset += 4;
1415 }
1416 break;
1417
1418 case 62:
1419 if (check_slsk_format(tvb, offset, "is")) {
1420 /* Server-to-Client */
1421 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1422 "Room Added (Code: %02d)", msg_code);
1423 offset += 4;
1424 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1425 offset += str_len;
1426 }
1427 break;
1428
1429 case 63:
1430 if (check_slsk_format(tvb, offset, "is")) {
1431 /* Server-to-Client */
1432 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1433 "Room Removed (Code: %02d)", msg_code);
1434 offset += 4;
1435 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1436 offset += str_len;
1437 }
1438 break;
1439
1440 case 64:
1441 if (check_slsk_format(tvb, offset, "i")) {
1442 /* Client-to-Server */
1443 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1444 "Room List Request (Code: %02d)", msg_code);
1445 offset += 4;
1446 }
1447 else if (check_slsk_format(tvb, offset, "ii*")) {
1448 /* Server-to-Client */
1449 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1450 "Room List (Code: %02d)", msg_code);
1451 offset += 4;
1452 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_number_of_rooms, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1453 offset += 4;
1454 if (j > tvb_reported_length_remaining(tvb, offset))
1455 break;
1456 for (i = 0; i < j; i++) {
1457 if (check_slsk_format(tvb, offset, "s*")) {
1458 start_offset = offset;
1459 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 1, ett_slsk_room, &ti_subtree, "Room #%d", i+1);
1460 proto_tree_add_item_ret_length(subtree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1461 offset += str_len;
1462 proto_item_set_len(ti_subtree, offset-start_offset);
1463 } else {
1464 break; /* invalid format */
1465 }
1466 }
1467 if (check_slsk_format(tvb, offset, "i*")) {
1468 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1469 offset += 4;
1470 for (i = 0; i < j; i++) {
1471 if (check_slsk_format(tvb, offset, "i*")) {
1472 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 4, ett_slsk_room, &ti_subtree, "Room #%d", i+1);
1473 proto_tree_add_item(subtree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1474 offset += 4;
1475 } else {
1476 break; /* invalid format */
1477 }
1478 }
1479 }
1480 }
1481 break;
1482
1483 case 65:
1484 if (check_slsk_format(tvb, offset, "isissiii")) {
1485 /* Server-to-Client */
1486 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1487 "Exact File Search (Code: %02d)", msg_code);
1488 offset += 4;
1489 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1490 offset += str_len;
1491 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1492 offset += 4;
1493 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1494 offset += str_len;
1495 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_directory, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1496 offset += str_len;
1497 proto_tree_add_item(slsk_tree, hf_slsk_bytes, tvb, offset, 16, ENC_NA);
1498 offset += 12;
1499 }
1500 else if (check_slsk_format(tvb, offset, "iissiiib")) {
1501 /* Client-to-Server */
1502 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1503 "Exact File Search (Code: %02d)", msg_code);
1504 offset += 4;
1505 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1506 offset += 4;
1507 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_filename, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1508 offset += str_len;
1509 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_directory, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1510 offset += str_len;
1511 proto_tree_add_item(slsk_tree, hf_slsk_bytes, tvb, offset, 13, ENC_NA);
1512 offset += 13;
1513 }
1514 break;
1515
1516 case 66:
1517 if (check_slsk_format(tvb, offset, "is")) {
1518 /* Server-to-Client */
1519 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1520 "Admin Message (Code: %02d)", msg_code);
1521 offset += 4;
1522 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_chat_message, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1523 offset += str_len;
1524 }
1525 break;
1526
1527 case 67:
1528 if (check_slsk_format(tvb, offset, "i")) {
1529 /* Client-to-Server */
1530 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1531 "Global User List Request (Code: %02d)", msg_code);
1532 offset += 4;
1533 }
1534 else if (check_slsk_format(tvb, offset, "isi*")) { /* same as case 14 */
1535 /* Server-to-Client */
1536 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1537 "Global User List (Code: %02d)", msg_code);
1538 offset += 4;
1539 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_room, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1540 offset += str_len;
1541 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1542 offset += 4;
1543 if (j > tvb_reported_length_remaining(tvb, offset))
1544 break;
1545 for (i = 0; i < j; i++) {
1546 if (check_slsk_format(tvb, offset, "s*")) {
1547 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_user, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1548 offset += str_len;
1549 } else {
1550 break; /* invalid format */
1551 }
1552 }
1553 if (check_slsk_format(tvb, offset, "i*")) {
1554 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1555 offset += 4;
1556 for (i = 0; i < j; i++) {
1557 if (check_slsk_format(tvb, offset, "i*")) {
1558 proto_tree_add_item(slsk_tree, hf_slsk_status_code, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1559 offset += 4;
1560 } else {
1561 break; /* invalid format */
1562 }
1563 }
1564 }
1565 if (check_slsk_format(tvb, offset, "i*")) {
1566 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1567 offset += 4;
1568 if (j > tvb_reported_length_remaining(tvb, offset))
1569 break;
1570 for (i = 0; i < j; i++) {
1571 if (check_slsk_format(tvb, offset, "iiiii*")) {
1572 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 20, ett_slsk_user, NULL, "User #%d", i+1);
1573 proto_tree_add_item(subtree, hf_slsk_average_speed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1574 offset += 4;
1575 proto_tree_add_item(subtree, hf_slsk_download_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1576 offset += 4;
1577 proto_tree_add_item(subtree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1578 offset += 4;
1579 proto_tree_add_item(subtree, hf_slsk_files, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1580 offset += 4;
1581 proto_tree_add_item(subtree, hf_slsk_directories, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1582 offset += 4;
1583 } else {
1584 break; /* invalid format */
1585 }
1586 }
1587 }
1588 if (check_slsk_format(tvb, offset, "i*")) {
1589 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_slotsfull_records, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1590 offset += 4;
1591 if (j > tvb_reported_length_remaining(tvb, offset))
1592 break;
1593 for (i = 0; i < j; i++) {
1594 if (check_slsk_format(tvb, offset, "i*")) {
1595 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 4, ett_slsk_user, NULL, "User #%d", i+1);
1596 proto_tree_add_item(subtree, hf_slsk_slotsfull, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1597 offset += 4;
1598 } else {
1599 break; /* invalid format */
1600 }
1601 }
1602 }
1603 }
1604 break;
1605
1606 case 68:
1607 if (check_slsk_format(tvb, offset, "isiiiis")) {
1608 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1609 "Tunneled Message (Code: %02d)", msg_code);
1610 offset += 4;
1611 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1612 offset += str_len;
1613 proto_tree_add_item(slsk_tree, hf_slsk_code, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1614 offset += 4;
1615 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1616 offset += 4;
1617 proto_tree_add_item(slsk_tree, hf_slsk_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1618 offset += 4;
1619 proto_tree_add_item(slsk_tree, hf_slsk_port, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1620 offset += 4;
1621 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_chat_message, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1622 offset += str_len;
1623 }
1624 break;
1625
1626 case 69:
1627 if (check_slsk_format(tvb, offset, "i")) {
1628 /* Client-to-Server */
1629 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1630 "Privileged User List Request (Code: %02d)", msg_code);
1631 offset += 4;
1632 }
1633 else if (check_slsk_format(tvb, offset, "ii*")) {
1634 /* Server-to-Client */
1635 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1636 "Privileged User List (Code: %02d)", msg_code);
1637 offset += 4;
1638 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_number_of_priv_users, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1639 offset += 4;
1640 if (j > tvb_reported_length_remaining(tvb, offset))
1641 break;
1642 for (i = 0; i < j; i++) {
1643 if (check_slsk_format(tvb, offset, "s*")) {
1644 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_user, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1645 offset += str_len;
1646 } else {
1647 break; /* invalid format */
1648 }
1649 }
1650 }
1651 break;
1652
1653 case 71:
1654 if (check_slsk_format(tvb, offset, "ib")) {
1655 /* Client-to-Server */
1656 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1657 "Get Parent List (Code: %02d)", msg_code);
1658 offset += 4;
1659 proto_tree_add_item(slsk_tree, hf_slsk_byte, tvb, offset, 1, ENC_NA);
1660 offset += 1;
1661 }
1662 break;
1663
1664 case 73:
1665 if (check_slsk_format(tvb, offset, "ii")) {
1666 /* Client-to-Server */
1667 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1668 "Type 73 (Code: %02d)", msg_code);
1669 offset += 4;
1670 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1671 offset += 4;
1672 }
1673 break;
1674
1675 case 83:
1676 if (check_slsk_format(tvb, offset, "ii")) {
1677 /* Server-to-Client */
1678 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1679 "Parent Min Speed (Code: %02d)", msg_code);
1680 offset += 4;
1681 proto_tree_add_item(slsk_tree, hf_slsk_parent_min_speed, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1682 offset += 4;
1683 }
1684 break;
1685
1686 case 84:
1687 if (check_slsk_format(tvb, offset, "ii")) {
1688 /* Server-to-Client */
1689 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1690 "Parent Speed Connection Ratio (Code: %02d)", msg_code);
1691 offset += 4;
1692 proto_tree_add_item(slsk_tree, hf_slsk_parent_speed_connection_ratio, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1693 offset += 4;
1694 }
1695 break;
1696
1697 case 86:
1698 if (check_slsk_format(tvb, offset, "ii")) {
1699 /* Server-to-Client */
1700 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1701 "Parent Inactivity Before Disconnect (Code: %02d)", msg_code);
1702 offset += 4;
1703 proto_tree_add_item(slsk_tree, hf_slsk_seconds_parent_inactivity_before_disconnect, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1704 offset += 4;
1705 }
1706 break;
1707
1708 case 87:
1709 if (check_slsk_format(tvb, offset, "ii")) {
1710 /* Server-to-Client */
1711 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1712 "Server Inactivity Before Disconnect (Code: %02d)", msg_code);
1713 offset += 4;
1714 proto_tree_add_item(slsk_tree, hf_slsk_seconds_server_inactivity_before_disconnect, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1715 offset += 4;
1716 }
1717 break;
1718
1719 case 88:
1720 if (check_slsk_format(tvb, offset, "ii")) {
1721 /* Server-to-Client */
1722 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1723 "Nodes In Cache Before Disconnect (Code: %02d)", msg_code);
1724 offset += 4;
1725 proto_tree_add_item(slsk_tree, hf_slsk_nodes_in_cache_before_disconnect, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1726 offset += 4;
1727 }
1728 break;
1729
1730 case 90:
1731 if (check_slsk_format(tvb, offset, "ii")) {
1732 /* Server-to-Client */
1733 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1734 "Seconds Before Ping Children (Code: %02d)", msg_code);
1735 offset += 4;
1736 proto_tree_add_item(slsk_tree, hf_slsk_seconds_before_ping_children, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1737 offset += 4;
1738 }
1739 break;
1740
1741 case 91:
1742 if (check_slsk_format(tvb, offset, "is")) {
1743 /* Server-to-Client */
1744 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1745 "Add To Privileged (Code: %02d)", msg_code);
1746 offset += 4;
1747 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1748 offset += str_len;
1749 }
1750 break;
1751
1752 case 92:
1753 if (check_slsk_format(tvb, offset, "i")) {
1754 /* Client-to-Server */
1755 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1756 "Check Privileges (Code: %02d)", msg_code);
1757 offset += 4;
1758 }
1759 else if (check_slsk_format(tvb, offset, "ii")) {
1760 /* Server-to-Client */
1761 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1762 "Check Privileges Reply (Code: %02d)", msg_code);
1763 offset += 4;
1764 proto_tree_add_item(slsk_tree, hf_slsk_number_of_days, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1765 offset += 4;
1766 }
1767 break;
1768
1769 case 93:
1770 if (check_slsk_format(tvb, offset, "ibisis")) {
1771 /* Server-to-Client */
1772 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1773 "Embedded Message (Code: %02d)", msg_code);
1774 offset += 4;
1775 if ( tvb_get_guint8(tvb, offset) == 3 ){
1776 /* Client-to-Client */
1777 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_embedded_message_type, tvb, offset, 1, msg_code,
1778 "Distributed Search (Byte: %d)", 3);
1779 offset += 1;
1780 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1781 offset += 4;
1782 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1783 offset += str_len;
1784 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1785 offset += 4;
1786 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_search_text, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1787 offset += str_len;
1788 }
1789 }
1790 break;
1791
1792 case 100:
1793 if (check_slsk_format(tvb, offset, "ib")) {
1794 /* Client-to-Server */
1795 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1796 "Become Parent (Code: %02d)", msg_code);
1797 offset += 4;
1798 proto_tree_add_item(slsk_tree, hf_slsk_byte, tvb, offset, 1, ENC_NA);
1799 offset += 1;
1800 }
1801 break;
1802
1803 case 102:
1804 if (check_slsk_format(tvb, offset, "ii*")) {
1805 /* Server-to-Client */
1806 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1807 "Random Parent Addresses (Code: %02d)", msg_code);
1808 offset += 4;
1809 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_parent_address, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1810 offset += 4;
1811 if (j > tvb_reported_length_remaining(tvb, offset))
1812 break;
1813 for (i = 0; i < j; i++) {
1814 if (check_slsk_format(tvb, offset, "sii*")) {
1815
1816 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_user, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1817 offset += str_len;
1818 proto_tree_add_item(slsk_tree, hf_slsk_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
1819 offset += 4;
1820 proto_tree_add_item(slsk_tree, hf_slsk_port, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1821 offset += 4;
1822 } else {
1823 break; /* invalid format */
1824 }
1825 }
1826 }
1827 break;
1828
1829 case 103:
1830 if (check_slsk_format(tvb, offset, "iis")) {
1831 /* Server-to-Client */
1832 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1833 "Send Wishlist Entry (Code: %02d)", msg_code);
1834 offset += 4;
1835 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1836 offset += 4;
1837 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_search_text, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1838 offset += str_len;
1839 }
1840 break;
1841
1842 case 104:
1843 if (check_slsk_format(tvb, offset, "ii")) {
1844 /* Server-to-Client */
1845 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1846 "Type 104 (Code: %02d)", msg_code);
1847 offset += 4;
1848 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1849 offset += 4;
1850 }
1851 break;
1852
1853 case 110:
1854 if (check_slsk_format(tvb, offset, "i")) {
1855 /* Client-to-Server */
1856 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1857 "Get Similar Users (Code: %02d)", msg_code);
1858 offset += 4;
1859 }
1860 else if (check_slsk_format(tvb, offset, "ii*")) {
1861 /* Server-to-Client */
1862 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1863 "Get Similar Users Reply (Code: %02d)", msg_code);
1864 offset += 4;
1865 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1866 offset += 4;
1867 if (j > tvb_reported_length_remaining(tvb, offset))
1868 break;
1869 for (i = 0; i < j; i++) {
1870 if (check_slsk_format(tvb, offset, "si*")) {
1871 start_offset = offset;
1872 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 4, ett_slsk_user, &ti_subtree, "User #%d", i+1);
1873 proto_tree_add_item_ret_length(subtree, hf_slsk_user, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1874 offset += str_len;
1875 proto_tree_add_item(subtree, hf_slsk_same_recommendation, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1876 offset += 4;
1877 proto_item_set_len(ti_subtree, offset-start_offset);
1878 } else {
1879 break; /* invalid format */
1880 }
1881 }
1882 }
1883 break;
1884
1885 case 111:
1886 if (check_slsk_format(tvb, offset, "is")) {
1887 /* Client-to-Server */
1888 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1889 "Get Recommendations for Item (Code: %02d)", msg_code);
1890 offset += 4;
1891 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1892 offset += str_len;
1893 }
1894 else if (check_slsk_format(tvb, offset, "isi*")) {
1895 /* Server-to-Client */
1896 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1897 "Get Recommendations for Item Reply (Code: %02d)", msg_code);
1898 offset += 4;
1899 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1900 offset += str_len;
1901 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_recommendations, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1902 offset += 4;
1903 if (j > tvb_reported_length_remaining(tvb, offset))
1904 break;
1905 for (i = 0; i < j; i++) {
1906 if (check_slsk_format(tvb, offset, "si*")) {
1907 start_offset = offset;
1908 subtree = proto_tree_add_subtree_format(slsk_tree, tvb, offset, 1, ett_slsk_recommendation, &ti_subtree, "Recommendation #%d", i+1);
1909 proto_tree_add_item_ret_length(subtree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1910 offset += str_len;
1911 proto_tree_add_item(subtree, hf_slsk_ranking, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1912 offset += 4;
1913 proto_item_set_len(ti_subtree, offset-start_offset);
1914 } else {
1915 break; /* invalid format */
1916 }
1917 }
1918 }
1919 break;
1920
1921 case 112:
1922 if (check_slsk_format(tvb, offset, "is")) {
1923 /* Client-to-Server */
1924 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1925 "Get Similar Users for Item (Code: %02d)", msg_code);
1926 offset += 4;
1927 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1928 offset += str_len;
1929 }
1930 else if (check_slsk_format(tvb, offset, "isi*")) {
1931 /* Server-to-Client */
1932 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1933 "Get Similar Users for Item Reply (Code: %02d)", msg_code);
1934 offset += 4;
1935 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_recommendation, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1936 offset += str_len;
1937 proto_tree_add_item_ret_int(slsk_tree, hf_slsk_num_recommendations, tvb, offset, 4, ENC_LITTLE_ENDIAN, &j);
1938 offset += 4;
1939 if (j > tvb_reported_length_remaining(tvb, offset))
1940 break;
1941 for (i = 0; i < j; i++) {
1942 if (check_slsk_format(tvb, offset, "s*")) {
1943 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1944 offset += str_len;
1945 } else {
1946 break; /* invalid format */
1947 }
1948 }
1949 }
1950 break;
1951
1952 case 1001:
1953 if (check_slsk_format(tvb, offset, "iis")) {
1954 /* Client-to-Server */
1955 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1956 "Can't Connect To Peer (Code: %02d)", msg_code);
1957 offset += 4;
1958 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1959 offset += 4;
1960 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1961 offset += str_len;
1962 }
1963 else if (check_slsk_format(tvb, offset, "ii")) {
1964 /* Server-to-Client */
1965 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1966 "Can't Connect To Peer (Code: %02d)", msg_code);
1967 offset += 4;
1968 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1969 offset += 4;
1970 }
1971 break;
1972
1973 default:
1974 if (check_slsk_format(tvb, offset, "bisis")) {
1975 if ( tvb_get_guint8(tvb, offset) == 3 ){
1976 /* Client-to-Client */
1977 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
1978 "Distributed Search (Byte: %d)", 3);
1979 offset += 1;
1980 proto_tree_add_item(slsk_tree, hf_slsk_integer, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1981 offset += 4;
1982 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1983 offset += str_len;
1984 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1985 offset += 4;
1986 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_search_text, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1987 offset += str_len;
1988 }
1989 }
1990 else if (check_slsk_format(tvb, offset, "bssi")) {
1991 if ( tvb_get_guint8(tvb, offset) == 1 ){
1992 /* Client-to-Client */
1993 guint32 len;
1994
1995 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
1996 "Peer Init (Byte: %d)", 1);
1997 offset += 1;
1998 proto_tree_add_item_ret_length(slsk_tree, hf_slsk_username, tvb, offset, 4, ENC_ASCII|ENC_LITTLE_ENDIAN, &str_len);
1999 offset += str_len;
2000 len = tvb_get_letohl(tvb, offset);
2001 str = tvb_get_string_enc(pinfo->pool, tvb, offset+4, len, ENC_ASCII);
2002 proto_tree_add_string_format_value(slsk_tree, hf_slsk_connection_type, tvb, offset, 4+len, str,
2003 "%s (Char: %s)", connection_type(str),
2004 format_text(pinfo->pool, str, len));
2005 offset += 4+len;
2006 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2007 offset += 4;
2008 }
2009 }
2010 else if (check_slsk_format(tvb, offset, "bi")) {
2011 if ( tvb_get_guint8(tvb, offset) == 0 ){
2012 /* Client-to-Client */
2013 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
2014 "Pierce Fw (Byte: %d)", 0);
2015 offset += 1;
2016 proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2017 offset += 4;
2018 }
2019 }
2020 else {
2021 proto_tree_add_uint_format_value(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2022 "Unknown (Code: %02d)", msg_code);
2023 offset += 4;
2024 }
2025 break;
2026
2027 }
2028
2029 if(offset < (int)msg_len){
2030 expert_add_info(pinfo, ti_len, &ei_slsk_unknown_data);
2031 }
2032
2033 return tvb_captured_length(tvb);
2034 }
2035
2036
2037 static int dissect_slsk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2038 {
2039 tcp_dissect_pdus(tvb, pinfo, tree, slsk_desegment, 4, get_slsk_pdu_len, dissect_slsk_pdu, data);
2040 return tvb_captured_length(tvb);
2041 }
2042
2043
2044 /* Register the protocol with Wireshark */
2045
2046 void
2047 proto_register_slsk(void)
2048 {
2049
2050 /* Setup list of header fields */
2051 static hf_register_info hf[] = {
2052 { &hf_slsk_integer,
2053 { "Integer", "slsk.integer",
2054 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2055 { &hf_slsk_string,
2056 { "String", "slsk.string",
2057 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2058 { &hf_slsk_byte,
2059 { "Byte", "slsk.byte",
2060 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2061 { &hf_slsk_message_length,
2062 { "Message Length", "slsk.message.length",
2063 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2064 { &hf_slsk_message_code,
2065 { "Message Type", "slsk.message.code",
2066 FT_UINT32, BASE_DEC, NULL, 0, "Message Code with type string", HFILL } },
2067 { &hf_slsk_embedded_message_type,
2068 { "Embedded Message Type", "slsk.embedded_message.code",
2069 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2070 { &hf_slsk_client_ip,
2071 { "Client IP", "slsk.client.ip",
2072 FT_IPv4, BASE_NONE, NULL, 0, "Client IP Address", HFILL } },
2073 #if 0
2074 { &hf_slsk_server_ip,
2075 { "SoulSeek Server IP", "slsk.server.ip",
2076 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2077 #endif
2078 { &hf_slsk_directory_name,
2079 { "Directory name", "slsk.directory_name",
2080 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2081 { &hf_slsk_username,
2082 { "Username", "slsk.username",
2083 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2084 { &hf_slsk_password,
2085 { "Password", "slsk.password",
2086 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2087 { &hf_slsk_version,
2088 { "Version", "slsk.version",
2089 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2090 { &hf_slsk_login_successful,
2091 { "Login successful", "slsk.login.successful",
2092 FT_UINT8, BASE_DEC, VALS(slsk_yes_no), 0, NULL, HFILL } },
2093 { &hf_slsk_login_message,
2094 { "Login Message", "slsk.login.message",
2095 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2096 { &hf_slsk_port,
2097 { "Port Number", "slsk.port.number",
2098 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2099 { &hf_slsk_ip,
2100 { "IP Address", "slsk.ip.address",
2101 FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL } },
2102 { &hf_slsk_user_exists,
2103 { "User exists", "slsk.user.exists",
2104 FT_UINT8, BASE_DEC, VALS(slsk_yes_no), 0, NULL, HFILL } },
2105 { &hf_slsk_status_code,
2106 { "Status Code", "slsk.status.code",
2107 FT_UINT32, BASE_DEC, VALS(slsk_status_codes), 0, NULL, HFILL } },
2108 { &hf_slsk_room,
2109 { "Room", "slsk.room",
2110 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2111 { &hf_slsk_chat_message,
2112 { "Chat Message", "slsk.chat.message",
2113 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2114 { &hf_slsk_users_in_room,
2115 { "Users in Room", "slsk.room.users",
2116 FT_INT32, BASE_DEC, NULL, 0, "Number of Users in Room", HFILL } },
2117 { &hf_slsk_token,
2118 { "Token", "slsk.token",
2119 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2120 { &hf_slsk_connection_type,
2121 { "Connection Type", "slsk.connection.type",
2122 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2123 { &hf_slsk_chat_message_id,
2124 { "Chat Message ID", "slsk.chat.message.id",
2125 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2126 { &hf_slsk_timestamp,
2127 { "Timestamp", "slsk.timestamp",
2128 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2129 { &hf_slsk_search_text,
2130 { "Search Text", "slsk.search.text",
2131 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2132 { &hf_slsk_folder_count,
2133 { "Folder Count", "slsk.folder.count",
2134 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2135 { &hf_slsk_file_count,
2136 { "File Count", "slsk.file.count",
2137 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2138 { &hf_slsk_average_speed,
2139 { "Average Speed", "slsk.average.speed",
2140 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2141 { &hf_slsk_download_number,
2142 { "Download Number", "slsk.download.number",
2143 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2144 { &hf_slsk_files,
2145 { "Files", "slsk.files",
2146 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2147 { &hf_slsk_directories,
2148 { "Directories", "slsk.directories",
2149 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2150 { &hf_slsk_slotsfull,
2151 { "Slots full", "slsk.slots.full",
2152 FT_UINT32, BASE_DEC, NULL, 0, "Upload Slots Full", HFILL } },
2153 { &hf_slsk_place_in_queue,
2154 { "Place in Queue", "slsk.queue.place",
2155 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2156 { &hf_slsk_number_of_rooms,
2157 { "Number of Rooms", "slsk.room.count",
2158 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2159 { &hf_slsk_filename,
2160 { "Filename", "slsk.filename",
2161 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2162 { &hf_slsk_filename_ext,
2163 { "Filename ext", "slsk.filename_ext",
2164 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2165 { &hf_slsk_directory,
2166 { "Directory", "slsk.directory",
2167 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2168 { &hf_slsk_size,
2169 { "Size", "slsk.size",
2170 FT_UINT32, BASE_DEC, NULL, 0, "File Size", HFILL } },
2171 #if 0
2172 { &hf_slsk_checksum,
2173 { "Checksum", "slsk.checksum",
2174 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2175 #endif
2176 { &hf_slsk_code,
2177 { "Code", "slsk.code",
2178 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2179 { &hf_slsk_number_of_users,
2180 { "Number of Users", "slsk.user.count",
2181 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2182 { &hf_slsk_number_of_days,
2183 { "Number of Days", "slsk.day.count",
2184 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2185 { &hf_slsk_transfer_direction,
2186 { "Transfer Direction", "slsk.transfer.direction",
2187 FT_INT32, BASE_DEC, VALS(slsk_transfer_direction), 0, NULL, HFILL } },
2188 { &hf_slsk_user_description,
2189 { "User Description", "slsk.user.description",
2190 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2191 { &hf_slsk_picture_exists,
2192 { "Picture exists", "slsk.user.picture.exists",
2193 FT_UINT8, BASE_DEC, VALS(slsk_yes_no), 0, "User has a picture", HFILL } },
2194 { &hf_slsk_picture,
2195 { "User Picture", "slsk.user.picture",
2196 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2197 #if 0
2198 { &hf_slsk_user_uploads,
2199 { "User uploads", "slsk.uploads.user",
2200 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2201 #endif
2202 { &hf_slsk_total_uploads,
2203 { "Total uploads allowed", "slsk.uploads.total",
2204 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2205 { &hf_slsk_queued_uploads,
2206 { "Queued uploads", "slsk.uploads.queued",
2207 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2208 { &hf_slsk_slots_available,
2209 { "Upload Slots available", "slsk.uploads.available",
2210 FT_UINT8, BASE_DEC, VALS(slsk_yes_no), 0, NULL, HFILL } },
2211 { &hf_slsk_allowed,
2212 { "Download allowed", "slsk.user.allowed",
2213 FT_UINT8, BASE_DEC, VALS(slsk_yes_no), 0, NULL, HFILL } },
2214 { &hf_slsk_compr_packet,
2215 { "zlib compressed packet", "slsk.compr.packet",
2216 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } },
2217 { &hf_slsk_parent_min_speed,
2218 { "Parent Min Speed", "slsk.parent.min.speed",
2219 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2220 { &hf_slsk_parent_speed_connection_ratio,
2221 { "Parent Speed Connection Ratio", "slsk.parent.speed.connection.ratio",
2222 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2223 { &hf_slsk_seconds_parent_inactivity_before_disconnect,
2224 { "Seconds Parent Inactivity Before Disconnect", "slsk.seconds.parent.inactivity.before.disconnect",
2225 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2226 { &hf_slsk_seconds_server_inactivity_before_disconnect,
2227 { "Seconds Server Inactivity Before Disconnect", "slsk.seconds.server.inactivity.before.disconnect",
2228 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2229 { &hf_slsk_nodes_in_cache_before_disconnect,
2230 { "Nodes In Cache Before Disconnect", "slsk.nodes.in.cache.before.disconnect",
2231 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2232 { &hf_slsk_seconds_before_ping_children,
2233 { "Seconds Before Ping Children", "slsk.seconds.before.ping.children",
2234 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2235 { &hf_slsk_recommendation,
2236 { "Recommendation", "slsk.recommendation",
2237 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2238 { &hf_slsk_user,
2239 { "User", "slsk.user",
2240 FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2241 { &hf_slsk_ranking,
2242 { "Ranking", "slsk.ranking",
2243 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2244 { &hf_slsk_compressed_packet_length,
2245 { "Compressed packet length", "slsk.compressed_packet_length",
2246 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2247 { &hf_slsk_uncompressed_packet_length,
2248 { "Uncompressed packet length", "slsk.uncompressed_packet_length",
2249 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2250 { &hf_slsk_num_directories,
2251 { "Number of directories", "slsk.num_directories",
2252 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2253 { &hf_slsk_upload_speed,
2254 { "Upload speed", "slsk.upload_speed",
2255 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2256 { &hf_slsk_in_queue,
2257 { "In Queue", "slsk.in_queue",
2258 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2259 { &hf_slsk_num_slotsfull_records,
2260 { "Number of Slotsfull Records", "slsk.num_slotsfull_records",
2261 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2262 { &hf_slsk_num_recommendations,
2263 { "Number of Recommendations", "slsk.num_recommendations",
2264 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2265 { &hf_slsk_num_files,
2266 { "Number of Files", "slsk.num_files",
2267 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2268 { &hf_slsk_num_strings,
2269 { "Number of strings", "slsk.num_strings",
2270 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2271 { &hf_slsk_file_code,
2272 { "Code", "slsk.file_code",
2273 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2274 { &hf_slsk_file_size1,
2275 { "Size1", "slsk.file_size1",
2276 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2277 { &hf_slsk_file_size2,
2278 { "Size2", "slsk.file_size2",
2279 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2280 { &hf_slsk_file_num_attributes,
2281 { "Number of attributes", "slsk.file_num_attributes",
2282 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2283 { &hf_slsk_file_attribute_type,
2284 { "File attribute type", "slsk.file_attribute_type",
2285 FT_UINT32, BASE_DEC, VALS(slsk_attr_type), 0, NULL, HFILL } },
2286 { &hf_slsk_file_attribute_value,
2287 { "File attribute value", "slsk.file_attribute_value",
2288 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2289 { &hf_slsk_free_upload_slots,
2290 { "Free upload slots", "slsk.free_upload_slots",
2291 FT_UINT32, BASE_DEC, VALS(slsk_yes_no), 0, NULL, HFILL } },
2292 { &hf_slsk_bytes,
2293 { "Bytes", "slsk.bytes",
2294 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } },
2295 { &hf_slsk_same_recommendation,
2296 { "Same Recommendation", "slsk.same_recommendation",
2297 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2298 { &hf_slsk_number_of_priv_users,
2299 { "Number of Privileged Users", "slsk.priv_user.count",
2300 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2301 { &hf_slsk_num_parent_address,
2302 { "Number of Parent Addresses", "slsk.parent_addr.count",
2303 FT_INT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2304
2305 };
2306
2307 /* Setup protocol subtree array */
2308 static gint *ett[] = {
2309 &ett_slsk,
2310 &ett_slsk_compr_packet,
2311 &ett_slsk_directory,
2312 &ett_slsk_file,
2313 &ett_slsk_file_attribute,
2314 &ett_slsk_user,
2315 &ett_slsk_recommendation,
2316 &ett_slsk_room,
2317 &ett_slsk_string,
2318 };
2319
2320 static ei_register_info ei[] = {
2321 { &ei_slsk_unknown_data, { "slsk.unknown_data", PI_UNDECODED, PI_WARN, "Unknown Data (not interpreted)", EXPFILL }},
2322 { &ei_slsk_zlib_decompression_failed, { "slsk.zlib_decompression_failed", PI_PROTOCOL, PI_WARN, "zlib compressed packet failed to decompress", EXPFILL }},
2323 { &ei_slsk_decompression_failed, { "slsk.decompression_failed", PI_PROTOCOL, PI_WARN, "decompression failed", EXPFILL }},
2324 };
2325
2326 module_t *slsk_module;
2327 expert_module_t* expert_slsk;
2328
2329 /* Registers the protocol name and description */
2330 proto_slsk = proto_register_protocol("SoulSeek Protocol", "SoulSeek", "slsk");
2331
2332 /* Required function calls to register the header fields and subtrees used */
2333 proto_register_field_array(proto_slsk, hf, array_length(hf));
2334 proto_register_subtree_array(ett, array_length(ett));
2335 expert_slsk = expert_register_protocol(proto_slsk);
2336 expert_register_field_array(expert_slsk, ei, array_length(ei));
2337
2338 slsk_module = prefs_register_protocol(proto_slsk, NULL);
2339
2340 /* Registers the options in the menu preferences */
2341 prefs_register_bool_preference(slsk_module, "desegment",
2342 "Reassemble SoulSeek messages spanning multiple TCP segments",
2343 "Whether the SoulSeek dissector should reassemble messages spanning multiple TCP segments."
2344 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2345 &slsk_desegment);
2346 #ifdef HAVE_ZLIB
2347 prefs_register_bool_preference(slsk_module, "decompress",
2348 "Decompress zlib compressed packets inside SoulSeek messages",
2349 "Whether the SoulSeek dissector should decompress all zlib compressed packets inside messages",
2350 &slsk_decompress);
2351 #endif
2352
2353 }
2354
2355
2356 void
2357 proto_reg_handoff_slsk(void)
2358 {
2359 dissector_handle_t slsk_handle;
2360
2361 slsk_handle = create_dissector_handle(dissect_slsk, proto_slsk);
2362 dissector_add_uint_range_with_preference("tcp.port", SLSK_TCP_PORT_RANGE, slsk_handle);
2363 }
2364
2365 /*
2366 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2367 *
2368 * Local Variables:
2369 * c-basic-offset: 2
2370 * tab-width: 8
2371 * indent-tabs-mode: nil
2372 * End:
2373 *
2374 * ex: set shiftwidth=2 tabstop=8 expandtab:
2375 * :indentSize=2:tabSize=8:noTabs=true:
2376 */
2377