2 * Routines for bittorrent packet dissection
3 * Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-pop.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/prefs.h>
32 #include <epan/conversation.h>
33 #include <epan/packet.h>
34 #include <epan/strutil.h>
36 #include "packet-tcp.h"
41 * http://bittorrent.com/protocol.html
42 * http://wiki.theory.org/BitTorrentSpecification
43 * http://bitconjurer.org/BitTorrent/protocol.html
46 #define BITTORRENT_MESSAGE_CHOKE 0
47 #define BITTORRENT_MESSAGE_UNCHOKE 1
48 #define BITTORRENT_MESSAGE_INTERESTED 2
49 #define BITTORRENT_MESSAGE_NOT_INTERESTED 3
50 #define BITTORRENT_MESSAGE_HAVE 4
51 #define BITTORRENT_MESSAGE_BITFIELD 5
52 #define BITTORRENT_MESSAGE_REQUEST 6
53 #define BITTORRENT_MESSAGE_PIECE 7
54 #define BITTORRENT_MESSAGE_CANCEL 8
55 #define BITTORRENT_MESSAGE_PORT 9
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 { BITTORRENT_MESSAGE_EXTENDED
, "Extended" },
86 { AZUREUS_MESSAGE_KEEP_ALIVE
, "Keepalive" },
87 { AZUREUS_MESSAGE_HANDSHAKE
, "Azureus Handshake" },
88 { AZUREUS_MESSAGE_BT_HANDSHAKE
, "Azureus BitTorrent Handshake" },
89 { AZUREUS_MESSAGE_PEER_EXCHANGE
, "Azureus Peer Exchange" },
90 { AZUREUS_MESSAGE_JPC_HELLO
, "Azureus PeerCache Hello" },
91 { AZUREUS_MESSAGE_JPC_REPLY
, "Azureus PeerCache Reply" },
95 static const value_string azureus_priorities
[] = {
108 static const struct amp_message amp_messages
[] = {
109 { "BT_KEEP_ALIVE", AZUREUS_MESSAGE_KEEP_ALIVE
},
110 { "BT_CHOKE", BITTORRENT_MESSAGE_CHOKE
},
111 { "BT_UNCHOKE", BITTORRENT_MESSAGE_UNCHOKE
},
112 { "BT_INTERESTED", BITTORRENT_MESSAGE_INTERESTED
},
113 { "BT_UNINTERESTED", BITTORRENT_MESSAGE_NOT_INTERESTED
},
114 { "BT_HAVE", BITTORRENT_MESSAGE_HAVE
},
115 { "BT_BITFIELD", BITTORRENT_MESSAGE_BITFIELD
},
116 { "BT_REQUEST", BITTORRENT_MESSAGE_REQUEST
},
117 { "BT_PIECE", BITTORRENT_MESSAGE_PIECE
},
118 { "BT_CANCEL", BITTORRENT_MESSAGE_CANCEL
},
119 { "BT_PORT", BITTORRENT_MESSAGE_PORT
},
120 { "BT_EXTENDED", BITTORRENT_MESSAGE_EXTENDED
},
121 { "AZ_HANDSHAKE", AZUREUS_MESSAGE_HANDSHAKE
},
122 { "BT_HANDSHAKE", AZUREUS_MESSAGE_BT_HANDSHAKE
},
123 { "AZ_PEER_EXCHANGE", AZUREUS_MESSAGE_PEER_EXCHANGE
},
124 { "JPC_HELLO", AZUREUS_MESSAGE_JPC_HELLO
},
125 { "JPC_REPLY", AZUREUS_MESSAGE_JPC_REPLY
},
129 static dissector_handle_t dissector_handle
;
130 static int proto_bittorrent
= -1;
132 /* static gint hf_bittorrent_field_length = -1; */
133 static gint hf_bittorrent_prot_name_len
= -1;
134 static gint hf_bittorrent_prot_name
= -1;
135 static gint hf_bittorrent_reserved
= -1;
136 static gint hf_bittorrent_sha1_hash
= -1;
137 static gint hf_bittorrent_peer_id
= -1;
138 static gint hf_bittorrent_msg
= -1;
139 static gint hf_bittorrent_msg_len
= -1;
140 static gint hf_bittorrent_msg_type
= -1;
141 static gint hf_azureus_msg
= -1;
142 static gint hf_azureus_msg_type_len
= -1;
143 static gint hf_azureus_msg_type
= -1;
144 static gint hf_azureus_msg_prio
= -1;
145 static gint hf_bittorrent_bitfield_data
= -1;
146 static gint hf_bittorrent_piece_index
= -1;
147 static gint hf_bittorrent_piece_begin
= -1;
148 static gint hf_bittorrent_piece_length
= -1;
149 static gint hf_bittorrent_piece_data
= -1;
150 static gint hf_bittorrent_bstr_length
= -1;
151 static gint hf_bittorrent_bstr
= -1;
152 static gint hf_bittorrent_bint
= -1;
153 static gint hf_bittorrent_bdict
= -1;
154 static gint hf_bittorrent_bdict_entry
= -1;
155 static gint hf_bittorrent_blist
= -1;
156 static gint hf_azureus_jpc_addrlen
= -1;
157 static gint hf_azureus_jpc_addr
= -1;
158 static gint hf_azureus_jpc_port
= -1;
159 static gint hf_azureus_jpc_session
= -1;
160 static gint hf_bittorrent_port
= -1;
161 static gint hf_bittorrent_extended
= -1;
163 static gint ett_bittorrent
= -1;
164 static gint ett_bittorrent_msg
= -1;
165 static gint ett_peer_id
= -1;
166 static gint ett_bittorrent_bdict
= -1;
167 static gint ett_bittorrent_bdict_entry
= -1;
168 static gint ett_bittorrent_blist
= -1;
170 static gboolean bittorrent_desegment
= TRUE
;
171 static gboolean decode_client_information
= FALSE
;
173 struct client_information
{
174 char id
[5]; /* string length must be <= 4 to allow space for NUL termination byte */
176 const char *name
; /* NULL means array entry terminates the array */
179 static struct client_information peer_id
[] = {
182 {"-AR", 4, "Arctic"},
183 {"-AT", 4, "Artemis"},
184 {"-AV", 4, "Avicora"},
185 {"-AX", 4, "BitPump"},
186 {"-AZ", 4, "Azureus"},
187 {"-BB", 4, "BitBuddy"},
188 {"-BC", 4, "BitComet"},
189 {"-BF", 4, "Bitflu"},
190 {"-BG", 4, "BTG (uses Rasterbar libtorrent)"},
191 {"-BOW", 3, "Bits on Wheels"},
192 {"-BP", 4, "BitTorrent Pro (Azereus + spyware)"},
193 {"-BR", 4, "BitRocket"},
194 {"-BS", 4, "BTSlave"},
195 {"-BW", 4, "BitWombat"},
196 {"-BX", 4, "Bittorrent X"},
197 {"-CD", 4, "Enhanced CTorrent"},
198 {"-CT", 4, "CTorrent"},
199 {"-DE", 4, "DelugeTorrent"},
200 {"-DP", 4, "Propagate Data Client"},
202 {"-ES", 4, "electric sheep"},
203 {"-FC", 4, "FileCroc"},
204 {"-FG", 4, "FlashGet"},
205 {"-FT", 4, "FoxTorrent"},
206 {"-GS", 4, "GSTorrent"},
207 {"-HK", 4, "Hekate"},
208 {"-HL", 4, "Halite"},
209 {"-HN", 4, "Hydranode"},
211 {"-KT", 4, "KTorrent"},
212 {"-LC", 4, "LeechCraft"},
213 {"-LH", 4, "LH-ABC"},
214 {"-LP", 4, "Lphant"},
215 {"-LT", 4, "libtorrent"},
216 {"-lt", 4, "libTorrent"},
217 {"-LW", 4, "LimeWire"},
218 {"-MO", 4, "MonoTorrent"},
219 {"-MP", 4, "MooPolice"},
221 {"-MT", 4, "MoonlightTorrent"},
222 {"-NE", 4, "BT Next Evolution"},
223 {"-NX", 4, "Net Transport"},
224 {"-OS", 4, "OneSwarm"},
225 {"-OT", 4, "OmegaTorrent"},
227 {"-qB", 4, "qBittorrent"},
228 {"-QD", 4, "QQDownload"},
229 {"-QT", 4, "Qt 4 Torrent example"},
230 {"-RT", 4, "Retriever"},
231 {"-S~", 4, "Shareaza alpha/beta"},
232 {"-SB", 4, "Swiftbit"},
233 {"-SD", 4, "Thunder (aka XunLei)"},
234 {"-SS", 4, "SwarmScope"},
235 {"-ST", 4, "SymTorrent"},
236 {"-st", 4, "sharktorrent"},
237 {"-SZ", 4, "Shareaza"},
238 {"-TN", 4, "TorrentDotNET"},
239 {"-TR", 4, "Transmission"},
240 {"-TS", 4, "Torrentstorm"},
242 {"-UL", 4, "uLeecher!"},
243 {"-UM", 4, "(my)Torrent for Mac"},
244 {"-UT", 4, "(my)Torrent"},
246 {"-WT", 4, "BitLet"},
247 {"-WY", 4, "FireTorrent"},
248 {"-XL", 4, "Xunlei"},
249 {"-XT", 4, "XanTorrent"},
250 {"-XX", 4, "Xtorrent"},
251 {"-ZT", 4, "ZipTorrent"},
252 {"exbc", 2, "BitComet"},
255 {"XBT", 3, "XBT Client"},
257 {"O", 3, "Osprey Permaseed"},
260 {"S", 3, "Shadow's client"},
261 {"T", 3, "BitTornado"},
262 {"U", 3, "UPnP NAT Bit Torrent"},
267 get_bittorrent_pdu_length(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
272 if (tvb_get_guint8(tvb
, offset
) == 19 &&
273 tvb_memeql(tvb
, offset
+ 1, "BitTorrent protocol", 19) == 0) {
274 /* Return the length of a Handshake message */
275 return 1 + /* pstrlen */
278 20 + /* SHA1 hash of the info key */
281 /* Try to validate the length of the message indicated by the header. */
282 length
= tvb_get_ntohl(tvb
, offset
);
284 /* keep-alive - no message ID */
285 return BITTORRENT_HEADER_LENGTH
;
287 /* Do some sanity checking of the message, if we have the ID byte */
288 if(tvb_offset_exists(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
)) {
289 type
= tvb_get_guint8(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
);
290 if((type
<= BITTORRENT_MESSAGE_PORT
|| type
== BITTORRENT_MESSAGE_EXTENDED
) && length
<0x1000000) {
291 /* This seems to be a valid BitTorrent header with a known
293 return BITTORRENT_HEADER_LENGTH
+ length
;
295 /* The type is not known, so this message cannot be decoded
296 properly by this dissector. We assume it's continuation
297 data from the middle of a message, and just return the
298 remaining length in the tvbuff so the rest of the tvbuff
299 is displayed as continuation data. */
300 return tvb_length_remaining(tvb
, offset
);
303 /* We don't have the type field, so we can't determine
304 whether this is a valid message. For now, we assume
305 it's continuation data from the middle of a message,
306 and just return the remaining length in the tvbuff so
307 the rest of the tvbuff is displayed as continuation
309 return tvb_length_remaining(tvb
, offset
);
315 dissect_bencoding_str(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
316 int offset
, int length
, proto_tree
*tree
, proto_item
*ti
, int treeadd
)
319 int stringlen
= 0, nextstringlen
;
325 proto_tree_add_text(tree
, tvb
, offset
, length
, "Decode Aborted: Invalid String");
333 ch
= tvb_get_guint8(tvb
, offset
+used
);
337 if (ch
==':' && used
>1) {
338 if (stringlen
>length
|| stringlen
<0) {
340 proto_tree_add_text(tree
, tvb
, offset
, length
, "Decode Aborted: Invalid String Length");
345 proto_tree_add_uint(tree
, hf_bittorrent_bstr_length
, tvb
, offset
, used
, stringlen
);
346 proto_tree_add_item(tree
, hf_bittorrent_bstr
, tvb
, offset
+used
, stringlen
, ENC_ASCII
|ENC_NA
);
349 proto_item_append_text(ti
, " Key: %s", format_text((guchar
*)tvb_memdup(wmem_packet_scope(), tvb
, offset
+used
, stringlen
), stringlen
));
352 proto_item_append_text(ti
, " Value: %s", format_text((guchar
*)tvb_memdup(wmem_packet_scope(), tvb
, offset
+used
, stringlen
), stringlen
));
355 return used
+stringlen
;
358 if (!izero
&& ch
>='0' && ch
<='9') {
359 if (ch
=='0' && used
==1) {
363 nextstringlen
= (stringlen
* 10) + (ch
- '0');
364 if (nextstringlen
>=stringlen
) {
365 stringlen
= nextstringlen
;
371 proto_tree_add_text(tree
, tvb
, offset
, length
, "Decode Aborted: Invalid String");
377 proto_tree_add_text(tree
, tvb
, offset
, length
, "Truncated Data");
383 dissect_bencoding_int(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
384 int offset
, int length
, proto_tree
*tree
, proto_item
*ti
, int treeadd
)
394 proto_tree_add_text(tree
, tvb
, offset
, length
, "Decode Aborted: Invalid Integer");
403 ch
= tvb_get_guint8(tvb
, offset
+used
);
410 if (neg
) ival
= -ival
;
411 proto_tree_add_int(tree
, hf_bittorrent_bint
, tvb
, offset
, used
, ival
);
413 proto_item_append_text(ti
, " Value: %d", ival
);
426 if (!(ch
=='0' && used
==3 && neg
)) { /* -0 is invalid */
427 if (ch
=='0' && used
==2) { /* as is 0[0-9]+ */
431 if (!izero
&& ch
>='0' && ch
<='9') {
432 ival
= (ival
* 10) + (ch
- '0');
438 proto_tree_add_text(tree
, tvb
, offset
, length
, "Decode Aborted: Invalid Integer");
445 proto_tree_add_text(tree
, tvb
, offset
, length
, "Truncated Data");
451 dissect_bencoding_rec(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
452 int offset
, int length
, proto_tree
*tree
, int level
, proto_item
*treei
, int treeadd
)
455 int oplen
= 0, op1len
, op2len
;
458 proto_item
*ti
= NULL
, *td
= NULL
;
459 proto_tree
*itree
= NULL
, *dtree
= NULL
;
462 proto_tree_add_text(tree
, tvb
, offset
, -1, "Decode Aborted: Nested Too Deep");
466 proto_tree_add_text(tree
, tvb
, offset
, -1, "Truncated Data");
470 op
= tvb_get_guint8(tvb
, offset
);
472 oplen
= dissect_bencoding_rec(tvb
, pinfo
, offset
, length
, NULL
, level
, NULL
, 0);
473 if (oplen
<0) oplen
= length
;
479 td
= proto_tree_add_item(tree
, hf_bittorrent_bdict
, tvb
, offset
, oplen
, ENC_NA
);
480 dtree
= proto_item_add_subtree(td
, ett_bittorrent_bdict
);
487 op
= tvb_get_guint8(tvb
, offset
+used
);
493 op1len
= dissect_bencoding_str(tvb
, pinfo
, offset
+used
, length
, NULL
, NULL
, 0);
496 proto_tree_add_text(dtree
, tvb
, offset
+used
, -1, "Decode Aborted: Invalid Dictionary Key");
503 op2len
= dissect_bencoding_rec(tvb
, pinfo
, offset
+used
+op1len
, length
-op1len
, NULL
, level
+1, NULL
, 0);
506 proto_tree_add_text(dtree
, tvb
, offset
+used
+op1len
, -1, "Decode Aborted: Invalid Dictionary Value");
512 ti
= proto_tree_add_item(dtree
, hf_bittorrent_bdict_entry
, tvb
, offset
+used
, op1len
+op2len
, ENC_NA
);
513 itree
= proto_item_add_subtree(ti
, ett_bittorrent_bdict_entry
);
515 dissect_bencoding_str(tvb
, pinfo
, offset
+used
, length
, itree
, ti
, 1);
516 dissect_bencoding_rec(tvb
, pinfo
, offset
+used
+op1len
, length
-op1len
, itree
, level
+1, ti
, 2);
519 used
+= op1len
+op2len
;
520 length
-= op1len
+op2len
;
523 proto_tree_add_text(dtree
, tvb
, offset
+used
, -1, "Truncated Data");
529 ti
= proto_tree_add_item(tree
, hf_bittorrent_blist
, tvb
, offset
, oplen
, ENC_NA
);
530 itree
= proto_item_add_subtree(ti
, ett_bittorrent_blist
);
537 op
= tvb_get_guint8(tvb
, offset
+used
);
543 oplen
= dissect_bencoding_rec(tvb
, pinfo
, offset
+used
, length
, itree
, level
+1, ti
, 0);
544 if (oplen
<1) return oplen
;
550 proto_tree_add_text(itree
, tvb
, offset
+used
, -1, "Truncated Data");
555 return dissect_bencoding_int(tvb
, pinfo
, offset
, length
, tree
, treei
, treeadd
);
558 if (op
>='1' && op
<='9') {
559 return dissect_bencoding_str(tvb
, pinfo
, offset
, length
, tree
, treei
, treeadd
);
563 proto_tree_add_text(tree
, tvb
, offset
, -1, "Decode Aborted: Invalid Bencoding");
571 dissect_bencoding(tvbuff_t
*tvb
, packet_info
*pinfo _U_
,
572 int offset
, int length
, proto_tree
*tree
)
574 dissect_bencoding_rec(tvb
, pinfo
, offset
, length
, tree
, 0, NULL
, 0);
578 dissect_bittorrent_message (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
588 const char *msgtype
= NULL
;
590 guint32 piece_index
, piece_begin
, piece_length
;
593 if (tvb_bytes_exist(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
, 1)) {
594 /* Check for data from the middle of a message. */
595 length
= tvb_get_ntohl(tvb
, offset
);
596 type
= tvb_get_guint8(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
);
598 if (type
==BITTORRENT_MESSAGE_CHOKE
&& length
>4) {
600 * Choke messages have no payload, so this is likely an Azureus
601 * Messaging Protocol packet
603 if (!tvb_bytes_exist(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
, 4))
606 typelen
= tvb_get_ntohl(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
);
607 if (4+typelen
+1<=length
) {
608 if (!tvb_bytes_exist(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
+ 4, typelen
+1))
611 for ( i
=0 ; amp_messages
[i
].name
; i
++ ) {
612 if (strlen(amp_messages
[i
].name
)==typelen
&&
613 tvb_memeql(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
+ 4,
614 amp_messages
[i
].name
, (int)strlen(amp_messages
[i
].name
))==0) {
616 prio
= tvb_get_guint8(tvb
, offset
+ BITTORRENT_HEADER_LENGTH
+ 4 + typelen
);
617 if (prio
==0 || prio
==1 || prio
==2) {
618 type
= amp_messages
[i
].value
;
627 msgtype
= try_val_to_str(type
, bittorrent_messages
);
629 if (msgtype
== NULL
&& isamp
) {
630 msgtype
= try_val_to_str(type
, azureus_messages
);
633 if (msgtype
== NULL
) {
634 proto_tree_add_text(tree
, tvb
, offset
, -1, "Continuation data");
635 col_set_str(pinfo
->cinfo
, COL_INFO
, "Continuation data");
639 /* not enough bytes of the header, stop here */
644 ti
= proto_tree_add_item(tree
, hf_azureus_msg
, tvb
, offset
, length
+ BITTORRENT_HEADER_LENGTH
, ENC_NA
);
646 ti
= proto_tree_add_item(tree
, hf_bittorrent_msg
, tvb
, offset
, length
+ BITTORRENT_HEADER_LENGTH
, ENC_NA
);
648 mtree
= proto_item_add_subtree(ti
, ett_bittorrent_msg
);
650 /* Keepalive message */
652 proto_tree_add_item(mtree
, hf_bittorrent_msg_len
, tvb
, offset
, BITTORRENT_HEADER_LENGTH
, ENC_BIG_ENDIAN
);
653 col_set_str(pinfo
->cinfo
, COL_INFO
, "KeepAlive");
657 proto_tree_add_item(mtree
, hf_bittorrent_msg_len
, tvb
, offset
, BITTORRENT_HEADER_LENGTH
, ENC_BIG_ENDIAN
);
658 offset
+= BITTORRENT_HEADER_LENGTH
;
660 /* If the tvb_bytes_exist() call above returned FALSE, this will
661 throw an exception, so we won't use msgtype or type. */
663 proto_tree_add_item(mtree
, hf_azureus_msg_type_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
664 proto_tree_add_item(mtree
, hf_azureus_msg_type
, tvb
, offset
+4, typelen
, ENC_ASCII
|ENC_NA
);
665 proto_item_append_text(ti
, ": Len %u, %s", length
, msgtype
);
666 proto_tree_add_item(mtree
, hf_azureus_msg_prio
, tvb
, offset
+4+typelen
, 1, ENC_BIG_ENDIAN
);
667 offset
+= 4+typelen
+1;
668 length
-= 4+typelen
+1;
670 proto_tree_add_item(mtree
, hf_bittorrent_msg_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
671 proto_item_append_text(ti
, ": Len:%u, %s", length
, msgtype
);
675 col_set_str(pinfo
->cinfo
, COL_INFO
, msgtype
);
678 case BITTORRENT_MESSAGE_CHOKE
:
679 case BITTORRENT_MESSAGE_UNCHOKE
:
680 case BITTORRENT_MESSAGE_INTERESTED
:
681 case BITTORRENT_MESSAGE_NOT_INTERESTED
:
685 case BITTORRENT_MESSAGE_REQUEST
:
686 case BITTORRENT_MESSAGE_CANCEL
:
687 piece_index
= tvb_get_ntohl(tvb
, offset
);
688 proto_tree_add_uint(mtree
, hf_bittorrent_piece_index
, tvb
, offset
, 4, piece_index
); offset
+= 4;
689 piece_begin
= tvb_get_ntohl(tvb
, offset
);
690 proto_tree_add_uint(mtree
, hf_bittorrent_piece_begin
, tvb
, offset
, 4, piece_begin
); offset
+= 4;
691 piece_length
= tvb_get_ntohl(tvb
, offset
);
692 proto_tree_add_uint(mtree
, hf_bittorrent_piece_length
, tvb
, offset
, 4, piece_length
);
693 proto_item_append_text(ti
, ", Piece (Idx:0x%x,Begin:0x%x,Len:0x%x)", piece_index
, piece_begin
, piece_length
);
695 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Piece (Idx:0x%x,Begin:0x%x,Len:0x%x)", piece_index
, piece_begin
, piece_length
);
699 case BITTORRENT_MESSAGE_PORT
:
700 /* port as payload */
701 proto_tree_add_item(mtree
, hf_bittorrent_port
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
704 case BITTORRENT_MESSAGE_EXTENDED
:
705 /* extended message content */
706 proto_tree_add_item(mtree
, hf_bittorrent_extended
, tvb
, offset
, length
, ENC_NA
);
709 case BITTORRENT_MESSAGE_HAVE
:
710 piece_index
= tvb_get_ntohl(tvb
, offset
);
711 proto_tree_add_item(mtree
, hf_bittorrent_piece_index
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
712 proto_item_append_text(ti
, ", Piece (Idx:0x%x)", piece_index
);
714 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Piece (Idx:0x%x)", piece_index
);
718 case BITTORRENT_MESSAGE_BITFIELD
:
719 proto_tree_add_item(mtree
, hf_bittorrent_bitfield_data
, tvb
, offset
, length
, ENC_NA
);
720 proto_item_append_text(ti
, ", Len:0x%x", length
);
721 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Len:0x%x", length
);
725 case BITTORRENT_MESSAGE_PIECE
:
726 piece_index
= tvb_get_ntohl(tvb
, offset
);
727 proto_tree_add_uint(mtree
, hf_bittorrent_piece_index
, tvb
, offset
, 4, piece_index
);
730 piece_begin
= tvb_get_ntohl(tvb
, offset
);
731 proto_tree_add_uint(mtree
, hf_bittorrent_piece_begin
, tvb
, offset
, 4, piece_begin
);
734 proto_tree_add_item(mtree
, hf_bittorrent_piece_data
, tvb
, offset
, length
, ENC_NA
);
735 proto_item_append_text(ti
, ", Idx:0x%x,Begin:0x%x,Len:0x%x", piece_index
, piece_begin
, length
);
736 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Idx:0x%x,Begin:0x%x,Len:0x%x", piece_index
, piece_begin
, length
);
740 case AZUREUS_MESSAGE_HANDSHAKE
:
741 case AZUREUS_MESSAGE_PEER_EXCHANGE
:
742 dissect_bencoding(tvb
, pinfo
, offset
, length
, mtree
);
745 case AZUREUS_MESSAGE_JPC_HELLO
:
746 stringlen
= tvb_get_ntohl(tvb
, offset
);
747 proto_tree_add_item(mtree
, hf_azureus_jpc_addrlen
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
748 proto_tree_add_item(mtree
, hf_azureus_jpc_addr
, tvb
, offset
+4, stringlen
, ENC_ASCII
|ENC_NA
);
749 proto_tree_add_item(mtree
, hf_azureus_jpc_port
, tvb
, offset
+4+stringlen
, 4, ENC_BIG_ENDIAN
);
750 proto_tree_add_item(mtree
, hf_azureus_jpc_session
, tvb
, offset
+4+stringlen
+4, 4, ENC_BIG_ENDIAN
);
753 case AZUREUS_MESSAGE_JPC_REPLY
:
754 proto_tree_add_item(mtree
, hf_azureus_jpc_session
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
763 dissect_bittorrent_welcome (tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
)
769 col_set_str(pinfo
->cinfo
, COL_INFO
, "Handshake");
771 proto_tree_add_item(tree
, hf_bittorrent_prot_name_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
); offset
+=1;
772 proto_tree_add_item(tree
, hf_bittorrent_prot_name
, tvb
, offset
, 19, ENC_ASCII
|ENC_NA
); offset
+= 19;
773 proto_tree_add_item(tree
, hf_bittorrent_reserved
, tvb
, offset
, 8, ENC_NA
); offset
+= 8;
775 proto_tree_add_item(tree
, hf_bittorrent_sha1_hash
, tvb
, offset
, 20, ENC_NA
);
778 proto_tree_add_item(tree
, hf_bittorrent_peer_id
, tvb
, offset
, 20, ENC_NA
);
779 if(decode_client_information
) {
780 for(i
= 0; peer_id
[i
].name
!= NULL
; ++i
)
782 if(tvb_memeql(tvb
, offset
, peer_id
[i
].id
, (int)strlen(peer_id
[i
].id
)) == 0) {
783 version
= tvb_get_string(wmem_packet_scope(), tvb
, offset
+ (int)strlen(peer_id
[i
].id
),
785 proto_tree_add_text(tree
, tvb
, offset
, 20, "Client is %s v%s",
787 format_text((guchar
*)version
, peer_id
[i
].ver_len
));
797 int dissect_bittorrent_tcp_pdu (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
801 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "BitTorrent");
803 col_set_str(pinfo
->cinfo
, COL_INFO
, "BitTorrent ");
805 ti
= proto_tree_add_item (tree
, proto_bittorrent
, tvb
, 0, -1, ENC_NA
);
806 tree
= proto_item_add_subtree(ti
, ett_bittorrent
);
808 if (tvb_get_guint8(tvb
, 0) == 19 &&
809 tvb_memeql(tvb
, 1, "BitTorrent protocol", 19) == 0) {
810 dissect_bittorrent_welcome(tvb
, pinfo
, tree
);
812 dissect_bittorrent_message(tvb
, pinfo
, tree
);
815 col_append_str(pinfo
->cinfo
, COL_INFO
, " ");
816 col_set_fence(pinfo
->cinfo
, COL_INFO
);
818 return tvb_length(tvb
);
822 int dissect_bittorrent (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
824 tcp_dissect_pdus(tvb
, pinfo
, tree
, bittorrent_desegment
, BITTORRENT_HEADER_LENGTH
,
825 get_bittorrent_pdu_length
, dissect_bittorrent_tcp_pdu
, data
);
826 return tvb_length(tvb
);
830 gboolean
test_bittorrent_packet (tvbuff_t
*tvb
, packet_info
*pinfo
,
831 proto_tree
*tree
, void *data
)
833 conversation_t
*conversation
;
835 if (tvb_length(tvb
) >= 20 &&
836 tvb_get_guint8(tvb
, 0) == 19 &&
837 tvb_memeql(tvb
, 1, "BitTorrent protocol", 19) == 0) {
838 conversation
= find_or_create_conversation(pinfo
);
839 conversation_set_dissector(conversation
, dissector_handle
);
841 dissect_bittorrent(tvb
, pinfo
, tree
, data
);
850 proto_register_bittorrent(void)
852 static hf_register_info hf
[] = {
854 { &hf_bittorrent_field_length
,
855 { "Field Length", "bittorrent.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
858 { &hf_bittorrent_prot_name_len
,
859 { "Protocol Name Length", "bittorrent.protocol.name.length", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
861 { &hf_bittorrent_prot_name
,
862 { "Protocol Name", "bittorrent.protocol.name", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
864 { &hf_bittorrent_reserved
,
865 { "Reserved Extension Bytes", "bittorrent.reserved", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
867 { &hf_bittorrent_sha1_hash
,
868 { "SHA1 Hash of info dictionary", "bittorrent.info_hash", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
870 { &hf_bittorrent_peer_id
,
871 { "Peer ID", "bittorrent.peer_id", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
873 { &hf_bittorrent_msg
,
874 { "Message", "bittorrent.msg", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
876 { &hf_bittorrent_msg_len
,
877 { "Message Length", "bittorrent.msg.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
879 { &hf_bittorrent_msg_type
,
880 { "Message Type", "bittorrent.msg.type", FT_UINT8
, BASE_DEC
, VALS(bittorrent_messages
), 0x0, NULL
, HFILL
}
883 { "Azureus Message", "bittorrent.azureus_msg", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
885 { &hf_azureus_msg_type_len
,
886 { "Message Type Length", "bittorrent.msg.typelen", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
888 { &hf_azureus_msg_type
,
889 { "Message Type", "bittorrent.msg.aztype", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
891 { &hf_azureus_msg_prio
,
892 { "Message Priority", "bittorrent.msg.prio", FT_UINT8
, BASE_DEC
, VALS(azureus_priorities
), 0x0, NULL
, HFILL
}
894 { &hf_bittorrent_bitfield_data
,
895 { "Bitfield data", "bittorrent.msg.bitfield", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
897 { &hf_bittorrent_piece_index
,
898 { "Piece index", "bittorrent.piece.index", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
900 { &hf_bittorrent_piece_begin
,
901 { "Begin offset of piece", "bittorrent.piece.begin", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
903 { &hf_bittorrent_piece_data
,
904 { "Data in a piece", "bittorrent.piece.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
906 { &hf_bittorrent_piece_length
,
907 { "Piece Length", "bittorrent.piece.length", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
909 { &hf_bittorrent_bstr_length
,
910 { "String Length", "bittorrent.bstr.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
912 { &hf_bittorrent_bstr
,
913 { "String", "bittorrent.bstr", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
915 { &hf_bittorrent_bint
,
916 { "Integer", "bittorrent.bint", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
918 { &hf_bittorrent_bdict
,
919 { "Dictionary", "bittorrent.bdict", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
921 { &hf_bittorrent_bdict_entry
,
922 { "Entry", "bittorrent.bdict.entry", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
924 { &hf_bittorrent_blist
,
925 { "List", "bittorrent.blist", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
927 { &hf_azureus_jpc_addrlen
,
928 { "Cache Address Length", "bittorrent.jpc.addr.length", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
930 { &hf_azureus_jpc_addr
,
931 { "Cache Address", "bittorrent.jpc.addr", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
933 { &hf_azureus_jpc_port
,
934 { "Port", "bittorrent.jpc.port", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
936 { &hf_azureus_jpc_session
,
937 { "Session ID", "bittorrent.jpc.session", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
939 { &hf_bittorrent_port
,
940 { "Port", "bittorrent.port", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
942 { &hf_bittorrent_extended
,
943 { "Extended Message", "bittorrent.extended", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
947 static gint
*ett
[] = {
951 &ett_bittorrent_bdict
,
952 &ett_bittorrent_bdict_entry
,
953 &ett_bittorrent_blist
956 module_t
*bittorrent_module
;
958 proto_bittorrent
= proto_register_protocol("BitTorrent", "BitTorrent", "bittorrent");
959 proto_register_field_array(proto_bittorrent
, hf
, array_length(hf
));
960 proto_register_subtree_array(ett
, array_length(ett
));
962 new_register_dissector("bittorrent.tcp", dissect_bittorrent
, proto_bittorrent
);
964 bittorrent_module
= prefs_register_protocol(proto_bittorrent
, NULL
);
965 prefs_register_bool_preference(bittorrent_module
, "desegment",
966 "Reassemble BitTorrent messages spanning multiple TCP segments",
967 "Whether the BitTorrent dissector should reassemble messages spanning multiple TCP segments."
968 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
969 &bittorrent_desegment
);
970 prefs_register_bool_preference(bittorrent_module
, "decode_client",
971 "Decode the peer_id of the handshake messages",
972 "Enabling this will tell which BitTorrent client that produced the handshake message",
973 &decode_client_information
);
978 proto_reg_handoff_bittorrent(void)
980 dissector_handle
= find_dissector("bittorrent.tcp");
982 dissector_add_uint("tcp.port", 6881, dissector_handle
);
983 dissector_add_uint("tcp.port", 6882, dissector_handle
);
984 dissector_add_uint("tcp.port", 6883, dissector_handle
);
985 dissector_add_uint("tcp.port", 6884, dissector_handle
);
986 dissector_add_uint("tcp.port", 6885, dissector_handle
);
987 dissector_add_uint("tcp.port", 6886, dissector_handle
);
988 dissector_add_uint("tcp.port", 6887, dissector_handle
);
989 dissector_add_uint("tcp.port", 6888, dissector_handle
);
990 dissector_add_uint("tcp.port", 6889, dissector_handle
);
992 heur_dissector_add("tcp", test_bittorrent_packet
, proto_bittorrent
);
1001 * indent-tabs-mode: nil
1004 * ex: set shiftwidth=3 tabstop=8 expandtab:
1005 * :indentSize=3:tabSize=8:noTabs=true: