Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-bt-tracker.c
blob2c5d85719adea4934713f3187792b1a43d6b7790
1 /* packet-bt-tracker.c
2 * Routines for BitTorrent Tracker over UDP dissection
3 * Copyright 2023, Ivan Nardi <nardi.ivan@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1999 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/conversation.h>
16 #include <epan/to_str.h>
17 #include <epan/prefs.h>
18 #include <epan/unit_strings.h>
20 void proto_register_bt_tracker(void);
21 void proto_reg_handoff_bt_tracker(void);
23 /* Specifications:
24 * https://www.bittorrent.org/beps/bep_0015.html BEP 15 UDP Tracker Protocol for BitTorrent
25 * https://www.bittorrent.org/beps/bep_0041.html BEP 41 UDP Tracker Protocol Extensions
28 enum {
29 ACTION_CONNECT = 0,
30 ACTION_ANNOUNCE = 1,
31 ACTION_SCRAPE = 2,
32 ACTION_ERROR = 3,
35 enum {
36 MSG_TYPE_CONNECT_REQUEST,
37 MSG_TYPE_CONNECT_RESPONSE,
38 MSG_TYPE_ANNOUNCE_REQUEST,
39 MSG_TYPE_ANNOUNCE_RESPONSE,
40 MSG_TYPE_SCRAPE_REQUEST,
41 MSG_TYPE_SCRAPE_RESPONSE,
42 MSG_TYPE_ERROR_RESPONSE,
44 MSG_TYPE_UNKNOWN,
47 static const value_string bt_tracker_msg_type_vals[] = {
48 { MSG_TYPE_CONNECT_REQUEST, "Connection Request" },
49 { MSG_TYPE_CONNECT_RESPONSE, "Connection Response" },
50 { MSG_TYPE_ANNOUNCE_REQUEST, "Announce Request" },
51 { MSG_TYPE_ANNOUNCE_RESPONSE, "Announce Response" },
52 { MSG_TYPE_SCRAPE_REQUEST, "Scrape Request" },
53 { MSG_TYPE_SCRAPE_RESPONSE, "Scrape Response" },
54 { MSG_TYPE_ERROR_RESPONSE, "Error Response" },
55 { 0, NULL }
58 static const value_string bt_tracker_event_vals[] = {
59 { 0, "None" },
60 { 1, "Completed" },
61 { 2, "Started" },
62 { 3, "Stopped" },
63 { 0, NULL }
66 static const value_string bt_tracker_action_vals[] = {
67 { ACTION_CONNECT, "Connect" },
68 { ACTION_ANNOUNCE, "Announce" },
69 { ACTION_SCRAPE, "Scrape" },
70 { ACTION_ERROR, "Error" },
71 { 0, NULL }
74 enum {
75 EXT_END_OF_OPTIONS = 0,
76 EXT_NOP = 1,
77 EXT_URLDATA = 2,
78 EXT_MAX
81 static const value_string bt_tracker_extension_type_vals[] = {
82 { EXT_END_OF_OPTIONS, "End of Options" },
83 { EXT_NOP, "NOP" },
84 { EXT_URLDATA, "URL Data" },
85 { 0, NULL }
88 static int proto_bt_tracker;
89 static dissector_handle_t bt_tracker_handle;
91 static int hf_bt_tracker_msg_type;
92 static int hf_bt_tracker_protocol_id;
93 static int hf_bt_tracker_action;
94 static int hf_bt_tracker_transaction_id;
95 static int hf_bt_tracker_connection_id;
96 static int hf_bt_tracker_info_hash;
97 static int hf_bt_tracker_peer_id;
98 static int hf_bt_tracker_downloaded;
99 static int hf_bt_tracker_left;
100 static int hf_bt_tracker_uploaded;
101 static int hf_bt_tracker_event;
102 static int hf_bt_tracker_ip_address;
103 static int hf_bt_tracker_key;
104 static int hf_bt_tracker_num_want;
105 static int hf_bt_tracker_port;
106 static int hf_bt_tracker_interval;
107 static int hf_bt_tracker_leechers;
108 static int hf_bt_tracker_seeders;
109 static int hf_bt_tracker_trackers;
110 static int hf_bt_tracker_tracker;
111 static int hf_bt_tracker_tr_ip;
112 static int hf_bt_tracker_tr_ip6;
113 static int hf_bt_tracker_tr_port;
114 static int hf_bt_tracker_completed;
115 static int hf_bt_tracker_error_msg;
116 static int hf_bt_tracker_extension;
117 static int hf_bt_tracker_extension_type;
118 static int hf_bt_tracker_extension_len;
119 static int hf_bt_tracker_extension_unknown;
120 static int hf_bt_tracker_extension_urldata;
122 static int ett_bt_tracker;
123 static int ett_bt_tracker_trackers;
124 static int ett_bt_tracker_extension;
126 #define MAGIC_CONSTANT 0x41727101980
128 static unsigned
129 get_message_type(tvbuff_t *tvb)
131 if (tvb_get_ntoh64(tvb, 0) == MAGIC_CONSTANT &&
132 tvb_get_ntohl(tvb, 8) == ACTION_CONNECT)
133 return MSG_TYPE_CONNECT_REQUEST;
134 if (tvb_get_ntohl(tvb, 0) == ACTION_CONNECT)
135 return MSG_TYPE_CONNECT_RESPONSE;
136 if (tvb_get_ntohl(tvb, 8) == ACTION_ANNOUNCE)
137 return MSG_TYPE_ANNOUNCE_REQUEST;
138 if (tvb_get_ntohl(tvb, 0) == ACTION_ANNOUNCE)
139 return MSG_TYPE_ANNOUNCE_RESPONSE;
140 if (tvb_get_ntohl(tvb, 8) == ACTION_SCRAPE)
141 return MSG_TYPE_SCRAPE_REQUEST;
142 if (tvb_get_ntohl(tvb, 0) == ACTION_SCRAPE)
143 return MSG_TYPE_SCRAPE_RESPONSE;
144 if (tvb_get_ntohl(tvb, 0) == ACTION_ERROR)
145 return MSG_TYPE_ERROR_RESPONSE;
147 return MSG_TYPE_UNKNOWN;
150 static bool
151 is_ipv4_format(packet_info *pinfo)
153 wmem_list_frame_t *cur;
154 int cur_proto;
155 const char *cur_name;
157 /* Format of Announce Response message depends on IPv4 vs IPv6
158 "Which format is used is determined by the address family of the underlying UDP packet.
159 I.e. packets from a v4 address use the v4 format, those from a v6 address use the v6 format."
160 Check the innermost IP layer, to take into account tunnels
163 cur = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
164 while (cur != NULL) {
165 cur_proto = (int)GPOINTER_TO_UINT(wmem_list_frame_data(cur));
166 cur_name = proto_get_protocol_filter_name(cur_proto);
167 if (!strcmp(cur_name, "ip"))
168 return true;
169 if (!strcmp(cur_name, "ipv6"))
170 return false;
171 cur = wmem_list_frame_prev(cur);
173 return true;
175 static int
176 dissect_bt_tracker_extension(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset)
178 proto_item *ti;
179 proto_tree *ext_tree;
180 uint8_t extension_type;
181 uint32_t extension_length;
182 int32_t tot_length;
184 while (offset < (int)tvb_reported_length(tvb)) {
185 extension_type = tvb_get_uint8(tvb, offset);
187 tot_length = 1;
188 if (extension_type == EXT_URLDATA) {
189 tot_length += 1 + tvb_get_uint8(tvb, offset + 1);
190 } else if (extension_type >= EXT_MAX) {
191 tot_length = -1;
194 ti = proto_tree_add_none_format(tree, hf_bt_tracker_extension, tvb, offset, tot_length, "Extension: %s", val_to_str_const(extension_type, bt_tracker_extension_type_vals, "Unknown"));
195 ext_tree = proto_item_add_subtree(ti, ett_bt_tracker_extension);
196 proto_tree_add_item(ext_tree, hf_bt_tracker_extension_type, tvb, offset, 1, ENC_BIG_ENDIAN);
197 offset += 1;
199 switch (extension_type) {
200 case EXT_END_OF_OPTIONS:
201 /* Option parsing continues until either the end of the packet is reached, or an EndOfOptions option is encountered, whichever happens first */
202 return offset;
203 case EXT_NOP:
204 /* A special case option that has a fixed-length of one byte. It is not followed by a length field, or associated data.
205 A NOP has no affect on option parsing. It is used only if optional padding is necessary in the future. */
206 break;
207 case EXT_URLDATA:
208 proto_tree_add_item_ret_uint(ext_tree, hf_bt_tracker_extension_len, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_length);
209 offset += 1;
210 proto_tree_add_item(ext_tree, hf_bt_tracker_extension_urldata, tvb, offset, extension_length, ENC_ASCII);
211 offset += extension_length;
212 break;
213 default:
214 proto_tree_add_item(ext_tree, hf_bt_tracker_extension_unknown, tvb, offset, -1, ENC_NA);
215 return offset;
218 return offset;
221 static int
222 dissect_bt_tracker_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned msg_type)
224 unsigned node_index = 0;
225 int stride_length;
226 proto_item *ti;
227 proto_tree *sub_tree;
228 bool is_ipv6;
230 ti = proto_tree_add_uint(tree, hf_bt_tracker_msg_type, tvb, 0, 0, msg_type);
231 proto_item_set_generated(ti);
233 switch (msg_type) {
234 case MSG_TYPE_CONNECT_REQUEST:
235 proto_tree_add_item(tree, hf_bt_tracker_protocol_id, tvb, offset, 8, ENC_BIG_ENDIAN);
236 offset += 8;
237 proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN);
238 offset += 4;
239 proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
240 offset += 4;
241 break;
243 case MSG_TYPE_CONNECT_RESPONSE:
244 proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN);
245 offset += 4;
246 proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
247 offset += 4;
248 proto_tree_add_item(tree, hf_bt_tracker_connection_id, tvb, offset, 8, ENC_BIG_ENDIAN);
249 offset += 8;
250 break;
252 case MSG_TYPE_ANNOUNCE_REQUEST:
253 proto_tree_add_item(tree, hf_bt_tracker_connection_id, tvb, offset, 8, ENC_BIG_ENDIAN);
254 offset += 8;
255 proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN);
256 offset += 4;
257 proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
258 offset += 4;
259 proto_tree_add_item(tree, hf_bt_tracker_info_hash, tvb, offset, 20, ENC_NA);
260 offset += 20;
261 proto_tree_add_item(tree, hf_bt_tracker_peer_id, tvb, offset, 20, ENC_NA);
262 offset += 20;
263 proto_tree_add_item(tree, hf_bt_tracker_downloaded, tvb, offset, 8, ENC_BIG_ENDIAN);
264 offset += 8;
265 proto_tree_add_item(tree, hf_bt_tracker_left, tvb, offset, 8, ENC_BIG_ENDIAN);
266 offset += 8;
267 proto_tree_add_item(tree, hf_bt_tracker_uploaded, tvb, offset, 8, ENC_BIG_ENDIAN);
268 offset += 8;
269 proto_tree_add_item(tree, hf_bt_tracker_event, tvb, offset, 4, ENC_BIG_ENDIAN);
270 offset += 4;
271 proto_tree_add_item(tree, hf_bt_tracker_ip_address, tvb, offset, 4, ENC_BIG_ENDIAN);
272 offset += 4;
273 proto_tree_add_item(tree, hf_bt_tracker_key, tvb, offset, 4, ENC_BIG_ENDIAN);
274 offset += 4;
275 proto_tree_add_item(tree, hf_bt_tracker_num_want, tvb, offset, 4, ENC_BIG_ENDIAN);
276 offset += 4;
277 proto_tree_add_item(tree, hf_bt_tracker_port, tvb, offset, 2, ENC_BIG_ENDIAN);
278 offset += 2;
280 offset = dissect_bt_tracker_extension(tvb, pinfo, tree, offset);
281 break;
283 case MSG_TYPE_ANNOUNCE_RESPONSE:
284 proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN);
285 offset += 4;
286 proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
287 offset += 4;
288 proto_tree_add_item(tree, hf_bt_tracker_interval, tvb, offset, 4, ENC_BIG_ENDIAN);
289 offset += 4;
290 proto_tree_add_item(tree, hf_bt_tracker_leechers, tvb, offset, 4, ENC_BIG_ENDIAN);
291 offset += 4;
292 proto_tree_add_item(tree, hf_bt_tracker_seeders, tvb, offset, 4, ENC_BIG_ENDIAN);
293 offset += 4;
295 if (tvb_captured_length_remaining(tvb, offset) > 0)
297 stride_length = 6;
298 is_ipv6 = !is_ipv4_format(pinfo);
299 if (is_ipv6)
300 stride_length = 18;
301 ti = proto_tree_add_item(tree, hf_bt_tracker_trackers, tvb, offset, -1, ENC_NA);
302 sub_tree = proto_item_add_subtree(ti, ett_bt_tracker_trackers);
304 while (tvb_captured_length_remaining(tvb, offset) >= stride_length)
306 proto_item *node_ti;
307 proto_tree *node_tree;
309 node_index += 1;
311 node_ti = proto_tree_add_item(sub_tree, hf_bt_tracker_tracker, tvb, offset, stride_length, ENC_NA);
312 proto_item_append_text(node_ti, " %d", node_index);
313 node_tree = proto_item_add_subtree(node_ti, ett_bt_tracker_trackers);
315 if (is_ipv6)
317 proto_tree_add_item( node_tree, hf_bt_tracker_tr_ip6, tvb, offset, 16, ENC_NA);
318 proto_item_append_text(node_ti, ", IPv6/Port: [%s]", tvb_ip6_to_str(pinfo->pool, tvb, offset));
320 proto_tree_add_item( node_tree, hf_bt_tracker_tr_port, tvb, offset + 16, 2, ENC_BIG_ENDIAN);
321 proto_item_append_text(node_ti, ":%u", tvb_get_ntohs( tvb, offset + 16 ));
323 else
325 proto_tree_add_item( node_tree, hf_bt_tracker_tr_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
326 proto_item_append_text(node_ti, ", IPv4/Port: %s", tvb_ip_to_str(pinfo->pool, tvb, offset));
328 proto_tree_add_item( node_tree, hf_bt_tracker_tr_port, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
329 proto_item_append_text(node_ti, ":%u", tvb_get_ntohs( tvb, offset + 4 ));
332 offset += stride_length;
334 proto_item_set_text(ti, "Trackers: %d trackers", node_index);
335 col_append_fstr(pinfo->cinfo, COL_INFO, ": %d trackers", node_index);
338 break;
340 case MSG_TYPE_SCRAPE_REQUEST:
341 proto_tree_add_item(tree, hf_bt_tracker_connection_id, tvb, offset, 8, ENC_BIG_ENDIAN);
342 offset += 8;
343 proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN);
344 offset += 4;
345 proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
346 offset += 4;
348 while (tvb_captured_length_remaining(tvb, offset) >= 20)
350 proto_tree_add_item(tree, hf_bt_tracker_info_hash, tvb, offset, 20, ENC_NA);
351 offset += 20;
353 break;
355 case MSG_TYPE_SCRAPE_RESPONSE:
356 proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN);
357 offset += 4;
358 proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
359 offset += 4;
361 while (tvb_captured_length_remaining(tvb, offset) >= 12)
363 proto_tree_add_item(tree, hf_bt_tracker_seeders, tvb, offset, 4, ENC_BIG_ENDIAN);
364 offset += 4;
365 proto_tree_add_item(tree, hf_bt_tracker_completed, tvb, offset, 4, ENC_BIG_ENDIAN);
366 offset += 4;
367 proto_tree_add_item(tree, hf_bt_tracker_leechers, tvb, offset, 4, ENC_BIG_ENDIAN);
368 offset += 4;
371 break;
373 case MSG_TYPE_ERROR_RESPONSE:
374 proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN);
375 offset += 4;
376 proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
377 offset += 4;
378 proto_tree_add_item(tree, hf_bt_tracker_error_msg, tvb, offset, -1, ENC_ASCII);
379 offset = tvb_captured_length(tvb);
380 break;
384 return offset;
387 static int
388 dissect_bt_tracker(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
390 unsigned msg_type;
391 proto_item *ti;
392 proto_tree *sub_tree;
394 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BT-Tracker");
395 col_clear(pinfo->cinfo, COL_INFO);
397 msg_type = get_message_type(tvb);
399 col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(msg_type, bt_tracker_msg_type_vals, " Unknown Msg Type"));
401 ti = proto_tree_add_item(tree, proto_bt_tracker, tvb, 0, -1, ENC_NA);
402 sub_tree = proto_item_add_subtree(ti, ett_bt_tracker);
404 return dissect_bt_tracker_msg(tvb, pinfo, sub_tree, 0, msg_type);
408 static bool
409 dissect_bt_tracker_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
411 conversation_t *conversation;
413 /* Look for a Connect Request */
414 if (tvb_captured_length_remaining(tvb, 0) < 16)
415 return false;
416 if (tvb_get_ntoh64(tvb, 0) != MAGIC_CONSTANT)
417 return false;
418 if (tvb_get_ntohl(tvb, 8) != ACTION_CONNECT)
419 return false;
421 conversation = find_or_create_conversation(pinfo);
422 conversation_set_dissector_from_frame_number(conversation, pinfo->num, bt_tracker_handle);
424 dissect_bt_tracker(tvb, pinfo, tree, data);
425 return true;
428 void
429 proto_register_bt_tracker(void)
431 static hf_register_info hf[] = {
432 { &hf_bt_tracker_protocol_id,
433 { "Protocol", "bt-tracker.proto_id",
434 FT_UINT64, BASE_HEX, NULL, 0x00,
435 NULL, HFILL }
437 { &hf_bt_tracker_action,
438 { "Action", "bt-tracker.action",
439 FT_UINT32, BASE_DEC, VALS(bt_tracker_action_vals), 0x0,
440 NULL, HFILL }
442 { &hf_bt_tracker_transaction_id,
443 { "Transaction Id", "bt-tracker.transaction_id",
444 FT_UINT32, BASE_DEC, NULL, 0x00,
445 NULL, HFILL }
447 { &hf_bt_tracker_connection_id,
448 { "Connection Id", "bt-tracker.connection_id",
449 FT_UINT64, BASE_DEC, NULL, 0x00,
450 NULL, HFILL }
452 { &hf_bt_tracker_msg_type,
453 { "Message Type", "bt-tracker.msg_type",
454 FT_UINT8, BASE_DEC, VALS(bt_tracker_msg_type_vals), 0x0,
455 NULL, HFILL }
457 { &hf_bt_tracker_info_hash,
458 { "Info Hash", "bt-tracker.info_hash",
459 FT_BYTES, BASE_NONE, NULL, 0x00,
460 NULL, HFILL }
462 { &hf_bt_tracker_peer_id,
463 { "Peer Id", "bt-tracker.peer_id",
464 FT_BYTES, BASE_NONE, NULL, 0x00,
465 NULL, HFILL }
467 { &hf_bt_tracker_downloaded,
468 { "Downloaded", "bt-tracker.downloaded",
469 FT_UINT64, BASE_DEC, NULL, 0x00,
470 NULL, HFILL }
472 { &hf_bt_tracker_left,
473 { "Left", "bt-tracker.left",
474 FT_UINT64, BASE_DEC, NULL, 0x00,
475 NULL, HFILL }
477 { &hf_bt_tracker_uploaded,
478 { "Uploaded", "bt-tracker.uploaded",
479 FT_UINT64, BASE_DEC, NULL, 0x00,
480 NULL, HFILL }
482 { &hf_bt_tracker_event,
483 { "Event", "bt-tracker.event",
484 FT_UINT32, BASE_DEC, VALS(bt_tracker_event_vals), 0x00,
485 NULL, HFILL }
487 { &hf_bt_tracker_ip_address,
488 { "IP Address", "bt-tracker.ip_address",
489 FT_IPv4, BASE_NONE, NULL, 0x00,
490 NULL, HFILL }
492 { &hf_bt_tracker_key,
493 { "Key", "bt-tracker.key",
494 FT_UINT32, BASE_DEC, NULL, 0x00,
495 NULL, HFILL }
497 { &hf_bt_tracker_num_want,
498 { "Num Want", "bt-tracker.num_want",
499 FT_INT32, BASE_DEC, NULL, 0x00,
500 NULL, HFILL }
502 { &hf_bt_tracker_port,
503 { "Port", "bt-tracker.port",
504 FT_UINT16, BASE_DEC, NULL, 0x00,
505 NULL, HFILL }
507 { &hf_bt_tracker_interval,
508 { "Interval", "bt-tracker.interval",
509 FT_INT32, BASE_DEC, NULL, 0x00,
510 NULL, HFILL }
512 { &hf_bt_tracker_leechers,
513 { "Leechers", "bt-tracker.leechers",
514 FT_INT32, BASE_DEC, NULL, 0x00,
515 NULL, HFILL }
517 { &hf_bt_tracker_seeders,
518 { "Seeders", "bt-tracker.seeders",
519 FT_INT32, BASE_DEC, NULL, 0x00,
520 NULL, HFILL }
522 { &hf_bt_tracker_trackers,
523 { "Trackers", "bt-tracker.trackers",
524 FT_NONE, BASE_NONE, NULL, 0x0,
525 NULL, HFILL }
527 { &hf_bt_tracker_tracker,
528 { "Tracker", "bt-tracker.tracker",
529 FT_NONE, BASE_NONE, NULL, 0x0,
530 NULL, HFILL }
532 { &hf_bt_tracker_tr_ip,
533 { "IP", "bt-tracker.tracker.ip",
534 FT_IPv4, BASE_NONE, NULL, 0x00,
535 NULL, HFILL }
537 { &hf_bt_tracker_tr_ip6,
538 { "IPv6", "bt-tracker.tracker.ip6",
539 FT_IPv6, BASE_NONE, NULL, 0x00,
540 NULL, HFILL }
542 { &hf_bt_tracker_tr_port,
543 { "(TCP) Port", "bt-tracker.tracker.port",
544 FT_UINT16, BASE_DEC, NULL, 0x00,
545 NULL, HFILL }
547 { &hf_bt_tracker_completed,
548 { "Completed", "bt-tracker.completed",
549 FT_INT32, BASE_DEC, NULL, 0x00,
550 NULL, HFILL }
552 { &hf_bt_tracker_error_msg,
553 { "Error message", "bt-tracker.error_msg",
554 FT_STRING, BASE_NONE, NULL, 0x00,
555 NULL, HFILL }
557 { &hf_bt_tracker_extension,
558 { "Extension", "bt-tracker.extension",
559 FT_NONE, BASE_NONE, NULL, 0x0,
560 NULL, HFILL }
562 { &hf_bt_tracker_extension_type,
563 { "Extension Type", "bt-tracker.extension_type",
564 FT_UINT8, BASE_HEX, VALS(bt_tracker_extension_type_vals), 0x0,
565 NULL, HFILL }
567 { &hf_bt_tracker_extension_len,
568 { "Extension Length", "bt-tracker.extension_len",
569 FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
570 NULL, HFILL }
572 { &hf_bt_tracker_extension_unknown,
573 { "Extension Unknown", "bt-tracker.extension_unknown",
574 FT_BYTES, BASE_NONE, NULL, 0x0,
575 NULL, HFILL }
577 { &hf_bt_tracker_extension_urldata,
578 { "URL Data", "bt-tracker.extension.urldata",
579 FT_STRING, BASE_NONE, NULL, 0x00,
580 NULL, HFILL }
584 /* Setup protocol subtree array */
585 static int *ett[] = { &ett_bt_tracker, &ett_bt_tracker_trackers, &ett_bt_tracker_extension};
586 module_t *bt_tracker_module;
588 /* Register protocol */
589 proto_bt_tracker = proto_register_protocol ("BitTorrent Tracker", "BT-Tracker", "bt-tracker");
591 bt_tracker_module = prefs_register_protocol(proto_bt_tracker, NULL);
592 prefs_register_obsolete_preference(bt_tracker_module, "enable");
594 proto_register_field_array(proto_bt_tracker, hf, array_length(hf));
595 proto_register_subtree_array(ett, array_length(ett));
598 void
599 proto_reg_handoff_bt_tracker(void)
601 heur_dissector_add("udp", dissect_bt_tracker_heur, "BitTorrent Tracker over UDP", "bt_tracker_udp", proto_bt_tracker, HEURISTIC_ENABLE);
603 bt_tracker_handle = create_dissector_handle(dissect_bt_tracker, proto_bt_tracker);
604 dissector_add_for_decode_as_with_preference("udp.port", bt_tracker_handle);