Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-bittorrent.c
blob8093cb59b883f27ceae54b030d47a20496d461f4
1 /* packet-bittorrent.c
2 * Routines for bittorrent packet dissection
3 * Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Copied from packet-pop.c
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/prefs.h>
18 #include <epan/strutil.h>
20 #include "packet-tcp.h"
21 #include "packet-bt-utp.h"
23 void proto_register_bittorrent(void);
24 void proto_reg_handoff_bittorrent(void);
27 * See
29 * http://bittorrent.com/protocol.html
30 * http://wiki.theory.org/BitTorrentSpecification
31 * http://bitconjurer.org/BitTorrent/protocol.html
34 #define DEFAULT_TCP_PORT_RANGE "6881-6889" /* Not IANA registered */
36 #define BITTORRENT_MESSAGE_CHOKE 0
37 #define BITTORRENT_MESSAGE_UNCHOKE 1
38 #define BITTORRENT_MESSAGE_INTERESTED 2
39 #define BITTORRENT_MESSAGE_NOT_INTERESTED 3
40 #define BITTORRENT_MESSAGE_HAVE 4
41 #define BITTORRENT_MESSAGE_BITFIELD 5
42 #define BITTORRENT_MESSAGE_REQUEST 6
43 #define BITTORRENT_MESSAGE_PIECE 7
44 #define BITTORRENT_MESSAGE_CANCEL 8
45 #define BITTORRENT_MESSAGE_PORT 9
47 * BitTorrent BEP 06
48 * Fast Extension message type
51 #define BITT_FAST_EX_SUGGEST_PIECE 13
52 #define BITT_FAST_EX_HAVE_ALL 14
53 #define BITT_FAST_EX_HAVE_NONE 15
54 #define BITT_FAST_EX_REJECT_REQUEST 16
55 #define BITT_FAST_EX_ALLOWED_FAST 17
56 #define BITTORRENT_MESSAGE_EXTENDED 20
58 #define BITTORRENT_HEADER_LENGTH 4
61 * Azureus messages are specified by name so these are made up numbers
62 * for internal identification only.
64 * Standard BT message types are a single byte, so these won't clash
66 #define AZUREUS_MESSAGE_HANDSHAKE 256
67 #define AZUREUS_MESSAGE_KEEP_ALIVE 257
68 #define AZUREUS_MESSAGE_BT_HANDSHAKE 258
69 #define AZUREUS_MESSAGE_PEER_EXCHANGE 259
70 #define AZUREUS_MESSAGE_JPC_HELLO 260
71 #define AZUREUS_MESSAGE_JPC_REPLY 261
74 static const value_string bittorrent_messages[] = {
75 { BITTORRENT_MESSAGE_CHOKE, "Choke" },
76 { BITTORRENT_MESSAGE_UNCHOKE, "Unchoke" },
77 { BITTORRENT_MESSAGE_INTERESTED, "Interested" },
78 { BITTORRENT_MESSAGE_NOT_INTERESTED, "Not Interested" },
79 { BITTORRENT_MESSAGE_HAVE, "Have" },
80 { BITTORRENT_MESSAGE_BITFIELD, "Bitfield" },
81 { BITTORRENT_MESSAGE_REQUEST, "Request" },
82 { BITTORRENT_MESSAGE_PIECE, "Piece" },
83 { BITTORRENT_MESSAGE_CANCEL, "Cancel" },
84 { BITTORRENT_MESSAGE_PORT, "Port" },
85 { BITT_FAST_EX_SUGGEST_PIECE, "Suggest Piece" },
86 { BITT_FAST_EX_HAVE_ALL, "Have All" },
87 { BITT_FAST_EX_HAVE_NONE, "Have None" },
88 { BITT_FAST_EX_REJECT_REQUEST, "Reject Request" },
89 { BITT_FAST_EX_ALLOWED_FAST, "Allowed Fast" },
90 { BITTORRENT_MESSAGE_EXTENDED, "Extended" },
91 { AZUREUS_MESSAGE_KEEP_ALIVE, "Keepalive" },
92 { AZUREUS_MESSAGE_HANDSHAKE, "Azureus Handshake" },
93 { AZUREUS_MESSAGE_BT_HANDSHAKE, "Azureus BitTorrent Handshake" },
94 { AZUREUS_MESSAGE_PEER_EXCHANGE, "Azureus Peer Exchange" },
95 { AZUREUS_MESSAGE_JPC_HELLO, "Azureus PeerCache Hello" },
96 { AZUREUS_MESSAGE_JPC_REPLY, "Azureus PeerCache Reply" },
97 { 0, NULL }
100 static const value_string azureus_priorities[] = {
101 { 0, "Low" },
102 { 1, "Normal" },
103 { 2, "High" },
104 { 0, NULL }
108 struct amp_message {
109 const char *name;
110 uint32_t value;
113 static const struct amp_message amp_messages[] = {
114 { "BT_KEEP_ALIVE", AZUREUS_MESSAGE_KEEP_ALIVE },
115 { "BT_CHOKE", BITTORRENT_MESSAGE_CHOKE },
116 { "BT_UNCHOKE", BITTORRENT_MESSAGE_UNCHOKE },
117 { "BT_INTERESTED", BITTORRENT_MESSAGE_INTERESTED },
118 { "BT_UNINTERESTED", BITTORRENT_MESSAGE_NOT_INTERESTED },
119 { "BT_HAVE", BITTORRENT_MESSAGE_HAVE },
120 { "BT_BITFIELD", BITTORRENT_MESSAGE_BITFIELD },
121 { "BT_REQUEST", BITTORRENT_MESSAGE_REQUEST },
122 { "BT_PIECE", BITTORRENT_MESSAGE_PIECE },
123 { "BT_CANCEL", BITTORRENT_MESSAGE_CANCEL },
124 { "BT_PORT", BITTORRENT_MESSAGE_PORT },
125 { "BT_SUGGEST", BITT_FAST_EX_SUGGEST_PIECE },
126 { "BT_HAVE_ALL", BITT_FAST_EX_HAVE_ALL },
127 { "BT_HAVE_NONE", BITT_FAST_EX_HAVE_NONE },
128 { "BT_REJECT_REQUEST",BITT_FAST_EX_REJECT_REQUEST },
129 { "BT_ALLOWED_FAST", BITT_FAST_EX_ALLOWED_FAST },
130 { "BT_EXTENDED", BITTORRENT_MESSAGE_EXTENDED },
131 { "AZ_HANDSHAKE", AZUREUS_MESSAGE_HANDSHAKE },
132 { "BT_HANDSHAKE", AZUREUS_MESSAGE_BT_HANDSHAKE },
133 { "AZ_PEER_EXCHANGE", AZUREUS_MESSAGE_PEER_EXCHANGE },
134 { "JPC_HELLO", AZUREUS_MESSAGE_JPC_HELLO },
135 { "JPC_REPLY", AZUREUS_MESSAGE_JPC_REPLY },
136 { NULL, 0 }
139 static dissector_handle_t dissector_handle;
140 static dissector_handle_t bencode_handle;
141 static int proto_bittorrent;
143 /* static int hf_bittorrent_field_length; */
144 static int hf_bittorrent_prot_name_len;
145 static int hf_bittorrent_prot_name;
146 static int hf_bittorrent_reserved;
147 static int hf_bittorrent_sha1_hash;
148 static int hf_bittorrent_peer_id;
149 static int hf_bittorrent_msg;
150 static int hf_bittorrent_msg_len;
151 static int hf_bittorrent_msg_type;
152 static int hf_azureus_msg;
153 static int hf_azureus_msg_type_len;
154 static int hf_azureus_msg_type;
155 static int hf_azureus_msg_prio;
156 static int hf_bittorrent_bitfield_data;
157 static int hf_bittorrent_piece_index;
158 static int hf_bittorrent_piece_begin;
159 static int hf_bittorrent_piece_length;
160 static int hf_bittorrent_piece_data;
161 static int hf_azureus_jpc_addrlen;
162 static int hf_azureus_jpc_addr;
163 static int hf_azureus_jpc_port;
164 static int hf_azureus_jpc_session;
165 static int hf_bittorrent_port;
166 static int hf_bittorrent_extended_id;
167 static int hf_bittorrent_extended;
168 static int hf_bittorrent_continuous_data;
169 static int hf_bittorrent_version;
171 static int ett_bittorrent;
172 static int ett_bittorrent_msg;
173 static int ett_peer_id;
175 static bool bittorrent_desegment = true;
176 static bool decode_client_information;
178 struct client_information {
179 char id[5]; /* string length must be <= 4 to allow space for NUL termination byte */
180 char ver_len;
181 const char *name; /* NULL means array entry terminates the array */
184 static struct client_information peer_id[] = {
185 {"-AG", 4, "Ares"},
186 {"-A~", 4, "Ares"},
187 {"-AR", 4, "Arctic"},
188 {"-AT", 4, "Artemis"},
189 {"-AV", 4, "Avicora"},
190 {"-AX", 4, "BitPump"},
191 {"-AZ", 4, "Azureus"},
192 {"-BB", 4, "BitBuddy"},
193 {"-BC", 4, "BitComet"},
194 {"-BF", 4, "Bitflu"},
195 {"-BG", 4, "BTG (uses Rasterbar libtorrent)"},
196 {"-BOW", 3, "Bits on Wheels"},
197 {"-BP", 4, "BitTorrent Pro (Azereus + spyware)"},
198 {"-BR", 4, "BitRocket"},
199 {"-BS", 4, "BTSlave"},
200 {"-BW", 4, "BitWombat"},
201 {"-BX", 4, "Bittorrent X"},
202 {"-CD", 4, "Enhanced CTorrent"},
203 {"-CT", 4, "CTorrent"},
204 {"-DE", 4, "DelugeTorrent"},
205 {"-DP", 4, "Propagate Data Client"},
206 {"-EB", 4, "EBit"},
207 {"-ES", 4, "electric sheep"},
208 {"-FC", 4, "FileCroc"},
209 {"-FG", 4, "FlashGet"},
210 {"-FT", 4, "FoxTorrent"},
211 {"-GS", 4, "GSTorrent"},
212 {"-HK", 4, "Hekate"},
213 {"-HL", 4, "Halite"},
214 {"-HN", 4, "Hydranode"},
215 {"-KG", 4, "KGet"},
216 {"-KT", 4, "KTorrent"},
217 {"-LC", 4, "LeechCraft"},
218 {"-LH", 4, "LH-ABC"},
219 {"-LP", 4, "Lphant"},
220 {"-LT", 4, "libtorrent"},
221 {"-lt", 4, "libTorrent"},
222 {"-LW", 4, "LimeWire"},
223 {"-MO", 4, "MonoTorrent"},
224 {"-MP", 4, "MooPolice"},
225 {"-MR", 4, "Miro"},
226 {"-MT", 4, "MoonlightTorrent"},
227 {"-NE", 4, "BT Next Evolution"},
228 {"-NX", 4, "Net Transport"},
229 {"-OS", 4, "OneSwarm"},
230 {"-OT", 4, "OmegaTorrent"},
231 {"-PD", 4, "Pando"},
232 {"-qB", 4, "qBittorrent"},
233 {"-QD", 4, "QQDownload"},
234 {"-QT", 4, "Qt 4 Torrent example"},
235 {"-RT", 4, "Retriever"},
236 {"-S~", 4, "Shareaza alpha/beta"},
237 {"-SB", 4, "Swiftbit"},
238 {"-SD", 4, "Thunder (aka XunLei)"},
239 {"-SS", 4, "SwarmScope"},
240 {"-ST", 4, "SymTorrent"},
241 {"-st", 4, "sharktorrent"},
242 {"-SZ", 4, "Shareaza"},
243 {"-TN", 4, "TorrentDotNET"},
244 {"-TR", 4, "Transmission"},
245 {"-TS", 4, "Torrentstorm"},
246 {"-TT", 4, "TuoTu"},
247 {"-UL", 4, "uLeecher!"},
248 {"-UM", 4, "(my)Torrent for Mac"},
249 {"-UT", 4, "(my)Torrent"},
250 {"-VG", 4, "Vagaa"},
251 {"-WT", 4, "BitLet"},
252 {"-WY", 4, "FireTorrent"},
253 {"-XL", 4, "Xunlei"},
254 {"-XT", 4, "XanTorrent"},
255 {"-XX", 4, "Xtorrent"},
256 {"-ZT", 4, "ZipTorrent"},
257 {"exbc", 2, "BitComet"},
258 {"OP", 4, "Opera"},
259 {"QVOD", 4, "Qvod"},
260 {"XBT", 3, "XBT Client"},
261 {"A", 3, "ABC"},
262 {"O", 3, "Osprey Permaseed"},
263 {"Q", 3, "BTQueue"},
264 {"R", 3, "Tribler"},
265 {"S", 3, "Shadow's client"},
266 {"T", 3, "BitTornado"},
267 {"U", 3, "UPnP NAT Bit Torrent"},
268 {"", 0, NULL}
271 /* Tests a given length for a message type to see if it looks valid.
272 * The exact length is known for many message types, which prevents us
273 * from returning a false positive match based on a single byte when
274 * we're in the middle of Continuation Data or an encrypted transfer.
276 static bool
277 test_type_length(uint16_t type, uint32_t length)
279 switch (type) {
281 case BITTORRENT_MESSAGE_UNCHOKE:
282 case BITTORRENT_MESSAGE_INTERESTED:
283 case BITTORRENT_MESSAGE_NOT_INTERESTED:
284 case BITT_FAST_EX_HAVE_ALL:
285 case BITT_FAST_EX_HAVE_NONE:
286 /* No payload */
287 if (length != 1) {
288 return false;
290 return true;
292 case BITTORRENT_MESSAGE_PORT:
293 if (length != 3) {
294 return false;
296 return true;
298 case BITTORRENT_MESSAGE_HAVE:
299 case BITT_FAST_EX_SUGGEST_PIECE:
300 case BITT_FAST_EX_ALLOWED_FAST:
301 if (length != 5) {
302 return false;
304 return true;
306 case BITTORRENT_MESSAGE_REQUEST:
307 case BITTORRENT_MESSAGE_CANCEL:
308 case BITT_FAST_EX_REJECT_REQUEST:
309 if (length != 13) {
310 return false;
312 return true;
314 /* Now to the messages that can have variable and longer lengths. */
316 case BITTORRENT_MESSAGE_EXTENDED:
317 case BITTORRENT_MESSAGE_PIECE:
318 /* All known implementations use 0x4000 for the piece length by default
319 * (only smaller for the last piece at EOF), and disconnect from clients
320 * that use a larger value, which is mentioned in BEP-3. Including the
321 * other parts of the message, that yields a length of 0x4009. There
322 * might exist some non-standard traffic somewhere, I suppose.
324 * This is excessively long for any extension message.
326 if (length > 0x4009) {
327 return false;
329 return true;
331 case BITTORRENT_MESSAGE_CHOKE:
332 /* Choke could be an Azureus message instead, which could be any
333 * of the other messages, so it has to be as long as our longest
334 * message. XXX: To reduce false positives (since 0 is a common
335 * byte to see), a pref to disable Azureus support could be useful.
336 * Alternatively, if we tracked conversations, we could disable
337 * support for AMP if the extension bits in the handshake (if seen)
338 * indicated that it's not supported.
340 case AZUREUS_MESSAGE_HANDSHAKE:
341 case AZUREUS_MESSAGE_KEEP_ALIVE:
342 case AZUREUS_MESSAGE_BT_HANDSHAKE:
343 case AZUREUS_MESSAGE_PEER_EXCHANGE:
344 case AZUREUS_MESSAGE_JPC_HELLO:
345 case AZUREUS_MESSAGE_JPC_REPLY:
346 case BITTORRENT_MESSAGE_BITFIELD:
347 /* A bitfield length is N bits, where N is the number of pieces
348 * in the torrent. The absolute boundary is 2^32 pieces (because
349 * it has to fit in the piece message). In practice the piece
350 * length varies to balance a number of factors. (Some clients
351 * don't work with too many pieces; at one point 2^16 was a common
352 * maximum.) The minimum common piece length is 2^18 bytes, and higher
353 * powers of two are also frequently used.
355 * 0x20000 allows 0x100000 pieces, or over a million. That's more
356 * than most clients support, and cuts down on false positives.
358 if (length > 0x20000) {
359 return false;
361 return true;
363 default:
364 if (!try_val_to_str(type, bittorrent_messages)) {
365 return false;
369 return true;
372 static unsigned
373 get_bittorrent_pdu_length(packet_info *pinfo _U_, tvbuff_t *tvb,
374 int offset, void *data _U_)
376 uint8_t type;
377 uint32_t length;
379 if (tvb_get_uint8(tvb, offset) == 19 &&
380 tvb_memeql(tvb, offset + 1, (const uint8_t*)"BitTorrent protocol", 19) == 0) {
381 /* Return the length of a Handshake message */
382 return 1 + /* pstrlen */
383 19 + /* pstr */
384 8 + /* reserved */
385 20 + /* SHA1 hash of the info key */
386 20; /* peer id */
387 } else {
388 /* Try to validate the length of the message indicated by the header. */
389 length = tvb_get_ntohl(tvb, offset);
390 if(length == 0) {
391 /* keep-alive - no message ID */
392 return BITTORRENT_HEADER_LENGTH;
394 /* Do some sanity checking of the message, if we have the ID byte */
395 if(tvb_offset_exists(tvb, offset + BITTORRENT_HEADER_LENGTH)) {
396 type = tvb_get_uint8(tvb, offset + BITTORRENT_HEADER_LENGTH);
397 if (test_type_length(type, length)) {
398 /* This seems to be a valid BitTorrent header with a known
399 type identifier and valid length */
400 return BITTORRENT_HEADER_LENGTH + length;
401 } else {
402 /* The type is not known, so this message cannot be decoded
403 properly by this dissector. We assume it's continuation
404 data from the middle of a message, and just return the
405 remaining length in the tvbuff so the rest of the tvbuff
406 is displayed as continuation data. */
407 return tvb_reported_length_remaining(tvb, offset);
409 } else {
410 /* We don't have the type field, so we can't determine
411 whether this is a valid message. Return 0, which
412 tcp_dissect_pdus (and utp_dissect_pdus) treats as
413 "variable length, needs one more segment". */
414 return 0;
419 static void
420 dissect_bittorrent_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
422 int offset = 0;
423 int i;
424 int isamp = 0;
425 proto_tree *mtree;
426 uint16_t type = 0;
427 uint32_t typelen = 0;
428 uint8_t prio = 0;
429 uint32_t ext_id = 0;
430 uint32_t length;
431 const char *msgtype = NULL;
432 proto_item *ti;
433 uint32_t piece_index, piece_begin, piece_length;
434 uint32_t stringlen;
435 tvbuff_t *subtvb;
437 /* Guaranteed BITTORRENT_HEADER_LENGTH by tcp_dissect_pdus */
438 length = tvb_get_ntohl(tvb, offset);
440 /* Keepalive message */
441 if (length == 0) {
442 ti = proto_tree_add_item(tree, hf_bittorrent_msg, tvb, offset, length + BITTORRENT_HEADER_LENGTH, ENC_NA);
443 mtree = proto_item_add_subtree(ti, ett_bittorrent_msg);
444 proto_tree_add_item(mtree, hf_bittorrent_msg_len, tvb, offset, BITTORRENT_HEADER_LENGTH, ENC_BIG_ENDIAN);
445 col_set_str(pinfo->cinfo, COL_INFO, "KeepAlive");
446 return;
449 if (tvb_bytes_exist(tvb, offset + BITTORRENT_HEADER_LENGTH, 1)) {
450 /* Check for data from the middle of a message. */
451 type = tvb_get_uint8(tvb, offset + BITTORRENT_HEADER_LENGTH);
453 if (type==BITTORRENT_MESSAGE_CHOKE && length>4) {
455 * Choke messages have no payload, so this is likely an Azureus
456 * Messaging Protocol packet
458 if (!tvb_bytes_exist(tvb, offset + BITTORRENT_HEADER_LENGTH, 4))
459 return;
461 typelen = tvb_get_ntohl(tvb, offset + BITTORRENT_HEADER_LENGTH);
462 if (4+typelen+1<=length) {
463 if (!tvb_bytes_exist(tvb, offset + BITTORRENT_HEADER_LENGTH + 4, typelen+1))
464 return;
466 for ( i=0 ; amp_messages[i].name ; i++ ) {
467 if (strlen(amp_messages[i].name)==typelen &&
468 tvb_memeql(tvb, offset + BITTORRENT_HEADER_LENGTH + 4,
469 amp_messages[i].name, (int)strlen(amp_messages[i].name))==0) {
471 prio = tvb_get_uint8(tvb, offset + BITTORRENT_HEADER_LENGTH + 4 + typelen);
472 if (prio==0 || prio==1 || prio==2) {
473 type = amp_messages[i].value;
474 isamp = 1;
476 break;
482 msgtype = try_val_to_str(type, bittorrent_messages);
483 #if 0
484 if (msgtype == NULL && isamp) {
485 msgtype = try_val_to_str(type, azureus_messages);
487 #endif
488 if (msgtype == NULL || !(test_type_length(type, length))) {
489 /* In modern captures, this is likely Protocol Encryption/
490 * Message Stream Encryption, particularly if we're actually
491 * desegmenting and have the whole connection starting from
492 * the SYN. We don't try to do that yet.
494 proto_tree_add_item(tree, hf_bittorrent_continuous_data, tvb, offset, -1, ENC_NA);
495 col_set_str(pinfo->cinfo, COL_INFO, "Continuation data");
496 return;
498 } else {
499 /* not enough bytes of the header, stop here */
500 return;
503 if (isamp) {
504 ti = proto_tree_add_item(tree, hf_azureus_msg, tvb, offset, length + BITTORRENT_HEADER_LENGTH, ENC_NA);
505 } else {
506 ti = proto_tree_add_item(tree, hf_bittorrent_msg, tvb, offset, length + BITTORRENT_HEADER_LENGTH, ENC_NA);
508 mtree = proto_item_add_subtree(ti, ett_bittorrent_msg);
510 proto_tree_add_item(mtree, hf_bittorrent_msg_len, tvb, offset, BITTORRENT_HEADER_LENGTH, ENC_BIG_ENDIAN);
511 offset += BITTORRENT_HEADER_LENGTH;
513 /* If the tvb_bytes_exist() call above returned false, this will
514 throw an exception, so we won't use msgtype or type. */
515 if (isamp) {
516 proto_tree_add_item(mtree, hf_azureus_msg_type_len, tvb, offset, 4, ENC_BIG_ENDIAN);
517 proto_tree_add_item(mtree, hf_azureus_msg_type, tvb, offset+4, typelen, ENC_ASCII);
518 proto_item_append_text(ti, ": Len %u, %s", length, msgtype);
519 proto_tree_add_item(mtree, hf_azureus_msg_prio, tvb, offset+4+typelen, 1, ENC_BIG_ENDIAN);
520 offset += 4+typelen+1;
521 length -= 4+typelen+1;
522 } else {
523 proto_tree_add_item(mtree, hf_bittorrent_msg_type, tvb, offset, 1, ENC_BIG_ENDIAN);
524 proto_item_append_text(ti, ": Len:%u, %s", length, msgtype);
525 offset += 1;
526 length -= 1;
528 col_set_str(pinfo->cinfo, COL_INFO, msgtype);
530 switch (type) {
531 case BITTORRENT_MESSAGE_CHOKE:
532 case BITTORRENT_MESSAGE_UNCHOKE:
533 case BITTORRENT_MESSAGE_INTERESTED:
534 case BITTORRENT_MESSAGE_NOT_INTERESTED:
535 case BITT_FAST_EX_HAVE_ALL:
536 case BITT_FAST_EX_HAVE_NONE:
537 /* No payload */
538 break;
540 case BITTORRENT_MESSAGE_REQUEST:
541 case BITTORRENT_MESSAGE_CANCEL:
542 case BITT_FAST_EX_REJECT_REQUEST:
543 piece_index = tvb_get_ntohl(tvb, offset);
544 proto_tree_add_uint(mtree, hf_bittorrent_piece_index, tvb, offset, 4, piece_index); offset += 4;
545 piece_begin = tvb_get_ntohl(tvb, offset);
546 proto_tree_add_uint(mtree, hf_bittorrent_piece_begin, tvb, offset, 4, piece_begin); offset += 4;
547 piece_length = tvb_get_ntohl(tvb, offset);
548 proto_tree_add_uint(mtree, hf_bittorrent_piece_length, tvb, offset, 4, piece_length);
549 proto_item_append_text(ti, ", Piece (Idx:0x%x,Begin:0x%x,Len:0x%x)", piece_index, piece_begin, piece_length);
551 col_append_fstr(pinfo->cinfo, COL_INFO, ", Piece (Idx:0x%x,Begin:0x%x,Len:0x%x)", piece_index, piece_begin, piece_length);
553 break;
555 case BITTORRENT_MESSAGE_PORT:
556 /* port as payload */
557 proto_tree_add_item(mtree, hf_bittorrent_port, tvb, offset, 2, ENC_BIG_ENDIAN);
558 break;
560 case BITTORRENT_MESSAGE_EXTENDED:
561 /* extended message content */
562 proto_tree_add_item_ret_uint(mtree, hf_bittorrent_extended_id, tvb, offset, 1, ENC_NA, &ext_id);
563 offset += 1;
564 length -= 1;
565 if (ext_id == 0) {
566 call_dissector(bencode_handle, tvb_new_subset_length(tvb, offset, length), pinfo, mtree);
567 } else {
568 proto_tree_add_item(mtree, hf_bittorrent_extended, tvb, offset, length, ENC_NA);
570 break;
572 case BITTORRENT_MESSAGE_HAVE:
573 case BITT_FAST_EX_SUGGEST_PIECE:
574 case BITT_FAST_EX_ALLOWED_FAST:
575 piece_index = tvb_get_ntohl(tvb, offset);
576 proto_tree_add_item(mtree, hf_bittorrent_piece_index, tvb, offset, 4, ENC_BIG_ENDIAN);
577 proto_item_append_text(ti, ", Piece (Idx:0x%x)", piece_index);
579 col_append_fstr(pinfo->cinfo, COL_INFO, ", Piece (Idx:0x%x)", piece_index);
581 break;
583 case BITTORRENT_MESSAGE_BITFIELD:
584 proto_tree_add_item(mtree, hf_bittorrent_bitfield_data, tvb, offset, length, ENC_NA);
585 proto_item_append_text(ti, ", Len:0x%x", length);
586 col_append_fstr(pinfo->cinfo, COL_INFO, ", Len:0x%x", length);
588 break;
590 case BITTORRENT_MESSAGE_PIECE:
591 piece_index = tvb_get_ntohl(tvb, offset);
592 proto_tree_add_uint(mtree, hf_bittorrent_piece_index, tvb, offset, 4, piece_index);
593 offset += 4;
594 length -= 4;
595 piece_begin = tvb_get_ntohl(tvb, offset);
596 proto_tree_add_uint(mtree, hf_bittorrent_piece_begin, tvb, offset, 4, piece_begin);
597 offset += 4;
598 length -= 4;
599 proto_tree_add_item(mtree, hf_bittorrent_piece_data, tvb, offset, length, ENC_NA);
600 proto_item_append_text(ti, ", Idx:0x%x,Begin:0x%x,Len:0x%x", piece_index, piece_begin, length);
601 col_append_fstr(pinfo->cinfo, COL_INFO, ", Idx:0x%x,Begin:0x%x,Len:0x%x", piece_index, piece_begin, length);
603 break;
605 case AZUREUS_MESSAGE_HANDSHAKE:
606 case AZUREUS_MESSAGE_PEER_EXCHANGE:
607 subtvb = tvb_new_subset_length(tvb, offset, length);
608 call_dissector(bencode_handle, subtvb, pinfo, mtree);
609 break;
611 case AZUREUS_MESSAGE_JPC_HELLO:
612 stringlen = tvb_get_ntohl(tvb, offset);
613 proto_tree_add_item(mtree, hf_azureus_jpc_addrlen, tvb, offset, 4, ENC_BIG_ENDIAN);
614 proto_tree_add_item(mtree, hf_azureus_jpc_addr, tvb, offset+4, stringlen, ENC_ASCII);
615 proto_tree_add_item(mtree, hf_azureus_jpc_port, tvb, offset+4+stringlen, 4, ENC_BIG_ENDIAN);
616 proto_tree_add_item(mtree, hf_azureus_jpc_session, tvb, offset+4+stringlen+4, 4, ENC_BIG_ENDIAN);
617 break;
619 case AZUREUS_MESSAGE_JPC_REPLY:
620 proto_tree_add_item(mtree, hf_azureus_jpc_session, tvb, offset, 4, ENC_BIG_ENDIAN);
621 break;
623 default:
624 break;
628 static int
629 dissect_bittorrent_welcome (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
631 int offset = 0;
632 int i;
633 char *version;
635 col_set_str(pinfo->cinfo, COL_INFO, "Handshake");
637 proto_tree_add_item(tree, hf_bittorrent_prot_name_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset+=1;
638 proto_tree_add_item(tree, hf_bittorrent_prot_name, tvb, offset, 19, ENC_ASCII); offset += 19;
639 proto_tree_add_item(tree, hf_bittorrent_reserved, tvb, offset, 8, ENC_NA); offset += 8;
641 proto_tree_add_item(tree, hf_bittorrent_sha1_hash, tvb, offset, 20, ENC_NA);
642 offset += 20;
644 proto_tree_add_item(tree, hf_bittorrent_peer_id, tvb, offset, 20, ENC_NA);
645 if(decode_client_information) {
646 for(i = 0; peer_id[i].name != NULL; ++i)
648 if(tvb_memeql(tvb, offset, (const uint8_t*)peer_id[i].id, (int)strlen(peer_id[i].id)) == 0) {
649 version = tvb_get_string_enc(pinfo->pool, tvb, offset + (int)strlen(peer_id[i].id),
650 peer_id[i].ver_len, ENC_ASCII);
651 proto_tree_add_string_format(tree, hf_bittorrent_version, tvb, offset, 20, version, "Client is %s v%s",
652 peer_id[i].name, format_text(pinfo->pool, (unsigned char*)version, peer_id[i].ver_len));
653 break;
657 offset += 20;
658 return offset;
661 static
662 int dissect_bittorrent_tcp_pdu (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
664 proto_item *ti;
666 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BitTorrent");
668 col_set_str(pinfo->cinfo, COL_INFO, "BitTorrent ");
670 ti = proto_tree_add_item (tree, proto_bittorrent, tvb, 0, -1, ENC_NA);
671 tree = proto_item_add_subtree(ti, ett_bittorrent);
673 if (tvb_get_uint8(tvb, 0) == 19 &&
674 tvb_memeql(tvb, 1, (const uint8_t*)"BitTorrent protocol", 19) == 0) {
675 dissect_bittorrent_welcome(tvb, pinfo, tree);
676 } else {
677 dissect_bittorrent_message(tvb, pinfo, tree);
680 col_append_str(pinfo->cinfo, COL_INFO, " ");
681 col_set_fence(pinfo->cinfo, COL_INFO);
683 return tvb_reported_length(tvb);
686 static
687 int dissect_bittorrent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
689 tcp_dissect_pdus(tvb, pinfo, tree, bittorrent_desegment, BITTORRENT_HEADER_LENGTH,
690 get_bittorrent_pdu_length, dissect_bittorrent_tcp_pdu, data);
691 return tvb_reported_length(tvb);
694 static
695 int dissect_bittorrent_utp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
697 utp_dissect_pdus(tvb, pinfo, tree, bittorrent_desegment, BITTORRENT_HEADER_LENGTH,
698 get_bittorrent_pdu_length, dissect_bittorrent_tcp_pdu, data);
699 return tvb_reported_length(tvb);
702 static
703 bool test_bittorrent_packet (tvbuff_t *tvb, packet_info *pinfo,
704 proto_tree *tree, void *data)
706 conversation_t *conversation;
708 if (tvb_captured_length(tvb) >= 20 &&
709 tvb_get_uint8(tvb, 0) == 19 &&
710 tvb_memeql(tvb, 1, (const uint8_t*)"BitTorrent protocol", 19) == 0) {
711 conversation = find_or_create_conversation(pinfo);
712 conversation_set_dissector(conversation, dissector_handle);
714 dissect_bittorrent(tvb, pinfo, tree, data);
716 return true;
719 return false;
722 void
723 proto_register_bittorrent(void)
725 static hf_register_info hf[] = {
726 #if 0
727 { &hf_bittorrent_field_length,
728 { "Field Length", "bittorrent.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
730 #endif
731 { &hf_bittorrent_prot_name_len,
732 { "Protocol Name Length", "bittorrent.protocol.name.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
734 { &hf_bittorrent_prot_name,
735 { "Protocol Name", "bittorrent.protocol.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
737 { &hf_bittorrent_reserved,
738 { "Reserved Extension Bytes", "bittorrent.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
740 { &hf_bittorrent_sha1_hash,
741 { "SHA1 Hash of info dictionary", "bittorrent.info_hash", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
743 { &hf_bittorrent_peer_id,
744 { "Peer ID", "bittorrent.peer_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
746 { &hf_bittorrent_msg,
747 { "Message", "bittorrent.msg", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
749 { &hf_bittorrent_msg_len,
750 { "Message Length", "bittorrent.msg.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
752 { &hf_bittorrent_msg_type,
753 { "Message Type", "bittorrent.msg.type", FT_UINT8, BASE_DEC, VALS(bittorrent_messages), 0x0, NULL, HFILL }
755 { &hf_azureus_msg,
756 { "Azureus Message", "bittorrent.azureus_msg", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
758 { &hf_azureus_msg_type_len,
759 { "Message Type Length", "bittorrent.msg.typelen", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
761 { &hf_azureus_msg_type,
762 { "Message Type", "bittorrent.msg.aztype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
764 { &hf_azureus_msg_prio,
765 { "Message Priority", "bittorrent.msg.prio", FT_UINT8, BASE_DEC, VALS(azureus_priorities), 0x0, NULL, HFILL }
767 { &hf_bittorrent_bitfield_data,
768 { "Bitfield data", "bittorrent.msg.bitfield", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
770 { &hf_bittorrent_piece_index,
771 { "Piece index", "bittorrent.piece.index", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
773 { &hf_bittorrent_piece_begin,
774 { "Begin offset of piece", "bittorrent.piece.begin", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
776 { &hf_bittorrent_piece_data,
777 { "Data in a piece", "bittorrent.piece.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
779 { &hf_bittorrent_piece_length,
780 { "Piece Length", "bittorrent.piece.length", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
782 { &hf_azureus_jpc_addrlen,
783 { "Cache Address Length", "bittorrent.jpc.addr.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
785 { &hf_azureus_jpc_addr,
786 { "Cache Address", "bittorrent.jpc.addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
788 { &hf_azureus_jpc_port,
789 { "Port", "bittorrent.jpc.port", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
791 { &hf_azureus_jpc_session,
792 { "Session ID", "bittorrent.jpc.session", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }
794 { &hf_bittorrent_port,
795 { "Port", "bittorrent.port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
797 { &hf_bittorrent_extended_id,
798 { "Extended Message ID", "bittorrent.extended.id", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
800 { &hf_bittorrent_extended,
801 { "Extended Message", "bittorrent.extended", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
803 { &hf_bittorrent_continuous_data,
804 { "Extended Message", "bittorrent.continuous_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
806 { &hf_bittorrent_version,
807 { "Client version", "bittorrent.version", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
811 static int *ett[] = {
812 &ett_bittorrent,
813 &ett_bittorrent_msg,
814 &ett_peer_id,
817 module_t *bittorrent_module;
819 proto_bittorrent = proto_register_protocol("BitTorrent", "BitTorrent", "bittorrent");
820 proto_register_field_array(proto_bittorrent, hf, array_length(hf));
821 proto_register_subtree_array(ett, array_length(ett));
823 dissector_handle = register_dissector("bittorrent.tcp", dissect_bittorrent, proto_bittorrent);
824 register_dissector("bittorrent.utp", dissect_bittorrent_utp, proto_bittorrent);
826 bittorrent_module = prefs_register_protocol(proto_bittorrent, NULL);
827 prefs_register_bool_preference(bittorrent_module, "desegment",
828 "Reassemble BitTorrent messages spanning multiple TCP segments",
829 "Whether the BitTorrent dissector should reassemble messages spanning multiple TCP segments."
830 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
831 &bittorrent_desegment);
832 prefs_register_bool_preference(bittorrent_module, "decode_client",
833 "Decode the peer_id of the handshake messages",
834 "Enabling this will tell which BitTorrent client that produced the handshake message",
835 &decode_client_information);
839 void
840 proto_reg_handoff_bittorrent(void)
842 bencode_handle = find_dissector_add_dependency("bencode", proto_bittorrent);
844 dissector_add_uint_range_with_preference("tcp.port", DEFAULT_TCP_PORT_RANGE, dissector_handle);
846 heur_dissector_add("tcp", test_bittorrent_packet, "BitTorrent over TCP", "bittorrent_tcp", proto_bittorrent, HEURISTIC_ENABLE);
850 * Editor modelines
852 * Local Variables:
853 * c-basic-offset: 3
854 * tab-width: 8
855 * indent-tabs-mode: nil
856 * End:
858 * ex: set shiftwidth=3 tabstop=8 expandtab:
859 * :indentSize=3:tabSize=8:noTabs=true: