Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-tftp.c
Line
Count
Source
1
/* packet-tftp.c
2
 * Routines for tftp packet dissection
3
 *
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
9
 *
10
 * Wireshark - Network traffic analyzer
11
 * By Gerald Combs <gerald@wireshark.org>
12
 * Copyright 1998 Gerald Combs
13
 *
14
 * Copied from packet-bootp.c
15
 *
16
 * SPDX-License-Identifier: GPL-2.0-or-later
17
 */
18
19
/* Documentation:
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
28
 *
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"
33
 *    (floor(e * 10000)).
34
 *  - Each subsequent ACK will include an extra byte carrying the next
35
 *    windowsize -- the number of DATA blocks expected before another ACK will
36
 *    be sent.
37
 */
38
39
#include "config.h"
40
41
#include <stdlib.h>
42
#include <epan/packet.h>
43
#include <epan/conversation.h>
44
#include <epan/expert.h>
45
#include <epan/prefs.h>
46
#include <epan/tap.h>
47
#include <epan/export_object.h>
48
#include <epan/proto_data.h>
49
#include <epan/reassemble.h>
50
51
#include "packet-tftp.h"
52
53
void proto_register_tftp(void);
54
55
/* Things we may want to remember for a whole conversation */
56
typedef struct _tftp_conv_info_t {
57
  uint16_t     blocksize;
58
  const char  *source_file, *destination_file;
59
  uint32_t     request_frame;
60
  bool         tsize_requested;
61
  bool         dynamic_windowing_active;
62
  uint16_t     windowsize;
63
  uint16_t     prev_opcode;
64
65
  /* Sequence analysis */
66
  uint32_t     next_block_num;
67
  bool         blocks_missing;
68
  unsigned     file_length;
69
  bool         last_package_available;
70
71
  /* When exporting file object, build data here */
72
  uint32_t     next_tap_block_num;
73
  uint8_t      *payload_data;
74
75
  /* Assembly of fragments */
76
  uint32_t     reassembly_id;
77
  uint32_t     last_reassembly_package;
78
79
  /* Is the TFTP payload a regular file, or a frame of a higher protocol */
80
  bool         is_simple_file;
81
} tftp_conv_info_t;
82
83
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;
98
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;
110
111
static int ett_tftp;
112
static int ett_tftp_option;
113
114
static int ett_tftp_fragment;
115
static int ett_tftp_fragments;
116
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;
124
125
0
#define LIKELY_TSIZE_PROBE_KEY 0
126
8
#define FULL_BLOCKNUM_KEY 1
127
0
#define CONVERSATION_KEY 2
128
0
#define WINDOWSIZE_CHANGE_KEY 3
129
130
static dissector_handle_t tftp_handle;
131
132
static heur_dissector_list_t heur_subdissector_list;
133
static reassembly_table tftp_reassembly_table;
134
135
static const fragment_items tftp_frag_items = {
136
  &ett_tftp_fragment,
137
  &ett_tftp_fragments,
138
  &hf_tftp_fragments,
139
  &hf_tftp_fragment,
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,
149
  "TFTP fragments"
150
};
151
152
14
#define UDP_PORT_TFTP_RANGE    "69"
153
154
void proto_reg_handoff_tftp (void);
155
156
/* User definable values */
157
static range_t *global_tftp_port_range;
158
159
/* minimum length is an ACK message of 4 bytes */
160
78
#define MIN_HDR_LEN  4
161
162
1.55k
#define TFTP_RRQ            1
163
417
#define TFTP_WRQ            2
164
7
#define TFTP_DATA           3
165
1
#define TFTP_ACK            4
166
2
#define TFTP_ERROR          5
167
305
#define TFTP_OACK           6
168
20
#define TFTP_INFO         255
169
38
#define TFTP_NO_OPCODE 0xFFFF
170
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)" },
179
  { 0,          NULL }
180
};
181
182
/* Error codes 0 through 7 are defined in RFC 1350. */
183
2
#define TFTP_ERR_NOT_DEF      0
184
0
#define TFTP_ERR_NOT_FOUND    1
185
0
#define TFTP_ERR_NOT_ALLOWED  2
186
0
#define TFTP_ERR_DISK_FULL    3
187
0
#define TFTP_ERR_BAD_OP       4
188
0
#define TFTP_ERR_BAD_ID       5
189
0
#define TFTP_ERR_EXISTS       6
190
0
#define TFTP_ERR_NO_USER      7
191
192
/* Error code 8 is defined in RFC 1782. */
193
4
#define TFTP_ERR_OPT_FAIL     8
194
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" },
205
  { 0, NULL }
206
};
207
208
static int tftp_eo_tap;
209
210
/* Preference setting - defragment fragmented TFTP files */
211
static bool tftp_defragment;
212
213
/* Used for TFTP Export Object feature */
214
typedef struct _tftp_eo_t {
215
  char     *filename;
216
  uint32_t payload_len;
217
  uint8_t  *payload_data;
218
} tftp_eo_t;
219
220
/* Tap function */
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_)
223
0
{
224
0
  export_object_list_t *object_list = (export_object_list_t *)tapdata;
225
0
  const tftp_eo_t *eo_info = (const tftp_eo_t *)data;
226
0
  export_object_entry_t *entry;
227
228
  /* These values will be freed when the Export Object window is closed. */
229
0
  entry = g_new(export_object_entry_t, 1);
230
231
  /* Remember which frame had the last block of the file */
232
0
  entry->pkt_num = pinfo->num;
233
234
  /* Copy filename */
235
0
  entry->filename = g_path_get_basename(eo_info->filename);
236
237
  /* Free up unnecessary memory */
238
0
  g_free(eo_info->filename);
239
240
  /* Pass out the contiguous data and length already accumulated. */
241
0
  entry->payload_len = eo_info->payload_len;
242
0
  entry->payload_data = eo_info->payload_data;
243
244
  /* These 2 fields not used */
245
0
  entry->hostname = NULL;
246
0
  entry->content_type = NULL;
247
248
  /* Pass out entry to the GUI */
249
0
  object_list->add_entry(object_list->gui_data, entry);
250
251
0
  return TAP_PACKET_REDRAW; /* State changed - window should be redrawn */
252
0
}
253
254
static void
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)
257
46
{
258
46
  int         option_len, value_len;
259
46
  int         value_offset;
260
46
  const char *optionname;
261
46
  const char *optionvalue;
262
46
  proto_tree *opt_tree;
263
264
751
  while (tvb_offset_exists(tvb, offset)) {
265
    /* option_len and value_len include the trailing 0 byte */
266
705
    option_len = tvb_strsize(tvb, offset);
267
705
    value_offset = offset + option_len;
268
705
    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
705
    optionname = tvb_format_text(pinfo->pool, tvb, offset, option_len-1);
273
705
    optionvalue = tvb_format_text(pinfo->pool, tvb, value_offset, value_len-1);
274
705
    opt_tree = proto_tree_add_subtree_format(tree, tvb, offset, option_len+value_len,
275
705
                                   ett_tftp_option, NULL, "Option: %s = %s", optionname, optionvalue);
276
277
705
    proto_tree_add_item(opt_tree, hf_tftp_option_name, tvb, offset,
278
705
                        option_len, ENC_ASCII);
279
705
    proto_tree_add_item(opt_tree, hf_tftp_option_value, tvb, value_offset,
280
705
                        value_len, ENC_ASCII);
281
282
705
    offset += option_len + value_len;
283
284
705
    col_append_fstr(pinfo->cinfo, COL_INFO, ", %s=%s",
285
705
                    optionname, optionvalue);
286
287
    /* Special code to handle individual options */
288
705
    if ((opcode == TFTP_RRQ || opcode == TFTP_WRQ)) {
289
415
      if (!g_ascii_strcasecmp((const char *)optionname, "msftwindow")) {
290
0
        if (g_strcmp0((const char *)optionvalue, "31416")) {
291
0
          expert_add_info(pinfo, opt_tree, &ei_tftp_msftwindow_unrecognized);
292
0
        }
293
415
      } else if (!g_ascii_strcasecmp((const char *)optionname, "windowsize")) {
294
0
        int windowsize = (int)strtol((const char *)optionvalue, NULL, 10);
295
0
        if (windowsize < 1 || windowsize > 65535) {
296
0
          expert_add_info(pinfo, opt_tree, &ei_tftp_windowsize_range);
297
0
        }
298
415
      } else if (!g_ascii_strcasecmp((const char *)optionname, "tsize") &&
299
0
               opcode == TFTP_RRQ) {
300
0
        tftp_info->tsize_requested = true;
301
0
      }
302
415
    } else if (opcode == TFTP_OACK) {
303
176
      if (!g_ascii_strcasecmp((const char *)optionname, "blksize")) {
304
0
        int blocksize = (int)strtol((const char *)optionvalue, NULL, 10);
305
0
        if (blocksize < 8 || blocksize > 65464) {
306
0
          expert_add_info(pinfo, opt_tree, &ei_tftp_blocksize_range);
307
0
        } else {
308
0
          tftp_info->blocksize = blocksize;
309
0
        }
310
176
      } else if (!g_ascii_strcasecmp((const char *)optionname, "windowsize")) {
311
0
        int windowsize = (int)strtol((const char *)optionvalue, NULL, 10);
312
0
        if (windowsize < 1 || windowsize > 65535) {
313
0
          expert_add_info(pinfo, opt_tree, &ei_tftp_windowsize_range);
314
0
        } else {
315
0
          tftp_info->windowsize = windowsize;
316
0
        }
317
176
      } else if (!g_ascii_strcasecmp((const char *)optionname, "msftwindow")) {
318
0
        if (!g_strcmp0((const char *)optionvalue, "27182")) {
319
0
          tftp_info->dynamic_windowing_active = true;
320
0
        } else {
321
0
          expert_add_info(pinfo, opt_tree, &ei_tftp_msftwindow_unrecognized);
322
0
        }
323
0
      }
324
176
    }
325
705
  }
326
46
}
327
328
static bool
329
error_is_likely_tsize_probe(uint16_t error, const tftp_conv_info_t *tftp_info)
330
2
{
331
  /*
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).
340
   *
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
343
   * size query.
344
   */
345
2
  if (error != TFTP_ERR_OPT_FAIL && error != TFTP_ERR_NOT_DEF) {
346
1
    return false;
347
1
  }
348
349
1
  if (tftp_info->source_file != NULL && tftp_info->tsize_requested) {
350
    /* There was an earlier RRQ requesting the transfer size. */
351
0
    if (tftp_info->prev_opcode == TFTP_OACK) {
352
      /* Response to RRQ when server supports Option Negotiation. */
353
0
      return true;
354
0
    }
355
0
    if (tftp_info->prev_opcode == TFTP_DATA && tftp_info->next_block_num == 2) {
356
      /* Response to RRQ when server doesn't support Option Negotiation. */
357
0
      return true;
358
0
    }
359
0
  }
360
1
  return false;
361
1
}
362
363
static uint32_t
364
determine_full_blocknum(uint16_t blocknum, const tftp_conv_info_t *tftp_info)
365
8
{
366
  /*
367
   * 'blocknum' might have wrapped around after extending beyond 16 bits.  Use
368
   * the rest of the conversation state to recover any missing bits.
369
   */
370
8
  int16_t delta = (int16_t)(tftp_info->next_block_num - blocknum);
371
8
  if (delta > (int32_t)tftp_info->next_block_num) {
372
    /* Avoid wrapping back across 0. */
373
2
    return blocknum;
374
2
  }
375
6
  return tftp_info->next_block_num - delta;
376
8
}
377
378
static void dissect_tftp_message(tftp_conv_info_t *tftp_info,
379
                                 tvbuff_t *tvb, packet_info *pinfo,
380
                                 proto_tree *tree)
381
64
{
382
64
  proto_tree *tftp_tree;
383
64
  proto_item *root_ti;
384
64
  proto_item *ti;
385
64
  proto_item *blocknum_item;
386
64
  int         offset    = 0;
387
64
  uint16_t    opcode;
388
64
  const char  *filename = NULL;
389
64
  uint16_t    bytes;
390
64
  uint32_t    blocknum;
391
64
  unsigned    i1;
392
64
  uint16_t    error;
393
64
  bool        likely_tsize_probe;
394
64
  bool        is_last_package;
395
64
  bool        is_fragmented;
396
64
  tvbuff_t    *next_tvb;
397
64
  fragment_head *tftpfd_head = NULL;
398
64
  heur_dtbl_entry_t *hdtbl_entry;
399
64
  struct tftpinfo tftpinfo;
400
64
  uint32_t    payload_data_offset;
401
402
64
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFTP");
403
404
  /* Protocol root */
405
64
  root_ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA);
406
64
  tftp_tree = proto_item_add_subtree(root_ti, ett_tftp);
407
408
  /* Opcode */
409
64
  opcode = tvb_get_ntohs(tvb, offset);
410
64
  proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb, offset, 2, opcode);
411
64
  col_add_str(pinfo->cinfo, COL_INFO,
412
64
              val_to_str(pinfo->pool, opcode, tftp_opcode_vals, "Unknown (0x%04x)"));
413
64
  offset += 2;
414
415
  /* read and write requests contain file names
416
     for other messages, we add the filenames from the conversation */
417
64
  if (tftp_info->request_frame != 0 && opcode != TFTP_RRQ && opcode != TFTP_WRQ) {
418
6
    if (tftp_info->source_file) {
419
2
      filename = tftp_info->source_file;
420
4
    } else if (tftp_info->destination_file) {
421
4
      filename = tftp_info->destination_file;
422
4
    }
423
424
6
    ti = proto_tree_add_string(tftp_tree, hf_tftp_destination_file, tvb, 0, 0, filename);
425
6
    proto_item_set_generated(ti);
426
427
6
    ti = proto_tree_add_uint_format(tftp_tree, hf_tftp_request_frame,
428
6
                                    tvb, 0, 0, tftp_info->request_frame,
429
6
                                    "%s in frame %u",
430
6
                                    tftp_info->source_file ? "Read Request" : "Write Request",
431
6
                                    tftp_info->request_frame);
432
6
    proto_item_set_generated(ti);
433
6
  }
434
435
64
  switch (opcode) {
436
437
12
  case TFTP_RRQ:
438
12
    i1 = tvb_strsize(tvb, offset);
439
12
    proto_tree_add_item_ret_string(tftp_tree, hf_tftp_source_file,
440
12
                        tvb, offset, i1, ENC_ASCII|ENC_NA, wmem_file_scope(), (const uint8_t**)&tftp_info->source_file);
441
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
12
    tftp_info->destination_file = NULL;
446
12
    tftp_info->request_frame = pinfo->num;
447
448
12
    col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
449
12
                    tvb_format_stringzpad(pinfo->pool, tvb, offset, i1));
450
451
12
    offset += i1;
452
453
12
    i1 = tvb_strsize(tvb, offset);
454
12
    proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
455
12
                        tvb, offset, i1, ENC_ASCII);
456
457
12
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
458
12
                    tvb_format_stringzpad(pinfo->pool, tvb, offset, i1));
459
460
12
    offset += i1;
461
462
12
    tftp_dissect_options(tvb, pinfo,  offset, tftp_tree,
463
12
                         opcode, tftp_info);
464
12
    break;
465
466
12
  case TFTP_WRQ:
467
12
    i1 = tvb_strsize(tvb, offset);
468
12
    proto_tree_add_item_ret_string(tftp_tree, hf_tftp_destination_file,
469
12
                        tvb, offset, i1, ENC_ASCII|ENC_NA, wmem_file_scope(), (const uint8_t**)&tftp_info->destination_file);
470
471
12
    tftp_info->source_file = NULL; /* see above */
472
12
    tftp_info->request_frame = pinfo->num;
473
474
12
    col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
475
12
                    tvb_format_stringzpad(pinfo->pool, tvb, offset, i1));
476
477
12
    offset += i1;
478
479
12
    i1 = tvb_strsize(tvb, offset);
480
12
    proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
481
12
                        tvb, offset, i1, ENC_ASCII);
482
483
12
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
484
12
                    tvb_format_stringzpad(pinfo->pool, tvb, offset, i1));
485
486
12
    offset += i1;
487
488
12
    tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
489
12
                         opcode,  tftp_info);
490
12
    break;
491
492
13
  case TFTP_INFO:
493
13
    tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
494
13
                         opcode,  tftp_info);
495
13
    break;
496
497
7
  case TFTP_DATA:
498
7
    proto_item_set_len(root_ti, 4);
499
7
    blocknum_item = proto_tree_add_item_ret_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
500
7
                                                 ENC_BIG_ENDIAN, &blocknum);
501
7
    offset += 2;
502
503
7
    if (!PINFO_FD_VISITED(pinfo)) {
504
7
      blocknum = determine_full_blocknum(blocknum, tftp_info);
505
7
      p_add_proto_data(wmem_file_scope(), pinfo, proto_tftp, FULL_BLOCKNUM_KEY,
506
7
                       GUINT_TO_POINTER(blocknum));
507
7
    } else {
508
0
      blocknum = GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo,
509
0
                                                   proto_tftp, FULL_BLOCKNUM_KEY));
510
0
    }
511
7
    ti = proto_tree_add_uint(tftp_tree, hf_tftp_full_blocknum, tvb, 0, 0,
512
7
                             blocknum);
513
7
    proto_item_set_generated(ti);
514
515
7
    bytes = tvb_reported_length_remaining(tvb, offset);
516
7
    is_last_package = (bytes < tftp_info->blocksize);
517
518
    /* Sequence analysis on blocknums (first pass only) */
519
7
    if (!PINFO_FD_VISITED(pinfo)) {
520
7
      tftp_info->last_package_available |= is_last_package;
521
7
      if (blocknum > tftp_info->next_block_num) {
522
        /* There is a gap.  Don't try to recover from this. */
523
4
        tftp_info->next_block_num = blocknum + 1;
524
4
        tftp_info->blocks_missing = true;
525
        /* TODO: add info to a result table for showing expert info in later passes */
526
4
      }
527
3
      else if (blocknum == tftp_info->next_block_num) {
528
        /* OK, inc what we expect next */
529
1
        tftp_info->next_block_num++;
530
1
        tftp_info->file_length += bytes;
531
1
      }
532
7
    }
533
534
    /* Show number of bytes in this block, and whether it is the end of the file */
535
7
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %u%s",
536
7
                    blocknum,
537
7
                    is_last_package ?" (last)":"" );
538
539
7
    is_fragmented = !(is_last_package && blocknum == 1);
540
7
    if (is_fragmented) {
541
      /* If tftp_defragment is on, this is a fragment,
542
       * then just add the fragment to the hashtable.
543
       */
544
6
      if (tftp_defragment && (pinfo->num <= tftp_info->last_reassembly_package)) {
545
0
        tftpfd_head = fragment_add_seq_check(&tftp_reassembly_table, tvb, offset, pinfo,
546
0
                                             tftp_info->reassembly_id, /* id */
547
0
                                             NULL,                     /* data */
548
0
                                             blocknum - 1,
549
0
                                             bytes, !is_last_package);
550
551
0
        next_tvb = process_reassembled_data(tvb, offset, pinfo,
552
0
                                            "Reassembled TFTP", tftpfd_head,
553
0
                                            &tftp_frag_items, NULL, tftp_tree);
554
6
      } else {
555
6
        next_tvb = NULL;
556
6
      }
557
6
    } else {
558
1
      next_tvb = tvb_new_subset_remaining(tvb, offset);
559
1
    }
560
561
7
    if (next_tvb == NULL) {
562
      /* Reassembly continues */
563
6
      call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
564
6
    } else {
565
      /* Reassembly completed successfully */
566
1
      tftp_info->last_reassembly_package = pinfo->num;
567
1
      if (tvb_reported_length(next_tvb) > 0) {
568
1
        tftpinfo.filename = filename;
569
        /* Is the payload recognised by another dissector? */
570
1
        if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo,
571
1
                                     tree, &hdtbl_entry, &tftpinfo)) {
572
1
          call_data_dissector(next_tvb, pinfo, tree);
573
1
        } else {
574
0
          tftp_info->is_simple_file = false;
575
0
        }
576
1
      }
577
1
    }
578
579
7
    if (blocknum == 0xFFFF && bytes == tftp_info->blocksize) {
580
       /* There will be a block 0x10000. */
581
0
       expert_add_info(pinfo, blocknum_item, &ei_tftp_blocknum_will_wrap);
582
0
    }
583
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.
586
       */
587
7
    if (have_tap_listener(tftp_eo_tap) &&
588
0
        tftp_info->is_simple_file            /* This is a simple file */
589
0
        && filename != NULL                  /* There is a file name */
590
0
        && !tftp_info->blocks_missing        /* No missing blocks */
591
0
        && (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. */
595
7
    ) {
596
597
0
      if (PINFO_FD_VISITED(pinfo)) {
598
0
        if (blocknum == 1 && !tftp_info->payload_data) {
599
0
          tftp_info->payload_data = (uint8_t *)g_try_malloc((size_t)tftp_info->file_length);
600
0
        }
601
0
      } else {
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
604
         * to the tap.
605
         */
606
0
        tftp_info->payload_data = (uint8_t *)wmem_realloc(wmem_file_scope(), tftp_info->payload_data, (size_t)tftp_info->file_length);
607
0
      }
608
609
0
      if (tftp_info->payload_data == NULL ||
610
0
          (blocknum != tftp_info->next_tap_block_num)) {
611
        /* Ignore. Not enough memory or just clicking previous frame */
612
0
        break;
613
0
      }
614
0
      payload_data_offset =
615
0
          (tftp_info->next_tap_block_num - 1) * tftp_info->blocksize;
616
617
      /* Copy data to its place in the payload_data */
618
0
      tvb_memcpy(tvb, tftp_info->payload_data + payload_data_offset, offset,
619
0
                 bytes);
620
0
      tftp_info->next_tap_block_num++;
621
622
      /* Tap export object only when reach end of file */
623
0
      if (is_last_package) {
624
0
        tftp_eo_t        *eo_info;
625
626
        /* Create the eo_info to pass to the listener */
627
0
        eo_info = wmem_new(pinfo->pool, tftp_eo_t);
628
629
        /* Set filename */
630
0
        eo_info->filename = g_strdup(filename);
631
632
        /* Set payload */
633
0
        eo_info->payload_len = tftp_info->file_length;
634
0
        eo_info->payload_data = tftp_info->payload_data;
635
636
        /* Send to tap */
637
0
        tap_queue_packet(tftp_eo_tap, pinfo, eo_info);
638
639
        /* Have sent, so forget payload_data, and only pay attention if we
640
           get back to the first block again. */
641
0
        tftp_info->next_tap_block_num = 1;
642
0
        tftp_info->payload_data = NULL;
643
0
      }
644
0
    }
645
7
    break;
646
647
7
  case TFTP_ACK:
648
1
    proto_tree_add_item_ret_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
649
1
                                 ENC_BIG_ENDIAN, &blocknum);
650
651
1
    if (!PINFO_FD_VISITED(pinfo)) {
652
1
      blocknum = determine_full_blocknum(blocknum, tftp_info);
653
1
      p_add_proto_data(wmem_file_scope(), pinfo, proto_tftp, FULL_BLOCKNUM_KEY,
654
1
                       GUINT_TO_POINTER(blocknum));
655
1
    } else {
656
0
      blocknum = GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo,
657
0
                                                   proto_tftp, FULL_BLOCKNUM_KEY));
658
0
    }
659
1
    ti = proto_tree_add_uint(tftp_tree, hf_tftp_full_blocknum, tvb, 0, 0,
660
1
                             blocknum);
661
1
    proto_item_set_generated(ti);
662
663
1
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %u",
664
1
                    blocknum);
665
1
    offset += 2;
666
667
1
    if (tftp_info->dynamic_windowing_active && tvb_bytes_exist(tvb, offset, 1)) {
668
0
      bool windowsize_changed;
669
0
      uint8_t windowsize = tvb_get_uint8(tvb, offset);
670
0
      ti = proto_tree_add_uint(tftp_tree, hf_tftp_nextwindowsize, tvb,
671
0
                               offset, 1, windowsize);
672
0
      if (!PINFO_FD_VISITED(pinfo)) {
673
        /*
674
         * Note changes in window size, but ignore the final ACK which includes
675
         * an unnecessary (and seemingly bogus) window size.
676
         */
677
0
        windowsize_changed = windowsize != tftp_info->windowsize &&
678
0
                             !tftp_info->last_package_available;
679
0
        if (windowsize_changed) {
680
0
          p_add_proto_data(wmem_file_scope(), pinfo, proto_tftp,
681
0
                           WINDOWSIZE_CHANGE_KEY, GUINT_TO_POINTER(1));
682
0
          tftp_info->windowsize = windowsize;
683
0
        }
684
0
      } else {
685
0
        windowsize_changed = p_get_proto_data(wmem_file_scope(), pinfo, proto_tftp, WINDOWSIZE_CHANGE_KEY) != NULL;
686
0
      }
687
688
0
      if (windowsize_changed) {
689
0
        expert_add_info(pinfo, ti, &ei_tftp_windowsize_change);
690
0
      }
691
0
    }
692
1
    break;
693
694
2
  case TFTP_ERROR:
695
2
    error = tvb_get_ntohs(tvb, offset);
696
2
    proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2,
697
2
                        error);
698
699
2
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s",
700
2
                    val_to_str(pinfo->pool, error, tftp_error_code_vals, "Unknown (%u)"));
701
702
2
    offset += 2;
703
704
2
    i1 = tvb_strsize(tvb, offset);
705
2
    proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset,
706
2
                        i1, ENC_ASCII);
707
708
2
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s",
709
2
                    tvb_format_stringzpad(pinfo->pool, tvb, offset, i1));
710
711
    /*
712
     * If the packet looks like an intentional "close" after a transfer-size
713
     * probe, don't report it as an error.
714
     */
715
716
2
    if (!PINFO_FD_VISITED(pinfo)) {
717
2
      likely_tsize_probe = error_is_likely_tsize_probe(error, tftp_info);
718
2
      if (likely_tsize_probe) {
719
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_tftp, LIKELY_TSIZE_PROBE_KEY, GUINT_TO_POINTER(1));
720
0
      }
721
2
    } else {
722
0
      likely_tsize_probe = GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo, proto_tftp,
723
0
                                                             LIKELY_TSIZE_PROBE_KEY)) != 0;
724
0
    }
725
726
2
    expert_add_info(pinfo, tftp_tree, likely_tsize_probe ? &ei_tftp_likely_tsize_probe : &ei_tftp_error);
727
2
    break;
728
729
11
  case TFTP_OACK:
730
11
    tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
731
11
                         opcode, tftp_info);
732
11
    break;
733
734
5
  default:
735
5
    proto_tree_add_item(tftp_tree, hf_tftp_data, tvb, offset, -1, ENC_NA);
736
5
    break;
737
738
64
  }
739
32
  tftp_info->prev_opcode = opcode;
740
32
}
741
742
static tftp_conv_info_t *
743
tftp_info_for_conversation(conversation_t *conversation)
744
64
{
745
64
  tftp_conv_info_t *tftp_info;
746
747
64
  tftp_info = (tftp_conv_info_t *)conversation_get_proto_data(conversation, proto_tftp);
748
64
  if (!tftp_info) {
749
38
    tftp_info = wmem_new(wmem_file_scope(), tftp_conv_info_t);
750
38
    tftp_info->blocksize = 512; /* TFTP default block size */
751
38
    tftp_info->source_file = NULL;
752
38
    tftp_info->destination_file = NULL;
753
38
    tftp_info->request_frame = 0;
754
38
    tftp_info->tsize_requested = false;
755
38
    tftp_info->dynamic_windowing_active = false;
756
38
    tftp_info->windowsize = 0;
757
38
    tftp_info->prev_opcode = TFTP_NO_OPCODE;
758
38
    tftp_info->next_block_num = 1;
759
38
    tftp_info->blocks_missing = false;
760
38
    tftp_info->file_length = 0;
761
38
    tftp_info->last_package_available = false;
762
38
    tftp_info->next_tap_block_num = 1;
763
38
    tftp_info->payload_data = NULL;
764
38
    tftp_info->reassembly_id = conversation->conv_index;
765
38
    tftp_info->last_reassembly_package = UINT32_MAX;
766
38
    tftp_info->is_simple_file = true;
767
38
    conversation_add_proto_data(conversation, proto_tftp, tftp_info);
768
38
  }
769
64
  return tftp_info;
770
64
}
771
772
static bool
773
is_valid_request_body(tvbuff_t *tvb, packet_info *pinfo)
774
1.44k
{
775
1.44k
  int offset = 2;
776
1.44k
  unsigned zeros_counter = 0;
777
7.02k
  for (int i = offset; i < (int)tvb_captured_length(tvb); ++i) {
778
6.74k
    char c = (char)tvb_get_uint8(tvb, i);
779
6.74k
    if (c == '\0') {
780
1.64k
      zeros_counter++;
781
5.09k
    } else if (!g_ascii_isprint(c)) {
782
1.16k
      return false;
783
1.16k
    }
784
6.74k
  }
785
786
279
  if (zeros_counter % 2 != 0 || zeros_counter == 0)
787
243
    return false;
788
789
36
  offset += tvb_strsize(tvb, offset);
790
36
  unsigned len = tvb_strsize(tvb, offset);
791
36
  const char* mode = tvb_format_stringzpad(pinfo->pool, tvb, offset, len);
792
793
36
  const char* modes[] = {"netascii", "octet", "mail"};
794
144
  for(unsigned i = 0; i < array_length(modes); ++i) {
795
108
    if (g_ascii_strcasecmp(mode, modes[i]) == 0) return true;
796
108
  }
797
798
36
  return false;
799
36
}
800
801
static bool
802
is_valid_request(tvbuff_t *tvb, packet_info *pinfo)
803
57
{
804
57
  if (tvb_captured_length(tvb) < MIN_HDR_LEN)
805
4
    return false;
806
53
  uint16_t opcode = tvb_get_ntohs(tvb, 0);
807
53
  if ((opcode != TFTP_RRQ) && (opcode != TFTP_WRQ))
808
30
    return false;
809
23
  return is_valid_request_body(tvb, pinfo);
810
53
}
811
812
static conversation_t* create_tftp_conversation(packet_info *pinfo)
813
0
{
814
0
  conversation_t* conversation = NULL;
815
0
  if (!PINFO_FD_VISITED(pinfo)) {
816
    /* New read or write request on first pass, so create conversation with client port only */
817
    /* XXX - We might want to create one conversation for the addresses and
818
     * port, and have a wmem_tree_t of tftp_conv_info_t, which is the
819
     * information for a single transfer.
820
     */
821
0
    conversation = conversation_new_strat(pinfo, CONVERSATION_UDP, NO_PORT2);
822
823
0
    conversation_set_dissector(conversation, tftp_handle);
824
    /* Store conversation in this frame */
825
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_tftp, CONVERSATION_KEY,
826
0
                     (void *)conversation);
827
0
  } else {
828
    /* Read or write request, but not first pass, so look up existing conversation */
829
0
    conversation = (conversation_t *)p_get_proto_data(wmem_file_scope(), pinfo,
830
0
                                                      proto_tftp, CONVERSATION_KEY);
831
0
  }
832
0
  return conversation;
833
0
}
834
835
static bool
836
dissect_tftp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
837
1.42k
{
838
1.42k
  if (is_valid_request_body(tvb, pinfo)) {
839
0
    conversation_t* conversation = create_tftp_conversation(pinfo);
840
0
    dissect_tftp_message(tftp_info_for_conversation(conversation), tvb, pinfo, tree);
841
0
    return true;
842
0
  }
843
1.42k
  return false;
844
1.42k
}
845
846
static bool
847
dissect_embeddedtftp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
848
21
{
849
  /* Used to dissect TFTP packets where one can not assume
850
     that the TFTP is the only protocol used by that port, and
851
     that TFTP may not be carried by UDP */
852
21
  conversation_t   *conversation;
853
21
  uint16_t          opcode;
854
855
  /*
856
   * We need to verify it could be a TFTP message before creating a conversation
857
   */
858
859
21
  if (tvb_captured_length(tvb) < MIN_HDR_LEN)
860
5
    return false;
861
862
16
  opcode = tvb_get_ntohs(tvb, 0);
863
864
16
  switch (opcode) {
865
3
    case TFTP_RRQ:
866
3
    case TFTP_WRQ:
867
      /* These 2 opcodes have a NULL-terminated source file name after opcode. Verify */
868
3
      if (!is_valid_request_body(tvb, pinfo))
869
3
        return false;
870
     /* Intentionally dropping through here... */
871
0
    case TFTP_DATA:
872
0
    case TFTP_ACK:
873
4
    case TFTP_OACK:
874
7
    case TFTP_INFO:
875
7
      break;
876
0
    case TFTP_ERROR:
877
      /* for an error, we can verify the error code is legit */
878
0
      switch (tvb_get_ntohs(tvb, 2)) {
879
0
        case TFTP_ERR_NOT_DEF:
880
0
        case TFTP_ERR_NOT_FOUND:
881
0
        case TFTP_ERR_NOT_ALLOWED:
882
0
        case TFTP_ERR_DISK_FULL:
883
0
        case TFTP_ERR_BAD_OP:
884
0
        case TFTP_ERR_BAD_ID:
885
0
        case TFTP_ERR_EXISTS:
886
0
        case TFTP_ERR_NO_USER:
887
0
        case TFTP_ERR_OPT_FAIL:
888
0
          break;
889
0
        default:
890
0
          return false;
891
0
      }
892
0
      break;
893
6
    default:
894
6
      return false;
895
16
  }
896
897
7
  conversation = find_or_create_conversation(pinfo);
898
7
  dissect_tftp_message(tftp_info_for_conversation(conversation), tvb, pinfo, tree);
899
7
  return true;
900
16
}
901
902
static int
903
dissect_tftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
904
57
{
905
57
  conversation_t   *conversation = NULL;
906
907
  /*
908
   * The first TFTP packet (which is always a read or write request)
909
   * goes to the TFTP port; the second one comes from some *other* port,
910
   * but goes back to the same IP address and port as the ones from which
911
   * the first packet came; all subsequent packets go between those two
912
   * IP addresses and ports.
913
   *
914
   * If this packet looks like the first of a transfer, we create
915
   * a conversation, with its address 1/port 1 pair being
916
   * the source address/port of this packet, its address 2 being
917
   * the destination address of this packet, and its port 2 being
918
   * wildcarded, and give it the TFTP dissector as a dissector.
919
   *
920
   * By checking if it looks like a request, we handle the case where
921
   * the same port is reused for another file transfer later in the
922
   * capture, and also handle the (rare but apparently existing) case
923
   * where the *other* port is still the TFTP port.
924
   */
925
57
  if (is_valid_request(tvb, pinfo))
926
0
  {
927
0
    conversation = create_tftp_conversation(pinfo);
928
0
  }
929
930
57
  if (conversation == NULL)
931
57
  {
932
    /* Not the initial read or write request */
933
    /* Look for wildcarded conversation based upon client port, checking
934
     * both directions (we don't know which side *is* the client port.) */
935
57
    if ((conversation = find_conversation_strat(pinfo, CONVERSATION_UDP,
936
57
                                     NO_PORT_B, true)) && conversation_get_dissector(conversation, pinfo->num) == tftp_handle) {
937
#if 0
938
      /* XXX: While setting the wildcarded port makes sense, if we do that,
939
       * it's more complicated to find the correct conversation if ports are
940
       * reused. (find_conversation with full information prefers any exact
941
       * match, even with an earlier setup frame, to any wildcarded match.)
942
       * We would want to find the most recent conversations with one wildcard
943
       * and with both ports, and take the latest of those.
944
       */
945
      /* Set other side of conversation (server port) */
946
      if (pinfo->destport == conversation_key_port1(conversation->key_ptr))
947
        conversation_set_port2(conversation, pinfo->srcport);
948
#endif
949
57
    } else if ((conversation = find_conversation_strat(pinfo, CONVERSATION_UDP,
950
57
                                     NO_PORT_B, false)) && conversation_get_dissector(conversation, pinfo->num) == tftp_handle) {
951
952
57
    } else {
953
      /* How did we get here? We must have matched one of the TFTP ports
954
       * and missed the WRQ/RRQ. While it is contrary to the spirit of
955
       * RFC 1350 for the server not to change ports, there appear to be
956
       * such servers out there (issue #18122), and since the default port
957
       * is IANA assigned it doesn't do harm to process it. Note that in
958
       * that case the conversation won't have the tftp dissector set. */
959
57
      conversation = find_conversation_pinfo_strat(pinfo, 0);
960
57
      if (conversation == NULL) {
961
0
        return 0;
962
0
      }
963
57
    }
964
57
  }
965
966
57
  if (pinfo->num > conversation->last_frame) {
967
0
    conversation->last_frame = pinfo->num;
968
0
  }
969
57
  dissect_tftp_message(tftp_info_for_conversation(conversation), tvb, pinfo, tree);
970
57
  return tvb_captured_length(tvb);
971
57
}
972
973
974
static void
975
14
apply_tftp_prefs(void) {
976
14
  global_tftp_port_range = prefs_get_range_value("tftp", "udp.port");
977
14
}
978
979
void
980
proto_register_tftp(void)
981
14
{
982
14
  static hf_register_info hf[] = {
983
14
    { &hf_tftp_opcode,
984
14
      { "Opcode",             "tftp.opcode",
985
14
        FT_UINT16, BASE_DEC, VALS(tftp_opcode_vals), 0x0,
986
14
        "TFTP message type", HFILL }},
987
988
14
    { &hf_tftp_source_file,
989
14
      { "Source File",        "tftp.source_file",
990
14
        FT_STRINGZ, BASE_NONE, NULL, 0x0,
991
14
        "TFTP source file name", HFILL }},
992
993
14
    { &hf_tftp_destination_file,
994
14
      { "Destination File",   "tftp.destination_file",
995
14
        FT_STRINGZ, BASE_NONE, NULL, 0x0,
996
14
        "TFTP destination file name", HFILL }},
997
998
14
    { &hf_tftp_request_frame,
999
14
      { "Request frame",        "tftp.request_frame",
1000
14
        FT_FRAMENUM, BASE_NONE, NULL, 0x00,
1001
14
        "TFTP request is in frame", HFILL }},
1002
1003
14
    { &hf_tftp_transfer_type,
1004
14
      { "Type",               "tftp.type",
1005
14
        FT_STRINGZ, BASE_NONE, NULL, 0x0,
1006
14
        "TFTP transfer type", HFILL }},
1007
1008
14
    { &hf_tftp_blocknum,
1009
14
      { "Block",              "tftp.block",
1010
14
        FT_UINT16, BASE_DEC, NULL, 0x0,
1011
14
        "Block number", HFILL }},
1012
1013
14
    { &hf_tftp_full_blocknum,
1014
14
      { "Full Block Number",  "tftp.block.full",
1015
14
        FT_UINT32, BASE_DEC, NULL, 0x0,
1016
14
        "Block number, adjusted for wrapping", HFILL }},
1017
1018
14
    { &hf_tftp_nextwindowsize,
1019
14
      { "Next Window Size", "tftp.nextwindowsize",
1020
14
        FT_UINT16, BASE_DEC, NULL, 0x0,
1021
14
        "Number of blocks in next transfer window", HFILL }},
1022
1023
14
    { &hf_tftp_error_code,
1024
14
      { "Error code",         "tftp.error.code",
1025
14
        FT_UINT16, BASE_DEC, VALS(tftp_error_code_vals), 0x0,
1026
14
        "Error code in case of TFTP error message", HFILL }},
1027
1028
14
    { &hf_tftp_error_string,
1029
14
      { "Error message",      "tftp.error.message",
1030
14
        FT_STRINGZ, BASE_NONE, NULL, 0x0,
1031
14
        "Error string in case of TFTP error message", HFILL }},
1032
1033
14
    { &hf_tftp_option_name,
1034
14
      { "Option name",        "tftp.option.name",
1035
14
        FT_STRINGZ, BASE_NONE, NULL, 0x0,
1036
14
        NULL, HFILL }},
1037
1038
14
    { &hf_tftp_option_value,
1039
14
      { "Option value",       "tftp.option.value",
1040
14
        FT_STRINGZ, BASE_NONE, NULL, 0x0,
1041
14
        NULL, HFILL }},
1042
1043
14
    { &hf_tftp_data,
1044
14
      { "Data",       "tftp.data",
1045
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
1046
14
        NULL, HFILL }},
1047
1048
14
    { &hf_tftp_fragments,
1049
14
      { "TFTP Fragments",        "tftp.fragments",
1050
14
        FT_NONE, BASE_NONE, NULL, 0x00,
1051
14
        NULL, HFILL }},
1052
1053
14
    { &hf_tftp_fragment,
1054
14
      { "TFTP Fragment",        "tftp.fragment",
1055
14
        FT_FRAMENUM, BASE_NONE, NULL, 0x00,
1056
14
        NULL, HFILL }},
1057
1058
14
    { &hf_tftp_fragment_overlap,
1059
14
      { "Fragment overlap",        "tftp.fragment.overlap",
1060
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1061
14
        "Fragment overlaps with other fragments", HFILL }},
1062
1063
14
    { &hf_tftp_fragment_overlap_conflicts,
1064
14
      { "Conflicting data in fragment overlap",
1065
14
        "tftp.fragment.overlap.conflicts",
1066
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1067
14
        "Overlapping fragments contained conflicting data", HFILL }},
1068
1069
14
    { &hf_tftp_fragment_multiple_tails,
1070
14
      { "Multiple tail fragments found",        "tftp.fragment.multipletails",
1071
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1072
14
        "Several tails were found when defragmenting the packet", HFILL }},
1073
1074
14
    { &hf_tftp_fragment_too_long_fragment,
1075
14
      { "Fragment too long",        "tftp.fragment.toolongfragment",
1076
14
        FT_BOOLEAN, BASE_NONE, NULL, 0x00,
1077
14
        "Fragment contained data past end of packet", HFILL }},
1078
1079
14
    { &hf_tftp_fragment_error,
1080
14
      { "Defragmentation error",        "tftp.fragment.error",
1081
14
        FT_FRAMENUM, BASE_NONE, NULL, 0x00,
1082
14
        "Defragmentation error due to illegal fragments", HFILL }},
1083
1084
14
    { &hf_tftp_fragment_count,
1085
14
      { "Fragment count",        "tftp.fragment.count",
1086
14
        FT_UINT32, BASE_DEC, NULL, 0x00,
1087
14
        NULL, HFILL }},
1088
1089
14
    { &hf_tftp_reassembled_in,
1090
14
      { "Reassembled TFTP in frame",        "tftp.reassembled_in",
1091
14
        FT_FRAMENUM, BASE_NONE, NULL, 0x00,
1092
14
        "This TFTP packet is reassembled in this frame", HFILL }},
1093
1094
14
    { &hf_tftp_reassembled_length,
1095
14
      { "Reassembled TFTP length",        "tftp.reassembled.length",
1096
14
        FT_UINT32, BASE_DEC, NULL, 0x00,
1097
14
        "The total length of the reassembled payload", HFILL }},
1098
1099
14
    { &hf_tftp_reassembled_data,
1100
14
      { "Reassembled TFTP data",        "tftp.reassembled.data",
1101
14
        FT_BYTES, BASE_NONE, NULL, 0x0,
1102
14
        "The reassembled payload", HFILL }},
1103
14
  };
1104
14
  static int *ett[] = {
1105
14
    &ett_tftp,
1106
14
    &ett_tftp_option,
1107
14
    &ett_tftp_fragment,
1108
14
    &ett_tftp_fragments,
1109
14
  };
1110
1111
14
  static ei_register_info ei[] = {
1112
14
     { &ei_tftp_error, { "tftp.error", PI_RESPONSE_CODE, PI_WARN, "TFTP ERROR packet", EXPFILL }},
1113
14
     { &ei_tftp_likely_tsize_probe, { "tftp.likely_tsize_probe", PI_REQUEST_CODE, PI_CHAT, "Likely transfer size (tsize) probe", EXPFILL }},
1114
14
     { &ei_tftp_blocksize_range, { "tftp.blocksize_range", PI_RESPONSE_CODE, PI_WARN, "TFTP blocksize out of range", EXPFILL }},
1115
14
     { &ei_tftp_blocknum_will_wrap, { "tftp.block.wrap", PI_SEQUENCE, PI_NOTE, "TFTP block number is about to wrap", EXPFILL }},
1116
14
     { &ei_tftp_windowsize_range, { "tftp.windowsize_range", PI_RESPONSE_CODE, PI_WARN, "TFTP windowsize out of range", EXPFILL }},
1117
14
     { &ei_tftp_msftwindow_unrecognized, { "tftp.msftwindow.unrecognized", PI_RESPONSE_CODE, PI_WARN, "Unrecognized msftwindow option", EXPFILL }},
1118
14
     { &ei_tftp_windowsize_change, { "tftp.windowsize.change", PI_SEQUENCE, PI_CHAT, "TFTP window size is changing", EXPFILL }},
1119
14
  };
1120
1121
14
  module_t *tftp_module;
1122
14
  expert_module_t* expert_tftp;
1123
1124
14
  proto_tftp = proto_register_protocol("Trivial File Transfer Protocol", "TFTP", "tftp");
1125
14
  proto_register_field_array(proto_tftp, hf, array_length(hf));
1126
14
  proto_register_subtree_array(ett, array_length(ett));
1127
14
  expert_tftp = expert_register_protocol(proto_tftp);
1128
14
  expert_register_field_array(expert_tftp, ei, array_length(ei));
1129
1130
14
  heur_subdissector_list = register_heur_dissector_list_with_description("tftp", "TFTP payload", proto_tftp);
1131
14
  reassembly_table_register(&tftp_reassembly_table, &addresses_ports_reassembly_table_functions);
1132
1133
14
  tftp_handle = register_dissector("tftp", dissect_tftp, proto_tftp);
1134
1135
14
  tftp_module = prefs_register_protocol(proto_tftp, apply_tftp_prefs);
1136
14
  prefs_register_bool_preference(tftp_module, "defragment",
1137
14
    "Reassemble fragmented TFTP files",
1138
14
    "Whether fragmented TFTP files should be reassembled", &tftp_defragment);
1139
1140
  /* Register the tap for the "Export Object" function */
1141
14
  tftp_eo_tap = register_export_object(proto_tftp, tftp_eo_packet, NULL);
1142
14
}
1143
1144
void
1145
proto_reg_handoff_tftp(void)
1146
14
{
1147
14
  heur_dissector_add("stun", dissect_embeddedtftp_heur, "TFTP over TURN", "tftp_stun", proto_tftp, HEURISTIC_ENABLE);
1148
14
  heur_dissector_add("udp", dissect_tftp_heur, "TFTP", "tftp", proto_tftp, HEURISTIC_ENABLE);
1149
1150
14
  dissector_add_uint_range_with_preference("udp.port", UDP_PORT_TFTP_RANGE, tftp_handle);
1151
14
  apply_tftp_prefs();
1152
14
}
1153
1154
/*
1155
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1156
 *
1157
 * Local variables:
1158
 * c-basic-offset: 2
1159
 * tab-width: 8
1160
 * indent-tabs-mode: nil
1161
 * End:
1162
 *
1163
 * vi: set shiftwidth=2 tabstop=8 expandtab:
1164
 * :indentSize=2:tabSize=8:noTabs=true:
1165
 */