/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 | | */ |