Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-smb-direct.c
Line
Count
Source
1
/*
2
 * packet-smb-direct.c
3
 *
4
 * Routines for [MS-SMBD] the RDMA transport layer for SMB2/3
5
 *
6
 * Copyright 2012-2014 Stefan Metzmacher <metze@samba.org>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/reassemble.h>
19
#include <epan/prefs.h>
20
#include <epan/proto_data.h>
21
#include "packet-windows-common.h"
22
#include "packet-iwarp-ddp-rdmap.h"
23
#include "packet-infiniband.h"
24
25
void proto_register_smb_direct(void);
26
void proto_reg_handoff_smb_direct(void);
27
28
static dissector_handle_t smb_direct_handle;
29
30
static int proto_smb_direct;
31
32
static int ett_smb_direct;
33
static int ett_smb_direct_hdr;
34
static int ett_smb_direct_flags;
35
static int ett_smb_direct_fragment;
36
static int ett_smb_direct_fragments;
37
38
static int hf_smb_direct_negotiate_request;
39
static int hf_smb_direct_negotiate_response;
40
static int hf_smb_direct_data_message;
41
static int hf_smb_direct_min_version;
42
static int hf_smb_direct_max_version;
43
static int hf_smb_direct_negotiated_version;
44
static int hf_smb_direct_credits_requested;
45
static int hf_smb_direct_credits_granted;
46
static int hf_smb_direct_status;
47
static int hf_smb_direct_max_read_write_size;
48
static int hf_smb_direct_preferred_send_size;
49
static int hf_smb_direct_max_receive_size;
50
static int hf_smb_direct_max_fragmented_size;
51
static int hf_smb_direct_flags;
52
static int hf_smb_direct_flags_response_requested;
53
static int hf_smb_direct_remaining_length;
54
static int hf_smb_direct_data_offset;
55
static int hf_smb_direct_data_length;
56
static int hf_smb_direct_fragments;
57
static int hf_smb_direct_fragment;
58
static int hf_smb_direct_fragment_overlap;
59
static int hf_smb_direct_fragment_overlap_conflict;
60
static int hf_smb_direct_fragment_multiple_tails;
61
static int hf_smb_direct_fragment_too_long_fragment;
62
static int hf_smb_direct_fragment_error;
63
static int hf_smb_direct_fragment_count;
64
static int hf_smb_direct_reassembled_in;
65
static int hf_smb_direct_reassembled_length;
66
static int hf_smb_direct_reassembled_data;
67
68
static const fragment_items smb_direct_frag_items = {
69
  &ett_smb_direct_fragment,
70
  &ett_smb_direct_fragments,
71
  &hf_smb_direct_fragments,
72
  &hf_smb_direct_fragment,
73
  &hf_smb_direct_fragment_overlap,
74
  &hf_smb_direct_fragment_overlap_conflict,
75
  &hf_smb_direct_fragment_multiple_tails,
76
  &hf_smb_direct_fragment_too_long_fragment,
77
  &hf_smb_direct_fragment_error,
78
  &hf_smb_direct_fragment_count,
79
  &hf_smb_direct_reassembled_in,
80
  &hf_smb_direct_reassembled_length,
81
  &hf_smb_direct_reassembled_data,
82
  "SMB Direct fragments"
83
};
84
85
enum SMB_DIRECT_HDR_TYPE {
86
  SMB_DIRECT_HDR_UNKNOWN = -1,
87
  SMB_DIRECT_HDR_NEG_REQ = 1,
88
  SMB_DIRECT_HDR_NEG_REP = 2,
89
  SMB_DIRECT_HDR_DATA = 3
90
};
91
92
16
#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
93
94
static heur_dissector_list_t smb_direct_heur_subdissector_list;
95
96
static bool smb_direct_reassemble = true;
97
static reassembly_table smb_direct_reassembly_table;
98
static bool smb_direct_infiniband_reassemble = true;
99
100
static void
101
dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo,
102
         proto_tree *tree, uint32_t remaining_length)
103
0
{
104
0
  bool save_fragmented = pinfo->fragmented;
105
0
  conversation_t *conversation = NULL;
106
0
  fragment_head *fd_head = NULL;
107
0
  tvbuff_t *payload_tvb = NULL;
108
0
  bool more_frags = false;
109
0
  bool fd_head_not_cached = false;
110
0
  heur_dtbl_entry_t *hdtbl_entry;
111
112
0
  if (!smb_direct_reassemble) {
113
0
    payload_tvb = tvb;
114
0
    goto dissect_payload;
115
0
  }
116
117
0
  conversation = find_or_create_conversation(pinfo);
118
119
0
  if (remaining_length > 0) {
120
0
    more_frags = true;
121
0
  }
122
123
0
  fd_head = (fragment_head *)p_get_proto_data(wmem_file_scope(), pinfo, proto_smb_direct, 0);
124
0
  if (fd_head == NULL) {
125
0
    fd_head_not_cached = true;
126
127
0
    if (!PINFO_FD_VISITED(pinfo)) {
128
0
      fd_head = fragment_add_seq_next(&smb_direct_reassembly_table,
129
0
              tvb, 0, pinfo,
130
0
              conversation->conv_index,
131
0
              NULL, tvb_captured_length(tvb),
132
0
              more_frags);
133
0
    }
134
0
  }
135
136
0
  if (fd_head == NULL) {
137
    /*
138
     * We really want the fd_head and pass it to
139
     * process_reassembled_data()
140
     *
141
     * So that individual fragments gets the
142
     * reassembled in field.
143
     */
144
0
    fd_head = fragment_get_reassembled_id(&smb_direct_reassembly_table,
145
0
                  pinfo,
146
0
                  conversation->conv_index);
147
0
  }
148
149
0
  if (fd_head == NULL) {
150
    /*
151
     * we need more data...
152
     */
153
0
    goto done;
154
0
  }
155
156
0
  if (fd_head_not_cached) {
157
0
    p_add_proto_data(wmem_file_scope(), pinfo,
158
0
         proto_smb_direct, 0, fd_head);
159
0
  }
160
161
0
  payload_tvb = process_reassembled_data(tvb, 0, pinfo,
162
0
                 "Reassembled SMB Direct",
163
0
                 fd_head,
164
0
                 &smb_direct_frag_items,
165
0
                 NULL, /* update_col_info*/
166
0
                 tree);
167
0
  if (payload_tvb == NULL) {
168
    /*
169
     * we need more data...
170
     */
171
0
    goto done;
172
0
  }
173
174
0
dissect_payload:
175
0
  pinfo->fragmented = false;
176
0
  if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
177
0
             payload_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
178
0
    call_data_dissector(payload_tvb, pinfo, tree);
179
0
  }
180
0
done:
181
0
  pinfo->fragmented = save_fragmented;
182
0
  return;
183
0
}
184
185
static void
186
dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
187
       enum SMB_DIRECT_HDR_TYPE hdr_type)
188
189
0
{
190
0
  proto_tree *tree = NULL;
191
0
  proto_item *item = NULL;
192
0
  proto_tree *neg_req_tree = NULL;
193
0
  proto_tree *neg_rep_tree = NULL;
194
0
  proto_tree *data_tree = NULL;
195
0
  unsigned offset = 0;
196
0
  uint32_t status = 0;
197
0
  uint32_t remaining_length = 0;
198
0
  uint32_t data_offset = 0;
199
0
  uint32_t data_length = 0;
200
0
  unsigned rlen = tvb_reported_length(tvb);
201
0
  int len = 0;
202
0
  tvbuff_t *next_tvb = NULL;
203
0
  static int * const flags[] = {
204
0
    &hf_smb_direct_flags_response_requested,
205
0
    NULL
206
0
  };
207
208
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMBDirect");
209
0
  col_clear(pinfo->cinfo, COL_INFO);
210
211
0
  if (parent_tree != NULL) {
212
0
    item = proto_tree_add_item(parent_tree, proto_smb_direct, tvb, 0, -1, ENC_NA);
213
0
    tree = proto_item_add_subtree(item, ett_smb_direct);
214
0
  }
215
216
0
  switch (hdr_type) {
217
0
  case SMB_DIRECT_HDR_UNKNOWN:
218
0
    break;
219
220
0
  case SMB_DIRECT_HDR_NEG_REQ:
221
0
    col_append_str(pinfo->cinfo, COL_INFO, "NegotiateRequest");
222
223
0
    if (tree == NULL) {
224
0
      break;
225
0
    }
226
227
0
    item = proto_tree_add_item(tree, hf_smb_direct_negotiate_request, tvb, 0, -1, ENC_NA);
228
0
    neg_req_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);
229
230
0
    proto_tree_add_item(neg_req_tree, hf_smb_direct_min_version,
231
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
232
0
    offset += 2;
233
234
0
    proto_tree_add_item(neg_req_tree, hf_smb_direct_max_version,
235
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
236
0
    offset += 2;
237
238
    /* 2 bytes reserved */
239
0
    offset += 2;
240
241
0
    proto_tree_add_item(neg_req_tree, hf_smb_direct_credits_requested,
242
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
243
0
    offset += 2;
244
245
0
    proto_tree_add_item(neg_req_tree, hf_smb_direct_preferred_send_size,
246
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
247
0
    offset += 4;
248
249
0
    proto_tree_add_item(neg_req_tree, hf_smb_direct_max_receive_size,
250
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
251
0
    offset += 4;
252
253
0
    proto_tree_add_item(neg_req_tree, hf_smb_direct_max_fragmented_size,
254
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
255
    /* offset += 4; */
256
0
    break;
257
258
0
  case SMB_DIRECT_HDR_NEG_REP:
259
0
    col_append_str(pinfo->cinfo, COL_INFO, "NegotiateResponse");
260
261
0
    status = tvb_get_letohl(tvb, 12);
262
0
    if (status != 0) {
263
0
      col_append_fstr(
264
0
        pinfo->cinfo, COL_INFO, ", Error: %s",
265
0
        val_to_str_ext(pinfo->pool, status, &NT_errors_ext, "Unknown (0x%08X)"));
266
0
    }
267
268
0
    if (tree == NULL) {
269
0
      break;
270
0
    }
271
272
0
    item = proto_tree_add_item(tree, hf_smb_direct_negotiate_response, tvb, 0, -1, ENC_NA);
273
0
    neg_rep_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);
274
275
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_min_version,
276
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
277
0
    offset += 2;
278
279
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_version,
280
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
281
0
    offset += 2;
282
283
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_negotiated_version,
284
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
285
0
    offset += 2;
286
287
    /* 2 bytes reserved */
288
0
    offset += 2;
289
290
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_requested,
291
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
292
0
    offset += 2;
293
294
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_granted,
295
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
296
0
    offset += 2;
297
298
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_status,
299
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
300
0
    offset += 4;
301
302
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_read_write_size,
303
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
304
0
    offset += 4;
305
306
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_preferred_send_size,
307
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
308
0
    offset += 4;
309
310
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_receive_size,
311
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
312
0
    offset += 4;
313
314
0
    proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_fragmented_size,
315
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
316
    /* offset += 4; */
317
0
    break;
318
319
0
  case SMB_DIRECT_HDR_DATA:
320
0
    col_append_str(pinfo->cinfo, COL_INFO, "DataMessage");
321
322
0
    rlen = MIN(rlen, 24);
323
324
0
    item = proto_tree_add_item(tree, hf_smb_direct_data_message, tvb, 0, rlen, ENC_NA);
325
0
    data_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);
326
327
0
    proto_tree_add_item(data_tree, hf_smb_direct_credits_requested,
328
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
329
0
    offset += 2;
330
331
0
    proto_tree_add_item(data_tree, hf_smb_direct_credits_granted,
332
0
            tvb, offset, 2, ENC_LITTLE_ENDIAN);
333
0
    offset += 2;
334
335
0
    proto_tree_add_bitmask(data_tree, tvb, offset, hf_smb_direct_flags,
336
0
             ett_smb_direct_flags, flags, ENC_LITTLE_ENDIAN);
337
0
    offset += 2;
338
339
    /* 2 bytes reserved */
340
0
    offset += 2;
341
342
0
    remaining_length = tvb_get_letohl(tvb, offset);
343
0
    proto_tree_add_item(data_tree, hf_smb_direct_remaining_length,
344
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
345
0
    offset += 4;
346
347
0
    data_offset = tvb_get_letohl(tvb, offset);
348
0
    proto_tree_add_item(data_tree, hf_smb_direct_data_offset,
349
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
350
0
    offset += 4;
351
352
0
    data_length = tvb_get_letohl(tvb, offset);
353
0
    proto_tree_add_item(data_tree, hf_smb_direct_data_length,
354
0
            tvb, offset, 4, ENC_LITTLE_ENDIAN);
355
0
    offset += 4;
356
357
0
    if (data_length > 0 && data_offset > (uint32_t)offset) {
358
0
      len = tvb_reported_length_remaining(tvb, data_offset);
359
0
    }
360
361
0
    if (data_length <= (uint32_t)len) {
362
0
      next_tvb = tvb_new_subset_length(tvb, data_offset,
363
0
              data_length);
364
0
    }
365
366
0
    if (next_tvb != NULL) {
367
0
      dissect_smb_direct_payload(next_tvb, pinfo,
368
0
               parent_tree, remaining_length);
369
0
    }
370
371
    /* offset = data_offset + data_length; */
372
0
    break;
373
0
  }
374
375
0
  return;
376
0
}
377
378
static enum SMB_DIRECT_HDR_TYPE
379
is_smb_direct(tvbuff_t *tvb, packet_info *pinfo _U_)
380
96
{
381
96
  bool maybe_neg_req = false;
382
96
  bool maybe_data = false;
383
96
  unsigned len = tvb_reported_length(tvb);
384
385
96
  if (len < 20) {
386
18
    return SMB_DIRECT_HDR_UNKNOWN;
387
18
  }
388
389
78
  if (len == 32 &&
390
2
      tvb_get_letohs(tvb, 0) == 0x0100 && /* min version */
391
1
      tvb_get_letohs(tvb, 2) == 0x0100 && /* max version */
392
0
      tvb_get_letohs(tvb, 4) == 0x0100 && /* negotiated version */
393
0
      tvb_get_letohs(tvb, 6) == 0x0000)   /* reserved */
394
0
  {
395
    /* Negotiate Response */
396
0
    return SMB_DIRECT_HDR_NEG_REP;
397
0
  }
398
399
78
  if (tvb_get_letohs(tvb, 0) == 0x0100 && /* min version */
400
1
      tvb_get_letohs(tvb, 2) == 0x0100 && /* max version */
401
0
      tvb_get_letohs(tvb, 4) == 0x0000)   /* reserved */
402
0
  {
403
0
    maybe_neg_req = true;
404
0
  }
405
406
78
  if (tvb_get_letohs(tvb, 0) <= 255 &&    /* credits up to 255 */
407
36
      tvb_get_letohs(tvb, 2) <= 255 &&    /* credits up to 255 */
408
20
      tvb_get_letohs(tvb, 4) <= 1   &&    /* flags 0 or 1 */
409
14
      tvb_get_letohs(tvb, 6) == 0)    /* reserved */
410
4
  {
411
4
    maybe_data = true;
412
4
  }
413
414
78
  if (len == 20) {
415
3
    if (tvb_get_letohl(tvb, 8) != 0) { /* remaining */
416
3
      maybe_data = false;
417
3
    }
418
3
    if (tvb_get_letohl(tvb, 12) != 0) { /* data offset */
419
3
      maybe_data = false;
420
3
    }
421
3
    if (tvb_get_letohl(tvb, 16) != 0) { /* data length */
422
3
      maybe_data = false;
423
3
    }
424
425
3
    if (maybe_neg_req && !maybe_data) {
426
      /* Negotiate Request */
427
0
      return SMB_DIRECT_HDR_NEG_REQ;
428
0
    }
429
    /* maybe_neg_req = false; */
430
3
    if (maybe_data) {
431
      /* Data Message */
432
0
      return SMB_DIRECT_HDR_DATA;
433
0
    }
434
3
  }
435
436
78
  if (len <= 24) {
437
14
    return SMB_DIRECT_HDR_UNKNOWN;
438
14
  }
439
440
64
  if (tvb_get_letohl(tvb, 12) != 24) { /* data offset */
441
64
    return SMB_DIRECT_HDR_UNKNOWN;
442
64
  }
443
444
0
  if (tvb_get_letohl(tvb, 16) == 0) {  /* data length */
445
0
    return SMB_DIRECT_HDR_UNKNOWN;
446
0
  }
447
448
0
  if (tvb_get_letohl(tvb, 20) != 0) { /* padding */
449
0
    return SMB_DIRECT_HDR_UNKNOWN;
450
0
  }
451
452
0
  if (maybe_data) {
453
    /* Data Message */
454
0
    return SMB_DIRECT_HDR_DATA;
455
0
  }
456
457
0
  return SMB_DIRECT_HDR_UNKNOWN;
458
0
}
459
460
static bool
461
dissect_smb_direct_iwarp_heur(tvbuff_t *tvb, packet_info *pinfo,
462
            proto_tree *parent_tree, void *data)
463
0
{
464
0
  struct rdmapinfo *info = (struct rdmapinfo *)data;
465
0
  enum SMB_DIRECT_HDR_TYPE hdr_type;
466
467
0
  if (info == NULL) {
468
0
    return false;
469
0
  }
470
471
0
  switch (info->opcode) {
472
0
  case RDMA_SEND:
473
0
  case RDMA_SEND_INVALIDATE:
474
0
  case RDMA_SEND_SE:
475
0
  case RDMA_SEND_SE_INVALIDATE:
476
0
    break;
477
0
  default:
478
0
    return false;
479
0
  }
480
481
0
  hdr_type = is_smb_direct(tvb, pinfo);
482
0
  if (hdr_type == SMB_DIRECT_HDR_UNKNOWN) {
483
0
    return false;
484
0
  }
485
486
0
  dissect_smb_direct(tvb, pinfo, parent_tree, hdr_type);
487
0
  return true;
488
0
}
489
490
static int
491
dissect_smb_direct_infiniband(tvbuff_t *tvb, packet_info *pinfo,
492
           proto_tree *parent_tree, void *data)
493
176
{
494
176
  struct infinibandinfo *info = (struct infinibandinfo *)data;
495
176
  enum SMB_DIRECT_HDR_TYPE hdr_type;
496
497
176
  if (info == NULL) {
498
0
    return 0;
499
0
  }
500
501
176
  switch (info->opCode) {
502
29
  case RC_SEND_FIRST:
503
33
  case RC_SEND_MIDDLE:
504
79
  case RC_SEND_LAST:
505
80
  case RC_SEND_LAST_IMM:
506
88
  case RC_SEND_ONLY:
507
89
  case RC_SEND_ONLY_IMM:
508
95
  case RC_SEND_LAST_INVAL:
509
96
  case RC_SEND_ONLY_INVAL:
510
96
    break;
511
80
  default:
512
80
    return 0;
513
176
  }
514
515
96
  hdr_type = is_smb_direct(tvb, pinfo);
516
96
  if (hdr_type == SMB_DIRECT_HDR_UNKNOWN) {
517
96
    return 0;
518
96
  }
519
520
0
  if (!info->do_rc_send_reassembling && smb_direct_infiniband_reassemble) {
521
    /*
522
     * Let the infiniband layer
523
     * do RC Send reassembling
524
     * for this conversation
525
     */
526
0
    info->do_rc_send_reassembling = smb_direct_infiniband_reassemble;
527
0
    return 0;
528
0
  }
529
530
0
  dissect_smb_direct(tvb, pinfo, parent_tree, hdr_type);
531
0
  return tvb_captured_length(tvb);
532
0
}
533
534
static bool
535
dissect_smb_direct_infiniband_heur(tvbuff_t *tvb, packet_info *pinfo,
536
        proto_tree *parent_tree, void *data)
537
176
{
538
176
  return (dissect_smb_direct_infiniband(tvb, pinfo, parent_tree, data) > 0);
539
176
}
540
541
void proto_register_smb_direct(void)
542
16
{
543
16
  static int *ett[] = {
544
16
    &ett_smb_direct,
545
16
    &ett_smb_direct_hdr,
546
16
    &ett_smb_direct_flags,
547
16
    &ett_smb_direct_fragment,
548
16
    &ett_smb_direct_fragments,
549
16
  };
550
551
16
  static hf_register_info hf[] = {
552
16
  { &hf_smb_direct_negotiate_request,
553
16
    { "NegotiateRequest", "smb_direct.negotiate_request",
554
16
    FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
555
556
16
  { &hf_smb_direct_negotiate_response,
557
16
    { "NegotiateResponse", "smb_direct.negotiate_response",
558
16
    FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
559
560
16
  { &hf_smb_direct_data_message,
561
16
    { "DataMessage", "smb_direct.data_message",
562
16
    FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
563
564
16
  { &hf_smb_direct_min_version,
565
16
    { "MinVersion", "smb_direct.version.min",
566
16
    FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
567
568
16
  { &hf_smb_direct_max_version,
569
16
    { "MaxVersion", "smb_direct.version.max",
570
16
    FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
571
572
16
  { &hf_smb_direct_negotiated_version,
573
16
    { "NegotiatedVersion", "smb_direct.version.negotiated",
574
16
    FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
575
576
16
  { &hf_smb_direct_credits_requested,
577
16
    { "CreditsRequested", "smb_direct.credits.requested",
578
16
    FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
579
580
16
  { &hf_smb_direct_credits_granted,
581
16
    { "CreditsGranted", "smb_direct.credits.granted",
582
16
    FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
583
584
16
  { &hf_smb_direct_status,
585
16
    { "Status", "smb_direct.status",
586
16
    FT_UINT32, BASE_HEX|BASE_EXT_STRING, &NT_errors_ext, 0,
587
16
    "NT Status code", HFILL }},
588
589
16
  { &hf_smb_direct_max_read_write_size,
590
16
    { "MaxReadWriteSize", "smb_direct.max_read_write_size",
591
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
592
593
16
  { &hf_smb_direct_preferred_send_size,
594
16
    { "PreferredSendSize", "smb_direct.preferred_send_size",
595
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
596
597
16
  { &hf_smb_direct_max_receive_size,
598
16
    { "MaxReceiveSize", "smb_direct.max_receive_size",
599
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
600
601
16
  { &hf_smb_direct_max_fragmented_size,
602
16
    { "MaxFragmentedSize", "smb_direct.max_fragmented_size",
603
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
604
605
16
  { &hf_smb_direct_flags,
606
16
    { "Flags", "smb_direct.flags",
607
16
    FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
608
609
16
  { &hf_smb_direct_flags_response_requested,
610
16
    { "ResponseRequested", "smb_direct.flags.response_requested",
611
16
    FT_BOOLEAN, 16, NULL, SMB_DIRECT_RESPONSE_REQUESTED,
612
16
    NULL, HFILL }},
613
614
16
  { &hf_smb_direct_remaining_length,
615
16
    { "RemainingLength", "smb_direct.remaining_length",
616
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
617
618
16
  { &hf_smb_direct_data_offset,
619
16
    { "DataOffset", "smb_direct.data_offset",
620
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
621
622
16
  { &hf_smb_direct_data_length,
623
16
    { "DataLength", "smb_direct.data_length",
624
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
625
626
16
  { &hf_smb_direct_fragments,
627
16
    { "Reassembled SMB Direct Fragments", "smb_direct.fragments",
628
16
    FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
629
630
16
  { &hf_smb_direct_fragment,
631
16
    { "SMB Direct Fragment", "smb_direct.fragment",
632
16
    FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
633
16
  { &hf_smb_direct_fragment_overlap,
634
16
    { "Fragment overlap", "smb_direct.fragment.overlap",
635
16
    FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
636
637
16
  { &hf_smb_direct_fragment_overlap_conflict,
638
16
    { "Conflicting data in fragment overlap", "smb_direct.fragment.overlap.conflict",
639
16
    FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
640
641
16
  { &hf_smb_direct_fragment_multiple_tails,
642
16
    { "Multiple tail fragments found", "smb_direct.fragment.multipletails",
643
16
    FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
644
645
16
  { &hf_smb_direct_fragment_too_long_fragment,
646
16
    { "Fragment too long", "smb_direct.fragment.toolongfragment",
647
16
    FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
648
649
16
  { &hf_smb_direct_fragment_error,
650
16
    { "Defragmentation error", "smb_direct.fragment.error",
651
16
    FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
652
653
16
  { &hf_smb_direct_fragment_count,
654
16
    { "Fragment count", "smb_direct.fragment.count",
655
16
    FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
656
657
16
  { &hf_smb_direct_reassembled_in,
658
16
    { "Reassembled PDU in frame", "smb_direct.reassembled_in",
659
16
    FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
660
661
16
  { &hf_smb_direct_reassembled_length,
662
16
    { "Reassembled SMB Direct length", "smb_direct.reassembled.length",
663
16
    FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
664
665
16
  { &hf_smb_direct_reassembled_data,
666
16
    { "Reassembled SMB Direct data", "smb_direct.reassembled.data",
667
16
    FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
668
669
16
  };
670
16
  module_t *smb_direct_module;
671
672
16
  proto_smb_direct = proto_register_protocol("SMB-Direct (SMB RDMA Transport)",
673
16
               "SMBDirect", "smb_direct");
674
16
  proto_register_subtree_array(ett, array_length(ett));
675
16
  proto_register_field_array(proto_smb_direct, hf, array_length(hf));
676
677
16
  smb_direct_handle = register_dissector("smb_direct", dissect_smb_direct_infiniband, proto_smb_direct);
678
679
16
  smb_direct_heur_subdissector_list = register_heur_dissector_list_with_description("smb_direct", "SMB-Direct payload", proto_smb_direct);
680
681
16
  smb_direct_module = prefs_register_protocol(proto_smb_direct, NULL);
682
16
  prefs_register_bool_preference(smb_direct_module,
683
16
               "reassemble_smb_direct",
684
16
               "Reassemble SMB Direct fragments",
685
16
               "Whether the SMB Direct dissector should reassemble fragmented payloads",
686
16
               &smb_direct_reassemble);
687
16
  reassembly_table_register(&smb_direct_reassembly_table,
688
16
      &addresses_ports_reassembly_table_functions);
689
16
  prefs_register_bool_preference(smb_direct_module,
690
16
               "reassemble_smb_direct_infiniband",
691
16
               "Reassemble Infiniband Send fragments for SMB Direct",
692
16
               "Whether the SMB Direct dissector should reassemble Infiniband Send fragments",
693
16
               &smb_direct_infiniband_reassemble);
694
16
}
695
696
void
697
proto_reg_handoff_smb_direct(void)
698
16
{
699
16
  heur_dissector_add("iwarp_ddp_rdmap",
700
16
        dissect_smb_direct_iwarp_heur,
701
16
        "SMB Direct over iWARP", "smb_direct_iwarp",
702
16
        proto_smb_direct, HEURISTIC_ENABLE);
703
16
  heur_dissector_add("infiniband.payload",
704
16
        dissect_smb_direct_infiniband_heur,
705
16
        "SMB Direct Infiniband", "smb_direct_infiniband",
706
16
        proto_smb_direct, HEURISTIC_ENABLE);
707
16
  dissector_add_for_decode_as("infiniband", smb_direct_handle);
708
709
16
}
710
711
/*
712
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
713
 *
714
 * Local variables:
715
 * c-basic-offset: 8
716
 * tab-width: 8
717
 * indent-tabs-mode: t
718
 * End:
719
 *
720
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
721
 * :indentSize=8:tabSize=8:noTabs=false:
722
 */