2 * Routines for tftp packet dissection
4 * Richard Sharpe <rsharpe@ns.aus.com>
5 * Craig Newell <CraigN@cheque.uq.edu.au>
6 * RFC2347 TFTP Option Extension
7 * Joerg Mayer (see AUTHORS file)
8 * RFC2348 TFTP Blocksize Option
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * Copied from packet-bootp.c
16 * SPDX-License-Identifier: GPL-2.0-or-later
20 * RFC 1350: THE TFTP PROTOCOL (REVISION 2)
21 * RFC 2090: TFTP Multicast Option
22 * (not yet implemented)
23 * RFC 2347: TFTP Option Extension
24 * RFC 2348: TFTP Blocksize Option
25 * RFC 2349: TFTP Timeout Interval and Transfer Size Options
26 * (not yet implemented)
27 * RFC 7440: TFTP Windowsize Option
29 * "msftwindow" reverse-engineered from Windows Deployment Services traffic:
30 * - Requested by RRQ (or WRQ?) including "msftwindow" option, with value
31 * "31416" (round(M_PI * 10000)).
32 * - Granted by OACK including "msftwindow" option, with value "27182"
34 * - Each subsequent ACK will include an extra byte carrying the next
35 * windowsize -- the number of DATA blocks expected before another ACK will
42 #include <epan/packet.h>
43 #include <epan/conversation.h>
44 #include <epan/expert.h>
45 #include <epan/prefs.h>
47 #include <epan/export_object.h>
48 #include <epan/proto_data.h>
49 #include <epan/reassemble.h>
51 #include "packet-tftp.h"
53 void proto_register_tftp(void);
55 /* Things we may want to remember for a whole conversation */
56 typedef struct _tftp_conv_info_t
{
58 const uint8_t *source_file
, *destination_file
;
59 uint32_t request_frame
;
61 bool dynamic_windowing_active
;
65 /* Sequence analysis */
66 uint32_t next_block_num
;
69 bool last_package_available
;
71 /* When exporting file object, build data here */
72 uint32_t next_tap_block_num
;
73 uint8_t *payload_data
;
75 /* Assembly of fragments */
76 uint32_t reassembly_id
;
77 uint32_t last_reassembly_package
;
79 /* Is the TFTP payload a regular file, or a frame of a higher protocol */
84 static int proto_tftp
;
85 static int hf_tftp_opcode
;
86 static int hf_tftp_source_file
;
87 static int hf_tftp_destination_file
;
88 static int hf_tftp_request_frame
;
89 static int hf_tftp_transfer_type
;
90 static int hf_tftp_blocknum
;
91 static int hf_tftp_full_blocknum
;
92 static int hf_tftp_nextwindowsize
;
93 static int hf_tftp_error_code
;
94 static int hf_tftp_error_string
;
95 static int hf_tftp_option_name
;
96 static int hf_tftp_option_value
;
97 static int hf_tftp_data
;
99 static int hf_tftp_fragments
;
100 static int hf_tftp_fragment
;
101 static int hf_tftp_fragment_overlap
;
102 static int hf_tftp_fragment_overlap_conflicts
;
103 static int hf_tftp_fragment_multiple_tails
;
104 static int hf_tftp_fragment_too_long_fragment
;
105 static int hf_tftp_fragment_error
;
106 static int hf_tftp_fragment_count
;
107 static int hf_tftp_reassembled_in
;
108 static int hf_tftp_reassembled_length
;
109 static int hf_tftp_reassembled_data
;
112 static int ett_tftp_option
;
114 static int ett_tftp_fragment
;
115 static int ett_tftp_fragments
;
117 static expert_field ei_tftp_error
;
118 static expert_field ei_tftp_likely_tsize_probe
;
119 static expert_field ei_tftp_blocksize_range
;
120 static expert_field ei_tftp_blocknum_will_wrap
;
121 static expert_field ei_tftp_windowsize_range
;
122 static expert_field ei_tftp_msftwindow_unrecognized
;
123 static expert_field ei_tftp_windowsize_change
;
125 #define LIKELY_TSIZE_PROBE_KEY 0
126 #define FULL_BLOCKNUM_KEY 1
127 #define CONVERSATION_KEY 2
128 #define WINDOWSIZE_CHANGE_KEY 3
130 static dissector_handle_t tftp_handle
;
132 static heur_dissector_list_t heur_subdissector_list
;
133 static reassembly_table tftp_reassembly_table
;
135 static const fragment_items tftp_frag_items
= {
140 &hf_tftp_fragment_overlap
,
141 &hf_tftp_fragment_overlap_conflicts
,
142 &hf_tftp_fragment_multiple_tails
,
143 &hf_tftp_fragment_too_long_fragment
,
144 &hf_tftp_fragment_error
,
145 &hf_tftp_fragment_count
,
146 &hf_tftp_reassembled_in
,
147 &hf_tftp_reassembled_length
,
148 &hf_tftp_reassembled_data
,
152 #define UDP_PORT_TFTP_RANGE "69"
154 void proto_reg_handoff_tftp (void);
156 /* User definable values */
157 static range_t
*global_tftp_port_range
;
159 /* minimum length is an ACK message of 4 bytes */
160 #define MIN_HDR_LEN 4
168 #define TFTP_INFO 255
169 #define TFTP_NO_OPCODE 0xFFFF
171 static const value_string tftp_opcode_vals
[] = {
172 { TFTP_RRQ
, "Read Request" },
173 { TFTP_WRQ
, "Write Request" },
174 { TFTP_DATA
, "Data Packet" },
175 { TFTP_ACK
, "Acknowledgement" },
176 { TFTP_ERROR
, "Error Code" },
177 { TFTP_OACK
, "Option Acknowledgement" },
178 { TFTP_INFO
, "Information (MSDP)" },
182 /* Error codes 0 through 7 are defined in RFC 1350. */
183 #define TFTP_ERR_NOT_DEF 0
184 #define TFTP_ERR_NOT_FOUND 1
185 #define TFTP_ERR_NOT_ALLOWED 2
186 #define TFTP_ERR_DISK_FULL 3
187 #define TFTP_ERR_BAD_OP 4
188 #define TFTP_ERR_BAD_ID 5
189 #define TFTP_ERR_EXISTS 6
190 #define TFTP_ERR_NO_USER 7
192 /* Error code 8 is defined in RFC 1782. */
193 #define TFTP_ERR_OPT_FAIL 8
195 static const value_string tftp_error_code_vals
[] = {
196 { TFTP_ERR_NOT_DEF
, "Not defined" },
197 { TFTP_ERR_NOT_FOUND
, "File not found" },
198 { TFTP_ERR_NOT_ALLOWED
, "Access violation" },
199 { TFTP_ERR_DISK_FULL
, "Disk full or allocation exceeded" },
200 { TFTP_ERR_BAD_OP
, "Illegal TFTP Operation" },
201 { TFTP_ERR_BAD_ID
, "Unknown transfer ID" }, /* Does not cause termination */
202 { TFTP_ERR_EXISTS
, "File already exists" },
203 { TFTP_ERR_NO_USER
, "No such user" },
204 { TFTP_ERR_OPT_FAIL
, "Option negotiation failed" },
208 static int tftp_eo_tap
;
210 /* Preference setting - defragment fragmented TFTP files */
211 static bool tftp_defragment
;
213 /* Used for TFTP Export Object feature */
214 typedef struct _tftp_eo_t
{
216 uint32_t payload_len
;
217 uint8_t *payload_data
;
221 static tap_packet_status
222 tftp_eo_packet(void *tapdata
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *data
, tap_flags_t flags _U_
)
224 export_object_list_t
*object_list
= (export_object_list_t
*)tapdata
;
225 const tftp_eo_t
*eo_info
= (const tftp_eo_t
*)data
;
226 export_object_entry_t
*entry
;
228 /* These values will be freed when the Export Object window is closed. */
229 entry
= g_new(export_object_entry_t
, 1);
231 /* Remember which frame had the last block of the file */
232 entry
->pkt_num
= pinfo
->num
;
235 entry
->filename
= g_path_get_basename(eo_info
->filename
);
237 /* Free up unnecessary memory */
238 g_free(eo_info
->filename
);
240 /* Pass out the contiguous data and length already accumulated. */
241 entry
->payload_len
= eo_info
->payload_len
;
242 entry
->payload_data
= eo_info
->payload_data
;
244 /* These 2 fields not used */
245 entry
->hostname
= NULL
;
246 entry
->content_type
= NULL
;
248 /* Pass out entry to the GUI */
249 object_list
->add_entry(object_list
->gui_data
, entry
);
251 return TAP_PACKET_REDRAW
; /* State changed - window should be redrawn */
255 tftp_dissect_options(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
,
256 proto_tree
*tree
, uint16_t opcode
, tftp_conv_info_t
*tftp_info
)
258 int option_len
, value_len
;
260 const char *optionname
;
261 const char *optionvalue
;
262 proto_tree
*opt_tree
;
264 while (tvb_offset_exists(tvb
, offset
)) {
265 /* option_len and value_len include the trailing 0 byte */
266 option_len
= tvb_strsize(tvb
, offset
);
267 value_offset
= offset
+ option_len
;
268 value_len
= tvb_strsize(tvb
, value_offset
);
269 /* use xxx_len-1 to exclude the trailing 0 byte, it would be
270 displayed as nonprinting character
271 tvb_format_text(pinfo->pool, ) creates a temporary 0-terminated buffer */
272 optionname
= tvb_format_text(pinfo
->pool
, tvb
, offset
, option_len
-1);
273 optionvalue
= tvb_format_text(pinfo
->pool
, tvb
, value_offset
, value_len
-1);
274 opt_tree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, option_len
+value_len
,
275 ett_tftp_option
, NULL
, "Option: %s = %s", optionname
, optionvalue
);
277 proto_tree_add_item(opt_tree
, hf_tftp_option_name
, tvb
, offset
,
278 option_len
, ENC_ASCII
);
279 proto_tree_add_item(opt_tree
, hf_tftp_option_value
, tvb
, value_offset
,
280 value_len
, ENC_ASCII
);
282 offset
+= option_len
+ value_len
;
284 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %s=%s",
285 optionname
, optionvalue
);
287 /* Special code to handle individual options */
288 if ((opcode
== TFTP_RRQ
|| opcode
== TFTP_WRQ
)) {
289 if (!g_ascii_strcasecmp((const char *)optionname
, "msftwindow")) {
290 if (g_strcmp0((const char *)optionvalue
, "31416")) {
291 expert_add_info(pinfo
, opt_tree
, &ei_tftp_msftwindow_unrecognized
);
293 } else if (!g_ascii_strcasecmp((const char *)optionname
, "windowsize")) {
294 int windowsize
= (int)strtol((const char *)optionvalue
, NULL
, 10);
295 if (windowsize
< 1 || windowsize
> 65535) {
296 expert_add_info(pinfo
, opt_tree
, &ei_tftp_windowsize_range
);
298 } else if (!g_ascii_strcasecmp((const char *)optionname
, "tsize") &&
299 opcode
== TFTP_RRQ
) {
300 tftp_info
->tsize_requested
= true;
302 } else if (opcode
== TFTP_OACK
) {
303 if (!g_ascii_strcasecmp((const char *)optionname
, "blksize")) {
304 int blocksize
= (int)strtol((const char *)optionvalue
, NULL
, 10);
305 if (blocksize
< 8 || blocksize
> 65464) {
306 expert_add_info(pinfo
, opt_tree
, &ei_tftp_blocksize_range
);
308 tftp_info
->blocksize
= blocksize
;
310 } else if (!g_ascii_strcasecmp((const char *)optionname
, "windowsize")) {
311 int windowsize
= (int)strtol((const char *)optionvalue
, NULL
, 10);
312 if (windowsize
< 1 || windowsize
> 65535) {
313 expert_add_info(pinfo
, opt_tree
, &ei_tftp_windowsize_range
);
315 tftp_info
->windowsize
= windowsize
;
317 } else if (!g_ascii_strcasecmp((const char *)optionname
, "msftwindow")) {
318 if (!g_strcmp0((const char *)optionvalue
, "27182")) {
319 tftp_info
->dynamic_windowing_active
= true;
321 expert_add_info(pinfo
, opt_tree
, &ei_tftp_msftwindow_unrecognized
);
329 error_is_likely_tsize_probe(uint16_t error
, const tftp_conv_info_t
*tftp_info
)
332 * The TFTP protocol does not define an explicit "close" for non-error
333 * conditions, but it is traditionally implemented as an ERROR packet with
334 * code zero (not defined) or 8 (option negotiation failed). It is usually
335 * produced when a client did not intend to proceed with a transfer, but was
336 * just querying the transfer size ("tsize") through Option Negotiation. The
337 * ERROR packet would be observed directly after an OACK (when the server
338 * supports Option Negotiation) or directly after DATA block #1 (when the
339 * server does not support Option Negotiation).
341 * Inspect the state of the connection to see whether the ERROR packet would
342 * most likely just be a request to close the connection after a transfer
345 if (error
!= TFTP_ERR_OPT_FAIL
&& error
!= TFTP_ERR_NOT_DEF
) {
349 if (tftp_info
->source_file
!= NULL
&& tftp_info
->tsize_requested
) {
350 /* There was an earlier RRQ requesting the transfer size. */
351 if (tftp_info
->prev_opcode
== TFTP_OACK
) {
352 /* Response to RRQ when server supports Option Negotiation. */
355 if (tftp_info
->prev_opcode
== TFTP_DATA
&& tftp_info
->next_block_num
== 2) {
356 /* Response to RRQ when server doesn't support Option Negotiation. */
364 determine_full_blocknum(uint16_t blocknum
, const tftp_conv_info_t
*tftp_info
)
367 * 'blocknum' might have wrapped around after extending beyond 16 bits. Use
368 * the rest of the conversation state to recover any missing bits.
370 int16_t delta
= (int16_t)(tftp_info
->next_block_num
- blocknum
);
371 if (delta
> (int32_t)tftp_info
->next_block_num
) {
372 /* Avoid wrapping back across 0. */
375 return tftp_info
->next_block_num
- delta
;
378 static void dissect_tftp_message(tftp_conv_info_t
*tftp_info
,
379 tvbuff_t
*tvb
, packet_info
*pinfo
,
382 proto_tree
*tftp_tree
;
385 proto_item
*blocknum_item
;
388 const char *filename
= NULL
;
393 bool likely_tsize_probe
;
394 bool is_last_package
;
397 fragment_head
*tftpfd_head
= NULL
;
398 heur_dtbl_entry_t
*hdtbl_entry
;
399 struct tftpinfo tftpinfo
;
400 uint32_t payload_data_offset
;
402 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TFTP");
405 root_ti
= proto_tree_add_item(tree
, proto_tftp
, tvb
, offset
, -1, ENC_NA
);
406 tftp_tree
= proto_item_add_subtree(root_ti
, ett_tftp
);
409 opcode
= tvb_get_ntohs(tvb
, offset
);
410 proto_tree_add_uint(tftp_tree
, hf_tftp_opcode
, tvb
, offset
, 2, opcode
);
411 col_add_str(pinfo
->cinfo
, COL_INFO
,
412 val_to_str(opcode
, tftp_opcode_vals
, "Unknown (0x%04x)"));
415 /* read and write requests contain file names
416 for other messages, we add the filenames from the conversation */
417 if (tftp_info
->request_frame
!= 0 && opcode
!= TFTP_RRQ
&& opcode
!= TFTP_WRQ
) {
418 if (tftp_info
->source_file
) {
419 filename
= tftp_info
->source_file
;
420 } else if (tftp_info
->destination_file
) {
421 filename
= tftp_info
->destination_file
;
424 ti
= proto_tree_add_string(tftp_tree
, hf_tftp_destination_file
, tvb
, 0, 0, filename
);
425 proto_item_set_generated(ti
);
427 ti
= proto_tree_add_uint_format(tftp_tree
, hf_tftp_request_frame
,
428 tvb
, 0, 0, tftp_info
->request_frame
,
430 tftp_info
->source_file
? "Read Request" : "Write Request",
431 tftp_info
->request_frame
);
432 proto_item_set_generated(ti
);
438 i1
= tvb_strsize(tvb
, offset
);
439 proto_tree_add_item_ret_string(tftp_tree
, hf_tftp_source_file
,
440 tvb
, offset
, i1
, ENC_ASCII
|ENC_NA
, wmem_file_scope(), &tftp_info
->source_file
);
442 /* we either have a source file name (for read requests) or a
443 destination file name (for write requests)
444 when we set one of the names, we clear the other */
445 tftp_info
->destination_file
= NULL
;
446 tftp_info
->request_frame
= pinfo
->num
;
448 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", File: %s",
449 tvb_format_stringzpad(pinfo
->pool
, tvb
, offset
, i1
));
453 i1
= tvb_strsize(tvb
, offset
);
454 proto_tree_add_item(tftp_tree
, hf_tftp_transfer_type
,
455 tvb
, offset
, i1
, ENC_ASCII
);
457 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Transfer type: %s",
458 tvb_format_stringzpad(pinfo
->pool
, tvb
, offset
, i1
));
462 tftp_dissect_options(tvb
, pinfo
, offset
, tftp_tree
,
467 i1
= tvb_strsize(tvb
, offset
);
468 proto_tree_add_item_ret_string(tftp_tree
, hf_tftp_destination_file
,
469 tvb
, offset
, i1
, ENC_ASCII
|ENC_NA
, wmem_file_scope(), &tftp_info
->destination_file
);
471 tftp_info
->source_file
= NULL
; /* see above */
472 tftp_info
->request_frame
= pinfo
->num
;
474 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", File: %s",
475 tvb_format_stringzpad(pinfo
->pool
, tvb
, offset
, i1
));
479 i1
= tvb_strsize(tvb
, offset
);
480 proto_tree_add_item(tftp_tree
, hf_tftp_transfer_type
,
481 tvb
, offset
, i1
, ENC_ASCII
);
483 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Transfer type: %s",
484 tvb_format_stringzpad(pinfo
->pool
, tvb
, offset
, i1
));
488 tftp_dissect_options(tvb
, pinfo
, offset
, tftp_tree
,
493 tftp_dissect_options(tvb
, pinfo
, offset
, tftp_tree
,
498 proto_item_set_len(root_ti
, 4);
499 blocknum_item
= proto_tree_add_item_ret_uint(tftp_tree
, hf_tftp_blocknum
, tvb
, offset
, 2,
500 ENC_BIG_ENDIAN
, &blocknum
);
503 if (!PINFO_FD_VISITED(pinfo
)) {
504 blocknum
= determine_full_blocknum(blocknum
, tftp_info
);
505 p_add_proto_data(wmem_file_scope(), pinfo
, proto_tftp
, FULL_BLOCKNUM_KEY
,
506 GUINT_TO_POINTER(blocknum
));
508 blocknum
= GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo
,
509 proto_tftp
, FULL_BLOCKNUM_KEY
));
511 ti
= proto_tree_add_uint(tftp_tree
, hf_tftp_full_blocknum
, tvb
, 0, 0,
513 proto_item_set_generated(ti
);
515 bytes
= tvb_reported_length_remaining(tvb
, offset
);
516 is_last_package
= (bytes
< tftp_info
->blocksize
);
518 /* Sequence analysis on blocknums (first pass only) */
519 if (!PINFO_FD_VISITED(pinfo
)) {
520 tftp_info
->last_package_available
|= is_last_package
;
521 if (blocknum
> tftp_info
->next_block_num
) {
522 /* There is a gap. Don't try to recover from this. */
523 tftp_info
->next_block_num
= blocknum
+ 1;
524 tftp_info
->blocks_missing
= true;
525 /* TODO: add info to a result table for showing expert info in later passes */
527 else if (blocknum
== tftp_info
->next_block_num
) {
528 /* OK, inc what we expect next */
529 tftp_info
->next_block_num
++;
530 tftp_info
->file_length
+= bytes
;
534 /* Show number of bytes in this block, and whether it is the end of the file */
535 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Block: %u%s",
537 is_last_package
?" (last)":"" );
539 is_fragmented
= !(is_last_package
&& blocknum
== 1);
541 /* If tftp_defragment is on, this is a fragment,
542 * then just add the fragment to the hashtable.
544 if (tftp_defragment
&& (pinfo
->num
<= tftp_info
->last_reassembly_package
)) {
545 tftpfd_head
= fragment_add_seq_check(&tftp_reassembly_table
, tvb
, offset
, pinfo
,
546 tftp_info
->reassembly_id
, /* id */
549 bytes
, !is_last_package
);
551 next_tvb
= process_reassembled_data(tvb
, offset
, pinfo
,
552 "Reassembled TFTP", tftpfd_head
,
553 &tftp_frag_items
, NULL
, tftp_tree
);
558 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
561 if (next_tvb
== NULL
) {
562 /* Reassembly continues */
563 call_data_dissector(tvb_new_subset_remaining(tvb
, offset
), pinfo
, tree
);
565 /* Reassembly completed successfully */
566 tftp_info
->last_reassembly_package
= pinfo
->num
;
567 if (tvb_reported_length(next_tvb
) > 0) {
568 tftpinfo
.filename
= filename
;
569 /* Is the payload recognised by another dissector? */
570 if (!dissector_try_heuristic(heur_subdissector_list
, next_tvb
, pinfo
,
571 tree
, &hdtbl_entry
, &tftpinfo
)) {
572 call_data_dissector(next_tvb
, pinfo
, tree
);
574 tftp_info
->is_simple_file
= false;
579 if (blocknum
== 0xFFFF && bytes
== tftp_info
->blocksize
) {
580 /* There will be a block 0x10000. */
581 expert_add_info(pinfo
, blocknum_item
, &ei_tftp_blocknum_will_wrap
);
584 /* If Export Object tap is listening, need to accumulate blocks info list
585 to send to tap. But we have a number of conditions for this.
587 if (have_tap_listener(tftp_eo_tap
) &&
588 tftp_info
->is_simple_file
/* This is a simple file */
589 && filename
!= NULL
/* There is a file name */
590 && !tftp_info
->blocks_missing
/* No missing blocks */
591 && (tftp_info
->last_package_available
|| !PINFO_FD_VISITED(pinfo
))
592 /* If this is the first pass (i.e., this is tshark one-pass
593 * mode and we're tapping), then we can't know if the last
594 * block is present in the file yet. */
597 if (PINFO_FD_VISITED(pinfo
)) {
598 if (blocknum
== 1 && !tftp_info
->payload_data
) {
599 tftp_info
->payload_data
= (uint8_t *)g_try_malloc((size_t)tftp_info
->file_length
);
602 /* We allocate this in file scope so that it doesn't leak if it
603 * turns out we don't have all the blocks so we never send this
606 tftp_info
->payload_data
= (uint8_t *)wmem_realloc(wmem_file_scope(), tftp_info
->payload_data
, (size_t)tftp_info
->file_length
);
609 if (tftp_info
->payload_data
== NULL
||
610 (blocknum
!= tftp_info
->next_tap_block_num
)) {
611 /* Ignore. Not enough memory or just clicking previous frame */
614 payload_data_offset
=
615 (tftp_info
->next_tap_block_num
- 1) * tftp_info
->blocksize
;
617 /* Copy data to its place in the payload_data */
618 tvb_memcpy(tvb
, tftp_info
->payload_data
+ payload_data_offset
, offset
,
620 tftp_info
->next_tap_block_num
++;
622 /* Tap export object only when reach end of file */
623 if (is_last_package
) {
626 /* Create the eo_info to pass to the listener */
627 eo_info
= wmem_new(pinfo
->pool
, tftp_eo_t
);
630 eo_info
->filename
= g_strdup(filename
);
633 eo_info
->payload_len
= tftp_info
->file_length
;
634 eo_info
->payload_data
= tftp_info
->payload_data
;
637 tap_queue_packet(tftp_eo_tap
, pinfo
, eo_info
);
639 /* Have sent, so forget payload_data, and only pay attention if we
640 get back to the first block again. */
641 tftp_info
->next_tap_block_num
= 1;
642 tftp_info
->payload_data
= NULL
;
648 proto_tree_add_item_ret_uint(tftp_tree
, hf_tftp_blocknum
, tvb
, offset
, 2,
649 ENC_BIG_ENDIAN
, &blocknum
);
651 if (!PINFO_FD_VISITED(pinfo
)) {
652 blocknum
= determine_full_blocknum(blocknum
, tftp_info
);
653 p_add_proto_data(wmem_file_scope(), pinfo
, proto_tftp
, FULL_BLOCKNUM_KEY
,
654 GUINT_TO_POINTER(blocknum
));
656 blocknum
= GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo
,
657 proto_tftp
, FULL_BLOCKNUM_KEY
));
659 ti
= proto_tree_add_uint(tftp_tree
, hf_tftp_full_blocknum
, tvb
, 0, 0,
661 proto_item_set_generated(ti
);
663 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Block: %u",
667 if (tftp_info
->dynamic_windowing_active
&& tvb_bytes_exist(tvb
, offset
, 1)) {
668 bool windowsize_changed
;
669 uint8_t windowsize
= tvb_get_uint8(tvb
, offset
);
670 ti
= proto_tree_add_uint(tftp_tree
, hf_tftp_nextwindowsize
, tvb
,
671 offset
, 1, windowsize
);
672 if (!PINFO_FD_VISITED(pinfo
)) {
674 * Note changes in window size, but ignore the final ACK which includes
675 * an unnecessary (and seemingly bogus) window size.
677 windowsize_changed
= windowsize
!= tftp_info
->windowsize
&&
678 !tftp_info
->last_package_available
;
679 if (windowsize_changed
) {
680 p_add_proto_data(wmem_file_scope(), pinfo
, proto_tftp
,
681 WINDOWSIZE_CHANGE_KEY
, GUINT_TO_POINTER(1));
682 tftp_info
->windowsize
= windowsize
;
685 windowsize_changed
= p_get_proto_data(wmem_file_scope(), pinfo
, proto_tftp
, WINDOWSIZE_CHANGE_KEY
) != NULL
;
688 if (windowsize_changed
) {
689 expert_add_info(pinfo
, ti
, &ei_tftp_windowsize_change
);
695 error
= tvb_get_ntohs(tvb
, offset
);
696 proto_tree_add_uint(tftp_tree
, hf_tftp_error_code
, tvb
, offset
, 2,
699 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Code: %s",
700 val_to_str(error
, tftp_error_code_vals
, "Unknown (%u)"));
704 i1
= tvb_strsize(tvb
, offset
);
705 proto_tree_add_item(tftp_tree
, hf_tftp_error_string
, tvb
, offset
,
708 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Message: %s",
709 tvb_format_stringzpad(pinfo
->pool
, tvb
, offset
, i1
));
712 * If the packet looks like an intentional "close" after a transfer-size
713 * probe, don't report it as an error.
716 if (!PINFO_FD_VISITED(pinfo
)) {
717 likely_tsize_probe
= error_is_likely_tsize_probe(error
, tftp_info
);
718 if (likely_tsize_probe
) {
719 p_add_proto_data(wmem_file_scope(), pinfo
, proto_tftp
, LIKELY_TSIZE_PROBE_KEY
, GUINT_TO_POINTER(1));
722 likely_tsize_probe
= GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo
, proto_tftp
,
723 LIKELY_TSIZE_PROBE_KEY
)) != 0;
726 expert_add_info(pinfo
, tftp_tree
, likely_tsize_probe
? &ei_tftp_likely_tsize_probe
: &ei_tftp_error
);
730 tftp_dissect_options(tvb
, pinfo
, offset
, tftp_tree
,
735 proto_tree_add_item(tftp_tree
, hf_tftp_data
, tvb
, offset
, -1, ENC_NA
);
739 tftp_info
->prev_opcode
= opcode
;
742 static tftp_conv_info_t
*
743 tftp_info_for_conversation(conversation_t
*conversation
)
745 tftp_conv_info_t
*tftp_info
;
747 tftp_info
= (tftp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_tftp
);
749 tftp_info
= wmem_new(wmem_file_scope(), tftp_conv_info_t
);
750 tftp_info
->blocksize
= 512; /* TFTP default block size */
751 tftp_info
->source_file
= NULL
;
752 tftp_info
->destination_file
= NULL
;
753 tftp_info
->request_frame
= 0;
754 tftp_info
->tsize_requested
= false;
755 tftp_info
->dynamic_windowing_active
= false;
756 tftp_info
->windowsize
= 0;
757 tftp_info
->prev_opcode
= TFTP_NO_OPCODE
;
758 tftp_info
->next_block_num
= 1;
759 tftp_info
->blocks_missing
= false;
760 tftp_info
->file_length
= 0;
761 tftp_info
->last_package_available
= false;
762 tftp_info
->next_tap_block_num
= 1;
763 tftp_info
->payload_data
= NULL
;
764 tftp_info
->reassembly_id
= conversation
->conv_index
;
765 tftp_info
->last_reassembly_package
= UINT32_MAX
;
766 tftp_info
->is_simple_file
= true;
767 conversation_add_proto_data(conversation
, proto_tftp
, tftp_info
);
773 is_valid_request_body(tvbuff_t
*tvb
, packet_info
*pinfo
)
776 unsigned zeros_counter
= 0;
777 for (int i
= offset
; i
< (int)tvb_captured_length(tvb
); ++i
) {
778 char c
= (char)tvb_get_uint8(tvb
, i
);
781 } else if (!g_ascii_isprint(c
)) {
786 if (zeros_counter
% 2 != 0 || zeros_counter
== 0)
789 offset
+= tvb_strsize(tvb
, offset
);
790 unsigned len
= tvb_strsize(tvb
, offset
);
791 const char* mode
= tvb_format_stringzpad(pinfo
->pool
, tvb
, offset
, len
);
793 const char* modes
[] = {"netascii", "octet", "mail"};
794 for(unsigned i
= 0; i
< array_length(modes
); ++i
) {
795 if (g_ascii_strcasecmp(mode
, modes
[i
]) == 0) return true;
802 is_valid_request(tvbuff_t
*tvb
, packet_info
*pinfo
)
804 if (tvb_captured_length(tvb
) < MIN_HDR_LEN
)
806 uint16_t opcode
= tvb_get_ntohs(tvb
, 0);
807 if ((opcode
!= TFTP_RRQ
) && (opcode
!= TFTP_WRQ
))
809 return is_valid_request_body(tvb
, pinfo
);
812 static conversation_t
* create_tftp_conversation(packet_info
*pinfo
)
814 conversation_t
* conversation
= NULL
;
815 if (!PINFO_FD_VISITED(pinfo
)) {
816 /* New read or write request on first pass, so create conversation with client port only */
817 conversation
= conversation_new(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, CONVERSATION_UDP
,
818 pinfo
->srcport
, 0, NO_PORT2
);
819 conversation_set_dissector(conversation
, tftp_handle
);
820 /* Store conversation in this frame */
821 p_add_proto_data(wmem_file_scope(), pinfo
, proto_tftp
, CONVERSATION_KEY
,
822 (void *)conversation
);
824 /* Read or write request, but not first pass, so look up existing conversation */
825 conversation
= (conversation_t
*)p_get_proto_data(wmem_file_scope(), pinfo
,
826 proto_tftp
, CONVERSATION_KEY
);
832 dissect_tftp_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
834 if (is_valid_request_body(tvb
, pinfo
)) {
835 conversation_t
* conversation
= create_tftp_conversation(pinfo
);
836 dissect_tftp_message(tftp_info_for_conversation(conversation
), tvb
, pinfo
, tree
);
843 dissect_embeddedtftp_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
845 /* Used to dissect TFTP packets where one can not assume
846 that the TFTP is the only protocol used by that port, and
847 that TFTP may not be carried by UDP */
848 conversation_t
*conversation
;
852 * We need to verify it could be a TFTP message before creating a conversation
855 if (tvb_captured_length(tvb
) < MIN_HDR_LEN
)
858 opcode
= tvb_get_ntohs(tvb
, 0);
863 /* These 2 opcodes have a NULL-terminated source file name after opcode. Verify */
864 if (!is_valid_request_body(tvb
, pinfo
))
866 /* Intentionally dropping through here... */
873 /* for an error, we can verify the error code is legit */
874 switch (tvb_get_ntohs(tvb
, 2)) {
875 case TFTP_ERR_NOT_DEF
:
876 case TFTP_ERR_NOT_FOUND
:
877 case TFTP_ERR_NOT_ALLOWED
:
878 case TFTP_ERR_DISK_FULL
:
879 case TFTP_ERR_BAD_OP
:
880 case TFTP_ERR_BAD_ID
:
881 case TFTP_ERR_EXISTS
:
882 case TFTP_ERR_NO_USER
:
883 case TFTP_ERR_OPT_FAIL
:
893 conversation
= find_or_create_conversation(pinfo
);
894 dissect_tftp_message(tftp_info_for_conversation(conversation
), tvb
, pinfo
, tree
);
899 dissect_tftp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
901 conversation_t
*conversation
= NULL
;
904 * The first TFTP packet goes to the TFTP port; the second one
905 * comes from some *other* port, but goes back to the same
906 * IP address and port as the ones from which the first packet
907 * came; all subsequent packets go between those two IP addresses
910 * If this packet went to the TFTP port (either to one of the ports
911 * set in the preferences or to a port set via Decode As), we check
912 * to see if there's already a conversation with one address/port pair
913 * matching the source IP address and port of this packet,
914 * the other address matching the destination IP address of this
915 * packet, and any destination port.
917 * If not, we create one, with its address 1/port 1 pair being
918 * the source address/port of this packet, its address 2 being
919 * the destination address of this packet, and its port 2 being
920 * wildcarded, and give it the TFTP dissector as a dissector.
922 if ((value_is_in_range(global_tftp_port_range
, pinfo
->destport
) ||
923 (pinfo
->match_uint
== pinfo
->destport
)) &&
924 is_valid_request(tvb
, pinfo
))
926 conversation
= create_tftp_conversation(pinfo
);
929 if (conversation
== NULL
)
931 /* Not the initial read or write request */
932 /* Look for wildcarded conversation based upon client port */
933 if ((conversation
= find_conversation(pinfo
->num
, &pinfo
->dst
, &pinfo
->src
, CONVERSATION_UDP
,
934 pinfo
->destport
, 0, NO_PORT_B
)) && conversation_get_dissector(conversation
, pinfo
->num
) == tftp_handle
) {
936 /* XXX: While setting the wildcarded port makes sense, if we do that,
937 * it's more complicated to find the correct conversation if ports are
938 * reused. (find_conversation with full information prefers any exact
939 * match, even with an earlier setup frame, to any wildcarded match.)
940 * We would want to find the most recent conversations with one wildcard
941 * and with both ports, and take the latest of those.
943 /* Set other side of conversation (server port) */
944 if (pinfo
->destport
== conversation_key_port1(conversation
->key_ptr
))
945 conversation_set_port2(conversation
, pinfo
->srcport
);
947 } else if ((conversation
= find_conversation(pinfo
->num
, &pinfo
->src
, &pinfo
->dst
, CONVERSATION_UDP
,
948 pinfo
->srcport
, 0, NO_PORT_B
)) && conversation_get_dissector(conversation
, pinfo
->num
) == tftp_handle
) {
951 /* How did we get here? We must have matched one of the TFTP ports
952 * and missed the WRQ/RRQ. While it is contrary to the spirit of
953 * RFC 1350 for the server not to change ports, there appear to be
954 * such servers out there (issue #18122), and since the default port
955 * is IANA assigned it doesn't do harm to process it. Note that in
956 * that case the conversation won't have the tftp dissector set. */
957 conversation
= find_conversation_pinfo(pinfo
, 0);
958 if (conversation
== NULL
) {
964 if (pinfo
->num
> conversation
->last_frame
) {
965 conversation
->last_frame
= pinfo
->num
;
967 dissect_tftp_message(tftp_info_for_conversation(conversation
), tvb
, pinfo
, tree
);
968 return tvb_captured_length(tvb
);
973 apply_tftp_prefs(void) {
974 global_tftp_port_range
= prefs_get_range_value("tftp", "udp.port");
978 proto_register_tftp(void)
980 static hf_register_info hf
[] = {
982 { "Opcode", "tftp.opcode",
983 FT_UINT16
, BASE_DEC
, VALS(tftp_opcode_vals
), 0x0,
984 "TFTP message type", HFILL
}},
986 { &hf_tftp_source_file
,
987 { "Source File", "tftp.source_file",
988 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
989 "TFTP source file name", HFILL
}},
991 { &hf_tftp_destination_file
,
992 { "Destination File", "tftp.destination_file",
993 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
994 "TFTP destination file name", HFILL
}},
996 { &hf_tftp_request_frame
,
997 { "Request frame", "tftp.request_frame",
998 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
999 "TFTP request is in frame", HFILL
}},
1001 { &hf_tftp_transfer_type
,
1002 { "Type", "tftp.type",
1003 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
1004 "TFTP transfer type", HFILL
}},
1006 { &hf_tftp_blocknum
,
1007 { "Block", "tftp.block",
1008 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1009 "Block number", HFILL
}},
1011 { &hf_tftp_full_blocknum
,
1012 { "Full Block Number", "tftp.block.full",
1013 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
1014 "Block number, adjusted for wrapping", HFILL
}},
1016 { &hf_tftp_nextwindowsize
,
1017 { "Next Window Size", "tftp.nextwindowsize",
1018 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1019 "Number of blocks in next transfer window", HFILL
}},
1021 { &hf_tftp_error_code
,
1022 { "Error code", "tftp.error.code",
1023 FT_UINT16
, BASE_DEC
, VALS(tftp_error_code_vals
), 0x0,
1024 "Error code in case of TFTP error message", HFILL
}},
1026 { &hf_tftp_error_string
,
1027 { "Error message", "tftp.error.message",
1028 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
1029 "Error string in case of TFTP error message", HFILL
}},
1031 { &hf_tftp_option_name
,
1032 { "Option name", "tftp.option.name",
1033 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
1036 { &hf_tftp_option_value
,
1037 { "Option value", "tftp.option.value",
1038 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
1042 { "Data", "tftp.data",
1043 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1046 { &hf_tftp_fragments
,
1047 { "TFTP Fragments", "tftp.fragments",
1048 FT_NONE
, BASE_NONE
, NULL
, 0x00,
1051 { &hf_tftp_fragment
,
1052 { "TFTP Fragment", "tftp.fragment",
1053 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
1056 { &hf_tftp_fragment_overlap
,
1057 { "Fragment overlap", "tftp.fragment.overlap",
1058 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00,
1059 "Fragment overlaps with other fragments", HFILL
}},
1061 { &hf_tftp_fragment_overlap_conflicts
,
1062 { "Conflicting data in fragment overlap",
1063 "tftp.fragment.overlap.conflicts",
1064 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00,
1065 "Overlapping fragments contained conflicting data", HFILL
}},
1067 { &hf_tftp_fragment_multiple_tails
,
1068 { "Multiple tail fragments found", "tftp.fragment.multipletails",
1069 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00,
1070 "Several tails were found when defragmenting the packet", HFILL
}},
1072 { &hf_tftp_fragment_too_long_fragment
,
1073 { "Fragment too long", "tftp.fragment.toolongfragment",
1074 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00,
1075 "Fragment contained data past end of packet", HFILL
}},
1077 { &hf_tftp_fragment_error
,
1078 { "Defragmentation error", "tftp.fragment.error",
1079 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
1080 "Defragmentation error due to illegal fragments", HFILL
}},
1082 { &hf_tftp_fragment_count
,
1083 { "Fragment count", "tftp.fragment.count",
1084 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
1087 { &hf_tftp_reassembled_in
,
1088 { "Reassembled TFTP in frame", "tftp.reassembled_in",
1089 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
1090 "This TFTP packet is reassembled in this frame", HFILL
}},
1092 { &hf_tftp_reassembled_length
,
1093 { "Reassembled TFTP length", "tftp.reassembled.length",
1094 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
1095 "The total length of the reassembled payload", HFILL
}},
1097 { &hf_tftp_reassembled_data
,
1098 { "Reassembled TFTP data", "tftp.reassembled.data",
1099 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1100 "The reassembled payload", HFILL
}},
1102 static int *ett
[] = {
1106 &ett_tftp_fragments
,
1109 static ei_register_info ei
[] = {
1110 { &ei_tftp_error
, { "tftp.error", PI_RESPONSE_CODE
, PI_WARN
, "TFTP ERROR packet", EXPFILL
}},
1111 { &ei_tftp_likely_tsize_probe
, { "tftp.likely_tsize_probe", PI_REQUEST_CODE
, PI_CHAT
, "Likely transfer size (tsize) probe", EXPFILL
}},
1112 { &ei_tftp_blocksize_range
, { "tftp.blocksize_range", PI_RESPONSE_CODE
, PI_WARN
, "TFTP blocksize out of range", EXPFILL
}},
1113 { &ei_tftp_blocknum_will_wrap
, { "tftp.block.wrap", PI_SEQUENCE
, PI_NOTE
, "TFTP block number is about to wrap", EXPFILL
}},
1114 { &ei_tftp_windowsize_range
, { "tftp.windowsize_range", PI_RESPONSE_CODE
, PI_WARN
, "TFTP windowsize out of range", EXPFILL
}},
1115 { &ei_tftp_msftwindow_unrecognized
, { "tftp.msftwindow.unrecognized", PI_RESPONSE_CODE
, PI_WARN
, "Unrecognized msftwindow option", EXPFILL
}},
1116 { &ei_tftp_windowsize_change
, { "tftp.windowsize.change", PI_SEQUENCE
, PI_CHAT
, "TFTP window size is changing", EXPFILL
}},
1119 module_t
*tftp_module
;
1120 expert_module_t
* expert_tftp
;
1122 proto_tftp
= proto_register_protocol("Trivial File Transfer Protocol", "TFTP", "tftp");
1123 proto_register_field_array(proto_tftp
, hf
, array_length(hf
));
1124 proto_register_subtree_array(ett
, array_length(ett
));
1125 expert_tftp
= expert_register_protocol(proto_tftp
);
1126 expert_register_field_array(expert_tftp
, ei
, array_length(ei
));
1128 heur_subdissector_list
= register_heur_dissector_list_with_description("tftp", "TFTP payload", proto_tftp
);
1129 reassembly_table_register(&tftp_reassembly_table
, &addresses_ports_reassembly_table_functions
);
1131 tftp_handle
= register_dissector("tftp", dissect_tftp
, proto_tftp
);
1133 tftp_module
= prefs_register_protocol(proto_tftp
, apply_tftp_prefs
);
1134 prefs_register_bool_preference(tftp_module
, "defragment",
1135 "Reassemble fragmented TFTP files",
1136 "Whether fragmented TFTP files should be reassembled", &tftp_defragment
);
1138 /* Register the tap for the "Export Object" function */
1139 tftp_eo_tap
= register_export_object(proto_tftp
, tftp_eo_packet
, NULL
);
1143 proto_reg_handoff_tftp(void)
1145 heur_dissector_add("stun", dissect_embeddedtftp_heur
, "TFTP over TURN", "tftp_stun", proto_tftp
, HEURISTIC_ENABLE
);
1146 heur_dissector_add("udp", dissect_tftp_heur
, "TFTP", "tftp", proto_tftp
, HEURISTIC_ENABLE
);
1148 dissector_add_uint_range_with_preference("udp.port", UDP_PORT_TFTP_RANGE
, tftp_handle
);
1153 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1158 * indent-tabs-mode: nil
1161 * vi: set shiftwidth=2 tabstop=8 expandtab:
1162 * :indentSize=2:tabSize=8:noTabs=true: