Frame numbers are unsigned.
[obnox/wireshark/wip.git] / packet-fcswils.c
1 /* packet-fcswils
2  * Routines for FC Inter-switch link services
3  * Copyright 2001, Dinesh G Dutt <ddutt@cisco.com>
4  *
5  * $Id: packet-fcswils.c,v 1.3 2003/03/05 07:41:23 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
12  * is a dissector file; if you just copied this from README.developer,
13  * don't bother with the "Copied from" - you don't even need to put
14  * in a "Copied from" if you copied an existing dissector, especially
15  * if the bulk of the code in the new dissector is your code)
16  * 
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  * 
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  * 
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #ifdef HAVE_SYS_TYPES_H
41 # include <sys/types.h>
42 #endif
43
44 #ifdef HAVE_NETINET_IN_H
45 # include <netinet/in.h>
46 #endif
47
48 #include <glib.h>
49
50 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
52 #endif
53
54 #include <epan/packet.h>
55 #include <epan/conversation.h>
56 #include "etypes.h"
57 #include "packet-fc.h"
58 #include "packet-fcswils.h"
59
60 #define FC_SWILS_RPLY               0x0
61 #define FC_SWILS_REQ                0x1
62 #define FC_SWILS_RSCN_DEVENTRY_SIZE 20
63
64 /* Zone name has the structure:
65  * name_len (1 byte), rsvd (3 bytes), name (m bytes), fill (n bytes)
66  * name_len excludes the 4 initial bytes before the name
67  */
68 #define ZONENAME_LEN(x, y)  (tvb_get_guint8(x, y)+4)
69
70 /* Initialize the protocol and registered fields */
71 static int proto_fcswils               = -1;
72 static int hf_swils_opcode             = -1;
73 static int hf_swils_elp_rev            = -1;
74 static int hf_swils_elp_flags          = -1;
75 static int hf_swils_elp_r_a_tov        = -1;
76 static int hf_swils_elp_e_d_tov        = -1;
77 static int hf_swils_elp_req_epn        = -1;
78 static int hf_swils_elp_req_esn        = -1;
79 static int hf_swils_elp_clsf_svcp      = -1;
80 static int hf_swils_elp_clsf_rcvsz     = -1;
81 static int hf_swils_elp_clsf_conseq    = -1;
82 static int hf_swils_elp_clsf_e2e       = -1;
83 static int hf_swils_elp_clsf_openseq   = -1;
84 static int hf_swils_elp_cls1_svcp      = -1;
85 static int hf_swils_elp_cls1_rcvsz     = -1;
86 static int hf_swils_elp_cls2_svcp      = -1;
87 static int hf_swils_elp_cls2_rcvsz     = -1;
88 static int hf_swils_elp_cls3_svcp      = -1;
89 static int hf_swils_elp_cls3_rcvsz     = -1;
90 static int hf_swils_elp_isl_fc_mode    = -1;
91 static int hf_swils_elp_fcplen         = -1;
92 static int hf_swils_elp_b2bcredit      = -1;
93 static int hf_swils_elp_compat1        = -1;
94 static int hf_swils_elp_compat2        = -1;
95 static int hf_swils_elp_compat3        = -1;
96 static int hf_swils_elp_compat4        = -1;
97 static int hf_swils_efp_rec_type       = -1;
98 static int hf_swils_efp_dom_id         = -1;
99 static int hf_swils_efp_switch_name    = -1;
100 static int hf_swils_efp_mcast_grpno    = -1;
101 static int hf_swils_efp_alias_token    = -1;
102 static int hf_swils_efp_payload_len    = -1;
103 static int hf_swils_efp_pswitch_pri    = -1;
104 static int hf_swils_efp_pswitch_name   = -1;
105 static int hf_swils_dia_switch_name    = -1;
106 static int hf_swils_rdi_payload_len    = -1;
107 static int hf_swils_rdi_req_sname      = -1;
108 static int hf_swils_fspfh_cmd          = -1;
109 static int hf_swils_fspfh_rev          = -1;
110 static int hf_swils_fspfh_ar_num       = -1;
111 static int hf_swils_fspfh_auth_type    = -1;
112 static int hf_swils_fspfh_dom_id       = -1;
113 static int hf_swils_fspfh_auth         = -1;
114 static int hf_swils_hlo_options        = -1;
115 static int hf_swils_hlo_hloint         = -1;
116 static int hf_swils_hlo_deadint        = -1;
117 static int hf_swils_hlo_rcv_domid      = -1;
118 static int hf_swils_hlo_orig_pidx      = -1;
119 static int hf_swils_ldrec_linkid       = -1;
120 static int hf_swils_ldrec_out_pidx     = -1;
121 static int hf_swils_ldrec_nbr_pidx     = -1;
122 static int hf_swils_ldrec_link_type    = -1;
123 static int hf_swils_ldrec_link_cost    = -1;
124 static int hf_swils_lsrh_lsr_type      = -1;
125 static int hf_swils_lsrh_lsid          = -1;
126 static int hf_swils_lsrh_adv_domid     = -1;
127 static int hf_swils_lsrh_ls_incid      = -1;
128 static int hf_swils_esc_pdesc_vendorid = -1;
129 static int hf_swils_esc_swvendorid     = -1;
130 static int hf_swils_esc_protocolid     = -1;
131 static int hf_swils_rscn_evtype        = -1;
132 static int hf_swils_rscn_addrfmt       = -1;
133 static int hf_swils_rscn_detectfn      = -1;
134 static int hf_swils_rscn_affectedport  = -1;
135 static int hf_swils_rscn_portstate     = -1;
136 static int hf_swils_rscn_portid        = -1;
137 static int hf_swils_rscn_pwwn          = -1;
138 static int hf_swils_rscn_nwwn          = -1;
139 static int hf_swils_zone_activezonenm  = -1;
140 static int hf_swils_zone_objname       = -1;
141 static int hf_swils_zone_objtype       = -1;
142 static int hf_swils_zone_mbrtype       = -1;
143 static int hf_swils_zone_protocol      = -1;
144 static int hf_swils_zone_mbrid         = -1;
145 static int hf_swils_zone_status        = -1;
146 static int hf_swils_zone_reason        = -1;
147 static int hf_swils_aca_domainid       = -1;
148 static int hf_swils_sfc_opcode         = -1;
149 static int hf_swils_sfc_zonenm         = -1;
150 static int hf_swils_rjt                = -1;
151 static int hf_swils_rjtdet             = -1;
152 static int hf_swils_rjtvendor          = -1;
153 static int hf_swils_zone_mbrid_lun     = -1;
154
155 /* Initialize the subtree pointers */
156 static gint ett_fcswils             = -1;
157 static gint ett_fcswils_swacc       = -1;
158 static gint ett_fcswils_swrjt       = -1;
159 static gint ett_fcswils_elp         = -1;
160 static gint ett_fcswils_efp         = -1;
161 static gint ett_fcswils_efplist     = -1;
162 static gint ett_fcswils_dia         = -1;
163 static gint ett_fcswils_rdi         = -1;
164 static gint ett_fcswils_fspfhdr     = -1;
165 static gint ett_fcswils_hlo         = -1;
166 static gint ett_fcswils_lsrec       = -1;
167 static gint ett_fcswils_lsrechdr    = -1;
168 static gint ett_fcswils_ldrec       = -1;
169 static gint ett_fcswils_lsu         = -1;
170 static gint ett_fcswils_lsa         = -1;
171 static gint ett_fcswils_bf          = -1;
172 static gint ett_fcswils_rcf         = -1;
173 static gint ett_fcswils_rscn        = -1;
174 static gint ett_fcswils_rscn_dev    = -1;
175 static gint ett_fcswils_drlir       = -1;
176 static gint ett_fcswils_mr          = -1;
177 static gint ett_fcswils_zoneobjlist = -1;
178 static gint ett_fcswils_zoneobj     = -1;
179 static gint ett_fcswils_zonembr     = -1;
180 static gint ett_fcswils_aca         = -1;
181 static gint ett_fcswils_rca         = -1;
182 static gint ett_fcswils_sfc         = -1;
183 static gint ett_fcswils_ufc         = -1;
184 static gint ett_fcswils_esc         = -1;
185 static gint ett_fcswils_esc_pdesc   = -1;
186
187 typedef struct _zonename {
188     guint32 namelen:8,
189             rsvd:24;
190     gchar *name;
191     gchar *pad;
192 } zonename_t;
193
194 typedef struct _fcswils_conv_key {
195     guint32 conv_idx;
196 } fcswils_conv_key_t;
197
198 typedef struct _fcswils_conv_data {
199     guint32 opcode;
200 } fcswils_conv_data_t;
201
202 GHashTable *fcswils_req_hash = NULL;
203 GMemChunk *fcswils_req_keys = NULL;
204 GMemChunk *fcswils_req_vals = NULL;
205 guint32 fcswils_init_count = 25;
206
207 static dissector_handle_t data_handle;
208
209 static gint get_zoneobj_len (tvbuff_t *tvb, gint offset);
210
211 /*
212  * Hash Functions
213  */
214 static gint
215 fcswils_equal(gconstpointer v, gconstpointer w)
216 {
217   fcswils_conv_key_t *v1 = (fcswils_conv_key_t *)v;
218   fcswils_conv_key_t *v2 = (fcswils_conv_key_t *)w;
219
220   return (v1->conv_idx == v2->conv_idx);
221 }
222
223 static guint
224 fcswils_hash (gconstpointer v)
225 {
226         fcswils_conv_key_t *key = (fcswils_conv_key_t *)v;
227         guint val;
228
229         val = key->conv_idx;
230
231         return val;
232 }
233
234 /*
235  * Protocol initialization
236  */
237 static void
238 fcswils_init_protocol(void)
239 {
240         if (fcswils_req_keys)
241             g_mem_chunk_destroy (fcswils_req_keys);
242         if (fcswils_req_vals)
243             g_mem_chunk_destroy (fcswils_req_vals);
244         if (fcswils_req_hash)
245             g_hash_table_destroy (fcswils_req_hash);
246
247         fcswils_req_hash = g_hash_table_new(fcswils_hash, fcswils_equal);
248         fcswils_req_keys = g_mem_chunk_new("fcswils_req_keys",
249                                            sizeof(fcswils_conv_key_t),
250                                            fcswils_init_count * sizeof(fcswils_conv_key_t),
251                                            G_ALLOC_AND_FREE);
252         fcswils_req_vals = g_mem_chunk_new("fcswils_req_vals",
253                                            sizeof(fcswils_conv_data_t),
254                                            fcswils_init_count * sizeof(fcswils_conv_data_t),
255                                            G_ALLOC_AND_FREE);
256 }
257
258 static gchar *
259 zonenm_to_str (tvbuff_t *tvb, gint offset)
260 {
261     int len = tvb_get_guint8 (tvb, offset);
262     return ((gchar *)tvb_get_ptr (tvb, offset+4, len));
263 }
264
265 /* Offset points to the start of the zone object */
266 static gint
267 get_zoneobj_len (tvbuff_t *tvb, gint offset)
268 {
269     gint numrec, numrec1;
270     guint8 objtype;
271     gint i, j, len;
272
273     /* zone object structure is:
274      * type (1 byte), protocol (1 byte), rsvd (2 bytes), obj name (x bytes),
275      * num of zone mbrs (4 bytes ), list of zone members (each member if of
276      * variable length).
277      *
278      * zone member structure is:
279      * type (1 byte), rsvd (1 byte), flags (1 byte), id_len (1 byte),
280      * id (id_len bytes)
281      */
282     objtype = tvb_get_guint8 (tvb, offset);
283     len = 4 + ZONENAME_LEN (tvb, offset+4); /* length upto num_of_mbrs field */
284     numrec = tvb_get_ntohl (tvb, offset+len); /* gets us num of zone mbrs */
285
286     len += 4;                   /* + num_mbrs */
287     for (i = 0; i < numrec; i++) {
288         if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
289             len += 4 + ZONENAME_LEN (tvb, offset+4+len); /* length upto num_of_mbrs field */
290             numrec1 = tvb_get_ntohl (tvb, offset+len);
291
292             len += 4;
293             for (j = 0; j < numrec1; j++) {
294                 len += 4 + tvb_get_guint8 (tvb, offset+3+len);
295             }
296         }
297         else if (objtype == FC_SWILS_ZONEOBJ_ZONE) {
298             len += 4 + tvb_get_guint8 (tvb, offset+3+len);
299         }
300     }
301
302     return len;
303 }
304
305 static void
306 dissect_swils_elp (tvbuff_t *tvb, proto_tree *elp_tree, guint8 isreq _U_)
307 {
308     
309     /* Set up structures needed to add the protocol subtree and manage it */
310     int offset = 0,
311         stroff = 0;
312     gchar flags[40];
313     fcswils_elp elp;
314
315     /* Response i.e. SW_ACC for an ELP has the same format as the request */
316     /* We skip the initial 4 bytes as we don't care about the opcode */
317     tvb_memcpy (tvb, (guint8 *)&elp, 4, FC_SWILS_ELP_SIZE);
318     
319     elp.r_a_tov = ntohl (elp.r_a_tov);
320     elp.e_d_tov = ntohl (elp.e_d_tov);
321     elp.isl_flwctrl_mode = ntohs (elp.isl_flwctrl_mode);
322     elp.flw_ctrl_parmlen = ntohs (elp.flw_ctrl_parmlen);
323     
324     if (elp_tree) {
325         offset += 4;
326         proto_tree_add_item (elp_tree, hf_swils_elp_rev, tvb, offset++, 1, 0);
327         proto_tree_add_item (elp_tree, hf_swils_elp_flags, tvb, offset, 2, 0);
328         offset += 3;
329         proto_tree_add_uint_format (elp_tree, hf_swils_elp_r_a_tov, tvb, offset, 4,
330                                     elp.r_a_tov, "R_A_TOV: %d msecs", elp.r_a_tov);
331         offset += 4;
332         proto_tree_add_uint_format (elp_tree, hf_swils_elp_e_d_tov, tvb, offset, 4,
333                                     elp.e_d_tov, "E_D_TOV: %d msecs", elp.e_d_tov);
334         offset += 4;
335         proto_tree_add_string (elp_tree, hf_swils_elp_req_epn, tvb, offset, 8,
336                                fcwwn_to_str (elp.req_epname));
337         offset += 8;
338         proto_tree_add_string (elp_tree, hf_swils_elp_req_esn, tvb, offset, 8,
339                                fcwwn_to_str (elp.req_sname));
340         offset += 8;
341
342         flags[0] = '\0';
343         if (elp.clsf_svcparm[0] & 0x80) {
344             strcpy (flags, "Class F Valid");
345
346             if (elp.clsf_svcparm[4] & 0x20) {
347                 strcpy (&flags[13], " | X_ID Interlock");
348             }
349             else {
350                 strcpy (&flags[13], " | No X_ID Interlk");
351             }
352         }
353         else {
354             strcpy (flags, "Class F Invld");
355         }
356         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_clsf_svcp, tvb, offset, 6, 
357                                      &elp.clsf_svcparm[0], "Class F Svc Parameters: (%s)", flags);
358         offset += 6;
359
360         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_rcvsz, tvb, offset, 2, 0);
361         offset += 2;
362         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_conseq, tvb, offset, 2, 0);
363         offset += 2;
364         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_e2e, tvb, offset, 2, 0);
365         offset += 2;
366         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_openseq, tvb, offset, 2, 0);
367         offset += 4;
368
369         flags[0] = '\0';
370         stroff = 0;
371         if (elp.cls1_svcparm[0] & 0x80) {
372             strcpy (&flags[stroff], "Class 1 Valid");
373             stroff += 13;
374             if (elp.cls1_svcparm[0] & 0x40) {
375                 strcpy (&flags[stroff], " | IMX");
376                 stroff += 6;
377             }
378             if (elp.cls1_svcparm[0] & 0x20) {
379                 strcpy (&flags[stroff], " | XPS");
380                 stroff += 6;
381             }
382             if (elp.cls1_svcparm[0] & 0x10) {
383                 strcpy (&flags[stroff], " | LKS");
384             }
385         }
386         else {
387             strcpy (&flags[0], "Class 1 Invalid");
388         }
389         
390         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls1_svcp, tvb, offset, 2,
391                                      tvb_get_ptr (tvb, offset, 2),
392                                      "Class 1 Svc Parameters: (%s)", flags);
393         offset += 2;
394         if (elp.cls1_svcparm[0] & 0x80) {
395             proto_tree_add_item (elp_tree, hf_swils_elp_cls1_rcvsz, tvb, offset, 2, 0);
396         }
397         offset += 2;
398
399         flags[0] = '\0';
400         if (elp.cls2_svcparm[0] & 0x80) {
401             strcpy (flags, "Class 2 Valid");
402
403             if (elp.cls2_svcparm[0] & 0x08) {
404                 strcpy (&flags[13], " | Seq Delivery");
405             }
406             else {
407                 strcpy (&flags[13], " | No Seq Delivery");
408             }
409         }
410         else {
411             strcpy (flags, "Class 2 Invld");
412         }
413         
414         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls2_svcp, tvb, offset, 2,
415                                      &elp.cls2_svcparm[0],
416                                      "Class 2 Svc Parameters: (%s)", flags);
417         offset += 2;
418         
419         if (elp.cls2_svcparm[0] & 0x80) {
420             proto_tree_add_item (elp_tree, hf_swils_elp_cls2_rcvsz, tvb, offset, 2, 0);
421         }
422         offset += 2;
423         
424         flags[0] = '\0';
425         if (elp.cls3_svcparm[0] & 0x80) {
426             strcpy (flags, "Class 3 Valid");
427
428             if (elp.cls3_svcparm[0] & 0x08) {
429                 strcpy (&flags[13], " | Seq Delivery");
430             }
431             else {
432                 strcpy (&flags[13], " | No Seq Delivery");
433             }
434         }
435         else {
436             strcpy (flags, "Class 3 Invld");
437         }
438         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls3_svcp, tvb, offset, 2,
439                                      &elp.cls3_svcparm[0],
440                                      "Class 3 Svc Parameters: (%s)", flags);
441         offset += 2;
442
443         if (elp.cls3_svcparm[0] & 0x80) {
444             proto_tree_add_item (elp_tree, hf_swils_elp_cls3_rcvsz, tvb, offset, 2, 0);
445         }
446         offset += 22;
447
448         proto_tree_add_string (elp_tree, hf_swils_elp_isl_fc_mode, tvb, offset, 2,
449                                val_to_str (elp.isl_flwctrl_mode, fcswils_elp_fc_val, "Vendor Unique"));
450         offset += 2;
451         proto_tree_add_item (elp_tree, hf_swils_elp_fcplen, tvb, offset, 2, 0);
452         offset += 2;
453         proto_tree_add_item (elp_tree, hf_swils_elp_b2bcredit, tvb, offset, 4, 0);
454         offset += 4;
455         proto_tree_add_item (elp_tree, hf_swils_elp_compat1, tvb, offset, 4, 0);
456         offset += 4;
457         proto_tree_add_item (elp_tree, hf_swils_elp_compat2, tvb, offset, 4, 0);
458         offset += 4;
459         proto_tree_add_item (elp_tree, hf_swils_elp_compat3, tvb, offset, 4, 0);
460         offset += 4;
461         proto_tree_add_item (elp_tree, hf_swils_elp_compat4, tvb, offset, 4, 0);
462     }
463
464 }
465
466 static void
467 dissect_swils_efp (tvbuff_t *tvb, proto_tree *efp_tree, guint8 isreq _U_)
468 {
469
470 /* Set up structures needed to add the protocol subtree and manage it */
471     proto_item *subti;
472     proto_tree *lrec_tree;
473     int num_listrec = 0,
474         offset = 0;
475     fcswils_efp efp;
476     fcswils_efp_listrec *lrec;
477     
478     tvb_memcpy (tvb, (guint8 *)&efp, offset, FC_SWILS_EFP_SIZE);
479     efp.payload_len = ntohs (efp.payload_len);
480     efp.listrec = (fcswils_efp_listrec *)tvb_get_ptr (tvb, FC_SWILS_EFP_SIZE,
481                                                       efp.payload_len - FC_SWILS_EFP_SIZE);
482     
483     if (efp_tree) {
484         offset += 2;
485         proto_tree_add_item (efp_tree, hf_swils_efp_payload_len, tvb, offset, 2, 0);
486         offset += 5;
487         proto_tree_add_item (efp_tree, hf_swils_efp_pswitch_pri, tvb,
488                              offset++, 1, 0);
489         proto_tree_add_string (efp_tree, hf_swils_efp_pswitch_name, tvb, offset,
490                                8, fcwwn_to_str (efp.pswitch_name));
491         offset += 8;
492
493         /* Add List Records now */
494         if (efp.reclen) {
495             num_listrec = (efp.payload_len - FC_SWILS_EFP_SIZE)/efp.reclen;
496         }
497         else {
498             num_listrec = 0;
499         }
500         
501         while (num_listrec--) {
502             lrec =  (fcswils_efp_listrec *)tvb_get_ptr (tvb, offset, efp.reclen);
503             if (lrec != NULL) {
504                 if (lrec->didrec.rec_type == FC_SWILS_LRECTYPE_DOMAIN) {
505                     subti = proto_tree_add_text (efp_tree, tvb, offset,
506                                                  (efp.payload_len - FC_SWILS_EFP_SIZE),
507                                                  "Domain ID Record");
508                     lrec_tree = proto_item_add_subtree (subti, ett_fcswils_efplist);
509                     proto_tree_add_item (lrec_tree, hf_swils_efp_dom_id, tvb, offset+1, 1, 0); 
510                     proto_tree_add_string (lrec_tree, hf_swils_efp_switch_name, tvb, offset+8, 8,
511                                            fcwwn_to_str (lrec->didrec.sname));
512                 }
513                 else if (lrec->didrec.rec_type == FC_SWILS_LRECTYPE_MCAST) {
514                     subti = proto_tree_add_text (efp_tree, tvb, offset,
515                                                  (efp.payload_len - FC_SWILS_EFP_SIZE),
516                                                  "Multicast ID Record");
517                     lrec_tree = proto_item_add_subtree (subti, ett_fcswils_efplist);
518                     proto_tree_add_item (lrec_tree, hf_swils_efp_mcast_grpno, tvb, offset+1, 1, 0);  
519                 }
520                 offset += efp.reclen;
521             }
522         }
523     }
524 }
525
526 static void
527 dissect_swils_dia (tvbuff_t *tvb, proto_tree *dia_tree, guint8 isreq _U_)
528 {
529     /* Set up structures needed to add the protocol subtree and manage it */
530     int offset = 0;
531
532     if (dia_tree) {
533         proto_tree_add_string (dia_tree, hf_swils_dia_switch_name, tvb, offset+4,
534                                8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
535     }
536 }
537
538 static void
539 dissect_swils_rdi (tvbuff_t *tvb, proto_tree *rdi_tree, guint8 isreq)
540 {
541     /* Set up structures needed to add the protocol subtree and manage it */
542     int offset = 0;
543     int i, plen, numrec;
544     
545     if (rdi_tree) {
546         plen = tvb_get_ntohs (tvb, offset+2);
547         
548         proto_tree_add_item (rdi_tree, hf_swils_rdi_payload_len, tvb, offset+2, 2, 0);
549         proto_tree_add_string (rdi_tree, hf_swils_rdi_req_sname, tvb, offset+4,
550                                8, fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
551
552         /* 12 is the length of the initial header and 4 is the size of each
553          * domain request record.
554          */
555         numrec = (plen - 12)/4;
556         offset = 12;
557         for (i = 0; i < numrec; i++) {
558             if (isreq) {
559                 proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
560                                      "Requested Domain ID: %d",
561                                      tvb_get_guint8 (tvb, offset+3));
562             }
563             else {
564                 proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
565                                      "Granted Domain ID: %d",
566                                      tvb_get_guint8 (tvb, offset+3));
567             }
568             offset += 4;
569         }
570     }
571 }
572
573 static void
574 dissect_swils_fspf_hdr (tvbuff_t *tvb, proto_tree *tree, int offset)
575 {
576     proto_item *subti;
577     proto_tree *fspfh_tree;
578     
579     if (tree) {
580         /* 20 is the size of FSPF header */
581         subti = proto_tree_add_text (tree, tvb, offset, 20, "FSPF Header");
582         fspfh_tree = proto_item_add_subtree (subti, ett_fcswils_fspfhdr);
583
584         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_rev, tvb, offset+4,
585                              1, 0);
586         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_ar_num, tvb,
587                              offset+5, 1, 0);
588         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth_type, tvb,
589                              offset+6, 1, 0);
590         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_dom_id, tvb, offset+11,
591                              1, 0);
592         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth, tvb, offset+12,
593                              8, 0);
594     }
595 }
596
597 static void
598 dissect_swils_fspf_lsrechdr (tvbuff_t *tvb, proto_tree *tree, int offset)
599 {
600     proto_tree_add_item (tree, hf_swils_lsrh_lsr_type, tvb, offset, 1, 0);
601     proto_tree_add_text (tree, tvb, offset+2, 2, "LSR Age: %d secs",
602                          tvb_get_ntohs (tvb, offset+2));
603     proto_tree_add_text (tree, tvb, offset+4, 4, "Options : 0x%x",
604                          tvb_get_ntohl (tvb, offset+4));
605     proto_tree_add_item (tree, hf_swils_lsrh_lsid, tvb, offset+11, 1, 0);
606     proto_tree_add_item (tree, hf_swils_lsrh_adv_domid, tvb, offset+15, 1, 0);
607     proto_tree_add_item (tree, hf_swils_lsrh_ls_incid, tvb, offset+16, 4, 0);
608     proto_tree_add_text (tree, tvb, offset+20, 2, "Checksum: 0x%x",
609                          tvb_get_ntohs (tvb, offset+20));
610     proto_tree_add_text (tree, tvb, offset+22, 2, "LSR Length: %d",
611                          tvb_get_ntohs (tvb, offset+22));
612 }
613
614 static void
615 dissect_swils_fspf_ldrec (tvbuff_t *tvb, proto_tree *tree, int offset)
616 {
617     proto_tree_add_string (tree, hf_swils_ldrec_linkid, tvb, offset, 4,
618                            fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
619     proto_tree_add_item (tree, hf_swils_ldrec_out_pidx, tvb, offset+5, 3, 0);
620     proto_tree_add_item (tree, hf_swils_ldrec_nbr_pidx, tvb, offset+9, 3, 0);
621     proto_tree_add_item (tree, hf_swils_ldrec_link_type, tvb, offset+12, 1, 0);
622     proto_tree_add_item (tree, hf_swils_ldrec_link_cost, tvb, offset+14, 2, 0);
623 }
624
625 static void
626 dissect_swils_fspf_lsrec (tvbuff_t *tvb, proto_tree *tree, int offset,
627                           int num_lsrec)
628 {
629     int i, j, num_ldrec;
630     proto_item *subti1, *subti;
631     proto_tree *lsrec_tree, *ldrec_tree, *lsrechdr_tree;
632
633     if (tree) {
634         for (j = 0; j < num_lsrec; j++) {
635             num_ldrec = tvb_get_ntohs (tvb, offset+26); 
636             subti = proto_tree_add_text (tree, tvb, offset, (28+num_ldrec*16),
637                                          "Link State Record %d (Domain %d)", j,
638                                          tvb_get_guint8 (tvb, offset+15));
639             lsrec_tree = proto_item_add_subtree (subti, ett_fcswils_lsrec);
640         
641             subti = proto_tree_add_text (lsrec_tree, tvb, offset, 24,
642                                          "Link State Record Header");
643             lsrechdr_tree = proto_item_add_subtree (subti,
644                                                     ett_fcswils_lsrechdr); 
645         
646             dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
647             proto_tree_add_text (tree, tvb, offset+26, 2, "Number of Links: %d",
648                                  num_ldrec);
649             offset += 28;
650         
651             for (i = 0; i < num_ldrec; i++) {
652                 subti1 = proto_tree_add_text (lsrec_tree, tvb, offset, 16,
653                                               "Link Descriptor %d "
654                                               "(Neighbor domain %d)", i,
655                                               tvb_get_guint8 (tvb, offset+3));
656                 ldrec_tree = proto_item_add_subtree (subti1, ett_fcswils_ldrec);
657                 dissect_swils_fspf_ldrec (tvb, ldrec_tree, offset);
658                 offset += 16;
659             }
660         }
661     }
662 }
663
664 static void
665 dissect_swils_hello (tvbuff_t *tvb, proto_tree *hlo_tree, guint8 isreq _U_)
666 {
667     /* Set up structures needed to add the protocol subtree and manage it */
668     int offset = 0;
669
670     if (hlo_tree) {
671         dissect_swils_fspf_hdr (tvb, hlo_tree, offset);
672
673         proto_tree_add_item (hlo_tree, hf_swils_hlo_options, tvb, offset+20, 4, 0);
674         proto_tree_add_item (hlo_tree, hf_swils_hlo_hloint, tvb, offset+24, 4, 0);
675         proto_tree_add_item (hlo_tree, hf_swils_hlo_deadint, tvb, offset+28, 4, 0);
676         proto_tree_add_item (hlo_tree, hf_swils_hlo_rcv_domid, tvb, offset+35, 1, 0);
677         proto_tree_add_item (hlo_tree, hf_swils_hlo_orig_pidx, tvb, offset+37, 3, 0);
678     }
679 }
680
681 static void
682 dissect_swils_lsupdate (tvbuff_t *tvb, proto_tree *lsu_tree, guint8 isreq _U_)
683 {
684     /* Set up structures needed to add the protocol subtree and manage it */
685     int offset = 0;
686     int num_lsrec;
687
688     if (lsu_tree) {
689         dissect_swils_fspf_hdr (tvb, lsu_tree, offset);
690
691         proto_tree_add_text (lsu_tree, tvb, offset+23, 1, "Flags : %s",
692                              val_to_str (tvb_get_guint8 (tvb, offset+23),
693                                          fc_swils_fspf_lsrflags_val, "0x%x"));
694         num_lsrec = tvb_get_ntohl (tvb, offset+24);
695
696         proto_tree_add_text (lsu_tree, tvb, offset+24, 4, "Num of LSRs: %d",
697                              num_lsrec);
698
699         offset = 28;
700         dissect_swils_fspf_lsrec (tvb, lsu_tree, offset, num_lsrec);
701     }
702 }
703
704 static void
705 dissect_swils_lsack (tvbuff_t *tvb, proto_tree *lsa_tree, guint8 isreq _U_)
706 {
707     /* Set up structures needed to add the protocol subtree and manage it */
708     int offset = 0;
709     int num_lsrechdr, i;
710     proto_item *subti;
711     proto_tree *lsrechdr_tree;
712
713     if (lsa_tree) {
714         dissect_swils_fspf_hdr (tvb, lsa_tree, offset);
715
716         proto_tree_add_text (lsa_tree, tvb, offset+23, 1, "Flags : %s",
717                              val_to_str (tvb_get_guint8 (tvb, offset+23),
718                                          fc_swils_fspf_lsrflags_val, "0x%x"));
719         num_lsrechdr = tvb_get_ntohl (tvb, offset+24);
720
721         proto_tree_add_text (lsa_tree, tvb, offset+24, 4, "Num of LSR Headers: %d",
722                              num_lsrechdr);
723
724         offset = 28;
725
726         for (i = 0; i < num_lsrechdr; i++) {
727             subti = proto_tree_add_text (lsa_tree, tvb, offset, 24,
728                                          "Link State Record Header (Domain %d)",
729                                          tvb_get_guint8 (tvb, offset+15));
730             lsrechdr_tree = proto_item_add_subtree (subti,
731                                                     ett_fcswils_lsrechdr); 
732             dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
733             offset += 24;
734         }
735     }
736 }
737
738 static void
739 dissect_swils_rscn (tvbuff_t *tvb, proto_tree *rscn_tree, guint8 isreq)
740 {
741     /* Set up structures needed to add the protocol subtree and manage it */
742     int offset = 0;
743     proto_tree *dev_tree;
744     int addrfmt, evtype;
745     int numrec, i;
746     proto_item *subti;
747     
748     if (rscn_tree) {
749         if (!isreq)
750             return;
751         
752         evtype = tvb_get_guint8 (tvb, offset+4);
753         addrfmt = evtype & 0x0F;
754         evtype = evtype >> 4;
755
756         proto_tree_add_item (rscn_tree, hf_swils_rscn_evtype, tvb, offset+4,
757                              1, 0);
758         proto_tree_add_item (rscn_tree, hf_swils_rscn_addrfmt, tvb, offset+4,
759                              1, 0);
760         proto_tree_add_string (rscn_tree, hf_swils_rscn_affectedport, tvb,
761                                offset+5, 3, fc_to_str (tvb_get_ptr (tvb,
762                                                                     offset+5, 3)));
763         proto_tree_add_item (rscn_tree, hf_swils_rscn_detectfn, tvb,
764                              offset+8, 4, 0);
765         numrec = tvb_get_ntohl (tvb, offset+12);
766         
767         if (!tvb_bytes_exist (tvb, offset+16, FC_SWILS_RSCN_DEVENTRY_SIZE*numrec)) {
768             /* Some older devices do not include device entry information. */
769             return;
770         }
771         
772         proto_tree_add_text (rscn_tree, tvb, offset+12, 4, "Num Entries: %d",
773                              numrec);
774
775         offset = 16;
776         for (i = 0; i < numrec; i++) {
777             subti = proto_tree_add_text (rscn_tree, tvb, offset, 20,
778                                          "Device Entry %d", i);
779             dev_tree = proto_item_add_subtree (rscn_tree, ett_fcswils_rscn_dev);
780
781             proto_tree_add_item (dev_tree, hf_swils_rscn_portstate, tvb, offset, 1, 0);
782             proto_tree_add_string (dev_tree, hf_swils_rscn_portid, tvb, offset+1, 3,
783                                    fc_to_str (tvb_get_ptr (tvb, offset+1, 3)));
784             proto_tree_add_string (dev_tree, hf_swils_rscn_pwwn, tvb, offset+4, 8,
785                                    fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
786             proto_tree_add_string (dev_tree, hf_swils_rscn_nwwn, tvb, offset+4, 8,
787                                    fcwwn_to_str (tvb_get_ptr (tvb, offset+4, 8)));
788             offset += 20;
789         }
790     }
791 }
792
793 /*
794  * Merge Request contains zoning objects organized in the following format:
795  *
796  * Zone Set Object
797  *      |
798  *      +---------------- Zone Object
799  *      |                      |
800  *      +--                    +---------------- Zone Member
801  *      |                      |                     |
802  *      +--                    +----                 +-----
803  *
804  * So the decoding of the zone merge request is based on this structure
805  */
806
807 static void
808 dissect_swils_zone_mbr (tvbuff_t *tvb, proto_tree *zmbr_tree, int offset)
809 {
810     int mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
811
812     proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrtype, tvb,
813                          offset, 1, 0);
814     proto_tree_add_text (zmbr_tree, tvb, offset+2, 1, "Flags: 0x%x",
815                          tvb_get_guint8 (tvb, offset+2));
816     proto_tree_add_text (zmbr_tree, tvb, offset+3, 1,
817                          "Identifier Length: %d",
818                          tvb_get_guint8 (tvb, offset+3));
819     switch (tvb_get_guint8 (tvb, offset)) {
820     case FC_SWILS_ZONEMBR_WWN:
821         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
822                                offset+4, 8,
823                                fcwwn_to_str (tvb_get_ptr (tvb,
824                                                           offset+4,
825                                                           8)));
826         break;
827     case FC_SWILS_ZONEMBR_DP:
828         proto_tree_add_string_format (zmbr_tree,
829                                       hf_swils_zone_mbrid,
830                                       tvb, offset+4, 4, " ",
831                                       "0x%x",
832                                       tvb_get_ntohl (tvb,
833                                                      offset+4));
834         break;
835     case FC_SWILS_ZONEMBR_FCID:
836         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
837                                offset+4, 4,
838                                fc_to_str (tvb_get_ptr (tvb,
839                                                        offset+5,
840                                                        3)));
841         break;
842     case FC_SWILS_ZONEMBR_ALIAS:
843         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
844                                offset+4,
845                                tvb_get_guint8 (tvb, offset+3),
846                                zonenm_to_str (tvb, offset+4));
847         break;
848     case FC_SWILS_ZONEMBR_WWN_LUN:
849         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
850                                offset+4, 8,
851                                fcwwn_to_str (tvb_get_ptr (tvb,
852                                                           offset+4,
853                                                           8)));
854         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
855                              offset+12, 8, 0);
856         break;
857     case FC_SWILS_ZONEMBR_DP_LUN:
858         proto_tree_add_string_format (zmbr_tree,
859                                       hf_swils_zone_mbrid,
860                                       tvb, offset+4, 4, " ",
861                                       "0x%x",
862                                       tvb_get_ntohl (tvb,
863                                                      offset+4));
864         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
865                              offset+8, 8, 0);
866         break;
867     case FC_SWILS_ZONEMBR_FCID_LUN:
868         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
869                                offset+4, 4,
870                                fc_to_str (tvb_get_ptr (tvb,
871                                                        offset+5,
872                                                        3)));
873         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
874                              offset+8, 8, 0);
875         break;
876     default:
877         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
878                                offset+4, mbrlen,
879                                "Unknown member type format");
880             
881     }
882 }
883
884 static void
885 dissect_swils_zone_obj (tvbuff_t *tvb, proto_tree *zobj_tree, int offset)
886 {
887     proto_tree *zmbr_tree;
888     int mbrlen, numrec, i, objtype;
889     proto_item *subti;
890
891     objtype = tvb_get_guint8 (tvb, offset);
892     
893     proto_tree_add_item (zobj_tree, hf_swils_zone_objtype, tvb, offset,
894                          1, 0);
895     proto_tree_add_item (zobj_tree, hf_swils_zone_protocol, tvb,
896                          offset+1, 1, 0);
897     proto_tree_add_string (zobj_tree, hf_swils_zone_objname, tvb,
898                            offset+4, ZONENAME_LEN (tvb, offset+4),
899                            zonenm_to_str (tvb, offset+4));
900
901     numrec = tvb_get_ntohl (tvb, offset+4+ZONENAME_LEN (tvb, offset+4));
902     proto_tree_add_text (zobj_tree, tvb,
903                          offset+4+ZONENAME_LEN (tvb, offset+4), 4,
904                          "Number of Zone Members: %d", numrec);
905
906     offset += 8 + ZONENAME_LEN (tvb, offset+4);
907     for (i = 0; i < numrec; i++) {
908         if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
909             dissect_swils_zone_obj (tvb, zobj_tree, offset);
910             offset += get_zoneobj_len (tvb, offset);
911         }
912         else {
913             mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
914             subti = proto_tree_add_text (zobj_tree, tvb, offset, mbrlen,
915                                          "Zone Member %d", i);
916             zmbr_tree = proto_item_add_subtree (zobj_tree,
917                                                 ett_fcswils_zonembr);
918             dissect_swils_zone_mbr (tvb, zmbr_tree, offset);
919             offset += mbrlen;
920         }
921     }
922 }
923
924 static void
925 dissect_swils_mergereq (tvbuff_t *tvb, proto_tree *mr_tree, guint8 isreq)
926 {
927     /* Set up structures needed to add the protocol subtree and manage it */
928     int offset = 0;
929     proto_tree *zobjlist_tree, *zobj_tree;
930     int numrec, i, zonesetlen, objlistlen, objlen;
931     proto_item *subti;
932
933     if (mr_tree) {
934         if (isreq) {
935             /* zonesetlen is the size of the zoneset including the zone name */ 
936             zonesetlen = tvb_get_ntohs (tvb, offset+2);
937             proto_tree_add_text (mr_tree, tvb, offset+2, 2,
938                                  "Active ZoneSet Length: %d", zonesetlen);
939
940             if (zonesetlen) {
941                 proto_tree_add_string (mr_tree, hf_swils_zone_activezonenm, tvb,
942                                        offset+4, ZONENAME_LEN (tvb, offset+4),
943                                        zonenm_to_str (tvb, offset+4));
944                 
945                 /* objlistlen gives the size of the active zoneset object list */ 
946                 objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
947                 /* Offset = start of the active zoneset zoning object list */
948                 offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
949                 numrec = tvb_get_ntohl (tvb, offset);
950                 
951                 subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
952                                              "Active Zone Set");
953                 zobjlist_tree = proto_item_add_subtree (subti,
954                                                         ett_fcswils_zoneobjlist);
955                 
956                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
957                                      "Number of zoning objects: %d", numrec);
958
959                 offset += 4;
960                 for (i = 0; i < numrec; i++) {
961                     objlen = get_zoneobj_len (tvb, offset);
962                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset+4,
963                                                  objlen, "Zone Object %d", i);
964                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
965                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
966                     offset += objlen;
967                 }
968             }
969             else {
970                 offset += 4;
971             }
972             
973             zonesetlen = tvb_get_ntohl (tvb, offset);
974             proto_tree_add_text (mr_tree, tvb, offset, 4,
975                                  "Full Zone Set Length: %d", zonesetlen);
976
977             if (zonesetlen) {
978                 objlistlen = zonesetlen;
979                 /* Offset = start of the active zoneset zoning object list */
980                 offset += 4;
981                 numrec = tvb_get_ntohl (tvb, offset);
982                 
983                 subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
984                                              "Full Zone Set");
985                 
986                 zobjlist_tree = proto_item_add_subtree (subti,
987                                                         ett_fcswils_zoneobjlist);
988                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
989                                      "Number of zoning objects: %d", numrec);
990                 offset += 4;
991                 for (i = 0; i < numrec; i++) {
992                     objlen = get_zoneobj_len (tvb, offset);
993                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
994                                                  objlen, "Zone Object %d", i);
995                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
996                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
997                     offset += objlen;
998                 }
999             }
1000         }
1001         else {
1002             proto_tree_add_item (mr_tree, hf_swils_zone_status, tvb,
1003                                  offset+5, 1, 0);
1004             proto_tree_add_item (mr_tree, hf_swils_zone_reason, tvb,
1005                                  offset+6, 1, 0);
1006             proto_tree_add_text (mr_tree, tvb, offset+7, 1,
1007                                  "Vendor Unique: 0x%x",
1008                                  tvb_get_guint8 (tvb, offset+7));
1009         }
1010     }
1011 }
1012
1013 static void
1014 dissect_swils_aca (tvbuff_t *tvb, proto_tree *aca_tree, guint8 isreq)
1015 {
1016     /* Set up structures needed to add the protocol subtree and manage it */
1017     int offset = 0;
1018     int numrec, plen, i;
1019
1020     if (aca_tree) {
1021         if (isreq) {
1022             plen = tvb_get_ntohs (tvb, offset+2);
1023             proto_tree_add_text (aca_tree, tvb, offset+2, 2,
1024                                  "Domain ID List Length: %d", plen);
1025             numrec = plen/4;
1026             offset = 4;
1027         
1028             for (i = 0; i < numrec; i++) {
1029                 proto_tree_add_uint_format (aca_tree, hf_swils_aca_domainid,
1030                                             tvb, offset+3, 1, 
1031                                             tvb_get_guint8 (tvb, offset+3),
1032                                             "Domain ID %d: %d", i,
1033                                             tvb_get_guint8 (tvb, offset+3));
1034                 offset += 4;
1035             }
1036         }
1037         else {
1038             proto_tree_add_item (aca_tree, hf_swils_zone_status, tvb,
1039                                  offset+5, 1, 0);
1040             proto_tree_add_item (aca_tree, hf_swils_zone_reason, tvb,
1041                                  offset+6, 1, 0);
1042             proto_tree_add_text (aca_tree, tvb, offset+7, 1,
1043                                  "Vendor Unique: 0x%x",
1044                                  tvb_get_guint8 (tvb, offset+7));
1045         }
1046     }
1047 }
1048
1049 static void
1050 dissect_swils_rca (tvbuff_t *tvb, proto_tree *rca_tree, guint8 isreq)
1051 {
1052     /* Set up structures needed to add the protocol subtree and manage it */
1053     int offset = 0;
1054
1055     if (rca_tree) {
1056         if (!isreq) {
1057             proto_tree_add_item (rca_tree, hf_swils_zone_status, tvb,
1058                                  offset+5, 1, 0);
1059             proto_tree_add_item (rca_tree, hf_swils_zone_reason, tvb,
1060                                  offset+6, 1, 0);
1061             proto_tree_add_text (rca_tree, tvb, offset+7, 1,
1062                                  "Vendor Unique: 0x%x",
1063                                  tvb_get_guint8 (tvb, offset+7));
1064         }
1065     }
1066 }
1067
1068 static void
1069 dissect_swils_sfc (tvbuff_t *tvb, proto_tree *sfc_tree, guint8 isreq)
1070 {
1071     /* Set up structures needed to add the protocol subtree and manage it */
1072     int offset = 0;
1073     proto_tree *zobjlist_tree, *zobj_tree;
1074     int numrec, i, zonesetlen, objlistlen, objlen;
1075     proto_item *subti;
1076
1077     if (sfc_tree) {
1078         if (isreq) {
1079             proto_tree_add_item (sfc_tree, hf_swils_sfc_opcode, tvb, offset+1, 1, 0);
1080
1081             zonesetlen = tvb_get_ntohs (tvb, offset+2);
1082             proto_tree_add_text (sfc_tree, tvb, offset+2, 2,
1083                                  "ZoneSet Length: %d", zonesetlen);
1084
1085             if (zonesetlen) {
1086                 proto_tree_add_string (sfc_tree, hf_swils_sfc_zonenm, tvb,
1087                                        offset+4, ZONENAME_LEN (tvb, offset+4),
1088                                        zonenm_to_str (tvb, offset+4));
1089                 
1090                 /* objlistlen gives the size of the active zoneset object list */ 
1091                 objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
1092                 /* Offset = start of the active zoneset zoning object list */
1093                 offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
1094                 numrec = tvb_get_ntohl (tvb, offset);
1095                 
1096                 subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
1097                                              "Zone Set");
1098                 zobjlist_tree = proto_item_add_subtree (subti,
1099                                                         ett_fcswils_zoneobjlist);
1100                 
1101                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1102                                      "Number of zoning objects: %d", numrec);
1103
1104                 offset += 4;
1105                 for (i = 0; i < numrec; i++) {
1106                     objlen = get_zoneobj_len (tvb, offset);
1107                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1108                                                  objlen, "Zone Object %d", i);
1109                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1110                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1111                     offset += objlen;
1112                 }
1113             }
1114             else {
1115                 offset += 4;
1116             }
1117
1118             zonesetlen = tvb_get_ntohl (tvb, offset);
1119             proto_tree_add_text (sfc_tree, tvb, offset, 4,
1120                                  "Full Zone Set Length: %d", zonesetlen);
1121
1122             if (zonesetlen) {
1123                 objlistlen = zonesetlen;
1124                 /* Offset = start of the active zoneset zoning object list */
1125                 offset += 4;
1126                 numrec = tvb_get_ntohl (tvb, offset);
1127                 
1128                 subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
1129                                              "Full Zone Set");
1130                 
1131                 zobjlist_tree = proto_item_add_subtree (subti,
1132                                                         ett_fcswils_zoneobjlist);
1133                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1134                                      "Number of zoning objects: %d", numrec);
1135                 offset += 4;
1136                 for (i = 0; i < numrec; i++) {
1137                     objlen = get_zoneobj_len (tvb, offset);
1138                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1139                                                  objlen, "Zone Object %d", i);
1140                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1141                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1142                     offset += objlen;
1143                 }
1144             }
1145         }
1146         else {
1147             proto_tree_add_item (sfc_tree, hf_swils_zone_status, tvb,
1148                                  offset+5, 1, 0);
1149             proto_tree_add_item (sfc_tree, hf_swils_zone_reason, tvb,
1150                                  offset+6, 1, 0);
1151             proto_tree_add_text (sfc_tree, tvb, offset+7, 1,
1152                                  "Vendor Unique: 0x%x",
1153                                  tvb_get_guint8 (tvb, offset+7));
1154         }
1155     }
1156 }
1157
1158 static void
1159 dissect_swils_ufc (tvbuff_t *tvb, proto_tree *ufc_tree, guint8 isreq)
1160 {
1161     /* Set up structures needed to add the protocol subtree and manage it */
1162     int offset = 0;
1163
1164     if (ufc_tree) {
1165         if (!isreq) {
1166             proto_tree_add_item (ufc_tree, hf_swils_zone_status, tvb,
1167                                  offset+5, 1, 0);
1168             proto_tree_add_item (ufc_tree, hf_swils_zone_reason, tvb,
1169                                  offset+6, 1, 0);
1170             proto_tree_add_text (ufc_tree, tvb, offset+7, 1,
1171                                  "Vendor Unique: 0x%x",
1172                                  tvb_get_guint8 (tvb, offset+7));
1173         }
1174     }
1175 }
1176
1177 static void
1178 dissect_swils_esc (tvbuff_t *tvb, proto_tree *esc_tree, guint8 isreq)
1179 {
1180     /* Set up structures needed to add the protocol subtree and manage it */
1181     int offset = 0;
1182     int i, numrec, plen;
1183     proto_tree *pdesc_tree;
1184     proto_item *subti;
1185
1186     if (esc_tree) {
1187         if (isreq) {
1188             plen = tvb_get_ntohs (tvb, offset+2);
1189             proto_tree_add_text (esc_tree, tvb, offset+2, 2,
1190                                  "Payload Length: %d", plen);
1191             proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
1192                                  offset+4, 8, 0);
1193             numrec = (plen - 12)/12;
1194             offset = 12;
1195
1196             for (i = 0; i < numrec; i++) {
1197                 subti = proto_tree_add_text (esc_tree, tvb, offset, 12,
1198                                              "Protocol Descriptor %d", i);
1199                 pdesc_tree = proto_item_add_subtree (subti,
1200                                                      ett_fcswils_esc_pdesc);
1201                 proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
1202                                      offset, 8, 0);
1203                 proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
1204                                      tvb, offset+10, 2, 0);
1205                 offset += 12;
1206             }
1207         }
1208         else {
1209             proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
1210                                  offset+4, 8, 0);
1211             subti = proto_tree_add_text (esc_tree, tvb, offset+12, 12,
1212                                          "Accepted Protocol Descriptor");
1213             pdesc_tree = proto_item_add_subtree (subti, ett_fcswils_esc_pdesc);
1214
1215             proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
1216                                  offset+12, 8, 0);
1217             proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
1218                                  tvb, offset+22, 2, 0);
1219         }
1220     }
1221 }
1222
1223 static void
1224 dissect_swils_drlir (tvbuff_t *tvb _U_, proto_tree *drlir_tree _U_,
1225                      guint8 isreq _U_)
1226 {
1227     /* Set up structures needed to add the protocol subtree and manage it */
1228     return;
1229 }
1230
1231 static void
1232 dissect_swils_swrjt (tvbuff_t *tvb, proto_tree *swrjt_tree)
1233 {
1234     /* Set up structures needed to add the protocol subtree and manage it */
1235     int offset = 0;
1236
1237     if (swrjt_tree) {
1238         proto_tree_add_item (swrjt_tree, hf_swils_rjt, tvb, offset+5, 1, 0);
1239         proto_tree_add_item (swrjt_tree, hf_swils_rjtdet, tvb, offset+6, 1, 0);
1240         proto_tree_add_item (swrjt_tree, hf_swils_rjtvendor, tvb, offset+7,
1241                              1, 0);
1242     }
1243 }
1244
1245 /* Code to actually dissect the packets */
1246 static void
1247 dissect_fcswils (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1248 {
1249     proto_item *ti = NULL;
1250     guint8 opcode,
1251         failed_opcode = 0;
1252     int offset = 0;
1253     conversation_t *conversation;
1254     fcswils_conv_data_t *cdata;
1255     fcswils_conv_key_t ckey, *req_key;
1256     proto_tree *swils_tree = NULL;
1257     guint8 isreq = FC_SWILS_REQ;
1258     tvbuff_t *next_tvb;
1259
1260     /* Make entries in Protocol column and Info column on summary display */
1261     if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
1262         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SW_ILS");
1263
1264     /* decoding of this is done by each individual opcode handler */
1265     opcode = tvb_get_guint8 (tvb, 0);
1266     
1267     if (tree) {
1268         ti = proto_tree_add_protocol_format (tree, proto_fcswils, tvb, 0,
1269                                              tvb_length (tvb), "SW_ILS");
1270         swils_tree = proto_item_add_subtree (ti, ett_fcswils);
1271     }
1272
1273     /* Register conversation if this is not a response */
1274     if ((opcode != FC_SWILS_SWACC) && (opcode != FC_SWILS_SWRJT)) {
1275         conversation = find_conversation (&pinfo->src, &pinfo->dst,
1276                                           pinfo->ptype, pinfo->oxid,
1277                                           pinfo->rxid, NO_PORT2);
1278         if (!conversation) {
1279             conversation = conversation_new (&pinfo->src, &pinfo->dst,
1280                                              pinfo->ptype, pinfo->oxid,
1281                                              pinfo->rxid, NO_PORT2);
1282         }
1283     
1284         ckey.conv_idx = conversation->index;
1285         
1286         cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash,
1287                                                             &ckey);
1288         if (cdata) {
1289             /* Since we never free the memory used by an exchange, this maybe a
1290              * case of another request using the same exchange as a previous
1291              * req. 
1292              */
1293             cdata->opcode = opcode;
1294         }
1295         else {
1296             req_key = g_mem_chunk_alloc (fcswils_req_keys);
1297             req_key->conv_idx = conversation->index;
1298             
1299             cdata = g_mem_chunk_alloc (fcswils_req_vals);
1300             cdata->opcode = opcode;
1301             
1302             g_hash_table_insert (fcswils_req_hash, req_key, cdata);
1303         }
1304     }
1305     else {
1306         /* Opcode is ACC or RJT */
1307         conversation = find_conversation (&pinfo->src, &pinfo->dst,
1308                                           pinfo->ptype, pinfo->oxid,
1309                                           pinfo->rxid, NO_PORT2);
1310         isreq = FC_SWILS_RPLY;
1311         if (!conversation) {
1312             if (tree && (opcode == FC_SWILS_SWACC)) {
1313                 /* No record of what this accept is for. Can't decode */
1314                 proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
1315                                      "No record of Exchg. Unable to decode SW_ACC");
1316                 return;
1317             }
1318         }
1319         else {
1320             ckey.conv_idx = conversation->index;
1321
1322             cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash, &ckey);
1323
1324             if (cdata != NULL) {
1325                 if (opcode == FC_SWILS_SWACC)
1326                     opcode = cdata->opcode;
1327                 else
1328                     failed_opcode = cdata->opcode;
1329             }
1330             
1331             if (tree) {
1332                 if ((cdata == NULL) && (opcode != FC_SWILS_SWRJT)) {
1333                     /* No record of what this accept is for. Can't decode */
1334                     proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
1335                                          "No record of SW_ILS Req. Unable to decode SW_ACC");
1336                     return;
1337                 }
1338             }
1339         }
1340     }
1341
1342     if (check_col (pinfo->cinfo, COL_INFO)) {
1343         if (isreq == FC_SWILS_REQ) {
1344             col_add_str (pinfo->cinfo, COL_INFO,
1345                          val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
1346         }
1347         else if (opcode == FC_SWILS_SWRJT) {
1348             col_add_fstr (pinfo->cinfo, COL_INFO, "SW_RJT (%s)",
1349                           val_to_str (failed_opcode, fc_swils_opcode_key_val, "0x%x"));
1350         }
1351         else {
1352             col_add_fstr (pinfo->cinfo, COL_INFO, "SW_ACC (%s)",
1353                           val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
1354         }
1355     }
1356
1357     if (tree) {
1358         proto_tree_add_item (swils_tree, hf_swils_opcode, tvb, offset, 1, 0);
1359     }
1360
1361     switch (opcode) {
1362     case FC_SWILS_SWRJT:
1363         dissect_swils_swrjt (tvb, swils_tree);
1364         break;
1365     case FC_SWILS_ELP:
1366         dissect_swils_elp (tvb, swils_tree, isreq);
1367         break;
1368     case FC_SWILS_EFP:
1369         dissect_swils_efp (tvb, swils_tree, isreq);
1370         break;
1371     case FC_SWILS_DIA:
1372         dissect_swils_dia (tvb, swils_tree, isreq);
1373         break;
1374     case FC_SWILS_RDI:
1375         dissect_swils_rdi (tvb, swils_tree, isreq);
1376         break;
1377     case FC_SWILS_HLO:
1378         dissect_swils_hello (tvb, swils_tree, isreq);
1379         break;
1380     case FC_SWILS_LSU:
1381         dissect_swils_lsupdate (tvb, swils_tree, isreq);
1382         break;
1383     case FC_SWILS_LSA:
1384         dissect_swils_lsack (tvb, swils_tree, isreq);
1385         break;
1386     case FC_SWILS_BF:
1387     case FC_SWILS_RCF:
1388         /* Nothing to be displayed for these two commands */
1389         break;
1390     case FC_SWILS_RSCN:
1391         dissect_swils_rscn (tvb, swils_tree, isreq);
1392         break;
1393     case FC_SWILS_DRLIR:
1394         dissect_swils_drlir (tvb, swils_tree, isreq);
1395         break;
1396     case FC_SWILS_MR:
1397         dissect_swils_mergereq (tvb, swils_tree, isreq);
1398         break;
1399     case FC_SWILS_ACA:
1400         dissect_swils_aca (tvb, swils_tree, isreq);
1401         break;
1402     case FC_SWILS_RCA:
1403         dissect_swils_rca (tvb, swils_tree, isreq);
1404         break;
1405     case FC_SWILS_SFC:
1406         dissect_swils_sfc (tvb, swils_tree, isreq);
1407         break;
1408     case FC_SWILS_UFC:
1409         dissect_swils_ufc (tvb, swils_tree, isreq);
1410         break;
1411     case FC_SWILS_ESC:
1412         dissect_swils_esc (tvb, swils_tree, isreq);
1413         break;
1414     default:
1415         next_tvb = tvb_new_subset (tvb, offset+4, -1, -1);
1416         call_dissector (data_handle, next_tvb, pinfo, tree);
1417     }
1418
1419 }
1420
1421 /* Register the protocol with Ethereal */
1422
1423 /* this format is require because a script is used to build the C function
1424    that calls all the protocol registration.
1425 */
1426
1427 void
1428 proto_register_fcswils (void)
1429 {
1430 /* Setup list of header fields  See Section 1.6.1 for details*/
1431     static hf_register_info hf[] = {
1432         { &hf_swils_opcode,
1433           {"Cmd Code", "swils.opcode", FT_UINT8, BASE_HEX,
1434            VALS (fc_swils_opcode_key_val), 0x0, "", HFILL}},
1435         { &hf_swils_elp_rev,
1436           {"Revision", "swils.elp.rev", FT_UINT8, BASE_DEC, NULL,
1437            0x0, "", HFILL}},
1438         { &hf_swils_elp_flags,
1439           {"Flag", "swils.elp.flag", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL}},
1440         { &hf_swils_elp_r_a_tov,
1441           {"R_A_TOV", "swils.elp.ratov", FT_UINT32, BASE_DEC, NULL,
1442            0x0, "", HFILL}},
1443         { &hf_swils_elp_e_d_tov,
1444           {"E_D_TOV", "swils.elp.edtov", FT_UINT32, BASE_DEC, NULL, 0x0, "",
1445            HFILL}},
1446         { &hf_swils_elp_req_epn,
1447           {"Req Eport Name", "swils.elp.reqepn", FT_STRING, BASE_HEX, NULL, 0x0,
1448            "", HFILL}},
1449         { &hf_swils_elp_req_esn,
1450           {"Req Switch Name", "swils.elp.reqesn", FT_STRING, BASE_HEX, NULL, 0x0,
1451            "", HFILL}},
1452         { &hf_swils_elp_clsf_svcp,
1453           {"Class F Svc Param", "swils.elp.clsfp", FT_BYTES, BASE_NONE, NULL, 0x0,
1454            "", HFILL}},
1455         { &hf_swils_elp_clsf_rcvsz,
1456           {"Max Class F Frame Size", "swils.elp.clsfrsz", FT_UINT16, BASE_DEC,
1457            NULL, 0x0, "", HFILL}},
1458         { &hf_swils_elp_clsf_conseq,
1459           {"Class F Max Concurrent Seq", "swils.elp.clsfcs", FT_UINT16, BASE_DEC,
1460            NULL, 0x0, "", HFILL}},
1461         { &hf_swils_elp_clsf_e2e,
1462           {"Class F E2E Credit", "swils.elp.cfe2e", FT_UINT16, BASE_DEC, NULL,
1463            0x0, "", HFILL}},
1464         { &hf_swils_elp_clsf_openseq,
1465           {"Class F Max Open Seq", "swils.elp.oseq", FT_UINT16, BASE_DEC, NULL,
1466            0x0, "", HFILL}},
1467         { &hf_swils_elp_cls1_svcp,
1468           {"Class 1 Svc Param", "swils.elp.cls1p", FT_BYTES, BASE_NONE, NULL, 0x0,
1469            "", HFILL}},
1470         { &hf_swils_elp_cls1_rcvsz,
1471           {"Class 1 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
1472            0x0, "", HFILL}},
1473         { &hf_swils_elp_cls2_svcp,
1474           {"Class 2 Svc Param", "swils.elp.cls2p", FT_BYTES, BASE_HEX, NULL, 0x0,
1475            "", HFILL}},
1476         { &hf_swils_elp_cls2_rcvsz,
1477           {"Class 2 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
1478            0x0, "", HFILL}},
1479         { &hf_swils_elp_cls3_svcp,
1480           {"Class 3 Svc Param", "swils.elp.cls3p", FT_BYTES, BASE_HEX, NULL, 0x0,
1481            "", HFILL}},
1482         { &hf_swils_elp_cls3_rcvsz,
1483           {"Class 3 Frame Size", "swils.elp.cls1rsz", FT_UINT16, BASE_DEC, NULL,
1484            0x0, "", HFILL}},
1485         { &hf_swils_elp_isl_fc_mode,
1486           {"ISL Flow Ctrl Mode", "swils.elp.fcmode", FT_STRING, BASE_HEX, NULL,
1487            0x0, "", HFILL}},
1488         { &hf_swils_elp_fcplen,
1489           {"Flow Ctrl Param Len", "swils.elp.fcplen", FT_UINT16, BASE_DEC, NULL,
1490            0x0, "", HFILL}},
1491         { &hf_swils_elp_b2bcredit,
1492           {"B2B Credit", "swils.elp.b2b", FT_UINT32, BASE_DEC, NULL, 0x0, "",
1493            HFILL}},
1494         { &hf_swils_elp_compat1,
1495           {"Compatability Param 1", "swils.elp.compat1", FT_UINT32, BASE_DEC, NULL,
1496            0x0, "", HFILL}},
1497         { &hf_swils_elp_compat2,
1498           {"Compatability Param 2", "swils.elp.compat2", FT_UINT32, BASE_DEC, NULL,
1499            0x0, "", HFILL}},
1500         { &hf_swils_elp_compat3,
1501           {"Compatability Param 3", "swils.elp.compat3", FT_UINT32, BASE_DEC, NULL,
1502            0x0, "", HFILL}},
1503         { &hf_swils_elp_compat4,
1504           {"Compatability Param 4", "swils.elp.compat4", FT_UINT32, BASE_DEC, NULL,
1505            0x0, "", HFILL}},
1506         { &hf_swils_efp_rec_type,
1507           {"Record Type", "swils.efp.rectype", FT_UINT8, BASE_HEX,
1508            VALS (fcswils_rectype_val), 0x0, "", HFILL}},
1509         { &hf_swils_efp_dom_id,
1510           {"Domain ID", "swils.efp.domid", FT_UINT8, BASE_HEX, NULL, 0x0,
1511            "", HFILL}},
1512         { &hf_swils_efp_switch_name,
1513           {"Switch Name", "swils.efp.sname", FT_STRING, BASE_HEX, NULL, 0x0,
1514            "", HFILL}},
1515         { &hf_swils_efp_mcast_grpno,
1516           {"Mcast Grp#", "swils.efp.mcastno", FT_UINT8, BASE_HEX, NULL, 0x0,
1517            "", HFILL}},
1518         { &hf_swils_efp_alias_token,
1519           {"Alias Token", "swils.efp.aliastok", FT_BYTES, BASE_HEX, NULL, 0x0,
1520            "", HFILL}},
1521         { &hf_swils_efp_payload_len,
1522           {"Payload Len", "swils.efp.payloadlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1523            "", HFILL}},
1524         { &hf_swils_efp_pswitch_pri,
1525           {"Principal Switch Priority", "swils.efp.psprio", FT_UINT8, BASE_DEC,
1526            NULL, 0x0, "", HFILL}},
1527         { &hf_swils_efp_pswitch_name,
1528           {"Principal Switch Name", "swils.efp.psname", FT_STRING, BASE_HEX, NULL,
1529            0x0, "", HFILL}},
1530         { &hf_swils_dia_switch_name,
1531           {"Switch Name", "swils.dia.sname", FT_STRING, BASE_HEX, NULL, 0x0,
1532            "", HFILL}},
1533         { &hf_swils_rdi_payload_len,
1534           {"Payload Len", "swils.rdi.len", FT_UINT16, BASE_DEC, NULL, 0x0, "",
1535            HFILL}},
1536         { &hf_swils_rdi_req_sname,
1537           {"Req Switch Name", "swils.rdi.reqsn", FT_STRING, BASE_HEX, NULL, 0x0,
1538            "", HFILL}},
1539         { &hf_swils_fspfh_cmd,
1540           {"Command: ", "swils.fspf.cmd", FT_UINT8, BASE_HEX, NULL, 0x0,
1541            "", HFILL}},
1542         { &hf_swils_fspfh_rev,
1543           {"Version", "swils.fspf.ver", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL}},
1544         { &hf_swils_fspfh_ar_num,
1545           {"AR Number", "swils.fspf.arnum", FT_UINT8, BASE_HEX, NULL, 0x0, "",
1546            HFILL}},
1547         { &hf_swils_fspfh_auth_type,
1548           {"Authentication Type", "swils.fspf.authtype", FT_UINT8, BASE_HEX, NULL,
1549            0x0, "", HFILL}},
1550         { &hf_swils_fspfh_dom_id,
1551           {"Originating Domain ID", "swils.fspf.origdomid", FT_UINT8, BASE_DEC,
1552            NULL, 0x0, "", HFILL}},
1553         { &hf_swils_fspfh_auth,
1554           {"Authentication", "swils.fspf.auth", FT_BYTES, BASE_HEX, NULL, 0x0,
1555            "", HFILL}},
1556         { &hf_swils_hlo_options,
1557           {"Options", "swils.hlo.options", FT_BYTES, BASE_HEX, NULL, 0x0,
1558            "", HFILL}},
1559         { &hf_swils_hlo_hloint,
1560           {"Hello Interval (secs)", "swils.hlo.hloint", FT_UINT32, BASE_DEC,
1561            NULL, 0x0, "", HFILL}},
1562         { &hf_swils_hlo_deadint,
1563           {"Dead Interval (secs)", "swils.hlo.deadint", FT_UINT32, BASE_DEC,
1564            NULL, 0x0, "", HFILL}},
1565         { &hf_swils_hlo_rcv_domid,
1566           {"Recipient Domain ID", "swils.hlo.rcvdomid", FT_UINT8, BASE_DEC,
1567            NULL, 0x0, "", HFILL}},
1568         { &hf_swils_hlo_orig_pidx,
1569           {"Originating Port Idx", "swils.hlo.origpidx", FT_UINT24, BASE_HEX,
1570            NULL, 0x0, "", HFILL}},
1571         { &hf_swils_lsrh_lsr_type,
1572           {"LSR Type", "swils.lsr.type", FT_UINT8, BASE_HEX,
1573            VALS (fc_swils_fspf_linkrec_val), 0x0, "", HFILL}},
1574         { &hf_swils_lsrh_lsid,
1575           {"Link State Id", "swils.ls.id", FT_UINT8, BASE_DEC, NULL, 0x0,
1576            "", HFILL}},
1577         { &hf_swils_lsrh_adv_domid,
1578           {"Advertising Domain Id", "swils.lsr.advdomid", FT_UINT8, BASE_DEC,
1579            NULL, 0x0, "", HFILL}},
1580         { &hf_swils_lsrh_ls_incid,
1581           {"LS Incarnation Number", "swils.lsr.incid", FT_UINT32, BASE_DEC,
1582            NULL, 0x0, "", HFILL}},
1583         { &hf_swils_ldrec_linkid,
1584           {"Link ID", "swils.ldr.linkid", FT_STRING, BASE_HEX, NULL, 0x0,
1585            "", HFILL}},
1586         { &hf_swils_ldrec_out_pidx,
1587           {"Output Port Idx", "swils.ldr.out_portidx", FT_UINT24, BASE_HEX, NULL,
1588            0x0, "", HFILL}},
1589         { &hf_swils_ldrec_nbr_pidx,
1590           {"Neighbor Port Idx", "swils.ldr.nbr_portidx", FT_UINT24, BASE_HEX,
1591            NULL, 0x0, "", HFILL}},
1592         { &hf_swils_ldrec_link_type,
1593           {"Link Type", "swils.ldr.linktype", FT_UINT8, BASE_HEX,
1594            VALS (fc_swils_link_type_val), 0x0, "", HFILL}},
1595         { &hf_swils_ldrec_link_cost,
1596           {"Link Cost", "swils.ldr.linkcost", FT_UINT16, BASE_DEC, NULL, 0x0,
1597            "", HFILL}},
1598         { &hf_swils_rscn_evtype,
1599           {"Event Type", "swils.rscn.evtype", FT_UINT8, BASE_DEC,
1600            VALS (fc_swils_rscn_portstate_val), 0xF0, "", HFILL}},
1601         { &hf_swils_rscn_addrfmt,
1602           {"Address Format", "swils.rscn.addrfmt", FT_UINT8, BASE_DEC, 
1603            VALS (fc_swils_rscn_addrfmt_val), 0x0F, "", HFILL}},
1604         { &hf_swils_rscn_affectedport,
1605           {"Affected Port ID", "swils.rscn.affectedport", FT_STRING, BASE_HEX,
1606            NULL, 0x0, "", HFILL}},
1607         { &hf_swils_rscn_detectfn,
1608           {"Detection Function", "swils.rscn.detectfn", FT_UINT32, BASE_HEX,
1609            VALS (fc_swils_rscn_detectfn_val), 0x0, "", HFILL}},
1610         { &hf_swils_rscn_portstate,
1611           {"Port State", "swils.rscn.portstate", FT_UINT8, BASE_HEX, NULL, 0x0,
1612            "", HFILL}},
1613         { &hf_swils_rscn_portid,
1614           {"Port Id", "swils.rscn.portid", FT_STRING, BASE_HEX, NULL, 0x0, "",
1615            HFILL}},
1616         { &hf_swils_rscn_pwwn,
1617           {"Port WWN", "swils.rscn.pwwn", FT_STRING, BASE_HEX, NULL, 0x0, "",
1618            HFILL}},
1619         { &hf_swils_rscn_nwwn,
1620           {"Node WWN", "swils.rscn.nwwn", FT_STRING, BASE_HEX, NULL, 0x0, "",
1621            HFILL}},
1622         { &hf_swils_esc_swvendorid,
1623           {"Switch Vendor ID", "swils.esc.swvendor", FT_STRING, BASE_HEX, NULL,
1624            0x0, "", HFILL}},
1625         { &hf_swils_esc_pdesc_vendorid,
1626           {"Vendor ID", "swils.esc.vendorid", FT_STRING, BASE_HEX, NULL, 0x0,
1627            "", HFILL}},
1628         { &hf_swils_esc_protocolid,
1629           {"Protocol ID", "swils.esc.protocol", FT_UINT16, BASE_HEX,
1630            VALS (fc_swils_esc_protocol_val), 0x0, "", HFILL}},
1631         { &hf_swils_zone_activezonenm,
1632           {"Active Zoneset Name", "swils.mr.activezonesetname", FT_STRING,
1633            BASE_HEX, NULL, 0x0, "", HFILL}},
1634         { &hf_swils_zone_objname,
1635           {"Zone Object Name", "swils.zone.zoneobjname", FT_STRING, BASE_HEX,
1636            NULL, 0x0, "", HFILL}},
1637         { &hf_swils_zone_objtype,
1638           {"Zone Object Type", "swils.zone.zoneobjtype", FT_UINT8, BASE_HEX,
1639            VALS (fc_swils_zoneobj_type_val), 0x0, "", HFILL}},
1640         { &hf_swils_zone_mbrtype,
1641           {"Zone Member Type", "swils.zone.mbrtype", FT_UINT8, BASE_HEX,
1642            VALS (fc_swils_zonembr_type_val), 0x0, "", HFILL}},
1643         { &hf_swils_zone_protocol,
1644           {"Zone Protocol", "swils.zone.protocol", FT_UINT8, BASE_HEX, NULL,
1645            0x0, "", HFILL}},
1646         { &hf_swils_zone_mbrid,
1647           {"Member Identifier", "swils.zone.mbrid", FT_STRING, BASE_HEX, NULL,
1648            0x0, "", HFILL}},
1649         { &hf_swils_zone_status,
1650           {"Zone Command Status", "swils.zone.status", FT_UINT8, BASE_HEX,
1651            VALS (fc_swils_mr_rsp_val), 0x0, "Applies to MR, ACA, RCA, SFC, UFC",
1652            HFILL}},
1653         { &hf_swils_zone_reason,
1654           {"Zone Command Reason Code", "swils.zone.reason", FT_UINT8, BASE_HEX,
1655            VALS (fc_swils_mr_reason_val), 0x0, "Applies to MR, ACA, RCA, SFC, UFC",
1656            HFILL}},
1657         { &hf_swils_aca_domainid,
1658           {"Known Domain ID", "swils.aca.domainid", FT_UINT8, BASE_HEX, NULL,
1659            0x0, "", HFILL}},
1660         { &hf_swils_sfc_opcode,
1661           {"Operation Request", "swils.sfc.opcode", FT_UINT8, BASE_HEX,
1662            VALS (fc_swils_sfc_op_val), 0x0, "", HFILL}},
1663         { &hf_swils_sfc_zonenm,
1664           {"Zone Set Name", "swils.sfc.zonename", FT_STRING, BASE_HEX, NULL,
1665            0x0, "", HFILL}},
1666         { &hf_swils_rjt,
1667           {"Reason Code", "swils.rjt.reason", FT_UINT8, BASE_HEX,
1668            VALS (fc_swils_rjt_val), 0x0, "", HFILL}},
1669         { &hf_swils_rjtdet,
1670           {"Reason Code Explanantion", "swils.rjt.reasonexpl", FT_UINT8,
1671            BASE_HEX, VALS (fc_swils_deterr_val), 0x0, "", HFILL}},
1672         { &hf_swils_rjtvendor,
1673           {"Vendor Unique Error Code", "swils.rjt.vendor", FT_UINT8, BASE_HEX,
1674            NULL, 0x0, "", HFILL}},
1675         { &hf_swils_zone_mbrid_lun,
1676           {"LUN", "swils.zone.lun", FT_BYTES, BASE_HEX, NULL, 0x0, "",
1677            HFILL}},
1678     };
1679
1680     /* Setup protocol subtree array */
1681     static gint *ett[] = {
1682         &ett_fcswils,
1683         &ett_fcswils_swacc,
1684         &ett_fcswils_swrjt,
1685         &ett_fcswils_elp,
1686         &ett_fcswils_efp,
1687         &ett_fcswils_efplist,
1688         &ett_fcswils_dia,
1689         &ett_fcswils_rdi,
1690         &ett_fcswils_fspfhdr,
1691         &ett_fcswils_hlo,
1692         &ett_fcswils_lsrec,
1693         &ett_fcswils_lsrechdr,
1694         &ett_fcswils_ldrec,
1695         &ett_fcswils_lsu,
1696         &ett_fcswils_lsa,
1697         &ett_fcswils_bf,
1698         &ett_fcswils_rcf,
1699         &ett_fcswils_rscn,
1700         &ett_fcswils_rscn_dev,
1701         &ett_fcswils_drlir,
1702         &ett_fcswils_mr,
1703         &ett_fcswils_zoneobjlist,
1704         &ett_fcswils_zoneobj,
1705         &ett_fcswils_zonembr,
1706         &ett_fcswils_aca,
1707         &ett_fcswils_rca,
1708         &ett_fcswils_sfc,
1709         &ett_fcswils_ufc,
1710         &ett_fcswils_esc,
1711         &ett_fcswils_esc_pdesc,
1712     };
1713
1714     /* Register the protocol name and description */
1715     proto_fcswils = proto_register_protocol("Fibre Channel SW_ILS", "FC-SWILS", "swils");
1716
1717     /* Required function calls to register the header fields and subtrees used */
1718     proto_register_field_array(proto_fcswils, hf, array_length(hf));
1719     proto_register_subtree_array(ett, array_length(ett));
1720     register_init_routine(&fcswils_init_protocol);
1721 }
1722
1723 /* If this dissector uses sub-dissector registration add a registration routine.
1724    This format is required because a script is used to find these routines and
1725    create the code that calls these routines.
1726 */
1727 void
1728 proto_reg_handoff_fcswils (void)
1729 {
1730     dissector_handle_t swils_handle;
1731
1732     swils_handle = create_dissector_handle (dissect_fcswils, proto_fcswils);
1733     dissector_add("fc.ftype", FC_FTYPE_SWILS, swils_handle);
1734
1735     data_handle = find_dissector ("data");
1736 }
1737
1738