Coverage Report

Created: 2025-02-15 06:25

/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
}