4 * Routines for [MS-SMBD] the RDMA transport layer for SMB2/3
6 * Copyright 2012-2014 Stefan Metzmacher <metze@samba.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
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"
25 void proto_register_smb_direct(void);
26 void proto_reg_handoff_smb_direct(void);
28 static dissector_handle_t smb_direct_handle
;
30 static int proto_smb_direct
;
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
;
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
;
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"
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
92 #define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
94 static heur_dissector_list_t smb_direct_heur_subdissector_list
;
96 static bool smb_direct_reassemble
= true;
97 static reassembly_table smb_direct_reassembly_table
;
100 dissect_smb_direct_payload(tvbuff_t
*tvb
, packet_info
*pinfo
,
101 proto_tree
*tree
, uint32_t remaining_length
)
103 bool save_fragmented
= pinfo
->fragmented
;
104 int save_visited
= pinfo
->fd
->visited
;
105 conversation_t
*conversation
= NULL
;
106 fragment_head
*fd_head
= NULL
;
107 tvbuff_t
*payload_tvb
= NULL
;
108 bool more_frags
= false;
109 bool fd_head_not_cached
= false;
110 heur_dtbl_entry_t
*hdtbl_entry
;
112 if (!smb_direct_reassemble
) {
114 goto dissect_payload
;
117 conversation
= find_or_create_conversation(pinfo
);
119 if (remaining_length
> 0) {
123 fd_head
= (fragment_head
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_smb_direct
, 0);
124 if (fd_head
== NULL
) {
125 fd_head_not_cached
= true;
127 pinfo
->fd
->visited
= 0;
128 fd_head
= fragment_add_seq_next(&smb_direct_reassembly_table
,
130 conversation
->conv_index
,
131 NULL
, tvb_captured_length(tvb
),
135 if (fd_head
== NULL
) {
137 * We really want the fd_head and pass it to
138 * process_reassembled_data()
140 * So that individual fragments gets the
141 * reassembled in field.
143 fd_head
= fragment_get_reassembled_id(&smb_direct_reassembly_table
,
145 conversation
->conv_index
);
148 if (fd_head
== NULL
) {
150 * we need more data...
155 if (fd_head_not_cached
) {
156 p_add_proto_data(wmem_file_scope(), pinfo
,
157 proto_smb_direct
, 0, fd_head
);
160 payload_tvb
= process_reassembled_data(tvb
, 0, pinfo
,
161 "Reassembled SMB Direct",
163 &smb_direct_frag_items
,
164 NULL
, /* update_col_info*/
166 if (payload_tvb
== NULL
) {
168 * we need more data...
174 pinfo
->fragmented
= false;
175 if (!dissector_try_heuristic(smb_direct_heur_subdissector_list
,
176 payload_tvb
, pinfo
, tree
, &hdtbl_entry
, NULL
)) {
177 call_data_dissector(payload_tvb
, pinfo
, tree
);
180 pinfo
->fragmented
= save_fragmented
;
181 pinfo
->fd
->visited
= save_visited
;
186 dissect_smb_direct(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
,
187 enum SMB_DIRECT_HDR_TYPE hdr_type
)
190 proto_tree
*tree
= NULL
;
191 proto_item
*item
= NULL
;
192 proto_tree
*neg_req_tree
= NULL
;
193 proto_tree
*neg_rep_tree
= NULL
;
194 proto_tree
*data_tree
= NULL
;
197 uint32_t remaining_length
= 0;
198 uint32_t data_offset
= 0;
199 uint32_t data_length
= 0;
200 unsigned rlen
= tvb_reported_length(tvb
);
202 tvbuff_t
*next_tvb
= NULL
;
203 static int * const flags
[] = {
204 &hf_smb_direct_flags_response_requested
,
208 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SMBDirect");
209 col_clear(pinfo
->cinfo
, COL_INFO
);
211 if (parent_tree
!= NULL
) {
212 item
= proto_tree_add_item(parent_tree
, proto_smb_direct
, tvb
, 0, -1, ENC_NA
);
213 tree
= proto_item_add_subtree(item
, ett_smb_direct
);
217 case SMB_DIRECT_HDR_UNKNOWN
:
220 case SMB_DIRECT_HDR_NEG_REQ
:
221 col_append_str(pinfo
->cinfo
, COL_INFO
, "NegotiateRequest");
227 item
= proto_tree_add_item(tree
, hf_smb_direct_negotiate_request
, tvb
, 0, -1, ENC_NA
);
228 neg_req_tree
= proto_item_add_subtree(item
, ett_smb_direct_hdr
);
230 proto_tree_add_item(neg_req_tree
, hf_smb_direct_min_version
,
231 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
234 proto_tree_add_item(neg_req_tree
, hf_smb_direct_max_version
,
235 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
238 /* 2 bytes reserved */
241 proto_tree_add_item(neg_req_tree
, hf_smb_direct_credits_requested
,
242 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
245 proto_tree_add_item(neg_req_tree
, hf_smb_direct_preferred_send_size
,
246 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
249 proto_tree_add_item(neg_req_tree
, hf_smb_direct_max_receive_size
,
250 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
253 proto_tree_add_item(neg_req_tree
, hf_smb_direct_max_fragmented_size
,
254 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
258 case SMB_DIRECT_HDR_NEG_REP
:
259 col_append_str(pinfo
->cinfo
, COL_INFO
, "NegotiateResponse");
261 status
= tvb_get_letohl(tvb
, 12);
264 pinfo
->cinfo
, COL_INFO
, ", Error: %s",
265 val_to_str_ext(status
, &NT_errors_ext
, "Unknown (0x%08X)"));
272 item
= proto_tree_add_item(tree
, hf_smb_direct_negotiate_response
, tvb
, 0, -1, ENC_NA
);
273 neg_rep_tree
= proto_item_add_subtree(item
, ett_smb_direct_hdr
);
275 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_min_version
,
276 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
279 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_max_version
,
280 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
283 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_negotiated_version
,
284 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
287 /* 2 bytes reserved */
290 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_credits_requested
,
291 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
294 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_credits_granted
,
295 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
298 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_status
,
299 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
302 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_max_read_write_size
,
303 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
306 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_preferred_send_size
,
307 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
310 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_max_receive_size
,
311 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
314 proto_tree_add_item(neg_rep_tree
, hf_smb_direct_max_fragmented_size
,
315 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
319 case SMB_DIRECT_HDR_DATA
:
320 col_append_str(pinfo
->cinfo
, COL_INFO
, "DataMessage");
322 rlen
= MIN(rlen
, 24);
324 item
= proto_tree_add_item(tree
, hf_smb_direct_data_message
, tvb
, 0, rlen
, ENC_NA
);
325 data_tree
= proto_item_add_subtree(item
, ett_smb_direct_hdr
);
327 proto_tree_add_item(data_tree
, hf_smb_direct_credits_requested
,
328 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
331 proto_tree_add_item(data_tree
, hf_smb_direct_credits_granted
,
332 tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
335 proto_tree_add_bitmask(data_tree
, tvb
, offset
, hf_smb_direct_flags
,
336 ett_smb_direct_flags
, flags
, ENC_LITTLE_ENDIAN
);
339 /* 2 bytes reserved */
342 remaining_length
= tvb_get_letohl(tvb
, offset
);
343 proto_tree_add_item(data_tree
, hf_smb_direct_remaining_length
,
344 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
347 data_offset
= tvb_get_letohl(tvb
, offset
);
348 proto_tree_add_item(data_tree
, hf_smb_direct_data_offset
,
349 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
352 data_length
= tvb_get_letohl(tvb
, offset
);
353 proto_tree_add_item(data_tree
, hf_smb_direct_data_length
,
354 tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
357 if (data_length
> 0 && data_offset
> (uint32_t)offset
) {
358 len
= tvb_reported_length_remaining(tvb
, data_offset
);
361 if (data_length
<= (uint32_t)len
) {
362 next_tvb
= tvb_new_subset_length(tvb
, data_offset
,
366 if (next_tvb
!= NULL
) {
367 dissect_smb_direct_payload(next_tvb
, pinfo
,
368 parent_tree
, remaining_length
);
371 /* offset = data_offset + data_length; */
378 static enum SMB_DIRECT_HDR_TYPE
379 is_smb_direct(tvbuff_t
*tvb
, packet_info
*pinfo _U_
)
381 bool maybe_neg_req
= false;
382 bool maybe_data
= false;
383 unsigned len
= tvb_reported_length(tvb
);
386 return SMB_DIRECT_HDR_UNKNOWN
;
390 tvb_get_letohs(tvb
, 0) == 0x0100 && /* min version */
391 tvb_get_letohs(tvb
, 2) == 0x0100 && /* max version */
392 tvb_get_letohs(tvb
, 4) == 0x0100 && /* negotiated version */
393 tvb_get_letohs(tvb
, 6) == 0x0000) /* reserved */
395 /* Negotiate Response */
396 return SMB_DIRECT_HDR_NEG_REP
;
399 if (tvb_get_letohs(tvb
, 0) == 0x0100 && /* min version */
400 tvb_get_letohs(tvb
, 2) == 0x0100 && /* max version */
401 tvb_get_letohs(tvb
, 4) == 0x0000) /* reserved */
403 maybe_neg_req
= true;
406 if (tvb_get_letohs(tvb
, 0) <= 255 && /* credits up to 255 */
407 tvb_get_letohs(tvb
, 2) <= 255 && /* credits up to 255 */
408 tvb_get_letohs(tvb
, 4) <= 1 && /* flags 0 or 1 */
409 tvb_get_letohs(tvb
, 6) == 0) /* reserved */
415 if (tvb_get_letohl(tvb
, 8) != 0) { /* remaining */
418 if (tvb_get_letohl(tvb
, 12) != 0) { /* data offset */
421 if (tvb_get_letohl(tvb
, 16) != 0) { /* data length */
425 if (maybe_neg_req
&& !maybe_data
) {
426 /* Negotiate Request */
427 return SMB_DIRECT_HDR_NEG_REQ
;
429 /* maybe_neg_req = false; */
432 return SMB_DIRECT_HDR_DATA
;
437 return SMB_DIRECT_HDR_UNKNOWN
;
440 if (tvb_get_letohl(tvb
, 12) != 24) { /* data offset */
441 return SMB_DIRECT_HDR_UNKNOWN
;
444 if (tvb_get_letohl(tvb
, 16) == 0) { /* data length */
445 return SMB_DIRECT_HDR_UNKNOWN
;
448 if (tvb_get_letohl(tvb
, 20) != 0) { /* padding */
449 return SMB_DIRECT_HDR_UNKNOWN
;
454 return SMB_DIRECT_HDR_DATA
;
457 return SMB_DIRECT_HDR_UNKNOWN
;
461 dissect_smb_direct_iwarp_heur(tvbuff_t
*tvb
, packet_info
*pinfo
,
462 proto_tree
*parent_tree
, void *data
)
464 struct rdmapinfo
*info
= (struct rdmapinfo
*)data
;
465 enum SMB_DIRECT_HDR_TYPE hdr_type
;
471 switch (info
->opcode
) {
473 case RDMA_SEND_INVALIDATE
:
475 case RDMA_SEND_SE_INVALIDATE
:
481 hdr_type
= is_smb_direct(tvb
, pinfo
);
482 if (hdr_type
== SMB_DIRECT_HDR_UNKNOWN
) {
486 dissect_smb_direct(tvb
, pinfo
, parent_tree
, hdr_type
);
491 dissect_smb_direct_infiniband(tvbuff_t
*tvb
, packet_info
*pinfo
,
492 proto_tree
*parent_tree
, void *data
)
494 struct infinibandinfo
*info
= (struct infinibandinfo
*)data
;
495 enum SMB_DIRECT_HDR_TYPE hdr_type
;
501 switch (info
->opCode
) {
505 case RC_SEND_LAST_IMM
:
507 case RC_SEND_ONLY_IMM
:
508 case RC_SEND_LAST_INVAL
:
509 case RC_SEND_ONLY_INVAL
:
515 hdr_type
= is_smb_direct(tvb
, pinfo
);
516 if (hdr_type
== SMB_DIRECT_HDR_UNKNOWN
) {
520 dissect_smb_direct(tvb
, pinfo
, parent_tree
, hdr_type
);
521 return tvb_captured_length(tvb
);
525 dissect_smb_direct_infiniband_heur(tvbuff_t
*tvb
, packet_info
*pinfo
,
526 proto_tree
*parent_tree
, void *data
)
528 return (dissect_smb_direct_infiniband(tvb
, pinfo
, parent_tree
, data
) > 0);
531 void proto_register_smb_direct(void)
533 static int *ett
[] = {
536 &ett_smb_direct_flags
,
537 &ett_smb_direct_fragment
,
538 &ett_smb_direct_fragments
,
541 static hf_register_info hf
[] = {
542 { &hf_smb_direct_negotiate_request
,
543 { "NegotiateRequest", "smb_direct.negotiate_request",
544 FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
546 { &hf_smb_direct_negotiate_response
,
547 { "NegotiateResponse", "smb_direct.negotiate_response",
548 FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
550 { &hf_smb_direct_data_message
,
551 { "DataMessage", "smb_direct.data_message",
552 FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
554 { &hf_smb_direct_min_version
,
555 { "MinVersion", "smb_direct.version.min",
556 FT_UINT16
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
558 { &hf_smb_direct_max_version
,
559 { "MaxVersion", "smb_direct.version.max",
560 FT_UINT16
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
562 { &hf_smb_direct_negotiated_version
,
563 { "NegotiatedVersion", "smb_direct.version.negotiated",
564 FT_UINT16
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
566 { &hf_smb_direct_credits_requested
,
567 { "CreditsRequested", "smb_direct.credits.requested",
568 FT_UINT16
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
570 { &hf_smb_direct_credits_granted
,
571 { "CreditsGranted", "smb_direct.credits.granted",
572 FT_UINT16
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
574 { &hf_smb_direct_status
,
575 { "Status", "smb_direct.status",
576 FT_UINT32
, BASE_HEX
|BASE_EXT_STRING
, &NT_errors_ext
, 0,
577 "NT Status code", HFILL
}},
579 { &hf_smb_direct_max_read_write_size
,
580 { "MaxReadWriteSize", "smb_direct.max_read_write_size",
581 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
583 { &hf_smb_direct_preferred_send_size
,
584 { "PreferredSendSize", "smb_direct.preferred_send_size",
585 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
587 { &hf_smb_direct_max_receive_size
,
588 { "MaxReceiveSize", "smb_direct.max_receive_size",
589 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
591 { &hf_smb_direct_max_fragmented_size
,
592 { "MaxFragmentedSize", "smb_direct.max_fragmented_size",
593 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
595 { &hf_smb_direct_flags
,
596 { "Flags", "smb_direct.flags",
597 FT_UINT16
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
599 { &hf_smb_direct_flags_response_requested
,
600 { "ResponseRequested", "smb_direct.flags.response_requested",
601 FT_BOOLEAN
, 16, NULL
, SMB_DIRECT_RESPONSE_REQUESTED
,
604 { &hf_smb_direct_remaining_length
,
605 { "RemainingLength", "smb_direct.remaining_length",
606 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
608 { &hf_smb_direct_data_offset
,
609 { "DataOffset", "smb_direct.data_offset",
610 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
612 { &hf_smb_direct_data_length
,
613 { "DataLength", "smb_direct.data_length",
614 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
616 { &hf_smb_direct_fragments
,
617 { "Reassembled SMB Direct Fragments", "smb_direct.fragments",
618 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
620 { &hf_smb_direct_fragment
,
621 { "SMB Direct Fragment", "smb_direct.fragment",
622 FT_FRAMENUM
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
623 { &hf_smb_direct_fragment_overlap
,
624 { "Fragment overlap", "smb_direct.fragment.overlap",
625 FT_BOOLEAN
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
627 { &hf_smb_direct_fragment_overlap_conflict
,
628 { "Conflicting data in fragment overlap", "smb_direct.fragment.overlap.conflict",
629 FT_BOOLEAN
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
631 { &hf_smb_direct_fragment_multiple_tails
,
632 { "Multiple tail fragments found", "smb_direct.fragment.multipletails",
633 FT_BOOLEAN
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
635 { &hf_smb_direct_fragment_too_long_fragment
,
636 { "Fragment too long", "smb_direct.fragment.toolongfragment",
637 FT_BOOLEAN
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
639 { &hf_smb_direct_fragment_error
,
640 { "Defragmentation error", "smb_direct.fragment.error",
641 FT_FRAMENUM
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
643 { &hf_smb_direct_fragment_count
,
644 { "Fragment count", "smb_direct.fragment.count",
645 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
647 { &hf_smb_direct_reassembled_in
,
648 { "Reassembled PDU in frame", "smb_direct.reassembled_in",
649 FT_FRAMENUM
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
651 { &hf_smb_direct_reassembled_length
,
652 { "Reassembled SMB Direct length", "smb_direct.reassembled.length",
653 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
655 { &hf_smb_direct_reassembled_data
,
656 { "Reassembled SMB Direct data", "smb_direct.reassembled.data",
657 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
660 module_t
*smb_direct_module
;
662 proto_smb_direct
= proto_register_protocol("SMB-Direct (SMB RDMA Transport)",
663 "SMBDirect", "smb_direct");
664 proto_register_subtree_array(ett
, array_length(ett
));
665 proto_register_field_array(proto_smb_direct
, hf
, array_length(hf
));
667 smb_direct_handle
= register_dissector("smb_direct", dissect_smb_direct_infiniband
, proto_smb_direct
);
669 smb_direct_heur_subdissector_list
= register_heur_dissector_list_with_description("smb_direct", "SMB-Direct payload", proto_smb_direct
);
671 smb_direct_module
= prefs_register_protocol(proto_smb_direct
, NULL
);
672 prefs_register_bool_preference(smb_direct_module
,
673 "reassemble_smb_direct",
674 "Reassemble SMB Direct fragments",
675 "Whether the SMB Direct dissector should reassemble fragmented payloads",
676 &smb_direct_reassemble
);
677 reassembly_table_register(&smb_direct_reassembly_table
,
678 &addresses_ports_reassembly_table_functions
);
682 proto_reg_handoff_smb_direct(void)
684 heur_dissector_add("iwarp_ddp_rdmap",
685 dissect_smb_direct_iwarp_heur
,
686 "SMB Direct over iWARP", "smb_direct_iwarp",
687 proto_smb_direct
, HEURISTIC_ENABLE
);
688 heur_dissector_add("infiniband.payload",
689 dissect_smb_direct_infiniband_heur
,
690 "SMB Direct Infiniband", "smb_direct_infiniband",
691 proto_smb_direct
, HEURISTIC_ENABLE
);
692 dissector_add_for_decode_as("infiniband", smb_direct_handle
);
697 * Editor modelines - https://www.wireshark.org/tools/modelines.html
702 * indent-tabs-mode: t
705 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
706 * :indentSize=8:tabSize=8:noTabs=false: