/src/wireshark/epan/dissectors/packet-bittorrent.c
Line | Count | Source |
1 | | /* packet-bittorrent.c |
2 | | * Routines for bittorrent packet dissection |
3 | | * Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * Copied from packet-pop.c |
10 | | * |
11 | | * SPDX-License-Identifier: GPL-2.0-or-later |
12 | | */ |
13 | | |
14 | | #include "config.h" |
15 | | |
16 | | #include <epan/packet.h> |
17 | | #include <epan/prefs.h> |
18 | | #include <epan/strutil.h> |
19 | | |
20 | | #include "packet-tcp.h" |
21 | | #include "packet-bt-utp.h" |
22 | | |
23 | | void proto_register_bittorrent(void); |
24 | | void proto_reg_handoff_bittorrent(void); |
25 | | |
26 | | /* |
27 | | * See |
28 | | * |
29 | | * http://bittorrent.com/protocol.html |
30 | | * http://wiki.theory.org/BitTorrentSpecification |
31 | | * http://bitconjurer.org/BitTorrent/protocol.html |
32 | | */ |
33 | | |
34 | 15 | #define DEFAULT_TCP_PORT_RANGE "6881-6889" /* Not IANA registered */ |
35 | | |
36 | 146 | #define BITTORRENT_MESSAGE_CHOKE 0 |
37 | 21 | #define BITTORRENT_MESSAGE_UNCHOKE 1 |
38 | 21 | #define BITTORRENT_MESSAGE_INTERESTED 2 |
39 | 23 | #define BITTORRENT_MESSAGE_NOT_INTERESTED 3 |
40 | 0 | #define BITTORRENT_MESSAGE_HAVE 4 |
41 | 49 | #define BITTORRENT_MESSAGE_BITFIELD 5 |
42 | 2 | #define BITTORRENT_MESSAGE_REQUEST 6 |
43 | 4 | #define BITTORRENT_MESSAGE_PIECE 7 |
44 | 2 | #define BITTORRENT_MESSAGE_CANCEL 8 |
45 | 2 | #define BITTORRENT_MESSAGE_PORT 9 |
46 | | /* |
47 | | * BitTorrent BEP 06 |
48 | | * Fast Extension message type |
49 | | * |
50 | | */ |
51 | 2 | #define BITT_FAST_EX_SUGGEST_PIECE 13 |
52 | 23 | #define BITT_FAST_EX_HAVE_ALL 14 |
53 | 25 | #define BITT_FAST_EX_HAVE_NONE 15 |
54 | 4 | #define BITT_FAST_EX_REJECT_REQUEST 16 |
55 | 4 | #define BITT_FAST_EX_ALLOWED_FAST 17 |
56 | 4 | #define BITTORRENT_MESSAGE_EXTENDED 20 |
57 | | |
58 | 653 | #define BITTORRENT_HEADER_LENGTH 4 |
59 | | |
60 | | /* |
61 | | * Azureus messages are specified by name so these are made up numbers |
62 | | * for internal identification only. |
63 | | * |
64 | | * Standard BT message types are a single byte, so these won't clash |
65 | | */ |
66 | 49 | #define AZUREUS_MESSAGE_HANDSHAKE 256 |
67 | 49 | #define AZUREUS_MESSAGE_KEEP_ALIVE 257 |
68 | 49 | #define AZUREUS_MESSAGE_BT_HANDSHAKE 258 |
69 | 49 | #define AZUREUS_MESSAGE_PEER_EXCHANGE 259 |
70 | 49 | #define AZUREUS_MESSAGE_JPC_HELLO 260 |
71 | 49 | #define AZUREUS_MESSAGE_JPC_REPLY 261 |
72 | | |
73 | | |
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_HANDSHAKE, "Azureus Handshake" }, |
92 | | { AZUREUS_MESSAGE_KEEP_ALIVE, "Keepalive" }, |
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 } |
98 | | }; |
99 | | |
100 | | static const value_string azureus_priorities[] = { |
101 | | { 0, "Low" }, |
102 | | { 1, "Normal" }, |
103 | | { 2, "High" }, |
104 | | { 0, NULL } |
105 | | }; |
106 | | |
107 | | |
108 | | struct amp_message { |
109 | | const char *name; |
110 | | uint32_t value; |
111 | | }; |
112 | | |
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 } |
137 | | }; |
138 | | |
139 | | static dissector_handle_t dissector_handle; |
140 | | static dissector_handle_t bencode_handle; |
141 | | static int proto_bittorrent; |
142 | | |
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; |
170 | | |
171 | | static int ett_bittorrent; |
172 | | static int ett_bittorrent_msg; |
173 | | static int ett_peer_id; |
174 | | |
175 | | static bool bittorrent_desegment = true; |
176 | | static bool decode_client_information; |
177 | | |
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 */ |
182 | | }; |
183 | | |
184 | | static const 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} |
269 | | }; |
270 | | |
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. |
275 | | */ |
276 | | static bool |
277 | | test_type_length(uint16_t type, uint32_t length) |
278 | 72 | { |
279 | 72 | switch (type) { |
280 | | |
281 | 2 | case BITTORRENT_MESSAGE_UNCHOKE: |
282 | 2 | case BITTORRENT_MESSAGE_INTERESTED: |
283 | 4 | case BITTORRENT_MESSAGE_NOT_INTERESTED: |
284 | 4 | case BITT_FAST_EX_HAVE_ALL: |
285 | 6 | case BITT_FAST_EX_HAVE_NONE: |
286 | | /* No payload */ |
287 | 6 | if (length != 1) { |
288 | 6 | return false; |
289 | 6 | } |
290 | 0 | return true; |
291 | | |
292 | 2 | case BITTORRENT_MESSAGE_PORT: |
293 | 2 | if (length != 3) { |
294 | 2 | return false; |
295 | 2 | } |
296 | 0 | return true; |
297 | | |
298 | 0 | case BITTORRENT_MESSAGE_HAVE: |
299 | 2 | case BITT_FAST_EX_SUGGEST_PIECE: |
300 | 4 | case BITT_FAST_EX_ALLOWED_FAST: |
301 | 4 | if (length != 5) { |
302 | 4 | return false; |
303 | 4 | } |
304 | 0 | return true; |
305 | | |
306 | 2 | case BITTORRENT_MESSAGE_REQUEST: |
307 | 2 | case BITTORRENT_MESSAGE_CANCEL: |
308 | 4 | case BITT_FAST_EX_REJECT_REQUEST: |
309 | 4 | if (length != 13) { |
310 | 4 | return false; |
311 | 4 | } |
312 | 0 | return true; |
313 | | |
314 | | /* Now to the messages that can have variable and longer lengths. */ |
315 | | |
316 | 4 | case BITTORRENT_MESSAGE_EXTENDED: |
317 | 4 | 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. |
323 | | * |
324 | | * This is excessively long for any extension message. |
325 | | */ |
326 | 4 | if (length > 0x4009) { |
327 | 4 | return false; |
328 | 4 | } |
329 | 0 | return true; |
330 | | |
331 | 49 | 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. |
339 | | */ |
340 | 49 | case AZUREUS_MESSAGE_HANDSHAKE: |
341 | 49 | case AZUREUS_MESSAGE_KEEP_ALIVE: |
342 | 49 | case AZUREUS_MESSAGE_BT_HANDSHAKE: |
343 | 49 | case AZUREUS_MESSAGE_PEER_EXCHANGE: |
344 | 49 | case AZUREUS_MESSAGE_JPC_HELLO: |
345 | 49 | case AZUREUS_MESSAGE_JPC_REPLY: |
346 | 49 | 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. |
354 | | * |
355 | | * 0x20000 allows 0x100000 pieces, or over a million. That's more |
356 | | * than most clients support, and cuts down on false positives. |
357 | | */ |
358 | 49 | if (length > 0x20000) { |
359 | 11 | return false; |
360 | 11 | } |
361 | 38 | return true; |
362 | | |
363 | 3 | default: |
364 | 3 | if (!try_val_to_str(type, bittorrent_messages)) { |
365 | 3 | return false; |
366 | 3 | } |
367 | 72 | } |
368 | | |
369 | 0 | return true; |
370 | 72 | } |
371 | | |
372 | | static unsigned |
373 | | get_bittorrent_pdu_length(packet_info *pinfo _U_, tvbuff_t *tvb, |
374 | | int offset, void *data _U_) |
375 | 157 | { |
376 | 157 | uint8_t type; |
377 | 157 | uint32_t length; |
378 | | |
379 | 157 | if (tvb_get_uint8(tvb, offset) == 19 && |
380 | 5 | tvb_memeql(tvb, offset + 1, (const uint8_t*)"BitTorrent protocol", 19) == 0) { |
381 | | /* Return the length of a Handshake message */ |
382 | 5 | return 1 + /* pstrlen */ |
383 | 5 | 19 + /* pstr */ |
384 | 5 | 8 + /* reserved */ |
385 | 5 | 20 + /* SHA1 hash of the info key */ |
386 | 5 | 20; /* peer id */ |
387 | 152 | } else { |
388 | | /* Try to validate the length of the message indicated by the header. */ |
389 | 152 | length = tvb_get_ntohl(tvb, offset); |
390 | 152 | if(length == 0) { |
391 | | /* keep-alive - no message ID */ |
392 | 113 | return BITTORRENT_HEADER_LENGTH; |
393 | 113 | } |
394 | | /* Do some sanity checking of the message, if we have the ID byte */ |
395 | 39 | if(tvb_offset_exists(tvb, offset + BITTORRENT_HEADER_LENGTH)) { |
396 | 39 | type = tvb_get_uint8(tvb, offset + BITTORRENT_HEADER_LENGTH); |
397 | 39 | 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 | 19 | return BITTORRENT_HEADER_LENGTH + length; |
401 | 20 | } 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 | 20 | return tvb_reported_length_remaining(tvb, offset); |
408 | 20 | } |
409 | 39 | } 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 | 0 | return 0; |
415 | 0 | } |
416 | 39 | } |
417 | 157 | } |
418 | | |
419 | | static void |
420 | | dissect_bittorrent_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
421 | 152 | { |
422 | 152 | int offset = 0; |
423 | 152 | int i; |
424 | 152 | int isamp = 0; |
425 | 152 | proto_tree *mtree; |
426 | 152 | uint16_t type = 0; |
427 | 152 | uint32_t typelen = 0; |
428 | 152 | uint8_t prio = 0; |
429 | 152 | uint32_t ext_id = 0; |
430 | 152 | uint32_t length; |
431 | 152 | const char *msgtype = NULL; |
432 | 152 | proto_item *ti; |
433 | 152 | uint32_t piece_index, piece_begin, piece_length; |
434 | 152 | uint32_t stringlen; |
435 | 152 | tvbuff_t *subtvb; |
436 | | |
437 | | /* Guaranteed BITTORRENT_HEADER_LENGTH by tcp_dissect_pdus */ |
438 | 152 | length = tvb_get_ntohl(tvb, offset); |
439 | | |
440 | | /* Keepalive message */ |
441 | 152 | if (length == 0) { |
442 | 113 | ti = proto_tree_add_item(tree, hf_bittorrent_msg, tvb, offset, length + BITTORRENT_HEADER_LENGTH, ENC_NA); |
443 | 113 | mtree = proto_item_add_subtree(ti, ett_bittorrent_msg); |
444 | 113 | proto_tree_add_item(mtree, hf_bittorrent_msg_len, tvb, offset, BITTORRENT_HEADER_LENGTH, ENC_BIG_ENDIAN); |
445 | 113 | col_set_str(pinfo->cinfo, COL_INFO, "KeepAlive"); |
446 | 113 | return; |
447 | 113 | } |
448 | | |
449 | 39 | if (tvb_bytes_exist(tvb, offset + BITTORRENT_HEADER_LENGTH, 1)) { |
450 | | /* Check for data from the middle of a message. */ |
451 | 39 | type = tvb_get_uint8(tvb, offset + BITTORRENT_HEADER_LENGTH); |
452 | | |
453 | 39 | if (type==BITTORRENT_MESSAGE_CHOKE && length>4) { |
454 | | /* |
455 | | * Choke messages have no payload, so this is likely an Azureus |
456 | | * Messaging Protocol packet |
457 | | */ |
458 | 20 | if (!tvb_bytes_exist(tvb, offset + BITTORRENT_HEADER_LENGTH, 4)) |
459 | 1 | return; |
460 | | |
461 | 19 | typelen = tvb_get_ntohl(tvb, offset + BITTORRENT_HEADER_LENGTH); |
462 | 19 | if (4+typelen+1<=length) { |
463 | 13 | if (!tvb_bytes_exist(tvb, offset + BITTORRENT_HEADER_LENGTH + 4, typelen+1)) |
464 | 2 | return; |
465 | | |
466 | 253 | for ( i=0 ; amp_messages[i].name ; i++ ) { |
467 | 242 | if (strlen(amp_messages[i].name)==typelen && |
468 | 5 | tvb_strneql(tvb, offset + BITTORRENT_HEADER_LENGTH + 4, |
469 | 5 | amp_messages[i].name, (int)strlen(amp_messages[i].name))==0) { |
470 | |
|
471 | 0 | prio = tvb_get_uint8(tvb, offset + BITTORRENT_HEADER_LENGTH + 4 + typelen); |
472 | 0 | if (prio==0 || prio==1 || prio==2) { |
473 | 0 | type = amp_messages[i].value; |
474 | 0 | isamp = 1; |
475 | 0 | } |
476 | 0 | break; |
477 | 0 | } |
478 | 242 | } |
479 | 11 | } |
480 | 19 | } |
481 | | |
482 | 36 | 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); |
486 | | } |
487 | | #endif |
488 | 36 | 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. |
493 | | */ |
494 | 17 | proto_tree_add_item(tree, hf_bittorrent_continuous_data, tvb, offset, -1, ENC_NA); |
495 | 17 | col_set_str(pinfo->cinfo, COL_INFO, "Continuation data"); |
496 | 17 | return; |
497 | 17 | } |
498 | 36 | } else { |
499 | | /* not enough bytes of the header, stop here */ |
500 | 0 | return; |
501 | 0 | } |
502 | | |
503 | 19 | if (isamp) { |
504 | 0 | ti = proto_tree_add_item(tree, hf_azureus_msg, tvb, offset, length + BITTORRENT_HEADER_LENGTH, ENC_NA); |
505 | 19 | } else { |
506 | 19 | ti = proto_tree_add_item(tree, hf_bittorrent_msg, tvb, offset, length + BITTORRENT_HEADER_LENGTH, ENC_NA); |
507 | 19 | } |
508 | 19 | mtree = proto_item_add_subtree(ti, ett_bittorrent_msg); |
509 | | |
510 | 19 | proto_tree_add_item(mtree, hf_bittorrent_msg_len, tvb, offset, BITTORRENT_HEADER_LENGTH, ENC_BIG_ENDIAN); |
511 | 19 | offset += BITTORRENT_HEADER_LENGTH; |
512 | | |
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 | 19 | if (isamp) { |
516 | 0 | proto_tree_add_item(mtree, hf_azureus_msg_type_len, tvb, offset, 4, ENC_BIG_ENDIAN); |
517 | 0 | proto_tree_add_item(mtree, hf_azureus_msg_type, tvb, offset+4, typelen, ENC_ASCII); |
518 | 0 | proto_item_append_text(ti, ": Len %u, %s", length, msgtype); |
519 | 0 | proto_tree_add_item(mtree, hf_azureus_msg_prio, tvb, offset+4+typelen, 1, ENC_BIG_ENDIAN); |
520 | 0 | offset += 4+typelen+1; |
521 | 0 | length -= 4+typelen+1; |
522 | 19 | } else { |
523 | 19 | proto_tree_add_item(mtree, hf_bittorrent_msg_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
524 | 19 | proto_item_append_text(ti, ": Len:%u, %s", length, msgtype); |
525 | 19 | offset += 1; |
526 | 19 | length -= 1; |
527 | 19 | } |
528 | 19 | col_set_str(pinfo->cinfo, COL_INFO, msgtype); |
529 | | |
530 | 19 | switch (type) { |
531 | 19 | case BITTORRENT_MESSAGE_CHOKE: |
532 | 19 | case BITTORRENT_MESSAGE_UNCHOKE: |
533 | 19 | case BITTORRENT_MESSAGE_INTERESTED: |
534 | 19 | case BITTORRENT_MESSAGE_NOT_INTERESTED: |
535 | 19 | case BITT_FAST_EX_HAVE_ALL: |
536 | 19 | case BITT_FAST_EX_HAVE_NONE: |
537 | | /* No payload */ |
538 | 19 | break; |
539 | | |
540 | 0 | case BITTORRENT_MESSAGE_REQUEST: |
541 | 0 | case BITTORRENT_MESSAGE_CANCEL: |
542 | 0 | case BITT_FAST_EX_REJECT_REQUEST: |
543 | 0 | proto_tree_add_item_ret_uint(mtree, hf_bittorrent_piece_index, tvb, offset, 4, ENC_BIG_ENDIAN, &piece_index); offset += 4; |
544 | 0 | proto_tree_add_item_ret_uint(mtree, hf_bittorrent_piece_begin, tvb, offset, 4, ENC_BIG_ENDIAN, &piece_begin); offset += 4; |
545 | 0 | proto_tree_add_item_ret_uint(mtree, hf_bittorrent_piece_length, tvb, offset, 4, ENC_BIG_ENDIAN, &piece_length); |
546 | 0 | proto_item_append_text(ti, ", Piece (Idx:0x%x,Begin:0x%x,Len:0x%x)", piece_index, piece_begin, piece_length); |
547 | |
|
548 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", Piece (Idx:0x%x,Begin:0x%x,Len:0x%x)", piece_index, piece_begin, piece_length); |
549 | |
|
550 | 0 | break; |
551 | | |
552 | 0 | case BITTORRENT_MESSAGE_PORT: |
553 | | /* port as payload */ |
554 | 0 | proto_tree_add_item(mtree, hf_bittorrent_port, tvb, offset, 2, ENC_BIG_ENDIAN); |
555 | 0 | break; |
556 | | |
557 | 0 | case BITTORRENT_MESSAGE_EXTENDED: |
558 | | /* extended message content */ |
559 | 0 | proto_tree_add_item_ret_uint(mtree, hf_bittorrent_extended_id, tvb, offset, 1, ENC_NA, &ext_id); |
560 | 0 | offset += 1; |
561 | 0 | length -= 1; |
562 | 0 | if (ext_id == 0) { |
563 | 0 | call_dissector(bencode_handle, tvb_new_subset_length(tvb, offset, length), pinfo, mtree); |
564 | 0 | } else { |
565 | 0 | proto_tree_add_item(mtree, hf_bittorrent_extended, tvb, offset, length, ENC_NA); |
566 | 0 | } |
567 | 0 | break; |
568 | | |
569 | 0 | case BITTORRENT_MESSAGE_HAVE: |
570 | 0 | case BITT_FAST_EX_SUGGEST_PIECE: |
571 | 0 | case BITT_FAST_EX_ALLOWED_FAST: |
572 | 0 | proto_tree_add_item_ret_uint(mtree, hf_bittorrent_piece_index, tvb, offset, 4, ENC_BIG_ENDIAN, &piece_index); |
573 | 0 | proto_item_append_text(ti, ", Piece (Idx:0x%x)", piece_index); |
574 | |
|
575 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", Piece (Idx:0x%x)", piece_index); |
576 | |
|
577 | 0 | break; |
578 | | |
579 | 0 | case BITTORRENT_MESSAGE_BITFIELD: |
580 | 0 | proto_tree_add_item(mtree, hf_bittorrent_bitfield_data, tvb, offset, length, ENC_NA); |
581 | 0 | proto_item_append_text(ti, ", Len:0x%x", length); |
582 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", Len:0x%x", length); |
583 | |
|
584 | 0 | break; |
585 | | |
586 | 0 | case BITTORRENT_MESSAGE_PIECE: |
587 | 0 | piece_index = tvb_get_ntohl(tvb, offset); |
588 | 0 | proto_tree_add_uint(mtree, hf_bittorrent_piece_index, tvb, offset, 4, piece_index); |
589 | 0 | offset += 4; |
590 | 0 | length -= 4; |
591 | 0 | piece_begin = tvb_get_ntohl(tvb, offset); |
592 | 0 | proto_tree_add_uint(mtree, hf_bittorrent_piece_begin, tvb, offset, 4, piece_begin); |
593 | 0 | offset += 4; |
594 | 0 | length -= 4; |
595 | 0 | proto_tree_add_item(mtree, hf_bittorrent_piece_data, tvb, offset, length, ENC_NA); |
596 | 0 | proto_item_append_text(ti, ", Idx:0x%x,Begin:0x%x,Len:0x%x", piece_index, piece_begin, length); |
597 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", Idx:0x%x,Begin:0x%x,Len:0x%x", piece_index, piece_begin, length); |
598 | |
|
599 | 0 | break; |
600 | | |
601 | 0 | case AZUREUS_MESSAGE_HANDSHAKE: |
602 | 0 | case AZUREUS_MESSAGE_PEER_EXCHANGE: |
603 | 0 | subtvb = tvb_new_subset_length(tvb, offset, length); |
604 | 0 | call_dissector(bencode_handle, subtvb, pinfo, mtree); |
605 | 0 | break; |
606 | | |
607 | 0 | case AZUREUS_MESSAGE_JPC_HELLO: |
608 | 0 | stringlen = tvb_get_ntohl(tvb, offset); |
609 | 0 | proto_tree_add_item(mtree, hf_azureus_jpc_addrlen, tvb, offset, 4, ENC_BIG_ENDIAN); |
610 | 0 | proto_tree_add_item(mtree, hf_azureus_jpc_addr, tvb, offset+4, stringlen, ENC_ASCII); |
611 | 0 | proto_tree_add_item(mtree, hf_azureus_jpc_port, tvb, offset+4+stringlen, 4, ENC_BIG_ENDIAN); |
612 | 0 | proto_tree_add_item(mtree, hf_azureus_jpc_session, tvb, offset+4+stringlen+4, 4, ENC_BIG_ENDIAN); |
613 | 0 | break; |
614 | | |
615 | 0 | case AZUREUS_MESSAGE_JPC_REPLY: |
616 | 0 | proto_tree_add_item(mtree, hf_azureus_jpc_session, tvb, offset, 4, ENC_BIG_ENDIAN); |
617 | 0 | break; |
618 | | |
619 | 0 | default: |
620 | 0 | break; |
621 | 19 | } |
622 | 19 | } |
623 | | |
624 | | static int |
625 | | dissect_bittorrent_welcome (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
626 | 5 | { |
627 | 5 | int offset = 0; |
628 | 5 | int i; |
629 | 5 | char *version; |
630 | | |
631 | 5 | col_set_str(pinfo->cinfo, COL_INFO, "Handshake"); |
632 | | |
633 | 5 | proto_tree_add_item(tree, hf_bittorrent_prot_name_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset+=1; |
634 | 5 | proto_tree_add_item(tree, hf_bittorrent_prot_name, tvb, offset, 19, ENC_ASCII); offset += 19; |
635 | 5 | proto_tree_add_item(tree, hf_bittorrent_reserved, tvb, offset, 8, ENC_NA); offset += 8; |
636 | | |
637 | 5 | proto_tree_add_item(tree, hf_bittorrent_sha1_hash, tvb, offset, 20, ENC_NA); |
638 | 5 | offset += 20; |
639 | | |
640 | 5 | proto_tree_add_item(tree, hf_bittorrent_peer_id, tvb, offset, 20, ENC_NA); |
641 | 5 | if(decode_client_information) { |
642 | 0 | for(i = 0; peer_id[i].name != NULL; ++i) |
643 | 0 | { |
644 | 0 | if(tvb_memeql(tvb, offset, (const uint8_t*)peer_id[i].id, (int)strlen(peer_id[i].id)) == 0) { |
645 | 0 | version = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset + (int)strlen(peer_id[i].id), |
646 | 0 | peer_id[i].ver_len, ENC_ASCII); |
647 | 0 | proto_tree_add_string_format(tree, hf_bittorrent_version, tvb, offset, 20, version, "Client is %s v%s", |
648 | 0 | peer_id[i].name, format_text(pinfo->pool, version, peer_id[i].ver_len)); |
649 | 0 | break; |
650 | 0 | } |
651 | 0 | } |
652 | 0 | } |
653 | 5 | offset += 20; |
654 | 5 | return offset; |
655 | 5 | } |
656 | | |
657 | | static |
658 | | int dissect_bittorrent_tcp_pdu (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
659 | 157 | { |
660 | 157 | proto_item *ti; |
661 | | |
662 | 157 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "BitTorrent"); |
663 | | |
664 | 157 | col_set_str(pinfo->cinfo, COL_INFO, "BitTorrent "); |
665 | | |
666 | 157 | ti = proto_tree_add_item (tree, proto_bittorrent, tvb, 0, -1, ENC_NA); |
667 | 157 | tree = proto_item_add_subtree(ti, ett_bittorrent); |
668 | | |
669 | 157 | if (tvb_get_uint8(tvb, 0) == 19 && |
670 | 5 | tvb_memeql(tvb, 1, (const uint8_t*)"BitTorrent protocol", 19) == 0) { |
671 | 5 | dissect_bittorrent_welcome(tvb, pinfo, tree); |
672 | 152 | } else { |
673 | 152 | dissect_bittorrent_message(tvb, pinfo, tree); |
674 | 152 | } |
675 | | |
676 | 157 | col_append_str(pinfo->cinfo, COL_INFO, " "); |
677 | 157 | col_set_fence(pinfo->cinfo, COL_INFO); |
678 | | |
679 | 157 | return tvb_reported_length(tvb); |
680 | 157 | } |
681 | | |
682 | | static |
683 | | int dissect_bittorrent (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
684 | 25 | { |
685 | 25 | tcp_dissect_pdus(tvb, pinfo, tree, bittorrent_desegment, BITTORRENT_HEADER_LENGTH, |
686 | 25 | get_bittorrent_pdu_length, dissect_bittorrent_tcp_pdu, data); |
687 | 25 | return tvb_reported_length(tvb); |
688 | 25 | } |
689 | | |
690 | | static |
691 | | int dissect_bittorrent_utp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
692 | 0 | { |
693 | 0 | utp_dissect_pdus(tvb, pinfo, tree, bittorrent_desegment, BITTORRENT_HEADER_LENGTH, |
694 | 0 | get_bittorrent_pdu_length, dissect_bittorrent_tcp_pdu, data); |
695 | 0 | return tvb_reported_length(tvb); |
696 | 0 | } |
697 | | |
698 | | static |
699 | | bool test_bittorrent_packet (tvbuff_t *tvb, packet_info *pinfo, |
700 | | proto_tree *tree, void *data) |
701 | 1.66k | { |
702 | 1.66k | conversation_t *conversation; |
703 | | |
704 | 1.66k | if (tvb_captured_length(tvb) >= 20 && |
705 | 1.15k | tvb_get_uint8(tvb, 0) == 19 && |
706 | 4 | tvb_memeql(tvb, 1, (const uint8_t*)"BitTorrent protocol", 19) == 0) { |
707 | 2 | conversation = find_or_create_conversation(pinfo); |
708 | 2 | conversation_set_dissector(conversation, dissector_handle); |
709 | | |
710 | 2 | dissect_bittorrent(tvb, pinfo, tree, data); |
711 | | |
712 | 2 | return true; |
713 | 2 | } |
714 | | |
715 | 1.66k | return false; |
716 | 1.66k | } |
717 | | |
718 | | void |
719 | | proto_register_bittorrent(void) |
720 | 15 | { |
721 | 15 | static hf_register_info hf[] = { |
722 | | #if 0 |
723 | | { &hf_bittorrent_field_length, |
724 | | { "Field Length", "bittorrent.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } |
725 | | }, |
726 | | #endif |
727 | 15 | { &hf_bittorrent_prot_name_len, |
728 | 15 | { "Protocol Name Length", "bittorrent.protocol.name.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } |
729 | 15 | }, |
730 | 15 | { &hf_bittorrent_prot_name, |
731 | 15 | { "Protocol Name", "bittorrent.protocol.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } |
732 | 15 | }, |
733 | 15 | { &hf_bittorrent_reserved, |
734 | 15 | { "Reserved Extension Bytes", "bittorrent.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } |
735 | 15 | }, |
736 | 15 | { &hf_bittorrent_sha1_hash, |
737 | 15 | { "SHA1 Hash of info dictionary", "bittorrent.info_hash", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } |
738 | 15 | }, |
739 | 15 | { &hf_bittorrent_peer_id, |
740 | 15 | { "Peer ID", "bittorrent.peer_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } |
741 | 15 | }, |
742 | 15 | { &hf_bittorrent_msg, |
743 | 15 | { "Message", "bittorrent.msg", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } |
744 | 15 | }, |
745 | 15 | { &hf_bittorrent_msg_len, |
746 | 15 | { "Message Length", "bittorrent.msg.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } |
747 | 15 | }, |
748 | 15 | { &hf_bittorrent_msg_type, |
749 | 15 | { "Message Type", "bittorrent.msg.type", FT_UINT16, BASE_DEC, VALS(bittorrent_messages), 0x0, NULL, HFILL } |
750 | 15 | }, |
751 | 15 | { &hf_azureus_msg, |
752 | 15 | { "Azureus Message", "bittorrent.azureus_msg", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } |
753 | 15 | }, |
754 | 15 | { &hf_azureus_msg_type_len, |
755 | 15 | { "Message Type Length", "bittorrent.msg.typelen", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } |
756 | 15 | }, |
757 | 15 | { &hf_azureus_msg_type, |
758 | 15 | { "Message Type", "bittorrent.msg.aztype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } |
759 | 15 | }, |
760 | 15 | { &hf_azureus_msg_prio, |
761 | 15 | { "Message Priority", "bittorrent.msg.prio", FT_UINT8, BASE_DEC, VALS(azureus_priorities), 0x0, NULL, HFILL } |
762 | 15 | }, |
763 | 15 | { &hf_bittorrent_bitfield_data, |
764 | 15 | { "Bitfield data", "bittorrent.msg.bitfield", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } |
765 | 15 | }, |
766 | 15 | { &hf_bittorrent_piece_index, |
767 | 15 | { "Piece index", "bittorrent.piece.index", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } |
768 | 15 | }, |
769 | 15 | { &hf_bittorrent_piece_begin, |
770 | 15 | { "Begin offset of piece", "bittorrent.piece.begin", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } |
771 | 15 | }, |
772 | 15 | { &hf_bittorrent_piece_data, |
773 | 15 | { "Data in a piece", "bittorrent.piece.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } |
774 | 15 | }, |
775 | 15 | { &hf_bittorrent_piece_length, |
776 | 15 | { "Piece Length", "bittorrent.piece.length", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } |
777 | 15 | }, |
778 | 15 | { &hf_azureus_jpc_addrlen, |
779 | 15 | { "Cache Address Length", "bittorrent.jpc.addr.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } |
780 | 15 | }, |
781 | 15 | { &hf_azureus_jpc_addr, |
782 | 15 | { "Cache Address", "bittorrent.jpc.addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } |
783 | 15 | }, |
784 | 15 | { &hf_azureus_jpc_port, |
785 | 15 | { "Port", "bittorrent.jpc.port", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } |
786 | 15 | }, |
787 | 15 | { &hf_azureus_jpc_session, |
788 | 15 | { "Session ID", "bittorrent.jpc.session", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } |
789 | 15 | }, |
790 | 15 | { &hf_bittorrent_port, |
791 | 15 | { "Port", "bittorrent.port", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } |
792 | 15 | }, |
793 | 15 | { &hf_bittorrent_extended_id, |
794 | 15 | { "Extended Message ID", "bittorrent.extended.id", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } |
795 | 15 | }, |
796 | 15 | { &hf_bittorrent_extended, |
797 | 15 | { "Extended Message", "bittorrent.extended", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } |
798 | 15 | }, |
799 | 15 | { &hf_bittorrent_continuous_data, |
800 | 15 | { "Extended Message", "bittorrent.continuous_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } |
801 | 15 | }, |
802 | 15 | { &hf_bittorrent_version, |
803 | 15 | { "Client version", "bittorrent.version", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } |
804 | 15 | }, |
805 | 15 | }; |
806 | | |
807 | 15 | static int *ett[] = { |
808 | 15 | &ett_bittorrent, |
809 | 15 | &ett_bittorrent_msg, |
810 | 15 | &ett_peer_id, |
811 | 15 | }; |
812 | | |
813 | 15 | module_t *bittorrent_module; |
814 | | |
815 | 15 | proto_bittorrent = proto_register_protocol("BitTorrent", "BitTorrent", "bittorrent"); |
816 | 15 | proto_register_field_array(proto_bittorrent, hf, array_length(hf)); |
817 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
818 | | |
819 | 15 | dissector_handle = register_dissector("bittorrent.tcp", dissect_bittorrent, proto_bittorrent); |
820 | 15 | register_dissector("bittorrent.utp", dissect_bittorrent_utp, proto_bittorrent); |
821 | | |
822 | 15 | bittorrent_module = prefs_register_protocol(proto_bittorrent, NULL); |
823 | 15 | prefs_register_bool_preference(bittorrent_module, "desegment", |
824 | 15 | "Reassemble BitTorrent messages spanning multiple TCP segments", |
825 | 15 | "Whether the BitTorrent dissector should reassemble messages spanning multiple TCP segments." |
826 | 15 | " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", |
827 | 15 | &bittorrent_desegment); |
828 | 15 | prefs_register_bool_preference(bittorrent_module, "decode_client", |
829 | 15 | "Decode the peer_id of the handshake messages", |
830 | 15 | "Enabling this will tell which BitTorrent client that produced the handshake message", |
831 | 15 | &decode_client_information); |
832 | 15 | } |
833 | | |
834 | | |
835 | | void |
836 | | proto_reg_handoff_bittorrent(void) |
837 | 15 | { |
838 | 15 | bencode_handle = find_dissector_add_dependency("bencode", proto_bittorrent); |
839 | | |
840 | 15 | dissector_add_uint_range_with_preference("tcp.port", DEFAULT_TCP_PORT_RANGE, dissector_handle); |
841 | | |
842 | 15 | heur_dissector_add("tcp", test_bittorrent_packet, "BitTorrent over TCP", "bittorrent_tcp", proto_bittorrent, HEURISTIC_ENABLE); |
843 | 15 | } |
844 | | |
845 | | /* |
846 | | * Editor modelines |
847 | | * |
848 | | * Local Variables: |
849 | | * c-basic-offset: 3 |
850 | | * tab-width: 8 |
851 | | * indent-tabs-mode: nil |
852 | | * End: |
853 | | * |
854 | | * ex: set shiftwidth=3 tabstop=8 expandtab: |
855 | | * :indentSize=3:tabSize=8:noTabs=true: |
856 | | */ |