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