HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-fcfzs.c
blob3ff9fcd3d69a1b70a42e36e81ae71b90d0a85e4c
1 /* packet-fcfzs.c
2 * Routines for FC Fabric Zone Server
3 * Copyright 2001, Dinesh G Dutt <ddutt@andiamo.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/to_str.h>
32 #include <epan/wmem/wmem.h>
33 #include <epan/conversation.h>
34 #include <epan/etypes.h>
35 #include "packet-scsi.h"
36 #include "packet-fc.h"
37 #include "packet-fcct.h"
38 #include "packet-fcfzs.h"
40 /* Initialize the protocol and registered fields */
41 static int proto_fcfzs = -1;
42 static int hf_fcfzs_opcode = -1;
43 static int hf_fcfzs_gzc_vendor = -1;
44 static int hf_fcfzs_gest_vendor = -1;
45 static int hf_fcfzs_numzoneattrs = -1;
46 static int hf_fcfzs_zonesetnmlen = -1;
47 static int hf_fcfzs_zonesetname = -1;
48 static int hf_fcfzs_numzones = -1;
49 static int hf_fcfzs_numzonesetattrs = -1;
50 static int hf_fcfzs_zonenmlen = -1;
51 static int hf_fcfzs_zonename = -1;
52 static int hf_fcfzs_nummbrs = -1;
53 static int hf_fcfzs_nummbrentries = -1;
54 static int hf_fcfzs_mbrid = -1;
55 /* static int hf_fcfzs_mbridlen = -1; */
56 static int hf_fcfzs_mbrtype = -1;
57 static int hf_fcfzs_reason = -1;
58 static int hf_fcfzs_rjtdetail = -1;
59 static int hf_fcfzs_rjtvendor = -1;
60 static int hf_fcfzs_maxres_size = -1;
61 static int hf_fcfzs_mbrid_lun = -1;
62 static int hf_fcfzs_gzc_flags = -1;
63 static int hf_fcfzs_gzc_flags_hard_zones = -1;
64 static int hf_fcfzs_gzc_flags_soft_zones = -1;
65 static int hf_fcfzs_gzc_flags_zoneset_db = -1;
66 static int hf_fcfzs_zone_state = -1;
67 static int hf_fcfzs_soft_zone_set_enforced = -1;
68 static int hf_fcfzs_hard_zone_set_enforced = -1;
70 /* Initialize the subtree pointers */
71 static gint ett_fcfzs = -1;
72 static gint ett_fcfzs_gzc_flags = -1;
73 static gint ett_fcfzs_zone_state = -1;
75 typedef struct _fcfzs_conv_key {
76 guint32 conv_idx;
77 } fcfzs_conv_key_t;
79 typedef struct _fcfzs_conv_data {
80 guint32 opcode;
81 } fcfzs_conv_data_t;
83 static GHashTable *fcfzs_req_hash = NULL;
85 static dissector_handle_t data_handle;
88 * Hash Functions
90 static gint
91 fcfzs_equal(gconstpointer v, gconstpointer w)
93 const fcfzs_conv_key_t *v1 = (const fcfzs_conv_key_t *)v;
94 const fcfzs_conv_key_t *v2 = (const fcfzs_conv_key_t *)w;
96 return (v1->conv_idx == v2->conv_idx);
99 static guint
100 fcfzs_hash(gconstpointer v)
102 const fcfzs_conv_key_t *key = (const fcfzs_conv_key_t *)v;
103 guint val;
105 val = key->conv_idx;
107 return val;
111 * Protocol initialization
113 static void
114 fcfzs_init_protocol(void)
116 if (fcfzs_req_hash)
117 g_hash_table_destroy(fcfzs_req_hash);
119 fcfzs_req_hash = g_hash_table_new(fcfzs_hash, fcfzs_equal);
122 /* Code to actually dissect the packets */
123 static void
124 dissect_fcfzs_zoneset(tvbuff_t *tvb, proto_tree *tree, int offset)
126 int numzones, nummbrs, i, j, len;
128 /* The zoneset structure has the following format */
129 /* zoneset name (len[not including pad], name, pad),
130 * number of zones,
131 * for each zone,
132 * Zone name (len[not including pad], name, pad), num zone mbrs
133 * for each zone mbr,
134 * zone mbr id type, zone mbr id (len, name, pad)
136 if (tree) {
138 /* Zoneset Name */
139 len = tvb_get_guint8(tvb, offset);
140 proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
141 1, ENC_BIG_ENDIAN);
142 proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
143 len, ENC_ASCII|ENC_NA);
144 offset += 4 + len + (4-(len % 4));
147 /* Number of zones */
148 numzones = tvb_get_ntohl(tvb, offset);
149 proto_tree_add_item(tree, hf_fcfzs_numzones, tvb, offset, 4, ENC_BIG_ENDIAN);
150 offset += 4;
152 /* For each zone... */
153 for (i = 0; i < numzones; i++) {
154 len = tvb_get_guint8(tvb, offset);
155 proto_tree_add_item(tree, hf_fcfzs_zonenmlen, tvb, offset,
156 1, ENC_BIG_ENDIAN);
157 proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+4,
158 len, ENC_ASCII|ENC_NA);
159 offset += 4 + len + (4-(len % 4));
161 nummbrs = tvb_get_ntohl(tvb, offset);
162 proto_tree_add_item(tree, hf_fcfzs_nummbrentries, tvb, offset,
163 4, ENC_BIG_ENDIAN);
165 offset += 4;
166 for (j = 0; j < nummbrs; j++) {
167 proto_tree_add_item(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN);
169 switch (tvb_get_guint8(tvb, offset)) {
170 case FC_FZS_ZONEMBR_PWWN:
171 case FC_FZS_ZONEMBR_NWWN:
172 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
173 offset+4, 8,
174 tvb_fcwwn_to_str(tvb, offset+4));
175 break;
176 case FC_FZS_ZONEMBR_DP:
177 proto_tree_add_string_format(tree,
178 hf_fcfzs_mbrid,
179 tvb, offset+4, 3, " ",
180 "0x%x",
181 tvb_get_ntoh24(tvb,
182 offset+4));
183 break;
184 case FC_FZS_ZONEMBR_FCID:
185 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
186 offset+4, 4,
187 tvb_fc_to_str(tvb, offset+4));
188 break;
189 case FC_FZS_ZONEMBR_PWWN_LUN:
190 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
191 offset+4, 8,
192 tvb_fcwwn_to_str(tvb, offset+4));
193 proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
194 offset+8, 8, ENC_NA);
195 break;
196 case FC_FZS_ZONEMBR_DP_LUN:
197 proto_tree_add_string_format(tree,
198 hf_fcfzs_mbrid,
199 tvb, offset+4, 3, " ",
200 "0x%x",
201 tvb_get_ntoh24(tvb,
202 offset+4));
203 proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
204 offset+4, 8, ENC_NA);
205 break;
206 case FC_FZS_ZONEMBR_FCID_LUN:
207 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
208 offset+4, 4,
209 tvb_fc_to_str(tvb, offset+4));
210 proto_tree_add_item(tree, hf_fcfzs_mbrid_lun, tvb,
211 offset+4, 8, ENC_NA);
212 break;
213 default:
214 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
215 offset+4, 8,
216 "Unknown member type format");
218 offset += 12;
225 static void
226 dissect_fcfzs_gzc(tvbuff_t *tvb, int offset, proto_tree *parent_tree, gboolean isreq)
228 if (!isreq) {
229 guint8 flags;
230 proto_item *item = NULL;
231 proto_tree *tree = NULL;
233 flags = tvb_get_guint8(tvb, offset);
234 if (parent_tree) {
235 item = proto_tree_add_uint(parent_tree, hf_fcfzs_gzc_flags, tvb, offset, 1, flags);
236 tree = proto_item_add_subtree(item, ett_fcfzs_gzc_flags);
239 proto_tree_add_boolean(tree, hf_fcfzs_gzc_flags_hard_zones, tvb, offset, 1, flags);
240 if (flags & 0x80) {
241 proto_item_append_text(item, " Hard Zones");
243 flags &= (~( 0x80 ));
245 proto_tree_add_boolean(tree, hf_fcfzs_gzc_flags_soft_zones, tvb, offset, 1, flags);
246 if (flags & 0x40) {
247 proto_item_append_text(item, " Soft Zones");
249 flags &= (~( 0x40 ));
251 proto_tree_add_boolean(tree, hf_fcfzs_gzc_flags_zoneset_db, tvb, offset, 1, flags);
252 if (flags & 0x01) {
253 proto_item_append_text(item, " ZoneSet Database Available");
255 /*flags &= (~( 0x01 ));*/
257 proto_tree_add_item(tree, hf_fcfzs_gzc_vendor, tvb, offset+4, 4, ENC_BIG_ENDIAN);
261 static void
262 dissect_fcfzs_gest(tvbuff_t *tvb, proto_tree *parent_tree, gboolean isreq)
264 int offset = 16; /* past the fc_ct header */
266 if (!isreq) {
267 guint8 flags;
268 proto_item *item = NULL;
269 proto_tree *tree = NULL;
271 flags = tvb_get_guint8(tvb, offset);
272 if (parent_tree) {
273 item = proto_tree_add_uint(parent_tree, hf_fcfzs_zone_state, tvb, offset, 1, flags);
274 tree = proto_item_add_subtree(item, ett_fcfzs_zone_state);
277 proto_tree_add_boolean(tree, hf_fcfzs_soft_zone_set_enforced, tvb, offset, 1, flags);
278 if (flags & 0x80) {
279 proto_item_append_text(item, " Soft Zone Set Enforced");
281 flags &= (~( 0x80 ));
283 proto_tree_add_boolean(tree, hf_fcfzs_hard_zone_set_enforced, tvb, offset, 1, flags);
284 if (flags & 0x40) {
285 proto_item_append_text(item, " Hard Zone Set Enforced");
287 /*flags &= (~( 0x40 ));*/
290 proto_tree_add_item(parent_tree, hf_fcfzs_gest_vendor, tvb, offset+4, 4, ENC_BIG_ENDIAN);
294 static void
295 dissect_fcfzs_gzsn(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
297 int numrec, i, len;
298 int offset = 16; /* past the fc_ct header */
300 if (tree) {
301 if (!isreq) {
302 numrec = tvb_get_ntohl(tvb, offset);
304 proto_tree_add_item(tree, hf_fcfzs_numzonesetattrs, tvb, offset,
305 4, ENC_BIG_ENDIAN);
307 offset += 4;
308 for (i = 0; i < numrec; i++) {
309 len = tvb_get_guint8(tvb, offset);
310 proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
311 1, ENC_BIG_ENDIAN);
312 proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+1,
313 len, ENC_ASCII|ENC_NA);
314 offset += len + 1 + (len % 4);
315 proto_tree_add_item(tree, hf_fcfzs_numzones, tvb, offset,
316 4, ENC_BIG_ENDIAN);
317 offset += 4;
323 static void
324 dissect_fcfzs_gzd(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
326 int numrec, i, len;
327 int offset = 16; /* past the fc_ct header */
329 if (tree) {
330 if (isreq) {
331 len = tvb_get_guint8(tvb, offset);
332 proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
333 1, ENC_BIG_ENDIAN);
334 proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+1,
335 len, ENC_ASCII|ENC_NA);
337 else {
338 numrec = tvb_get_ntohl(tvb, offset);
340 proto_tree_add_item(tree, hf_fcfzs_numzoneattrs, tvb, offset,
341 4, ENC_BIG_ENDIAN);
343 offset += 4;
344 for (i = 0; i < numrec; i++) {
345 len = tvb_get_guint8(tvb, offset);
346 proto_tree_add_item(tree, hf_fcfzs_zonenmlen, tvb, offset,
347 1, ENC_BIG_ENDIAN);
348 proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1,
349 len, ENC_ASCII|ENC_NA);
350 offset += len + 1 + (len % 4);
351 proto_tree_add_item(tree, hf_fcfzs_nummbrs, tvb, offset,
352 4, ENC_BIG_ENDIAN);
353 offset += 4;
359 static void
360 dissect_fcfzs_gzm(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
362 int numrec, i, len;
363 int offset = 16; /* past the fc_ct header */
365 if (tree) {
366 if (isreq) {
367 len = tvb_get_guint8(tvb, offset);
368 proto_tree_add_item(tree, hf_fcfzs_zonenmlen, tvb, offset,
369 1, ENC_BIG_ENDIAN);
370 proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1,
371 len, ENC_ASCII|ENC_NA);
373 else {
374 numrec = tvb_get_ntohl(tvb, offset);
376 proto_tree_add_item(tree, hf_fcfzs_nummbrentries, tvb, offset,
377 4, ENC_BIG_ENDIAN);
378 offset += 4;
379 for (i = 0; i < numrec; i++) {
380 proto_tree_add_item(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN);
381 switch (tvb_get_guint8(tvb, offset)) {
382 case FC_FZS_ZONEMBR_PWWN:
383 case FC_FZS_ZONEMBR_NWWN:
384 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
385 offset+4, 8,
386 tvb_fcwwn_to_str(tvb, offset+4));
387 break;
388 case FC_FZS_ZONEMBR_DP:
389 proto_tree_add_string_format(tree,
390 hf_fcfzs_mbrid,
391 tvb, offset+4, 3, " ",
392 "0x%x",
393 tvb_get_ntoh24(tvb,
394 offset+4));
395 break;
396 case FC_FZS_ZONEMBR_FCID:
397 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
398 offset+4, 4,
399 tvb_fc_to_str(tvb, offset+4));
400 break;
401 default:
402 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
403 offset+4, 8,
404 "Unknown member type format");
406 offset += 12;
412 static void
413 dissect_fcfzs_gazs(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
415 int offset = 16; /* past the fc_ct header */
417 if (tree) {
418 if (!isreq) {
419 dissect_fcfzs_zoneset(tvb, tree, offset);
424 static void
425 dissect_fcfzs_gzs(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
427 int offset = 16; /* past the fc_ct header */
428 int len;
430 if (tree) {
431 if (isreq) {
432 len = tvb_get_guint8(tvb, offset);
433 proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
434 1, ENC_BIG_ENDIAN);
435 proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
436 len, ENC_ASCII|ENC_NA);
438 else {
439 dissect_fcfzs_zoneset(tvb, tree, offset);
444 static void
445 dissect_fcfzs_adzs(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
447 int offset = 16; /* past the fc_ct header */
449 if (tree) {
450 if (isreq) {
451 dissect_fcfzs_zoneset(tvb, tree, offset);
456 static void
457 dissect_fcfzs_azsd(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
459 int offset = 16; /* past the fc_ct header */
461 if (tree) {
462 if (isreq) {
463 dissect_fcfzs_zoneset(tvb, tree, offset);
468 static void
469 dissect_fcfzs_arzs(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
471 int offset = 16; /* past the fc_ct header */
472 int len;
474 if (tree) {
475 if (isreq) {
476 len = tvb_get_guint8(tvb, offset);
477 proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
478 1, ENC_BIG_ENDIAN);
479 proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
480 len, ENC_ASCII|ENC_NA);
485 static void
486 dissect_fcfzs_dzs(tvbuff_t *tvb _U_, proto_tree *tree _U_, gboolean isreq _U_)
488 /* Both req & successful response contain just the FC_CT header */
489 return;
492 static void
493 dissect_fcfzs_arzm(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
495 int numrec, i, len, plen;
496 int offset = 16; /* past the fc_ct header */
498 if (tree) {
499 if (isreq) {
500 len = tvb_get_guint8(tvb, offset);
501 proto_tree_add_item(tree, hf_fcfzs_zonenmlen, tvb, offset,
502 1, ENC_BIG_ENDIAN);
503 proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+1,
504 len, ENC_ASCII|ENC_NA);
506 len += (len % 4);
507 plen = tvb_length(tvb) - offset - len;
509 numrec = plen/12; /* each mbr rec is 12 bytes long */
511 offset += len;
512 for (i = 0; i < numrec; i++) {
513 proto_tree_add_item(tree, hf_fcfzs_mbrtype, tvb, offset, 1, ENC_BIG_ENDIAN);
514 switch (tvb_get_guint8(tvb, offset)) {
515 case FC_FZS_ZONEMBR_PWWN:
516 case FC_FZS_ZONEMBR_NWWN:
517 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
518 offset+4, 8,
519 tvb_fcwwn_to_str(tvb, offset+4));
520 break;
521 case FC_FZS_ZONEMBR_DP:
522 proto_tree_add_string_format(tree,
523 hf_fcfzs_mbrid,
524 tvb, offset+4, 3, " ",
525 "0x%x",
526 tvb_get_ntoh24(tvb,
527 offset+4));
528 break;
529 case FC_FZS_ZONEMBR_FCID:
530 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
531 offset+4, 4,
532 tvb_fc_to_str(tvb, offset+4));
533 break;
534 default:
535 proto_tree_add_string(tree, hf_fcfzs_mbrid, tvb,
536 offset+4, 8,
537 "Unknown member type format");
539 offset += 12;
545 static void
546 dissect_fcfzs_arzd(tvbuff_t *tvb, proto_tree *tree, gboolean isreq)
548 int offset = 16; /* past the fc_ct header */
549 int len;
551 if (tree) {
552 if (isreq) {
553 len = tvb_get_guint8(tvb, offset);
554 proto_tree_add_item(tree, hf_fcfzs_zonesetnmlen, tvb, offset,
555 1, ENC_BIG_ENDIAN);
556 proto_tree_add_item(tree, hf_fcfzs_zonesetname, tvb, offset+4,
557 len, ENC_ASCII|ENC_NA);
558 len += (len % 4);
559 offset += len;
561 len = tvb_get_guint8(tvb, offset);
562 proto_tree_add_item(tree, hf_fcfzs_zonenmlen, tvb, offset, 1, ENC_BIG_ENDIAN);
563 proto_tree_add_item(tree, hf_fcfzs_zonename, tvb, offset+4,
564 len, ENC_ASCII|ENC_NA);
569 static void
570 dissect_fcfzs_rjt(tvbuff_t *tvb, proto_tree *tree)
572 int offset = 0;
574 if (tree) {
575 proto_tree_add_item(tree, hf_fcfzs_reason, tvb, offset+13, 1, ENC_BIG_ENDIAN);
576 proto_tree_add_item(tree, hf_fcfzs_rjtdetail, tvb, offset+14, 1, ENC_BIG_ENDIAN);
577 proto_tree_add_item(tree, hf_fcfzs_rjtvendor, tvb, offset+15, 1, ENC_BIG_ENDIAN);
581 static void
582 dissect_fcfzs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
585 /* Set up structures needed to add the protocol subtree and manage it */
586 proto_item *ti;
587 proto_tree *fcfzs_tree = NULL;
588 int offset = 0;
589 fc_ct_preamble cthdr;
590 int opcode;
591 int failed_opcode = 0;
592 conversation_t *conversation;
593 fcfzs_conv_data_t *cdata;
594 fcfzs_conv_key_t ckey, *req_key;
595 gboolean isreq = TRUE;
597 /* Make entries in Protocol column and Info column on summary display */
598 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Zone Server");
601 tvb_memcpy(tvb, (guint8 *)&cthdr, offset, FCCT_PRMBL_SIZE);
602 cthdr.revision = tvb_get_guint8(tvb, offset+1);
603 cthdr.in_id = tvb_get_ntoh24(tvb, offset);
604 cthdr.opcode = g_ntohs(cthdr.opcode);
605 opcode = cthdr.opcode;
606 cthdr.maxres_size = g_ntohs(cthdr.maxres_size);
608 if (tree) {
609 ti = proto_tree_add_protocol_format(tree, proto_fcfzs, tvb, 0,
610 tvb_length(tvb),
611 "Zone Server");
612 fcfzs_tree = proto_item_add_subtree(ti, ett_fcfzs);
613 proto_tree_add_item(fcfzs_tree, hf_fcfzs_opcode, tvb, offset+8, 2, ENC_BIG_ENDIAN);
614 proto_tree_add_item(fcfzs_tree, hf_fcfzs_maxres_size, tvb, offset+10,
615 2, ENC_BIG_ENDIAN);
618 if ((opcode != FCCT_MSG_ACC) && (opcode != FCCT_MSG_RJT)) {
619 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
620 pinfo->ptype, pinfo->oxid,
621 pinfo->rxid, NO_PORT2);
622 if (!conversation) {
623 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
624 pinfo->ptype, pinfo->oxid,
625 pinfo->rxid, NO_PORT2);
628 ckey.conv_idx = conversation->index;
630 cdata = (fcfzs_conv_data_t *)g_hash_table_lookup(fcfzs_req_hash,
631 &ckey);
632 if (cdata) {
633 /* Since we never free the memory used by an exchange, this maybe a
634 * case of another request using the same exchange as a previous
635 * req.
637 cdata->opcode = opcode;
639 else {
640 req_key = wmem_new(wmem_file_scope(), fcfzs_conv_key_t);
641 req_key->conv_idx = conversation->index;
643 cdata = wmem_new(wmem_file_scope(), fcfzs_conv_data_t);
644 cdata->opcode = opcode;
646 g_hash_table_insert(fcfzs_req_hash, req_key, cdata);
649 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, fc_fzs_opcode_val,
650 "0x%x"));
652 else {
653 /* Opcode is ACC or RJT */
654 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
655 pinfo->ptype, pinfo->oxid,
656 pinfo->rxid, NO_PORT2);
657 isreq = FALSE;
658 if (!conversation) {
659 if (opcode == FCCT_MSG_ACC) {
660 col_add_str(pinfo->cinfo, COL_INFO,
661 val_to_str(opcode, fc_fzs_opcode_val,
662 "0x%x"));
663 /* No record of what this accept is for. Can't decode */
664 proto_tree_add_text(fcfzs_tree, tvb, 0, tvb_length(tvb),
665 "No record of Exchg. Unable to decode MSG_ACC");
666 return;
669 else {
670 ckey.conv_idx = conversation->index;
672 cdata = (fcfzs_conv_data_t *)g_hash_table_lookup(fcfzs_req_hash, &ckey);
674 if (cdata != NULL) {
675 if (opcode == FCCT_MSG_ACC)
676 opcode = cdata->opcode;
677 else
678 failed_opcode = cdata->opcode;
681 if (opcode != FCCT_MSG_RJT) {
682 col_add_fstr(pinfo->cinfo, COL_INFO, "MSG_ACC (%s)",
683 val_to_str(opcode,
684 fc_fzs_opcode_val, "0x%x"));
686 else {
687 col_add_fstr(pinfo->cinfo, COL_INFO, "MSG_RJT (%s)",
688 val_to_str(failed_opcode,
689 fc_fzs_opcode_val, "0x%x"));
692 if ((cdata == NULL) && (opcode != FCCT_MSG_RJT)) {
693 /* No record of what this accept is for. Can't decode */
694 proto_tree_add_text(fcfzs_tree, tvb, 0, tvb_length(tvb),
695 "No record of Exchg. Unable to decode MSG_ACC/RJT");
696 return;
701 switch (opcode) {
702 case FCCT_MSG_RJT:
703 dissect_fcfzs_rjt(tvb, fcfzs_tree);
704 break;
705 case FC_FZS_GZC:
706 dissect_fcfzs_gzc(tvb, 16, fcfzs_tree, isreq);
707 break;
708 case FC_FZS_GEST:
709 dissect_fcfzs_gest(tvb, fcfzs_tree, isreq);
710 break;
711 case FC_FZS_GZSN:
712 dissect_fcfzs_gzsn(tvb, fcfzs_tree, isreq);
713 break;
714 case FC_FZS_GZD:
715 dissect_fcfzs_gzd(tvb, fcfzs_tree, isreq);
716 break;
717 case FC_FZS_GZM:
718 dissect_fcfzs_gzm(tvb, fcfzs_tree, isreq);
719 break;
720 case FC_FZS_GAZS:
721 dissect_fcfzs_gazs(tvb, fcfzs_tree, isreq);
722 break;
723 case FC_FZS_GZS:
724 dissect_fcfzs_gzs(tvb, fcfzs_tree, isreq);
725 break;
726 case FC_FZS_ADZS:
727 dissect_fcfzs_adzs(tvb, fcfzs_tree, isreq);
728 break;
729 case FC_FZS_AZSD:
730 dissect_fcfzs_azsd(tvb, fcfzs_tree, isreq);
731 break;
732 case FC_FZS_AZS:
733 dissect_fcfzs_arzs(tvb, fcfzs_tree, isreq);
734 break;
735 case FC_FZS_DZS:
736 dissect_fcfzs_dzs(tvb, fcfzs_tree, isreq);
737 break;
738 case FC_FZS_AZM:
739 dissect_fcfzs_arzm(tvb, fcfzs_tree, isreq);
740 break;
741 case FC_FZS_AZD:
742 dissect_fcfzs_arzd(tvb, fcfzs_tree, isreq);
743 break;
744 case FC_FZS_RZM:
745 dissect_fcfzs_arzm(tvb, fcfzs_tree, isreq);
746 break;
747 case FC_FZS_RZD:
748 dissect_fcfzs_arzd(tvb, fcfzs_tree, isreq);
749 break;
750 case FC_FZS_RZS:
751 dissect_fcfzs_arzs(tvb, fcfzs_tree, isreq);
752 break;
753 default:
754 call_dissector(data_handle, tvb, pinfo, tree);
755 break;
759 /* Register the protocol with Wireshark */
761 void
762 proto_register_fcfzs(void)
765 static hf_register_info hf[] = {
766 { &hf_fcfzs_opcode,
767 {"Opcode", "fcfzs.opcode",
768 FT_UINT16, BASE_HEX, VALS(fc_fzs_opcode_val), 0x0,
769 NULL, HFILL}},
771 { &hf_fcfzs_gzc_vendor,
772 {"Vendor Specific Flags", "fcfzs.gzc.vendor",
773 FT_UINT32, BASE_HEX, NULL, 0x0,
774 NULL, HFILL}},
776 { &hf_fcfzs_gest_vendor,
777 {"Vendor Specific State", "fcfzs.gest.vendor",
778 FT_UINT32, BASE_HEX, NULL, 0x0,
779 NULL, HFILL}},
781 { &hf_fcfzs_numzoneattrs,
782 {"Number of Zone Attribute Entries", "fcfzs.zone.numattrs",
783 FT_UINT32, BASE_DEC, NULL, 0x0,
784 NULL, HFILL}},
786 { &hf_fcfzs_zonesetnmlen,
787 {"Zone Set Name Length", "fcfzs.zoneset.namelen",
788 FT_UINT8, BASE_DEC, NULL, 0x0,
789 NULL, HFILL}},
791 { &hf_fcfzs_zonesetname,
792 {"Zone Set Name", "fcfzs.zoneset.name",
793 FT_STRING, BASE_NONE, NULL, 0x0,
794 NULL, HFILL}},
796 { &hf_fcfzs_numzones,
797 {"Number of Zones", "fcfzs.zoneset.numzones",
798 FT_UINT32, BASE_DEC, NULL, 0x0,
799 NULL, HFILL}},
801 { &hf_fcfzs_numzonesetattrs,
802 {"Number of Zone Set Attribute Entries", "fcfzs.zoneset.numattrs",
803 FT_UINT32, BASE_DEC, NULL, 0x0,
804 NULL, HFILL}},
806 { &hf_fcfzs_zonenmlen,
807 {"Zone Name Length", "fcfzs.zone.namelen",
808 FT_UINT8, BASE_DEC, NULL, 0x0,
809 NULL, HFILL}},
811 { &hf_fcfzs_zonename,
812 {"Zone Name", "fcfzs.zone.name",
813 FT_STRING, BASE_NONE, NULL, 0x0,
814 NULL, HFILL}},
816 { &hf_fcfzs_nummbrs,
817 {"Number of Zone Members", "fcfzs.zone.nummbrs",
818 FT_UINT32, BASE_DEC, NULL, 0x0,
819 NULL, HFILL}},
821 { &hf_fcfzs_nummbrentries,
822 {"Number of Zone Member Attribute Entries", "fcfzs.zonembr.numattrs",
823 FT_UINT32, BASE_DEC, NULL, 0x0,
824 NULL, HFILL}},
826 { &hf_fcfzs_mbrtype,
827 {"Zone Member Identifier Type", "fcfzs.zonembr.idtype",
828 FT_UINT8, BASE_HEX, VALS(fc_fzs_zonembr_type_val), 0x0,
829 NULL, HFILL}},
831 #if 0
832 { &hf_fcfzs_mbridlen,
833 {"Zone Member Identifier Length", "fcfzs.zonembr.idlen",
834 FT_UINT8, BASE_DEC, NULL, 0x0,
835 NULL, HFILL}},
836 #endif
838 { &hf_fcfzs_mbrid,
839 {"Zone Member Identifier", "fcfzs.zone.mbrid",
840 FT_STRING, BASE_NONE, NULL, 0x0,
841 NULL, HFILL}},
843 { &hf_fcfzs_reason,
844 {"Reason Code", "fcfzs.reason",
845 FT_UINT8, BASE_HEX, VALS(fc_ct_rjt_code_vals), 0x0,
846 NULL, HFILL}},
848 { &hf_fcfzs_rjtdetail,
849 {"Reason Code Explanation", "fcfzs.rjtdetail",
850 FT_UINT8, BASE_HEX, VALS(fc_fzs_rjt_code_val), 0x0,
851 NULL, HFILL}},
853 { &hf_fcfzs_rjtvendor,
854 {"Vendor Specific Reason", "fcfzs.rjtvendor",
855 FT_UINT8, BASE_HEX, NULL, 0x0,
856 NULL, HFILL}},
858 { &hf_fcfzs_maxres_size,
859 {"Maximum/Residual Size", "fcfzs.maxres_size",
860 FT_UINT16, BASE_DEC, NULL, 0x0,
861 NULL, HFILL}},
863 { &hf_fcfzs_mbrid_lun,
864 {"LUN", "fcfzs.zone.lun",
865 FT_BYTES, BASE_NONE, NULL, 0x0,
866 NULL, HFILL}},
868 { &hf_fcfzs_gzc_flags,
869 {"Capabilities", "fcfzs.gzc.flags",
870 FT_UINT8, BASE_HEX, NULL, 0x0,
871 NULL, HFILL}},
873 { &hf_fcfzs_gzc_flags_hard_zones,
874 {"Hard Zones", "fcfzs.gzc.flags.hard_zones",
875 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x80,
876 NULL, HFILL}},
878 { &hf_fcfzs_gzc_flags_soft_zones,
879 {"Soft Zones", "fcfzs.gzc.flags.soft_zones",
880 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), 0x40,
881 NULL, HFILL}},
883 { &hf_fcfzs_gzc_flags_zoneset_db,
884 {"ZoneSet Database", "fcfzs.gzc.flags.zoneset_db",
885 FT_BOOLEAN, 8, TFS(&tfs_available_not_available), 0x01,
886 NULL, HFILL}},
888 { &hf_fcfzs_zone_state,
889 {"Zone State", "fcfzs.zone.state",
890 FT_UINT8, BASE_HEX, NULL, 0x0,
891 NULL, HFILL}},
893 { &hf_fcfzs_soft_zone_set_enforced,
894 {"Soft Zone Set", "fcfzs.soft_zone_set.enforced",
895 FT_BOOLEAN, 8, TFS(&tfs_enforced_not_enforced), 0x80,
896 NULL, HFILL}},
898 { &hf_fcfzs_hard_zone_set_enforced,
899 {"Hard Zone Set", "fcfzs.hard_zone_set.enforced",
900 FT_BOOLEAN, 8, TFS(&tfs_enforced_not_enforced), 0x40,
901 NULL, HFILL}},
905 static gint *ett[] = {
906 &ett_fcfzs,
907 &ett_fcfzs_gzc_flags,
908 &ett_fcfzs_zone_state,
911 proto_fcfzs = proto_register_protocol("Fibre Channel Fabric Zone Server", "FC FZS", "fcfzs");
913 proto_register_field_array(proto_fcfzs, hf, array_length(hf));
914 proto_register_subtree_array(ett, array_length(ett));
915 register_init_routine(&fcfzs_init_protocol);
919 void
920 proto_reg_handoff_fcfzs(void)
922 dissector_handle_t fzs_handle;
924 fzs_handle = create_dissector_handle(dissect_fcfzs, proto_fcfzs);
925 dissector_add_uint("fcct.server", FCCT_GSRVR_FZS, fzs_handle);
927 data_handle = find_dissector("data");