/src/wireshark/epan/dissectors/packet-fcfzs.c
Line | Count | Source |
1 | | /* packet-fcfzs.c |
2 | | * Routines for FC Fabric Zone Server |
3 | | * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com> |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | /* |
13 | | * Fibre Channel Generic Services (FC-GS) specification. |
14 | | */ |
15 | | |
16 | | #include "config.h" |
17 | | |
18 | | #include <epan/packet.h> |
19 | | #include <epan/tfs.h> |
20 | | #include <epan/expert.h> |
21 | | |
22 | | #include <wsutil/ws_padding_to.h> |
23 | | |
24 | | #include "packet-fc.h" |
25 | | #include "packet-fcct.h" |
26 | | #include "packet-fcfzs.h" |
27 | | |
28 | | void proto_register_fcfzs(void); |
29 | | void proto_reg_handoff_fcfzs(void); |
30 | | |
31 | | static dissector_handle_t fzs_handle; |
32 | | |
33 | | /* Initialize the protocol and registered fields */ |
34 | | static int proto_fcfzs; |
35 | | static int hf_fcfzs_opcode; |
36 | | static int hf_fcfzs_gzc_vendor; |
37 | | static int hf_fcfzs_gest_vendor; |
38 | | static int hf_fcfzs_numzoneattrs; |
39 | | static int hf_fcfzs_zonesetnmlen; |
40 | | static int hf_fcfzs_zonesetname; |
41 | | static int hf_fcfzs_numzones; |
42 | | static int hf_fcfzs_numzonesetattrs; |
43 | | static int hf_fcfzs_zonenmlen; |
44 | | static int hf_fcfzs_zonename; |
45 | | static int hf_fcfzs_nummbrs; |
46 | | static int hf_fcfzs_nummbrentries; |
47 | | static int hf_fcfzs_mbrid_fcwwn; |
48 | | static int hf_fcfzs_mbrid_fc; |
49 | | static int hf_fcfzs_mbrid_uint; |
50 | | /* static int hf_fcfzs_mbridlen; */ |
51 | | static int hf_fcfzs_mbrtype; |
52 | | static int hf_fcfzs_reason; |
53 | | static int hf_fcfzs_rjtdetail; |
54 | | static int hf_fcfzs_rjtvendor; |
55 | | static int hf_fcfzs_maxres_size; |
56 | | static int hf_fcfzs_mbrid_lun; |
57 | | static int hf_fcfzs_gzc_flags; |
58 | | static int hf_fcfzs_gzc_flags_hard_zones; |
59 | | static int hf_fcfzs_gzc_flags_soft_zones; |
60 | | static int hf_fcfzs_gzc_flags_zoneset_db; |
61 | | static int hf_fcfzs_zone_state; |
62 | | static int hf_fcfzs_soft_zone_set_enforced; |
63 | | static int hf_fcfzs_hard_zone_set_enforced; |
64 | | |
65 | | /* Initialize the subtree pointers */ |
66 | | static int ett_fcfzs; |
67 | | static int ett_fcfzs_gzc_flags; |
68 | | static int ett_fcfzs_zone_state; |
69 | | |
70 | | static expert_field ei_fcfzs_no_exchange; |
71 | | static expert_field ei_fcfzs_mbrid; |
72 | | |
73 | | typedef struct _fcfzs_conv_key { |
74 | | uint32_t conv_idx; |
75 | | } fcfzs_conv_key_t; |
76 | | |
77 | | typedef struct _fcfzs_conv_data { |
78 | | uint32_t opcode; |
79 | | } fcfzs_conv_data_t; |
80 | | |
81 | | static wmem_map_t *fcfzs_req_hash; |
82 | | |
83 | | /* |
84 | | * Hash Functions |
85 | | */ |
86 | | static int |
87 | | fcfzs_equal(const void *v, const void *w) |
88 | 42 | { |
89 | 42 | const fcfzs_conv_key_t *v1 = (const fcfzs_conv_key_t *)v; |
90 | 42 | const fcfzs_conv_key_t *v2 = (const fcfzs_conv_key_t *)w; |
91 | | |
92 | 42 | return (v1->conv_idx == v2->conv_idx); |
93 | 42 | } |
94 | | |
95 | | static unsigned |
96 | | fcfzs_hash(const void *v) |
97 | 59 | { |
98 | 59 | const fcfzs_conv_key_t *key = (const fcfzs_conv_key_t *)v; |
99 | 59 | unsigned val; |
100 | | |
101 | 59 | val = key->conv_idx; |
102 | | |
103 | 59 | return val; |
104 | 59 | } |
105 | | |
106 | | /* Code to actually dissect the packets */ |
107 | | static void |
108 | | dissect_fcfzs_zoneset(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, unsigned offset) |
109 | 26 | { |
110 | 26 | unsigned numzones, nummbrs, i, j; |
111 | 26 | uint32_t len; |
112 | 26 | proto_item* ti; |
113 | | |
114 | | /* The zoneset structure has the following format */ |
115 | | /* zoneset name (len[not including pad], name, pad), |
116 | | * number of zones, |
117 | | * for each zone, |
118 | | * Zone name (len[not including pad], name, pad), num zone mbrs |
119 | | * for each zone mbr, |
120 | | * zone mbr id type, zone mbr id (len, name, pad) |
121 | | */ |
122 | | |
123 | | /* Zoneset Name */ |
124 | 26 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset, |
125 | 26 | 1, ENC_BIG_ENDIAN, &len); |
126 | 26 | offset += 4; |
127 | 26 | proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset, |
128 | 26 | len, ENC_ASCII); |
129 | 26 | offset += len; |
130 | | /* Fill Bytes */ |
131 | 26 | offset += WS_PADDING_TO_4(len); |
132 | | |
133 | | |
134 | | /* Number of zones */ |
135 | 26 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_numzones, tvb, offset, 4, ENC_BIG_ENDIAN, &numzones); |
136 | 26 | offset += 4; |
137 | | |
138 | | /* For each zone... */ |
139 | 96 | for (i = 0; i < numzones; i++) { |
140 | 93 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset, |
141 | 93 | 1, ENC_BIG_ENDIAN, &len); |
142 | 93 | offset += 4; |
143 | 93 | proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset, |
144 | 93 | len, ENC_ASCII); |
145 | 93 | offset += len; |
146 | | /* Fill Bytes */ |
147 | 93 | offset += WS_PADDING_TO_4(len); |
148 | | |
149 | 93 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_nummbrentries, tvb, offset, |
150 | 93 | 4, ENC_BIG_ENDIAN, &nummbrs); |
151 | | |
152 | 93 | offset += 4; |
153 | 391 | for (j = 0; j < nummbrs; j++) { |
154 | 321 | uint32_t mbrtype; |
155 | 321 | ti = proto_tree_add_item_ret_uint(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN, &mbrtype); |
156 | | |
157 | 321 | switch (mbrtype) { |
158 | 11 | case FC_FZS_ZONEMBR_PWWN: |
159 | 16 | case FC_FZS_ZONEMBR_NWWN: |
160 | 16 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb, |
161 | 16 | offset+4, 8, ENC_NA); |
162 | 16 | break; |
163 | 10 | case FC_FZS_ZONEMBR_DP: |
164 | 10 | proto_tree_add_item(tree, hf_fcfzs_mbrid_uint, |
165 | 10 | tvb, offset+4, 3, ENC_BIG_ENDIAN); |
166 | 10 | break; |
167 | 9 | case FC_FZS_ZONEMBR_FCID: |
168 | 9 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb, |
169 | 9 | offset+4, 3, ENC_NA); |
170 | 9 | break; |
171 | 0 | case FC_FZS_ZONEMBR_PWWN_LUN: |
172 | 0 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb, |
173 | 0 | offset+4, 8, ENC_NA); |
174 | 0 | proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb, |
175 | 0 | offset+8, 8, ENC_NA); |
176 | 0 | break; |
177 | 1 | case FC_FZS_ZONEMBR_DP_LUN: |
178 | 1 | proto_tree_add_item(tree, hf_fcfzs_mbrid_uint, |
179 | 1 | tvb, offset+4, 3, ENC_BIG_ENDIAN); |
180 | 1 | proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb, |
181 | 1 | offset+4, 8, ENC_NA); |
182 | 1 | break; |
183 | 0 | case FC_FZS_ZONEMBR_FCID_LUN: |
184 | 0 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb, |
185 | 0 | offset+4, 3, ENC_NA); |
186 | 0 | proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb, |
187 | 0 | offset+4, 8, ENC_NA); |
188 | 0 | break; |
189 | 262 | default: |
190 | 262 | expert_add_info(pinfo, ti, &ei_fcfzs_mbrid); |
191 | 321 | } |
192 | 298 | offset += 12; |
193 | 298 | } |
194 | 93 | } |
195 | 26 | } |
196 | | |
197 | | |
198 | | static void |
199 | | dissect_fcfzs_gzc(tvbuff_t *tvb, unsigned offset, proto_tree *parent_tree, bool isreq) |
200 | 0 | { |
201 | 0 | static int * const flags[] = { |
202 | 0 | &hf_fcfzs_gzc_flags_hard_zones, |
203 | 0 | &hf_fcfzs_gzc_flags_soft_zones, |
204 | 0 | &hf_fcfzs_gzc_flags_zoneset_db, |
205 | 0 | NULL |
206 | 0 | }; |
207 | |
|
208 | 0 | if (!isreq) { |
209 | 0 | proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_fcfzs_gzc_flags, |
210 | 0 | ett_fcfzs_gzc_flags, flags, ENC_NA, BMT_NO_FALSE|BMT_NO_TFS); |
211 | |
|
212 | 0 | proto_tree_add_item(parent_tree, hf_fcfzs_gzc_vendor, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
213 | 0 | } |
214 | 0 | } |
215 | | |
216 | | static void |
217 | | dissect_fcfzs_gest(tvbuff_t *tvb, proto_tree *parent_tree, bool isreq) |
218 | 0 | { |
219 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
220 | 0 | static int * const flags[] = { |
221 | 0 | &hf_fcfzs_soft_zone_set_enforced, |
222 | 0 | &hf_fcfzs_hard_zone_set_enforced, |
223 | 0 | NULL |
224 | 0 | }; |
225 | |
|
226 | 0 | if (!isreq) { |
227 | 0 | proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_fcfzs_zone_state, |
228 | 0 | ett_fcfzs_zone_state, flags, ENC_NA, BMT_NO_FALSE|BMT_NO_TFS); |
229 | |
|
230 | 0 | proto_tree_add_item(parent_tree, hf_fcfzs_gest_vendor, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
231 | 0 | } |
232 | 0 | } |
233 | | |
234 | | static void |
235 | | dissect_fcfzs_gzsn(tvbuff_t *tvb, proto_tree *tree, bool isreq) |
236 | 0 | { |
237 | 0 | uint32_t numrec, i; |
238 | 0 | uint32_t len; |
239 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
240 | |
|
241 | 0 | if (tree) { |
242 | 0 | if (!isreq) { |
243 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_numzonesetattrs, tvb, offset, |
244 | 0 | 4, ENC_BIG_ENDIAN, &numrec); |
245 | |
|
246 | 0 | offset += 4; |
247 | 0 | for (i = 0; i < numrec; i++) { |
248 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset, |
249 | 0 | 1, ENC_BIG_ENDIAN, &len); |
250 | 0 | proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+1, |
251 | 0 | len, ENC_ASCII); |
252 | 0 | offset += len + 1 + (len % 4); |
253 | 0 | proto_tree_add_item(tree, hf_fcfzs_numzones, tvb, offset, |
254 | 0 | 4, ENC_BIG_ENDIAN); |
255 | 0 | offset += 4; |
256 | 0 | } |
257 | 0 | } |
258 | 0 | } |
259 | 0 | } |
260 | | |
261 | | static void |
262 | | dissect_fcfzs_gzd(tvbuff_t *tvb, proto_tree *tree, bool isreq) |
263 | 0 | { |
264 | 0 | uint32_t numrec, i; |
265 | 0 | uint32_t len; |
266 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
267 | |
|
268 | 0 | if (tree) { |
269 | 0 | if (isreq) { |
270 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset, |
271 | 0 | 1, ENC_BIG_ENDIAN, &len); |
272 | 0 | proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+1, |
273 | 0 | len, ENC_ASCII); |
274 | 0 | } |
275 | 0 | else { |
276 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_numzonesetattrs, tvb, offset, |
277 | 0 | 4, ENC_BIG_ENDIAN, &numrec); |
278 | 0 | offset += 4; |
279 | 0 | for (i = 0; i < numrec; i++) { |
280 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset, |
281 | 0 | 1, ENC_BIG_ENDIAN, &len); |
282 | 0 | proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1, |
283 | 0 | len, ENC_ASCII); |
284 | 0 | offset += len + 1 + (len % 4); |
285 | 0 | proto_tree_add_item(tree, hf_fcfzs_nummbrs, tvb, offset, |
286 | 0 | 4, ENC_BIG_ENDIAN); |
287 | 0 | offset += 4; |
288 | 0 | } |
289 | 0 | } |
290 | 0 | } |
291 | 0 | } |
292 | | |
293 | | static void |
294 | | dissect_fcfzs_gzm(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq) |
295 | 0 | { |
296 | 0 | uint32_t numrec, i, len, mbrtype; |
297 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
298 | 0 | proto_item* ti; |
299 | |
|
300 | 0 | if (isreq) { |
301 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset, |
302 | 0 | 1, ENC_BIG_ENDIAN, &len); |
303 | 0 | proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1, |
304 | 0 | len, ENC_ASCII); |
305 | 0 | } |
306 | 0 | else { |
307 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_nummbrentries, tvb, offset, |
308 | 0 | 4, ENC_BIG_ENDIAN, &numrec); |
309 | 0 | offset += 4; |
310 | 0 | for (i = 0; i < numrec; i++) { |
311 | 0 | ti = proto_tree_add_item_ret_uint(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN, &mbrtype); |
312 | 0 | switch (mbrtype) { |
313 | 0 | case FC_FZS_ZONEMBR_PWWN: |
314 | 0 | case FC_FZS_ZONEMBR_NWWN: |
315 | 0 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb, |
316 | 0 | offset+4, 8, ENC_NA); |
317 | 0 | break; |
318 | 0 | case FC_FZS_ZONEMBR_DP: |
319 | 0 | proto_tree_add_item(tree, hf_fcfzs_mbrid_uint, |
320 | 0 | tvb, offset+4, 3, ENC_BIG_ENDIAN); |
321 | 0 | break; |
322 | 0 | case FC_FZS_ZONEMBR_FCID: |
323 | 0 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb, |
324 | 0 | offset+4, 3, ENC_NA); |
325 | 0 | break; |
326 | 0 | default: |
327 | 0 | expert_add_info(pinfo, ti, &ei_fcfzs_mbrid); |
328 | 0 | } |
329 | 0 | offset += 12; |
330 | 0 | } |
331 | 0 | } |
332 | 0 | } |
333 | | |
334 | | static void |
335 | | dissect_fcfzs_gazs(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq) |
336 | 0 | { |
337 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
338 | |
|
339 | 0 | if (!isreq) { |
340 | 0 | dissect_fcfzs_zoneset(tvb, pinfo, tree, offset); |
341 | 0 | } |
342 | 0 | } |
343 | | |
344 | | static void |
345 | | dissect_fcfzs_gzs(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq) |
346 | 0 | { |
347 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
348 | 0 | uint32_t len; |
349 | |
|
350 | 0 | if (isreq) { |
351 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset, |
352 | 0 | 1, ENC_BIG_ENDIAN, &len); |
353 | 0 | proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4, |
354 | 0 | len, ENC_ASCII); |
355 | 0 | } |
356 | 0 | else { |
357 | 0 | dissect_fcfzs_zoneset(tvb, pinfo, tree, offset); |
358 | 0 | } |
359 | 0 | } |
360 | | |
361 | | static void |
362 | | dissect_fcfzs_adzs(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq) |
363 | 26 | { |
364 | 26 | unsigned offset = 16; /* past the fc_ct header */ |
365 | | |
366 | 26 | if (isreq) { |
367 | 26 | dissect_fcfzs_zoneset(tvb, pinfo, tree, offset); |
368 | 26 | } |
369 | 26 | } |
370 | | |
371 | | static void |
372 | | dissect_fcfzs_azsd(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq) |
373 | 0 | { |
374 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
375 | |
|
376 | 0 | if (isreq) { |
377 | 0 | dissect_fcfzs_zoneset(tvb, pinfo, tree, offset); |
378 | 0 | } |
379 | 0 | } |
380 | | |
381 | | static void |
382 | | dissect_fcfzs_arzs(tvbuff_t *tvb, proto_tree *tree, bool isreq) |
383 | 1 | { |
384 | 1 | unsigned offset = 16; /* past the fc_ct header */ |
385 | 1 | uint32_t len; |
386 | | |
387 | 1 | if (tree) { |
388 | 1 | if (isreq) { |
389 | 1 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset, |
390 | 1 | 1, ENC_BIG_ENDIAN, &len); |
391 | 1 | proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4, |
392 | 1 | len, ENC_ASCII); |
393 | 1 | } |
394 | 1 | } |
395 | 1 | } |
396 | | |
397 | | static void |
398 | | dissect_fcfzs_dzs(tvbuff_t *tvb _U_, proto_tree *tree _U_, bool isreq _U_) |
399 | 1 | { |
400 | | /* Both req & successful response contain just the FC_CT header */ |
401 | 1 | return; |
402 | 1 | } |
403 | | |
404 | | static void |
405 | | dissect_fcfzs_arzm(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, bool isreq) |
406 | 16 | { |
407 | 16 | uint32_t numrec, i, len, plen, mbrtype; |
408 | 16 | unsigned offset = 16; /* past the fc_ct header */ |
409 | 16 | proto_item* ti; |
410 | | |
411 | 16 | if (isreq) { |
412 | 16 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset, |
413 | 16 | 1, ENC_BIG_ENDIAN, &len); |
414 | 16 | proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1, |
415 | 16 | len, ENC_ASCII); |
416 | | |
417 | 16 | len += (len % 4); |
418 | 16 | plen = tvb_reported_length(tvb) - offset - len; |
419 | | |
420 | 16 | numrec = plen/12; /* each mbr rec is 12 bytes long */ |
421 | | |
422 | 16 | offset += len; |
423 | 251 | for (i = 0; i < numrec; i++) { |
424 | 235 | ti = proto_tree_add_item_ret_uint(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN, &mbrtype); |
425 | 235 | switch (mbrtype) { |
426 | 2 | case FC_FZS_ZONEMBR_PWWN: |
427 | 3 | case FC_FZS_ZONEMBR_NWWN: |
428 | 3 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fcwwn, tvb, |
429 | 3 | offset+4, 8, ENC_NA); |
430 | 3 | break; |
431 | 22 | case FC_FZS_ZONEMBR_DP: |
432 | 22 | proto_tree_add_item(tree, hf_fcfzs_mbrid_uint, |
433 | 22 | tvb, offset+4, 3, ENC_BIG_ENDIAN); |
434 | 22 | break; |
435 | 10 | case FC_FZS_ZONEMBR_FCID: |
436 | 10 | proto_tree_add_item(tree, hf_fcfzs_mbrid_fc, tvb, |
437 | 10 | offset+4, 3, ENC_NA); |
438 | 10 | break; |
439 | 200 | default: |
440 | 200 | expert_add_info(pinfo, ti, &ei_fcfzs_mbrid); |
441 | 235 | } |
442 | 235 | offset += 12; |
443 | 235 | } |
444 | 16 | } |
445 | 16 | } |
446 | | |
447 | | static void |
448 | | dissect_fcfzs_arzd(tvbuff_t *tvb, proto_tree *tree, bool isreq) |
449 | 0 | { |
450 | 0 | unsigned offset = 16; /* past the fc_ct header */ |
451 | 0 | uint32_t len; |
452 | |
|
453 | 0 | if (tree) { |
454 | 0 | if (isreq) { |
455 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonesetnmlen, tvb, offset, |
456 | 0 | 1, ENC_BIG_ENDIAN, &len); |
457 | 0 | proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4, |
458 | 0 | len, ENC_ASCII); |
459 | 0 | len += (len % 4); |
460 | 0 | offset += len; |
461 | |
|
462 | 0 | proto_tree_add_item_ret_uint(tree, hf_fcfzs_zonenmlen, tvb, offset, |
463 | 0 | 1, ENC_BIG_ENDIAN, &len); |
464 | 0 | proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+4, |
465 | 0 | len, ENC_ASCII); |
466 | 0 | } |
467 | 0 | } |
468 | 0 | } |
469 | | |
470 | | static void |
471 | | dissect_fcfzs_rjt(tvbuff_t *tvb, proto_tree *tree) |
472 | 0 | { |
473 | 0 | unsigned offset = 0; |
474 | |
|
475 | 0 | if (tree) { |
476 | 0 | proto_tree_add_item(tree, hf_fcfzs_reason, tvb, offset+13, 1, ENC_BIG_ENDIAN); |
477 | 0 | proto_tree_add_item(tree, hf_fcfzs_rjtdetail, tvb, offset+14, 1, ENC_BIG_ENDIAN); |
478 | 0 | proto_tree_add_item(tree, hf_fcfzs_rjtvendor, tvb, offset+15, 1, ENC_BIG_ENDIAN); |
479 | 0 | } |
480 | 0 | } |
481 | | |
482 | | static int |
483 | | dissect_fcfzs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
484 | 51 | { |
485 | | |
486 | | /* Set up structures needed to add the protocol subtree and manage it */ |
487 | 51 | proto_item *ti; |
488 | 51 | proto_tree *fcfzs_tree = NULL; |
489 | 51 | int offset = 0; |
490 | 51 | fc_ct_preamble cthdr; |
491 | 51 | int opcode; |
492 | 51 | int failed_opcode = 0; |
493 | 51 | conversation_t *conversation; |
494 | 51 | fcfzs_conv_data_t *cdata; |
495 | 51 | fcfzs_conv_key_t ckey, *req_key; |
496 | 51 | bool isreq = true; |
497 | 51 | fc_hdr *fchdr; |
498 | | |
499 | | /* Reject the packet if data is NULL */ |
500 | 51 | if (data == NULL) |
501 | 0 | return 0; |
502 | 51 | fchdr = (fc_hdr *)data; |
503 | | |
504 | | /* Make entries in Protocol column and Info column on summary display */ |
505 | 51 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "Zone Server"); |
506 | | |
507 | | |
508 | 51 | tvb_memcpy(tvb, (uint8_t *)&cthdr, offset, FCCT_PRMBL_SIZE); |
509 | 51 | cthdr.revision = tvb_get_uint8(tvb, offset+1); |
510 | 51 | cthdr.in_id = tvb_get_ntoh24(tvb, offset); |
511 | 51 | cthdr.opcode = g_ntohs(cthdr.opcode); |
512 | 51 | opcode = cthdr.opcode; |
513 | 51 | cthdr.maxres_size = g_ntohs(cthdr.maxres_size); |
514 | | |
515 | 51 | if (tree) { |
516 | 51 | ti = proto_tree_add_protocol_format(tree, proto_fcfzs, tvb, 0, |
517 | 51 | tvb_captured_length(tvb), |
518 | 51 | "Zone Server"); |
519 | 51 | fcfzs_tree = proto_item_add_subtree(ti, ett_fcfzs); |
520 | 51 | proto_tree_add_item(fcfzs_tree, hf_fcfzs_opcode, tvb, offset+8, 2, ENC_BIG_ENDIAN); |
521 | 51 | proto_tree_add_item(fcfzs_tree, hf_fcfzs_maxres_size, tvb, offset+10, |
522 | 51 | 2, ENC_BIG_ENDIAN); |
523 | 51 | } |
524 | | |
525 | 51 | if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) { |
526 | 51 | conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, |
527 | 51 | conversation_pt_to_conversation_type(pinfo->ptype), fchdr->oxid, |
528 | 51 | fchdr->rxid, NO_PORT_B); |
529 | 51 | if (!conversation) { |
530 | 8 | conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst, |
531 | 8 | conversation_pt_to_conversation_type(pinfo->ptype), fchdr->oxid, |
532 | 8 | fchdr->rxid, NO_PORT2); |
533 | 8 | } |
534 | | |
535 | 51 | ckey.conv_idx = conversation->conv_index; |
536 | | |
537 | 51 | cdata = (fcfzs_conv_data_t *)wmem_map_lookup(fcfzs_req_hash, |
538 | 51 | &ckey); |
539 | 51 | if (cdata) { |
540 | | /* Since we never free the memory used by an exchange, this maybe a |
541 | | * case of another request using the same exchange as a previous |
542 | | * req. |
543 | | */ |
544 | 42 | cdata->opcode = opcode; |
545 | 42 | } |
546 | 9 | else { |
547 | 9 | req_key = wmem_new(wmem_file_scope(), fcfzs_conv_key_t); |
548 | 9 | req_key->conv_idx = conversation->conv_index; |
549 | | |
550 | 9 | cdata = wmem_new(wmem_file_scope(), fcfzs_conv_data_t); |
551 | 9 | cdata->opcode = opcode; |
552 | | |
553 | 9 | wmem_map_insert(fcfzs_req_hash, req_key, cdata); |
554 | 9 | } |
555 | | |
556 | 51 | col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pinfo->pool, opcode, fc_fzs_opcode_val, |
557 | 51 | "0x%x")); |
558 | 51 | } |
559 | 0 | else { |
560 | | /* Opcode is ACC or RJT */ |
561 | 0 | conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst, |
562 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), fchdr->oxid, |
563 | 0 | fchdr->rxid, NO_PORT_B); |
564 | 0 | isreq = false; |
565 | 0 | if (!conversation) { |
566 | 0 | if (opcode == FCCT_MSG_ACC) { |
567 | 0 | col_add_str(pinfo->cinfo, COL_INFO, |
568 | 0 | val_to_str(pinfo->pool, opcode, fc_fzs_opcode_val, |
569 | 0 | "0x%x")); |
570 | | /* No record of what this accept is for. Can't decode */ |
571 | 0 | proto_tree_add_expert_format_remaining(fcfzs_tree, pinfo, &ei_fcfzs_no_exchange, tvb, 0, |
572 | 0 | "No record of Exchg. Unable to decode MSG_ACC"); |
573 | 0 | return 0; |
574 | 0 | } |
575 | 0 | } |
576 | 0 | else { |
577 | 0 | ckey.conv_idx = conversation->conv_index; |
578 | |
|
579 | 0 | cdata = (fcfzs_conv_data_t *)wmem_map_lookup(fcfzs_req_hash, &ckey); |
580 | |
|
581 | 0 | if (cdata != NULL) { |
582 | 0 | if (opcode == FCCT_MSG_ACC) |
583 | 0 | opcode = cdata->opcode; |
584 | 0 | else |
585 | 0 | failed_opcode = cdata->opcode; |
586 | 0 | } |
587 | |
|
588 | 0 | if (opcode != FCCT_MSG_RJT) { |
589 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MSG_ACC (%s)", |
590 | 0 | val_to_str(pinfo->pool, opcode, |
591 | 0 | fc_fzs_opcode_val, "0x%x")); |
592 | 0 | } |
593 | 0 | else { |
594 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, "MSG_RJT (%s)", |
595 | 0 | val_to_str(pinfo->pool, failed_opcode, |
596 | 0 | fc_fzs_opcode_val, "0x%x")); |
597 | 0 | } |
598 | |
|
599 | 0 | if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) { |
600 | | /* No record of what this accept is for. Can't decode */ |
601 | 0 | proto_tree_add_expert_format_remaining(fcfzs_tree, pinfo, &ei_fcfzs_no_exchange, tvb, 0, |
602 | 0 | "No record of Exchg. Unable to decode MSG_ACC/RJT"); |
603 | 0 | return 0; |
604 | 0 | } |
605 | 0 | } |
606 | 0 | } |
607 | | |
608 | 51 | switch (opcode) { |
609 | 0 | case FCCT_MSG_RJT: |
610 | 0 | dissect_fcfzs_rjt(tvb, fcfzs_tree); |
611 | 0 | break; |
612 | 0 | case FC_FZS_GZC: |
613 | 0 | dissect_fcfzs_gzc(tvb, 16, fcfzs_tree, isreq); |
614 | 0 | break; |
615 | 0 | case FC_FZS_GEST: |
616 | 0 | dissect_fcfzs_gest(tvb, fcfzs_tree, isreq); |
617 | 0 | break; |
618 | 0 | case FC_FZS_GZSN: |
619 | 0 | dissect_fcfzs_gzsn(tvb, fcfzs_tree, isreq); |
620 | 0 | break; |
621 | 0 | case FC_FZS_GZD: |
622 | 0 | dissect_fcfzs_gzd(tvb, fcfzs_tree, isreq); |
623 | 0 | break; |
624 | 0 | case FC_FZS_GZM: |
625 | 0 | dissect_fcfzs_gzm(tvb, pinfo, fcfzs_tree, isreq); |
626 | 0 | break; |
627 | 0 | case FC_FZS_GAZS: |
628 | 0 | dissect_fcfzs_gazs(tvb, pinfo, fcfzs_tree, isreq); |
629 | 0 | break; |
630 | 0 | case FC_FZS_GZS: |
631 | 0 | dissect_fcfzs_gzs(tvb, pinfo, fcfzs_tree, isreq); |
632 | 0 | break; |
633 | 26 | case FC_FZS_ADZS: |
634 | 26 | dissect_fcfzs_adzs(tvb, pinfo, fcfzs_tree, isreq); |
635 | 26 | break; |
636 | 0 | case FC_FZS_AZSD: |
637 | 0 | dissect_fcfzs_azsd(tvb, pinfo, fcfzs_tree, isreq); |
638 | 0 | break; |
639 | 1 | case FC_FZS_AZS: |
640 | 1 | dissect_fcfzs_arzs(tvb, fcfzs_tree, isreq); |
641 | 1 | break; |
642 | 1 | case FC_FZS_DZS: |
643 | 1 | dissect_fcfzs_dzs(tvb, fcfzs_tree, isreq); |
644 | 1 | break; |
645 | 0 | case FC_FZS_AZM: |
646 | 0 | dissect_fcfzs_arzm(tvb, pinfo, fcfzs_tree, isreq); |
647 | 0 | break; |
648 | 0 | case FC_FZS_AZD: |
649 | 0 | dissect_fcfzs_arzd(tvb, fcfzs_tree, isreq); |
650 | 0 | break; |
651 | 16 | case FC_FZS_RZM: |
652 | 16 | dissect_fcfzs_arzm(tvb, pinfo, fcfzs_tree, isreq); |
653 | 16 | break; |
654 | 0 | case FC_FZS_RZD: |
655 | 0 | dissect_fcfzs_arzd(tvb, fcfzs_tree, isreq); |
656 | 0 | break; |
657 | 0 | case FC_FZS_RZS: |
658 | 0 | dissect_fcfzs_arzs(tvb, fcfzs_tree, isreq); |
659 | 0 | break; |
660 | 7 | default: |
661 | 7 | call_data_dissector(tvb, pinfo, tree); |
662 | 7 | break; |
663 | 51 | } |
664 | | |
665 | 26 | return tvb_captured_length(tvb); |
666 | 51 | } |
667 | | |
668 | | /* Register the protocol with Wireshark */ |
669 | | |
670 | | void |
671 | | proto_register_fcfzs(void) |
672 | 16 | { |
673 | | |
674 | 16 | static hf_register_info hf[] = { |
675 | 16 | { &hf_fcfzs_opcode, |
676 | 16 | {"Opcode", "fcfzs.opcode", |
677 | 16 | FT_UINT16, BASE_HEX, VALS(fc_fzs_opcode_val), 0x0, |
678 | 16 | NULL, HFILL}}, |
679 | | |
680 | 16 | { &hf_fcfzs_gzc_vendor, |
681 | 16 | {"Vendor Specific Flags", "fcfzs.gzc.vendor", |
682 | 16 | FT_UINT32, BASE_HEX, NULL, 0x0, |
683 | 16 | NULL, HFILL}}, |
684 | | |
685 | 16 | { &hf_fcfzs_gest_vendor, |
686 | 16 | {"Vendor Specific State", "fcfzs.gest.vendor", |
687 | 16 | FT_UINT32, BASE_HEX, NULL, 0x0, |
688 | 16 | NULL, HFILL}}, |
689 | | |
690 | 16 | { &hf_fcfzs_numzoneattrs, |
691 | 16 | {"Number of Zone Attribute Entries", "fcfzs.zone.numattrs", |
692 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
693 | 16 | NULL, HFILL}}, |
694 | | |
695 | 16 | { &hf_fcfzs_zonesetnmlen, |
696 | 16 | {"Zone Set Name Length", "fcfzs.zoneset.namelen", |
697 | 16 | FT_UINT8, BASE_DEC, NULL, 0x0, |
698 | 16 | NULL, HFILL}}, |
699 | | |
700 | 16 | { &hf_fcfzs_zonesetname, |
701 | 16 | {"Zone Set Name", "fcfzs.zoneset.name", |
702 | 16 | FT_STRING, BASE_NONE, NULL, 0x0, |
703 | 16 | NULL, HFILL}}, |
704 | | |
705 | 16 | { &hf_fcfzs_numzones, |
706 | 16 | {"Number of Zones", "fcfzs.zoneset.numzones", |
707 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
708 | 16 | NULL, HFILL}}, |
709 | | |
710 | 16 | { &hf_fcfzs_numzonesetattrs, |
711 | 16 | {"Number of Zone Set Attribute Entries", "fcfzs.zoneset.numattrs", |
712 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
713 | 16 | NULL, HFILL}}, |
714 | | |
715 | 16 | { &hf_fcfzs_zonenmlen, |
716 | 16 | {"Zone Name Length", "fcfzs.zone.namelen", |
717 | 16 | FT_UINT8, BASE_DEC, NULL, 0x0, |
718 | 16 | NULL, HFILL}}, |
719 | | |
720 | 16 | { &hf_fcfzs_zonename, |
721 | 16 | {"Zone Name", "fcfzs.zone.name", |
722 | 16 | FT_STRING, BASE_NONE, NULL, 0x0, |
723 | 16 | NULL, HFILL}}, |
724 | | |
725 | 16 | { &hf_fcfzs_nummbrs, |
726 | 16 | {"Number of Zone Members", "fcfzs.zone.nummbrs", |
727 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
728 | 16 | NULL, HFILL}}, |
729 | | |
730 | 16 | { &hf_fcfzs_nummbrentries, |
731 | 16 | {"Number of Zone Member Attribute Entries", "fcfzs.zonembr.numattrs", |
732 | 16 | FT_UINT32, BASE_DEC, NULL, 0x0, |
733 | 16 | NULL, HFILL}}, |
734 | | |
735 | 16 | { &hf_fcfzs_mbrtype, |
736 | 16 | {"Zone Member Identifier Type", "fcfzs.zonembr.idtype", |
737 | 16 | FT_UINT8, BASE_HEX, VALS(fc_fzs_zonembr_type_val), 0x0, |
738 | 16 | NULL, HFILL}}, |
739 | | |
740 | | #if 0 |
741 | | { &hf_fcfzs_mbridlen, |
742 | | {"Zone Member Identifier Length", "fcfzs.zonembr.idlen", |
743 | | FT_UINT8, BASE_DEC, NULL, 0x0, |
744 | | NULL, HFILL}}, |
745 | | #endif |
746 | | |
747 | 16 | { &hf_fcfzs_mbrid_fcwwn, |
748 | 16 | {"Zone Member Identifier", "fcfzs.zone.mbrid.fcwwn", |
749 | 16 | FT_FCWWN, BASE_NONE, NULL, 0x0, |
750 | 16 | NULL, HFILL}}, |
751 | | |
752 | 16 | { &hf_fcfzs_mbrid_fc, |
753 | 16 | {"Zone Member Identifier", "fcfzs.zone.mbrid.fc", |
754 | 16 | FT_BYTES, SEP_DOT, NULL, 0x0, |
755 | 16 | NULL, HFILL}}, |
756 | | |
757 | 16 | { &hf_fcfzs_mbrid_uint, |
758 | 16 | {"Zone Member Identifier", "fcfzs.zone.mbrid.uint", |
759 | 16 | FT_UINT24, BASE_HEX, NULL, 0x0, |
760 | 16 | NULL, HFILL}}, |
761 | | |
762 | 16 | { &hf_fcfzs_reason, |
763 | 16 | {"Reason Code", "fcfzs.reason", |
764 | 16 | FT_UINT8, BASE_HEX, VALS(fc_ct_rjt_code_vals), 0x0, |
765 | 16 | NULL, HFILL}}, |
766 | | |
767 | 16 | { &hf_fcfzs_rjtdetail, |
768 | 16 | {"Reason Code Explanation", "fcfzs.rjtdetail", |
769 | 16 | FT_UINT8, BASE_HEX, VALS(fc_fzs_rjt_code_val), 0x0, |
770 | 16 | NULL, HFILL}}, |
771 | | |
772 | 16 | { &hf_fcfzs_rjtvendor, |
773 | 16 | {"Vendor Specific Reason", "fcfzs.rjtvendor", |
774 | 16 | FT_UINT8, BASE_HEX, NULL, 0x0, |
775 | 16 | NULL, HFILL}}, |
776 | | |
777 | 16 | { &hf_fcfzs_maxres_size, |
778 | 16 | {"Maximum/Residual Size", "fcfzs.maxres_size", |
779 | 16 | FT_UINT16, BASE_DEC, NULL, 0x0, |
780 | 16 | NULL, HFILL}}, |
781 | | |
782 | 16 | { &hf_fcfzs_mbrid_lun, |
783 | 16 | {"LUN", "fcfzs.zone.lun", |
784 | 16 | FT_BYTES, BASE_NONE, NULL, 0x0, |
785 | 16 | NULL, HFILL}}, |
786 | | |
787 | 16 | { &hf_fcfzs_gzc_flags, |
788 | 16 | {"Capabilities", "fcfzs.gzc.flags", |
789 | 16 | FT_UINT8, BASE_HEX, NULL, 0x0, |
790 | 16 | NULL, HFILL}}, |
791 | | |
792 | 16 | { &hf_fcfzs_gzc_flags_hard_zones, |
793 | 16 | {"Hard Zones", "fcfzs.gzc.flags.hard_zones", |
794 | 16 | FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x80, |
795 | 16 | NULL, HFILL}}, |
796 | | |
797 | 16 | { &hf_fcfzs_gzc_flags_soft_zones, |
798 | 16 | {"Soft Zones", "fcfzs.gzc.flags.soft_zones", |
799 | 16 | FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x40, |
800 | 16 | NULL, HFILL}}, |
801 | | |
802 | 16 | { &hf_fcfzs_gzc_flags_zoneset_db, |
803 | 16 | {"ZoneSet Database", "fcfzs.gzc.flags.zoneset_db", |
804 | 16 | FT_BOOLEAN, 8, TFS(&tfs_available_not_available), 0x01, |
805 | 16 | NULL, HFILL}}, |
806 | | |
807 | 16 | { &hf_fcfzs_zone_state, |
808 | 16 | {"Zone State", "fcfzs.zone.state", |
809 | 16 | FT_UINT8, BASE_HEX, NULL, 0x0, |
810 | 16 | NULL, HFILL}}, |
811 | | |
812 | 16 | { &hf_fcfzs_soft_zone_set_enforced, |
813 | 16 | {"Soft Zone Set", "fcfzs.soft_zone_set.enforced", |
814 | 16 | FT_BOOLEAN, 8, TFS(&tfs_enforced_not_enforced), 0x80, |
815 | 16 | NULL, HFILL}}, |
816 | | |
817 | 16 | { &hf_fcfzs_hard_zone_set_enforced, |
818 | 16 | {"Hard Zone Set", "fcfzs.hard_zone_set.enforced", |
819 | 16 | FT_BOOLEAN, 8, TFS(&tfs_enforced_not_enforced), 0x40, |
820 | 16 | NULL, HFILL}}, |
821 | | |
822 | 16 | }; |
823 | | |
824 | 16 | static int *ett[] = { |
825 | 16 | &ett_fcfzs, |
826 | 16 | &ett_fcfzs_gzc_flags, |
827 | 16 | &ett_fcfzs_zone_state, |
828 | 16 | }; |
829 | | |
830 | 16 | static ei_register_info ei[] = { |
831 | 16 | { &ei_fcfzs_no_exchange, { "fcfzs.no_exchange", PI_UNDECODED, PI_WARN, "No record of Exchg. Unable to decode", EXPFILL }}, |
832 | 16 | { &ei_fcfzs_mbrid, { "fcfzs.mbrid.unknown_type", PI_PROTOCOL, PI_WARN, "Unknown member type format", EXPFILL }}, |
833 | 16 | }; |
834 | | |
835 | 16 | expert_module_t* expert_fcfzs; |
836 | | |
837 | 16 | proto_fcfzs = proto_register_protocol("Fibre Channel Fabric Zone Server", "FC FZS", "fcfzs"); |
838 | | |
839 | 16 | proto_register_field_array(proto_fcfzs, hf, array_length(hf)); |
840 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
841 | 16 | expert_fcfzs = expert_register_protocol(proto_fcfzs); |
842 | 16 | expert_register_field_array(expert_fcfzs, ei, array_length(ei)); |
843 | | |
844 | 16 | fcfzs_req_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), fcfzs_hash, fcfzs_equal); |
845 | | |
846 | 16 | fzs_handle = register_dissector("fcfzs", dissect_fcfzs, proto_fcfzs); |
847 | 16 | } |
848 | | |
849 | | void |
850 | | proto_reg_handoff_fcfzs(void) |
851 | 16 | { |
852 | 16 | dissector_add_uint("fcct.server", FCCT_GSRVR_FZS, fzs_handle); |
853 | 16 | } |
854 | | |
855 | | /* |
856 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
857 | | * |
858 | | * Local variables: |
859 | | * c-basic-offset: 4 |
860 | | * tab-width: 8 |
861 | | * indent-tabs-mode: nil |
862 | | * End: |
863 | | * |
864 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
865 | | * :indentSize=4:tabSize=8:noTabs=true: |
866 | | */ |