/src/wireshark/epan/dissectors/packet-bt-tracker.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-bt-tracker.c |
2 | | * Routines for BitTorrent Tracker over UDP dissection |
3 | | * Copyright 2023, Ivan Nardi <nardi.ivan@gmail.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1999 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
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> |
19 | | |
20 | | void proto_register_bt_tracker(void); |
21 | | void proto_reg_handoff_bt_tracker(void); |
22 | | |
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 |
26 | | */ |
27 | | |
28 | | enum { |
29 | | ACTION_CONNECT = 0, |
30 | | ACTION_ANNOUNCE = 1, |
31 | | ACTION_SCRAPE = 2, |
32 | | ACTION_ERROR = 3, |
33 | | }; |
34 | | |
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, |
43 | | |
44 | | MSG_TYPE_UNKNOWN, |
45 | | }; |
46 | | |
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 } |
56 | | }; |
57 | | |
58 | | static const value_string bt_tracker_event_vals[] = { |
59 | | { 0, "None" }, |
60 | | { 1, "Completed" }, |
61 | | { 2, "Started" }, |
62 | | { 3, "Stopped" }, |
63 | | { 0, NULL } |
64 | | }; |
65 | | |
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 } |
72 | | }; |
73 | | |
74 | | enum { |
75 | | EXT_END_OF_OPTIONS = 0, |
76 | | EXT_NOP = 1, |
77 | | EXT_URLDATA = 2, |
78 | | EXT_MAX |
79 | | }; |
80 | | |
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 } |
86 | | }; |
87 | | |
88 | | static int proto_bt_tracker; |
89 | | static dissector_handle_t bt_tracker_handle; |
90 | | |
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; |
121 | | |
122 | | static int ett_bt_tracker; |
123 | | static int ett_bt_tracker_trackers; |
124 | | static int ett_bt_tracker_extension; |
125 | | |
126 | 572 | #define MAGIC_CONSTANT 0x41727101980 |
127 | | |
128 | | static unsigned |
129 | | get_message_type(tvbuff_t *tvb) |
130 | 0 | { |
131 | 0 | if (tvb_get_ntoh64(tvb, 0) == MAGIC_CONSTANT && |
132 | 0 | tvb_get_ntohl(tvb, 8) == ACTION_CONNECT) |
133 | 0 | return MSG_TYPE_CONNECT_REQUEST; |
134 | 0 | if (tvb_get_ntohl(tvb, 0) == ACTION_CONNECT) |
135 | 0 | return MSG_TYPE_CONNECT_RESPONSE; |
136 | 0 | if (tvb_get_ntohl(tvb, 8) == ACTION_ANNOUNCE) |
137 | 0 | return MSG_TYPE_ANNOUNCE_REQUEST; |
138 | 0 | if (tvb_get_ntohl(tvb, 0) == ACTION_ANNOUNCE) |
139 | 0 | return MSG_TYPE_ANNOUNCE_RESPONSE; |
140 | 0 | if (tvb_get_ntohl(tvb, 8) == ACTION_SCRAPE) |
141 | 0 | return MSG_TYPE_SCRAPE_REQUEST; |
142 | 0 | if (tvb_get_ntohl(tvb, 0) == ACTION_SCRAPE) |
143 | 0 | return MSG_TYPE_SCRAPE_RESPONSE; |
144 | 0 | if (tvb_get_ntohl(tvb, 0) == ACTION_ERROR) |
145 | 0 | return MSG_TYPE_ERROR_RESPONSE; |
146 | | |
147 | 0 | return MSG_TYPE_UNKNOWN; |
148 | 0 | } |
149 | | |
150 | | static bool |
151 | | is_ipv4_format(packet_info *pinfo) |
152 | 0 | { |
153 | 0 | wmem_list_frame_t *cur; |
154 | 0 | int cur_proto; |
155 | 0 | const char *cur_name; |
156 | | |
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 |
161 | | */ |
162 | |
|
163 | 0 | cur = wmem_list_frame_prev(wmem_list_tail(pinfo->layers)); |
164 | 0 | while (cur != NULL) { |
165 | 0 | cur_proto = (int)GPOINTER_TO_UINT(wmem_list_frame_data(cur)); |
166 | 0 | cur_name = proto_get_protocol_filter_name(cur_proto); |
167 | 0 | if (!strcmp(cur_name, "ip")) |
168 | 0 | return true; |
169 | 0 | if (!strcmp(cur_name, "ipv6")) |
170 | 0 | return false; |
171 | 0 | cur = wmem_list_frame_prev(cur); |
172 | 0 | } |
173 | 0 | return true; |
174 | 0 | } |
175 | | static int |
176 | | dissect_bt_tracker_extension(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, int offset) |
177 | 0 | { |
178 | 0 | proto_item *ti; |
179 | 0 | proto_tree *ext_tree; |
180 | 0 | uint8_t extension_type; |
181 | 0 | uint32_t extension_length; |
182 | 0 | int32_t tot_length; |
183 | |
|
184 | 0 | while (offset < (int)tvb_reported_length(tvb)) { |
185 | 0 | extension_type = tvb_get_uint8(tvb, offset); |
186 | |
|
187 | 0 | tot_length = 1; |
188 | 0 | if (extension_type == EXT_URLDATA) { |
189 | 0 | tot_length += 1 + tvb_get_uint8(tvb, offset + 1); |
190 | 0 | } else if (extension_type >= EXT_MAX) { |
191 | 0 | tot_length = -1; |
192 | 0 | } |
193 | |
|
194 | 0 | 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 | 0 | ext_tree = proto_item_add_subtree(ti, ett_bt_tracker_extension); |
196 | 0 | proto_tree_add_item(ext_tree, hf_bt_tracker_extension_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
197 | 0 | offset += 1; |
198 | |
|
199 | 0 | switch (extension_type) { |
200 | 0 | 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 | 0 | return offset; |
203 | 0 | 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 | 0 | break; |
207 | 0 | case EXT_URLDATA: |
208 | 0 | proto_tree_add_item_ret_uint(ext_tree, hf_bt_tracker_extension_len, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_length); |
209 | 0 | offset += 1; |
210 | 0 | proto_tree_add_item(ext_tree, hf_bt_tracker_extension_urldata, tvb, offset, extension_length, ENC_ASCII); |
211 | 0 | offset += extension_length; |
212 | 0 | break; |
213 | 0 | default: |
214 | 0 | proto_tree_add_item(ext_tree, hf_bt_tracker_extension_unknown, tvb, offset, -1, ENC_NA); |
215 | 0 | return offset; |
216 | 0 | } |
217 | 0 | } |
218 | 0 | return offset; |
219 | 0 | } |
220 | | |
221 | | static int |
222 | | dissect_bt_tracker_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset, unsigned msg_type) |
223 | 0 | { |
224 | 0 | unsigned node_index = 0; |
225 | 0 | int stride_length; |
226 | 0 | proto_item *ti; |
227 | 0 | proto_tree *sub_tree; |
228 | 0 | bool is_ipv6; |
229 | |
|
230 | 0 | ti = proto_tree_add_uint(tree, hf_bt_tracker_msg_type, tvb, 0, 0, msg_type); |
231 | 0 | proto_item_set_generated(ti); |
232 | |
|
233 | 0 | switch (msg_type) { |
234 | 0 | case MSG_TYPE_CONNECT_REQUEST: |
235 | 0 | proto_tree_add_item(tree, hf_bt_tracker_protocol_id, tvb, offset, 8, ENC_BIG_ENDIAN); |
236 | 0 | offset += 8; |
237 | 0 | proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN); |
238 | 0 | offset += 4; |
239 | 0 | proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
240 | 0 | offset += 4; |
241 | 0 | break; |
242 | | |
243 | 0 | case MSG_TYPE_CONNECT_RESPONSE: |
244 | 0 | proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN); |
245 | 0 | offset += 4; |
246 | 0 | proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
247 | 0 | offset += 4; |
248 | 0 | proto_tree_add_item(tree, hf_bt_tracker_connection_id, tvb, offset, 8, ENC_BIG_ENDIAN); |
249 | 0 | offset += 8; |
250 | 0 | break; |
251 | | |
252 | 0 | case MSG_TYPE_ANNOUNCE_REQUEST: |
253 | 0 | proto_tree_add_item(tree, hf_bt_tracker_connection_id, tvb, offset, 8, ENC_BIG_ENDIAN); |
254 | 0 | offset += 8; |
255 | 0 | proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN); |
256 | 0 | offset += 4; |
257 | 0 | proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
258 | 0 | offset += 4; |
259 | 0 | proto_tree_add_item(tree, hf_bt_tracker_info_hash, tvb, offset, 20, ENC_NA); |
260 | 0 | offset += 20; |
261 | 0 | proto_tree_add_item(tree, hf_bt_tracker_peer_id, tvb, offset, 20, ENC_NA); |
262 | 0 | offset += 20; |
263 | 0 | proto_tree_add_item(tree, hf_bt_tracker_downloaded, tvb, offset, 8, ENC_BIG_ENDIAN); |
264 | 0 | offset += 8; |
265 | 0 | proto_tree_add_item(tree, hf_bt_tracker_left, tvb, offset, 8, ENC_BIG_ENDIAN); |
266 | 0 | offset += 8; |
267 | 0 | proto_tree_add_item(tree, hf_bt_tracker_uploaded, tvb, offset, 8, ENC_BIG_ENDIAN); |
268 | 0 | offset += 8; |
269 | 0 | proto_tree_add_item(tree, hf_bt_tracker_event, tvb, offset, 4, ENC_BIG_ENDIAN); |
270 | 0 | offset += 4; |
271 | 0 | proto_tree_add_item(tree, hf_bt_tracker_ip_address, tvb, offset, 4, ENC_BIG_ENDIAN); |
272 | 0 | offset += 4; |
273 | 0 | proto_tree_add_item(tree, hf_bt_tracker_key, tvb, offset, 4, ENC_BIG_ENDIAN); |
274 | 0 | offset += 4; |
275 | 0 | proto_tree_add_item(tree, hf_bt_tracker_num_want, tvb, offset, 4, ENC_BIG_ENDIAN); |
276 | 0 | offset += 4; |
277 | 0 | proto_tree_add_item(tree, hf_bt_tracker_port, tvb, offset, 2, ENC_BIG_ENDIAN); |
278 | 0 | offset += 2; |
279 | |
|
280 | 0 | offset = dissect_bt_tracker_extension(tvb, pinfo, tree, offset); |
281 | 0 | break; |
282 | | |
283 | 0 | case MSG_TYPE_ANNOUNCE_RESPONSE: |
284 | 0 | proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN); |
285 | 0 | offset += 4; |
286 | 0 | proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
287 | 0 | offset += 4; |
288 | 0 | proto_tree_add_item(tree, hf_bt_tracker_interval, tvb, offset, 4, ENC_BIG_ENDIAN); |
289 | 0 | offset += 4; |
290 | 0 | proto_tree_add_item(tree, hf_bt_tracker_leechers, tvb, offset, 4, ENC_BIG_ENDIAN); |
291 | 0 | offset += 4; |
292 | 0 | proto_tree_add_item(tree, hf_bt_tracker_seeders, tvb, offset, 4, ENC_BIG_ENDIAN); |
293 | 0 | offset += 4; |
294 | |
|
295 | 0 | if (tvb_captured_length_remaining(tvb, offset) > 0) |
296 | 0 | { |
297 | 0 | stride_length = 6; |
298 | 0 | is_ipv6 = !is_ipv4_format(pinfo); |
299 | 0 | if (is_ipv6) |
300 | 0 | stride_length = 18; |
301 | 0 | ti = proto_tree_add_item(tree, hf_bt_tracker_trackers, tvb, offset, -1, ENC_NA); |
302 | 0 | sub_tree = proto_item_add_subtree(ti, ett_bt_tracker_trackers); |
303 | |
|
304 | 0 | while (tvb_captured_length_remaining(tvb, offset) >= stride_length) |
305 | 0 | { |
306 | 0 | proto_item *node_ti; |
307 | 0 | proto_tree *node_tree; |
308 | |
|
309 | 0 | node_index += 1; |
310 | |
|
311 | 0 | node_ti = proto_tree_add_item(sub_tree, hf_bt_tracker_tracker, tvb, offset, stride_length, ENC_NA); |
312 | 0 | proto_item_append_text(node_ti, " %d", node_index); |
313 | 0 | node_tree = proto_item_add_subtree(node_ti, ett_bt_tracker_trackers); |
314 | |
|
315 | 0 | if (is_ipv6) |
316 | 0 | { |
317 | 0 | proto_tree_add_item( node_tree, hf_bt_tracker_tr_ip6, tvb, offset, 16, ENC_NA); |
318 | 0 | proto_item_append_text(node_ti, ", IPv6/Port: [%s]", tvb_ip6_to_str(pinfo->pool, tvb, offset)); |
319 | |
|
320 | 0 | proto_tree_add_item( node_tree, hf_bt_tracker_tr_port, tvb, offset + 16, 2, ENC_BIG_ENDIAN); |
321 | 0 | proto_item_append_text(node_ti, ":%u", tvb_get_ntohs( tvb, offset + 16 )); |
322 | 0 | } |
323 | 0 | else |
324 | 0 | { |
325 | 0 | proto_tree_add_item( node_tree, hf_bt_tracker_tr_ip, tvb, offset, 4, ENC_BIG_ENDIAN); |
326 | 0 | proto_item_append_text(node_ti, ", IPv4/Port: %s", tvb_ip_to_str(pinfo->pool, tvb, offset)); |
327 | |
|
328 | 0 | proto_tree_add_item( node_tree, hf_bt_tracker_tr_port, tvb, offset + 4, 2, ENC_BIG_ENDIAN); |
329 | 0 | proto_item_append_text(node_ti, ":%u", tvb_get_ntohs( tvb, offset + 4 )); |
330 | 0 | } |
331 | |
|
332 | 0 | offset += stride_length; |
333 | 0 | } |
334 | 0 | proto_item_set_text(ti, "Trackers: %d trackers", node_index); |
335 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ": %d trackers", node_index); |
336 | 0 | } |
337 | |
|
338 | 0 | break; |
339 | | |
340 | 0 | case MSG_TYPE_SCRAPE_REQUEST: |
341 | 0 | proto_tree_add_item(tree, hf_bt_tracker_connection_id, tvb, offset, 8, ENC_BIG_ENDIAN); |
342 | 0 | offset += 8; |
343 | 0 | proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN); |
344 | 0 | offset += 4; |
345 | 0 | proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
346 | 0 | offset += 4; |
347 | |
|
348 | 0 | while (tvb_captured_length_remaining(tvb, offset) >= 20) |
349 | 0 | { |
350 | 0 | proto_tree_add_item(tree, hf_bt_tracker_info_hash, tvb, offset, 20, ENC_NA); |
351 | 0 | offset += 20; |
352 | 0 | } |
353 | 0 | break; |
354 | | |
355 | 0 | case MSG_TYPE_SCRAPE_RESPONSE: |
356 | 0 | proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN); |
357 | 0 | offset += 4; |
358 | 0 | proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
359 | 0 | offset += 4; |
360 | |
|
361 | 0 | while (tvb_captured_length_remaining(tvb, offset) >= 12) |
362 | 0 | { |
363 | 0 | proto_tree_add_item(tree, hf_bt_tracker_seeders, tvb, offset, 4, ENC_BIG_ENDIAN); |
364 | 0 | offset += 4; |
365 | 0 | proto_tree_add_item(tree, hf_bt_tracker_completed, tvb, offset, 4, ENC_BIG_ENDIAN); |
366 | 0 | offset += 4; |
367 | 0 | proto_tree_add_item(tree, hf_bt_tracker_leechers, tvb, offset, 4, ENC_BIG_ENDIAN); |
368 | 0 | offset += 4; |
369 | 0 | } |
370 | |
|
371 | 0 | break; |
372 | | |
373 | 0 | case MSG_TYPE_ERROR_RESPONSE: |
374 | 0 | proto_tree_add_item(tree, hf_bt_tracker_action, tvb, offset, 4, ENC_BIG_ENDIAN); |
375 | 0 | offset += 4; |
376 | 0 | proto_tree_add_item(tree, hf_bt_tracker_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN); |
377 | 0 | offset += 4; |
378 | 0 | proto_tree_add_item(tree, hf_bt_tracker_error_msg, tvb, offset, -1, ENC_ASCII); |
379 | 0 | offset = tvb_captured_length(tvb); |
380 | 0 | break; |
381 | |
|
382 | 0 | } |
383 | | |
384 | 0 | return offset; |
385 | |
|
386 | 0 | } |
387 | | static int |
388 | | dissect_bt_tracker(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
389 | 0 | { |
390 | 0 | unsigned msg_type; |
391 | 0 | proto_item *ti; |
392 | 0 | proto_tree *sub_tree; |
393 | |
|
394 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "BT-Tracker"); |
395 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
396 | |
|
397 | 0 | msg_type = get_message_type(tvb); |
398 | |
|
399 | 0 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(msg_type, bt_tracker_msg_type_vals, " Unknown Msg Type")); |
400 | |
|
401 | 0 | ti = proto_tree_add_item(tree, proto_bt_tracker, tvb, 0, -1, ENC_NA); |
402 | 0 | sub_tree = proto_item_add_subtree(ti, ett_bt_tracker); |
403 | |
|
404 | 0 | return dissect_bt_tracker_msg(tvb, pinfo, sub_tree, 0, msg_type); |
405 | 0 | } |
406 | | |
407 | | |
408 | | static bool |
409 | | dissect_bt_tracker_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
410 | 869 | { |
411 | 869 | conversation_t *conversation; |
412 | | |
413 | | /* Look for a Connect Request */ |
414 | 869 | if (tvb_captured_length_remaining(tvb, 0) < 16) |
415 | 297 | return false; |
416 | 572 | if (tvb_get_ntoh64(tvb, 0) != MAGIC_CONSTANT) |
417 | 572 | return false; |
418 | 0 | if (tvb_get_ntohl(tvb, 8) != ACTION_CONNECT) |
419 | 0 | return false; |
420 | | |
421 | 0 | conversation = find_or_create_conversation(pinfo); |
422 | 0 | conversation_set_dissector_from_frame_number(conversation, pinfo->num, bt_tracker_handle); |
423 | |
|
424 | 0 | dissect_bt_tracker(tvb, pinfo, tree, data); |
425 | 0 | return true; |
426 | 0 | } |
427 | | |
428 | | void |
429 | | proto_register_bt_tracker(void) |
430 | 14 | { |
431 | 14 | static hf_register_info hf[] = { |
432 | 14 | { &hf_bt_tracker_protocol_id, |
433 | 14 | { "Protocol", "bt-tracker.proto_id", |
434 | 14 | FT_UINT64, BASE_HEX, NULL, 0x00, |
435 | 14 | NULL, HFILL } |
436 | 14 | }, |
437 | 14 | { &hf_bt_tracker_action, |
438 | 14 | { "Action", "bt-tracker.action", |
439 | 14 | FT_UINT32, BASE_DEC, VALS(bt_tracker_action_vals), 0x0, |
440 | 14 | NULL, HFILL } |
441 | 14 | }, |
442 | 14 | { &hf_bt_tracker_transaction_id, |
443 | 14 | { "Transaction Id", "bt-tracker.transaction_id", |
444 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
445 | 14 | NULL, HFILL } |
446 | 14 | }, |
447 | 14 | { &hf_bt_tracker_connection_id, |
448 | 14 | { "Connection Id", "bt-tracker.connection_id", |
449 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
450 | 14 | NULL, HFILL } |
451 | 14 | }, |
452 | 14 | { &hf_bt_tracker_msg_type, |
453 | 14 | { "Message Type", "bt-tracker.msg_type", |
454 | 14 | FT_UINT8, BASE_DEC, VALS(bt_tracker_msg_type_vals), 0x0, |
455 | 14 | NULL, HFILL } |
456 | 14 | }, |
457 | 14 | { &hf_bt_tracker_info_hash, |
458 | 14 | { "Info Hash", "bt-tracker.info_hash", |
459 | 14 | FT_BYTES, BASE_NONE, NULL, 0x00, |
460 | 14 | NULL, HFILL } |
461 | 14 | }, |
462 | 14 | { &hf_bt_tracker_peer_id, |
463 | 14 | { "Peer Id", "bt-tracker.peer_id", |
464 | 14 | FT_BYTES, BASE_NONE, NULL, 0x00, |
465 | 14 | NULL, HFILL } |
466 | 14 | }, |
467 | 14 | { &hf_bt_tracker_downloaded, |
468 | 14 | { "Downloaded", "bt-tracker.downloaded", |
469 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
470 | 14 | NULL, HFILL } |
471 | 14 | }, |
472 | 14 | { &hf_bt_tracker_left, |
473 | 14 | { "Left", "bt-tracker.left", |
474 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
475 | 14 | NULL, HFILL } |
476 | 14 | }, |
477 | 14 | { &hf_bt_tracker_uploaded, |
478 | 14 | { "Uploaded", "bt-tracker.uploaded", |
479 | 14 | FT_UINT64, BASE_DEC, NULL, 0x00, |
480 | 14 | NULL, HFILL } |
481 | 14 | }, |
482 | 14 | { &hf_bt_tracker_event, |
483 | 14 | { "Event", "bt-tracker.event", |
484 | 14 | FT_UINT32, BASE_DEC, VALS(bt_tracker_event_vals), 0x00, |
485 | 14 | NULL, HFILL } |
486 | 14 | }, |
487 | 14 | { &hf_bt_tracker_ip_address, |
488 | 14 | { "IP Address", "bt-tracker.ip_address", |
489 | 14 | FT_IPv4, BASE_NONE, NULL, 0x00, |
490 | 14 | NULL, HFILL } |
491 | 14 | }, |
492 | 14 | { &hf_bt_tracker_key, |
493 | 14 | { "Key", "bt-tracker.key", |
494 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
495 | 14 | NULL, HFILL } |
496 | 14 | }, |
497 | 14 | { &hf_bt_tracker_num_want, |
498 | 14 | { "Num Want", "bt-tracker.num_want", |
499 | 14 | FT_INT32, BASE_DEC, NULL, 0x00, |
500 | 14 | NULL, HFILL } |
501 | 14 | }, |
502 | 14 | { &hf_bt_tracker_port, |
503 | 14 | { "Port", "bt-tracker.port", |
504 | 14 | FT_UINT16, BASE_DEC, NULL, 0x00, |
505 | 14 | NULL, HFILL } |
506 | 14 | }, |
507 | 14 | { &hf_bt_tracker_interval, |
508 | 14 | { "Interval", "bt-tracker.interval", |
509 | 14 | FT_INT32, BASE_DEC, NULL, 0x00, |
510 | 14 | NULL, HFILL } |
511 | 14 | }, |
512 | 14 | { &hf_bt_tracker_leechers, |
513 | 14 | { "Leechers", "bt-tracker.leechers", |
514 | 14 | FT_INT32, BASE_DEC, NULL, 0x00, |
515 | 14 | NULL, HFILL } |
516 | 14 | }, |
517 | 14 | { &hf_bt_tracker_seeders, |
518 | 14 | { "Seeders", "bt-tracker.seeders", |
519 | 14 | FT_INT32, BASE_DEC, NULL, 0x00, |
520 | 14 | NULL, HFILL } |
521 | 14 | }, |
522 | 14 | { &hf_bt_tracker_trackers, |
523 | 14 | { "Trackers", "bt-tracker.trackers", |
524 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, |
525 | 14 | NULL, HFILL } |
526 | 14 | }, |
527 | 14 | { &hf_bt_tracker_tracker, |
528 | 14 | { "Tracker", "bt-tracker.tracker", |
529 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, |
530 | 14 | NULL, HFILL } |
531 | 14 | }, |
532 | 14 | { &hf_bt_tracker_tr_ip, |
533 | 14 | { "IP", "bt-tracker.tracker.ip", |
534 | 14 | FT_IPv4, BASE_NONE, NULL, 0x00, |
535 | 14 | NULL, HFILL } |
536 | 14 | }, |
537 | 14 | { &hf_bt_tracker_tr_ip6, |
538 | 14 | { "IPv6", "bt-tracker.tracker.ip6", |
539 | 14 | FT_IPv6, BASE_NONE, NULL, 0x00, |
540 | 14 | NULL, HFILL } |
541 | 14 | }, |
542 | 14 | { &hf_bt_tracker_tr_port, |
543 | 14 | { "(TCP) Port", "bt-tracker.tracker.port", |
544 | 14 | FT_UINT16, BASE_DEC, NULL, 0x00, |
545 | 14 | NULL, HFILL } |
546 | 14 | }, |
547 | 14 | { &hf_bt_tracker_completed, |
548 | 14 | { "Completed", "bt-tracker.completed", |
549 | 14 | FT_INT32, BASE_DEC, NULL, 0x00, |
550 | 14 | NULL, HFILL } |
551 | 14 | }, |
552 | 14 | { &hf_bt_tracker_error_msg, |
553 | 14 | { "Error message", "bt-tracker.error_msg", |
554 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
555 | 14 | NULL, HFILL } |
556 | 14 | }, |
557 | 14 | { &hf_bt_tracker_extension, |
558 | 14 | { "Extension", "bt-tracker.extension", |
559 | 14 | FT_NONE, BASE_NONE, NULL, 0x0, |
560 | 14 | NULL, HFILL } |
561 | 14 | }, |
562 | 14 | { &hf_bt_tracker_extension_type, |
563 | 14 | { "Extension Type", "bt-tracker.extension_type", |
564 | 14 | FT_UINT8, BASE_HEX, VALS(bt_tracker_extension_type_vals), 0x0, |
565 | 14 | NULL, HFILL } |
566 | 14 | }, |
567 | 14 | { &hf_bt_tracker_extension_len, |
568 | 14 | { "Extension Length", "bt-tracker.extension_len", |
569 | 14 | FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, |
570 | 14 | NULL, HFILL } |
571 | 14 | }, |
572 | 14 | { &hf_bt_tracker_extension_unknown, |
573 | 14 | { "Extension Unknown", "bt-tracker.extension_unknown", |
574 | 14 | FT_BYTES, BASE_NONE, NULL, 0x0, |
575 | 14 | NULL, HFILL } |
576 | 14 | }, |
577 | 14 | { &hf_bt_tracker_extension_urldata, |
578 | 14 | { "URL Data", "bt-tracker.extension.urldata", |
579 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
580 | 14 | NULL, HFILL } |
581 | 14 | }, |
582 | 14 | }; |
583 | | |
584 | | /* Setup protocol subtree array */ |
585 | 14 | static int *ett[] = { &ett_bt_tracker, &ett_bt_tracker_trackers, &ett_bt_tracker_extension}; |
586 | 14 | module_t *bt_tracker_module; |
587 | | |
588 | | /* Register protocol */ |
589 | 14 | proto_bt_tracker = proto_register_protocol ("BitTorrent Tracker", "BT-Tracker", "bt-tracker"); |
590 | | |
591 | 14 | bt_tracker_module = prefs_register_protocol(proto_bt_tracker, NULL); |
592 | 14 | prefs_register_obsolete_preference(bt_tracker_module, "enable"); |
593 | | |
594 | 14 | proto_register_field_array(proto_bt_tracker, hf, array_length(hf)); |
595 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
596 | 14 | } |
597 | | |
598 | | void |
599 | | proto_reg_handoff_bt_tracker(void) |
600 | 14 | { |
601 | 14 | heur_dissector_add("udp", dissect_bt_tracker_heur, "BitTorrent Tracker over UDP", "bt_tracker_udp", proto_bt_tracker, HEURISTIC_ENABLE); |
602 | | |
603 | 14 | bt_tracker_handle = create_dissector_handle(dissect_bt_tracker, proto_bt_tracker); |
604 | 14 | dissector_add_for_decode_as_with_preference("udp.port", bt_tracker_handle); |
605 | 14 | } |