Use tvb_fc_to_str() and tvb_fcwwm_to_str().
[metze/wireshark/wip.git] / epan / dissectors / 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$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
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.
20  *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdlib.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>
38 #endif
39
40 #include <glib.h>
41
42 #include <epan/packet.h>
43 #include <epan/emem.h>
44 #include <epan/conversation.h>
45 #include <epan/etypes.h>
46 #include "packet-scsi.h"
47 #include "packet-fc.h"
48 #include "packet-fcswils.h"
49 #include "packet-fcct.h"
50
51 /*
52  * See the FC-SW specifications.
53  */
54
55 #define FC_SWILS_RPLY               0x0
56 #define FC_SWILS_REQ                0x1
57 #define FC_SWILS_RSCN_DEVENTRY_SIZE 20
58
59 /* Zone name has the structure:
60  * name_len (1 byte), rsvd (3 bytes), name (m bytes), fill (n bytes)
61  * name_len excludes the 4 initial bytes before the name
62  */
63 #define ZONENAME_LEN(x, y)  (tvb_get_guint8(x, y)+4)
64
65 /* Initialize the protocol and registered fields */
66 static int proto_fcswils                  = -1;
67 static int hf_swils_opcode                = -1;
68 static int hf_swils_elp_rev               = -1;
69 static int hf_swils_elp_flags             = -1;
70 static int hf_swils_elp_r_a_tov           = -1;
71 static int hf_swils_elp_e_d_tov           = -1;
72 static int hf_swils_elp_req_epn           = -1;
73 static int hf_swils_elp_req_esn           = -1;
74 static int hf_swils_elp_clsf_svcp         = -1;
75 static int hf_swils_elp_clsf_rcvsz        = -1;
76 static int hf_swils_elp_clsf_conseq       = -1;
77 static int hf_swils_elp_clsf_e2e          = -1;
78 static int hf_swils_elp_clsf_openseq      = -1;
79 static int hf_swils_elp_cls1_svcp         = -1;
80 static int hf_swils_elp_cls1_rcvsz        = -1;
81 static int hf_swils_elp_cls2_svcp         = -1;
82 static int hf_swils_elp_cls2_rcvsz        = -1;
83 static int hf_swils_elp_cls3_svcp         = -1;
84 static int hf_swils_elp_cls3_rcvsz        = -1;
85 static int hf_swils_elp_isl_fc_mode       = -1;
86 static int hf_swils_elp_fcplen            = -1;
87 static int hf_swils_elp_b2bcredit         = -1;
88 static int hf_swils_elp_compat1           = -1;
89 static int hf_swils_elp_compat2           = -1;
90 static int hf_swils_elp_compat3           = -1;
91 static int hf_swils_elp_compat4           = -1;
92 static int hf_swils_efp_rec_type          = -1;
93 static int hf_swils_efp_dom_id            = -1;
94 static int hf_swils_efp_switch_name       = -1;
95 static int hf_swils_efp_mcast_grpno       = -1;
96 static int hf_swils_efp_alias_token       = -1;
97 static int hf_swils_efp_record_len        = -1;
98 static int hf_swils_efp_payload_len       = -1;
99 static int hf_swils_efp_pswitch_pri       = -1;
100 static int hf_swils_efp_pswitch_name      = -1;
101 static int hf_swils_dia_switch_name       = -1;
102 static int hf_swils_rdi_payload_len       = -1;
103 static int hf_swils_rdi_req_sname         = -1;
104 static int hf_swils_fspfh_cmd             = -1;
105 static int hf_swils_fspfh_rev             = -1;
106 static int hf_swils_fspfh_ar_num          = -1;
107 static int hf_swils_fspfh_auth_type       = -1;
108 static int hf_swils_fspfh_dom_id          = -1;
109 static int hf_swils_fspfh_auth            = -1;
110 static int hf_swils_hlo_options           = -1;
111 static int hf_swils_hlo_hloint            = -1;
112 static int hf_swils_hlo_deadint           = -1;
113 static int hf_swils_hlo_rcv_domid         = -1;
114 static int hf_swils_hlo_orig_pidx         = -1;
115 static int hf_swils_ldrec_linkid          = -1;
116 static int hf_swils_ldrec_out_pidx        = -1;
117 static int hf_swils_ldrec_nbr_pidx        = -1;
118 static int hf_swils_ldrec_link_type       = -1;
119 static int hf_swils_ldrec_link_cost       = -1;
120 static int hf_swils_lsrh_lsr_type         = -1;
121 static int hf_swils_lsrh_lsid             = -1;
122 static int hf_swils_lsrh_adv_domid        = -1;
123 static int hf_swils_lsrh_ls_incid         = -1;
124 static int hf_swils_esc_pdesc_vendorid    = -1;
125 static int hf_swils_esc_swvendorid        = -1;
126 static int hf_swils_esc_protocolid        = -1;
127 static int hf_swils_rscn_evtype           = -1;
128 static int hf_swils_rscn_addrfmt          = -1;
129 static int hf_swils_rscn_detectfn         = -1;
130 static int hf_swils_rscn_affectedport     = -1;
131 static int hf_swils_rscn_portstate        = -1;
132 static int hf_swils_rscn_portid           = -1;
133 static int hf_swils_rscn_pwwn             = -1;
134 static int hf_swils_rscn_nwwn             = -1;
135 static int hf_swils_zone_activezonenm     = -1;
136 static int hf_swils_zone_objname          = -1;
137 static int hf_swils_zone_objtype          = -1;
138 static int hf_swils_zone_mbrtype          = -1;
139 static int hf_swils_zone_protocol         = -1;
140 static int hf_swils_zone_mbrid            = -1;
141 static int hf_swils_zone_status           = -1;
142 static int hf_swils_zone_reason           = -1;
143 static int hf_swils_aca_domainid          = -1;
144 static int hf_swils_sfc_opcode            = -1;
145 static int hf_swils_sfc_zonenm            = -1;
146 static int hf_swils_rjt                   = -1;
147 static int hf_swils_rjtdet                = -1;
148 static int hf_swils_rjtvendor             = -1;
149 static int hf_swils_zone_mbrid_lun        = -1;
150 static int hf_swils_ess_rev               = -1;
151 static int hf_swils_ess_len               = -1;
152 static int hf_swils_ess_numobj            = -1;
153 static int hf_swils_interconnect_list_len = -1;
154 static int hf_swils_ess_vendorname        = -1;
155 static int hf_swils_ess_modelname         = -1;
156 static int hf_swils_ess_relcode           = -1;
157 static int hf_swils_ess_vendorspecific    = -1;
158 static int hf_swils_ess_cap_type          = -1;
159 static int hf_swils_ess_cap_subtype       = -1;
160 static int hf_swils_ess_cap_numentries    = -1;
161 static int hf_swils_ess_cap_svc           = -1;
162 static int hf_swils_ess_dns_obj0h         = -1;
163 static int hf_swils_ess_dns_obj1h         = -1;
164 static int hf_swils_ess_dns_obj2h         = -1;
165 static int hf_swils_ess_dns_obj3h         = -1;
166 static int hf_swils_ess_dns_zlacc         = -1;
167 static int hf_swils_ess_dns_vendor        = -1;
168 static int hf_swils_ess_fctlr_rscn        = -1;
169 static int hf_swils_ess_fctlr_vendor      = -1;
170 static int hf_swils_ess_fcs_basic         = -1;
171 static int hf_swils_ess_fcs_platform      = -1;
172 static int hf_swils_ess_fcs_topology      = -1;
173 static int hf_swils_ess_fcs_enhanced      = -1;
174 static int hf_swils_ess_fzs_enh_supp      = -1;
175 static int hf_swils_ess_fzs_enh_ena       = -1;
176 static int hf_swils_ess_fzs_mr            = -1;
177 static int hf_swils_ess_fzs_zsdb_supp     = -1;
178 static int hf_swils_ess_fzs_zsdb_ena      = -1;
179 static int hf_swils_ess_fzs_adc_supp      = -1;
180 static int hf_swils_ess_fzs_hardzone      = -1;
181 static int hf_swils_mrra_rev              = -1;
182 static int hf_swils_mrra_size             = -1;
183 static int hf_swils_mrra_vendorid         = -1;
184 static int hf_swils_mrra_reply            = -1;
185 static int hf_swils_mrra_reply_size       = -1;
186 static int hf_swils_mrra_waittime         = -1;
187 static int hf_swils_ess_cap_t10           = -1;
188 static int hf_swils_ess_cap_vendorobj     = -1;
189 static int hf_swils_ess_fzs_defzone       = -1;
190 static int hf_swils_ess_cap_len           = -1;
191 static int hf_swils_mrra_vendorinfo       = -1;
192
193
194 /* Initialize the subtree pointers */
195 static gint ett_fcswils             = -1;
196 static gint ett_fcswils_swacc       = -1;
197 static gint ett_fcswils_swrjt       = -1;
198 static gint ett_fcswils_elp         = -1;
199 static gint ett_fcswils_efp         = -1;
200 static gint ett_fcswils_efplist     = -1;
201 static gint ett_fcswils_dia         = -1;
202 static gint ett_fcswils_rdi         = -1;
203 static gint ett_fcswils_fspfhdr     = -1;
204 static gint ett_fcswils_hlo         = -1;
205 static gint ett_fcswils_lsrec       = -1;
206 static gint ett_fcswils_lsrechdr    = -1;
207 static gint ett_fcswils_ldrec       = -1;
208 static gint ett_fcswils_lsu         = -1;
209 static gint ett_fcswils_lsa         = -1;
210 static gint ett_fcswils_bf          = -1;
211 static gint ett_fcswils_rcf         = -1;
212 static gint ett_fcswils_rscn        = -1;
213 static gint ett_fcswils_rscn_dev    = -1;
214 static gint ett_fcswils_drlir       = -1;
215 static gint ett_fcswils_mr          = -1;
216 static gint ett_fcswils_zoneobjlist = -1;
217 static gint ett_fcswils_zoneobj     = -1;
218 static gint ett_fcswils_zonembr     = -1;
219 static gint ett_fcswils_aca         = -1;
220 static gint ett_fcswils_rca         = -1;
221 static gint ett_fcswils_sfc         = -1;
222 static gint ett_fcswils_ufc         = -1;
223 static gint ett_fcswils_esc         = -1;
224 static gint ett_fcswils_esc_pdesc   = -1;
225 static gint ett_fcswils_ieinfo      = -1;
226 static gint ett_fcswils_capinfo     = -1;
227
228 static const value_string fc_swils_opcode_key_val[] = {
229     {FC_SWILS_SWRJT  , "SW_RJT"},
230     {FC_SWILS_SWACC  , "SW_ACC"},
231     {FC_SWILS_ELP    , "ELP"},
232     {FC_SWILS_EFP    , "EFP"},
233     {FC_SWILS_DIA    , "DIA"},
234     {FC_SWILS_RDI    , "RDI"},
235     {FC_SWILS_HLO    , "HLO"},
236     {FC_SWILS_LSU    , "LSU"},
237     {FC_SWILS_LSA    , "LSA"},
238     {FC_SWILS_BF     , "BF"},
239     {FC_SWILS_RCF    , "RCF"},
240     {FC_SWILS_RSCN   , "SW_RSCN"},
241     {FC_SWILS_DRLIR  , "DRLIR"},
242     {FC_SWILS_DSCN   , "DSCN"},
243     {FC_SWILS_LOOPD  , "LOOPD"},
244     {FC_SWILS_MR     , "MR"},
245     {FC_SWILS_ACA    , "ACA"},
246     {FC_SWILS_RCA    , "RCA"},
247     {FC_SWILS_SFC    , "SFC"},
248     {FC_SWILS_UFC    , "UFC"},
249     {FC_SWILS_ESC    , "ESC"},
250     {FC_SWILS_ESS    , "ESS"},
251     {FC_SWILS_MRRA   , "MRRA"},
252     {FC_SWILS_AUTH_ILS, "AUTH_ILS"},
253     {0, NULL},
254 };
255
256 static const value_string fc_swils_rjt_val [] = {
257     {FC_SWILS_RJT_INVCODE   , "Invalid Cmd Code"},
258     {FC_SWILS_RJT_INVVER    , "Invalid Revision"},
259     {FC_SWILS_RJT_LOGERR    , "Logical Error"},
260     {FC_SWILS_RJT_INVSIZE   , "Invalid Size"},
261     {FC_SWILS_RJT_LOGBSY    , "Logical Busy"},
262     {FC_SWILS_RJT_PROTERR   , "Protocol Error"},
263     {FC_SWILS_RJT_GENFAIL   , "Unable to Perform"},
264     {FC_SWILS_RJT_CMDNOTSUPP, "Unsupported Cmd"},
265     {FC_SWILS_RJT_VENDUNIQ  , "Vendor Unique Err"},
266     {0, NULL},
267 };
268
269 static const value_string fc_swils_deterr_val [] = {
270     {FC_SWILS_RJT_NODET ,      "No Additional Details"},
271     {FC_SWILS_RJT_CLSF_ERR ,   "Class F Svc Param Err"},
272     {FC_SWILS_RJT_CLSN_ERR ,   "Class N Svc Param Err"},
273     {FC_SWILS_RJT_INVFC_CODE , "Unknown Flow Ctrl Code"},
274     {FC_SWILS_RJT_INVFC_PARM , "Invalid Flow Ctrl Parm"},
275     {FC_SWILS_RJT_INV_PNAME ,  "Invalid Port Name"},
276     {FC_SWILS_RJT_INV_SNAME ,  "Invalid Switch Name"},
277     {FC_SWILS_RJT_TOV_MSMTCH , "R_A_/E_D_TOV Mismatch"},
278     {FC_SWILS_RJT_INV_DIDLST,  "Invalid Domain ID List"},
279     {FC_SWILS_RJT_CMD_INPROG , "Cmd Already in Progress"},
280     {FC_SWILS_RJT_OORSRC ,     "Insufficient Resources"},
281     {FC_SWILS_RJT_NO_DID ,     "Domain ID Unavailable"},
282     {FC_SWILS_RJT_INV_DID,     "Invalid Domain ID"},
283     {FC_SWILS_RJT_NO_REQ ,     "Request Not Supported"},
284     {FC_SWILS_RJT_NOLNK_PARM , "Link Parm Not Estd."},
285     {FC_SWILS_RJT_NO_REQDID ,  "Group of Domain IDs Unavail"},
286     {FC_SWILS_RJT_EP_ISOL ,    "E_Port Isolated"},
287     {0, NULL}
288 };
289
290 static const value_string fcswils_elp_fc_val[] = {
291     {FC_SWILS_ELP_FC_VENDOR, "Vendor Unique"},
292     {FC_SWILS_ELP_FC_RRDY,   "R_RDY Flow Ctrl"},
293     {0, NULL},
294 };
295
296 static const value_string fcswils_rectype_val[] = {
297     {FC_SWILS_LRECTYPE_DOMAIN, "Domain ID Record"},
298     {FC_SWILS_LRECTYPE_MCAST, "Multicast ID Record"},
299     {0, NULL},
300 };
301
302 static const value_string fc_swils_link_type_val[] = {
303     {0x01, "P2P Link"},
304     {0xF0, "Vendor Specific"},
305     {0xF1, "Vendor Specific"},
306     {0xF2, "Vendor Specific"},
307     {0xF3, "Vendor Specific"},
308     {0xF4, "Vendor Specific"},
309     {0xF5, "Vendor Specific"},
310     {0xF6, "Vendor Specific"},
311     {0xF7, "Vendor Specific"},
312     {0xF8, "Vendor Specific"},
313     {0xF9, "Vendor Specific"},
314     {0xFA, "Vendor Specific"},
315     {0xFB, "Vendor Specific"},
316     {0xFC, "Vendor Specific"},
317     {0xFD, "Vendor Specific"},
318     {0xFE, "Vendor Specific"},
319     {0xFF, "Vendor Specific"},
320     {0, NULL},
321 };
322
323 static const value_string fc_swils_fspf_linkrec_val[] = {
324     {FC_SWILS_LSR_SLR, "Switch Link Record"},
325     {FC_SWILS_LSR_ARS, "AR Summary Record"},
326     {0, NULL},
327 };
328
329 static const value_string fc_swils_fspf_lsrflags_val[] = {
330     {0x0, "LSR is for a Topology Update"},
331     {0x1, "LSR is for Initial DB Sync | Not the last seq in DB sync"},
332     {0x2, "Last Seq in DB Sync. LSU has no LSRs"},
333     {0x3, "LSR is for Initial DB Sync | Last Seq in DB Sync"},
334     {0, NULL},
335 };
336
337 static const value_string fc_swils_rscn_portstate_val[] = {
338     {0, "No Additional Info"},
339     {1, "Port is online"},
340     {2, "Port is offline"},
341     {0, NULL},
342 };
343
344 static const value_string fc_swils_rscn_addrfmt_val[] = {
345     {0, "Port Addr Format"},
346     {1, "Area Addr Format"},
347     {2, "Domain Addr Format"},
348     {3, "Fabric Addr Format"},
349     {0, NULL},
350 };
351
352 static const value_string fc_swils_rscn_detectfn_val[] = {
353     {1, "Fabric Detected"},
354     {2, "N_Port Detected"},
355     {0, NULL},
356 };
357
358 static const value_string fc_swils_esc_protocol_val[] = {
359     {0, "Reserved"},
360     {1, "FSPF-Backbone Protocol"},
361     {2, "FSPF Protocol"},
362     {0, NULL},
363 };
364
365 static const value_string fc_swils_zoneobj_type_val[] = {
366     {0, "Reserved"},
367     {FC_SWILS_ZONEOBJ_ZONESET  , "Zone Set"},
368     {FC_SWILS_ZONEOBJ_ZONE     , "Zone"},
369     {FC_SWILS_ZONEOBJ_ZONEALIAS, "Zone Alias"},
370     {0, NULL},
371 };
372
373 const value_string fc_swils_zonembr_type_val[] = {
374     {0, "Reserved"},
375     {FC_SWILS_ZONEMBR_WWN, "WWN"},
376     {FC_SWILS_ZONEMBR_DP, "Domain/Physical Port (0x00ddpppp)"},
377     {FC_SWILS_ZONEMBR_FCID, "FC Address"},
378     {FC_SWILS_ZONEMBR_ALIAS, "Zone Alias"},
379     {FC_SWILS_ZONEMBR_WWN_LUN, "WWN+LUN"},
380     {FC_SWILS_ZONEMBR_DP_LUN, "Domain/Physical Port+LUN"},
381     {FC_SWILS_ZONEMBR_FCID_LUN, "FCID+LUN"},
382     {0, NULL},
383 };
384
385 static const value_string fc_swils_mr_rsp_val[] = {
386     {0, "Successful"},
387     {1, "Fabric Busy"},
388     {2, "Failed"},
389     {0, NULL},
390 };
391
392 static const value_string fc_swils_mr_reason_val[] = {
393     {0x0, "No Reason"},
394     {0x1, "Invalid Data Length"},
395     {0x2, "Unsupported Command"},
396     {0x3, "Reserved"},
397     {0x4, "Not Authorized"},
398     {0x5, "Invalid Request"},
399     {0x6, "Fabric Changing"},
400     {0x7, "Update Not Staged"},
401     {0x8, "Invalid Zone Set Format"},
402     {0x9, "Invalid Data"},
403     {0xA, "Cannot Merge"},
404     {0, NULL},
405 };
406
407 static const value_string fc_swils_sfc_op_val[] = {
408     {0, "Reserved"},
409     {1, "Reserved"},
410     {2, "Reserved"},
411     {3, "Activate Zone Set"},
412     {4, "Deactivate Zone Set"},
413     {0, NULL},
414 };
415
416 typedef struct _zonename {
417     guint32 namelen:8,
418             rsvd:24;
419     gchar *name;
420     gchar *pad;
421 } zonename_t;
422
423 typedef struct _fcswils_conv_key {
424     guint32 conv_idx;
425 } fcswils_conv_key_t;
426
427 typedef struct _fcswils_conv_data {
428     guint32 opcode;
429 } fcswils_conv_data_t;
430
431 static GHashTable *fcswils_req_hash = NULL;
432
433 /* list of commands for each commandset */
434 typedef void (*fcswils_dissector_t)(tvbuff_t *tvb, proto_tree *tree, guint8 isreq);
435
436 typedef struct _fcswils_func_table_t {
437     fcswils_dissector_t func;
438 } fcswils_func_table_t;
439
440 static dissector_handle_t data_handle, fcsp_handle;
441
442 static gint get_zoneobj_len (tvbuff_t *tvb, gint offset);
443
444 /*
445  * Hash Functions
446  */
447 static gint
448 fcswils_equal(gconstpointer v, gconstpointer w)
449 {
450     const fcswils_conv_key_t *v1 = v;
451     const fcswils_conv_key_t *v2 = w;
452
453     return (v1->conv_idx == v2->conv_idx);
454 }
455
456 static guint
457 fcswils_hash (gconstpointer v)
458 {
459     const fcswils_conv_key_t *key = v;
460     guint val;
461
462     val = key->conv_idx;
463
464     return val;
465 }
466
467 /*
468  * Protocol initialization
469  */
470 static void
471 fcswils_init_protocol(void)
472 {
473     if (fcswils_req_hash)
474         g_hash_table_destroy (fcswils_req_hash);
475
476     fcswils_req_hash = g_hash_table_new(fcswils_hash, fcswils_equal);
477
478 }
479
480 static guint8 *
481 zonenm_to_str (tvbuff_t *tvb, gint offset)
482 {
483     int len = tvb_get_guint8 (tvb, offset);
484     return tvb_get_ephemeral_string (tvb, offset+4, len);
485 }
486
487 /* Offset points to the start of the zone object */
488 static gint
489 get_zoneobj_len (tvbuff_t *tvb, gint offset)
490 {
491     gint numrec, numrec1;
492     guint8 objtype;
493     gint i, j, len;
494
495     /* zone object structure is:
496      * type (1 byte), protocol (1 byte), rsvd (2 bytes), obj name (x bytes),
497      * num of zone mbrs (4 bytes ), list of zone members (each member if of
498      * variable length).
499      *
500      * zone member structure is:
501      * type (1 byte), rsvd (1 byte), flags (1 byte), id_len (1 byte),
502      * id (id_len bytes)
503      */
504     objtype = tvb_get_guint8 (tvb, offset);
505     len = 4 + ZONENAME_LEN (tvb, offset+4); /* length upto num_of_mbrs field */
506     numrec = tvb_get_ntohl (tvb, offset+len); /* gets us num of zone mbrs */
507
508     len += 4;                   /* + num_mbrs */
509     for (i = 0; i < numrec; i++) {
510         if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
511             len += 4 + ZONENAME_LEN (tvb, offset+4+len); /* length upto num_of_mbrs field */
512             numrec1 = tvb_get_ntohl (tvb, offset+len);
513
514             len += 4;
515             for (j = 0; j < numrec1; j++) {
516                 len += 4 + tvb_get_guint8 (tvb, offset+3+len);
517             }
518         }
519         else {
520             len += 4 + tvb_get_guint8 (tvb, offset+3+len);
521         }
522     }
523
524     return len;
525 }
526
527 #define MAX_INTERCONNECT_ELEMENT_INFO_LEN  252
528 static int
529 dissect_swils_interconnect_element_info (tvbuff_t *tvb, proto_tree *tree, int offset)
530 {
531
532     int len, max_len = MAX_INTERCONNECT_ELEMENT_INFO_LEN;
533
534     if (tree) {
535         proto_tree_add_item (tree, hf_swils_interconnect_list_len, tvb, offset+3, 1, 0);
536         len = tvb_strsize (tvb, offset+4);
537         proto_tree_add_item (tree, hf_swils_ess_vendorname, tvb, offset+4, len, FALSE);
538         offset += (4 + len);
539         max_len -= len;
540         len = tvb_strsize (tvb, offset);
541         proto_tree_add_item (tree, hf_swils_ess_modelname, tvb, offset, len, FALSE);
542         offset += len;
543         max_len -= len;
544         len = tvb_strsize (tvb, offset);
545         proto_tree_add_item (tree, hf_swils_ess_relcode, tvb, offset, len, FALSE);
546         offset += len;
547         max_len -= len;
548         while (max_len > 0) {
549             /* Vendor specific field is a set of one or more null-terminated
550              * strings
551              */
552             len = tvb_strsize (tvb, offset);
553             proto_tree_add_item (tree, hf_swils_ess_vendorspecific, tvb, offset, len, FALSE);
554             offset += len;
555             max_len -= len;
556         }
557     }
558
559     return TRUE;
560 }
561
562 static void
563 dissect_swils_ess_capability (tvbuff_t *tvb, proto_tree *tree, int offset,
564                               guint8 srvr_type)
565 {
566     if (tree) {
567         switch (srvr_type) {
568         case FCCT_GSRVR_DNS:
569             proto_tree_add_item (tree, hf_swils_ess_dns_zlacc, tvb, offset+3,
570                                  1, 0);
571             proto_tree_add_item (tree, hf_swils_ess_dns_obj3h, tvb, offset+3,
572                                  1, 0);
573             proto_tree_add_item (tree, hf_swils_ess_dns_obj2h, tvb, offset+3,
574                                  1, 0);
575             proto_tree_add_item (tree, hf_swils_ess_dns_obj1h, tvb, offset+3,
576                                  1, 0);
577             proto_tree_add_item (tree, hf_swils_ess_dns_obj0h, tvb, offset+3,
578                                  1, 0);
579             proto_tree_add_item (tree, hf_swils_ess_dns_vendor, tvb,
580                                  offset+4, 4, 0);
581             break;
582         case FCCT_GSRVR_FCTLR:
583             proto_tree_add_item (tree, hf_swils_ess_fctlr_rscn, tvb,
584                                  offset+3, 1, 0);
585             proto_tree_add_item (tree, hf_swils_ess_fctlr_vendor, tvb,
586                                  offset+4, 4, 0);
587             break;
588         case FCCT_GSRVR_FCS:
589             proto_tree_add_item (tree, hf_swils_ess_fcs_basic, tvb,
590                                  offset+3, 1, 0);
591             proto_tree_add_item (tree, hf_swils_ess_fcs_platform, tvb,
592                                  offset+3, 1, 0);
593             proto_tree_add_item (tree, hf_swils_ess_fcs_topology, tvb,
594                                  offset+3, 1, 0);
595             proto_tree_add_item (tree, hf_swils_ess_fcs_enhanced, tvb,
596                                  offset+3, 1, 0);
597             break;
598         case FCCT_GSRVR_FZS:
599             proto_tree_add_item (tree, hf_swils_ess_fzs_enh_supp, tvb,
600                                  offset+3, 1, 0);
601             proto_tree_add_item (tree, hf_swils_ess_fzs_enh_ena, tvb,
602                                  offset+3, 1, 0);
603             proto_tree_add_item (tree, hf_swils_ess_fzs_mr, tvb, offset+3,
604                                  1, 0);
605             proto_tree_add_item (tree, hf_swils_ess_fzs_defzone, tvb,
606                                  offset+3, 1, 0);
607             proto_tree_add_item (tree, hf_swils_ess_fzs_zsdb_supp, tvb,
608                                  offset+3, 1, 0);
609             proto_tree_add_item (tree, hf_swils_ess_fzs_zsdb_ena, tvb,
610                                  offset+3, 1, 0);
611             proto_tree_add_item (tree, hf_swils_ess_fzs_adc_supp, tvb,
612                                  offset+3, 1, 0);
613             proto_tree_add_item (tree, hf_swils_ess_fzs_hardzone, tvb,
614                                  offset+3, 1, 0);
615             break;
616         default:
617             break;
618         }
619     }
620
621     return;
622 }
623
624 static int
625 dissect_swils_ess_capability_obj (tvbuff_t *tvb, proto_tree *tree, int offset)
626 {
627     int i = 0, num_entries = 0, len = 0, total_len = 0;
628     guint8 type, subtype, srvr_type;
629     proto_item *ti = NULL;
630     proto_tree *capinfo_tree = NULL;
631
632     if (tree) {
633         /*
634          * Structure of capability object is: WK type (2B), WK subtype(2),
635          * rsvd (1), num_cap_entries (1), entry_1 (8) ... entry_n (8)
636          */
637         /* Compute length first to create subtree of cap object */
638         type = tvb_get_guint8 (tvb, offset);
639         if (type != FCCT_GSTYPE_VENDOR) {
640             num_entries = tvb_get_guint8 (tvb, offset+3);
641             total_len = 4 + (num_entries*8);
642             ti = proto_tree_add_text (tree, tvb, offset,
643                                       total_len, "Capability Object (%s)",
644                                       val_to_str (type, fc_ct_gstype_vals,
645                                                   "Unknown (0x%x)"));
646             capinfo_tree = proto_item_add_subtree (ti, ett_fcswils_capinfo);
647
648         } else {
649             i = tvb_get_guint8 (tvb, offset+3);
650             i += 12;
651
652             ti = proto_tree_add_text (tree, tvb, offset,
653                                       i, "Capability Object (Vendor-specific 0x%x)",
654                                       type);
655             capinfo_tree = proto_item_add_subtree (ti, ett_fcswils_capinfo);
656         }
657
658         proto_tree_add_item (capinfo_tree, hf_swils_ess_cap_type, tvb, offset, 1, 0);
659         proto_tree_add_item (capinfo_tree, hf_swils_ess_cap_subtype, tvb, offset+1,
660                              1, 0);
661         subtype = tvb_get_guint8 (tvb, offset+1);
662
663         if (type != FCCT_GSTYPE_VENDOR) {
664             srvr_type = get_gs_server (type, subtype);
665             proto_tree_add_uint (capinfo_tree, hf_swils_ess_cap_svc, tvb, offset, 2,
666                                  srvr_type);
667             proto_tree_add_item (capinfo_tree, hf_swils_ess_cap_numentries, tvb,
668                                  offset+3, 1, 0);
669             offset += 4;
670             len += 4;
671
672             while ((num_entries > 0) && tvb_bytes_exist (tvb, offset, 8)) {
673                 dissect_swils_ess_capability (tvb, capinfo_tree, offset, srvr_type);
674                 num_entries--;
675                 offset += 8;
676                 len += 8;
677             }
678         } else {
679             /* Those damn T11 guys defined another format for
680              * Vendor-specific objects.
681              */
682             proto_tree_add_item (capinfo_tree, hf_swils_ess_cap_len, tvb, offset+3,
683                                  1, 0);
684             proto_tree_add_item (capinfo_tree, hf_swils_ess_cap_t10, tvb, offset+4,
685                                  8, 0);
686             i -= 8;          /* reduce length by t10 object size */
687             offset += 12;
688             len += 12;
689
690             while ((i > 0) && tvb_bytes_exist (tvb, offset, 8)) {
691                 proto_tree_add_item (capinfo_tree, hf_swils_ess_cap_vendorobj,
692                                      tvb, offset, 8, 0);
693                 i -= 8;
694                 offset += 8;
695                 len += 12;
696             }
697         }
698     }
699     return len;
700 }
701
702 static void
703 dissect_swils_nullpayload (tvbuff_t *tvb _U_, proto_tree *tree _U_,
704                            guint8 isreq _U_)
705 {
706     /* Common dissector for those ILSs without a payload */
707     return;
708 }
709
710 static void
711 dissect_swils_elp (tvbuff_t *tvb, proto_tree *elp_tree, guint8 isreq _U_)
712 {
713
714     /* Set up structures needed to add the protocol subtree and manage it */
715     int offset = 0;
716     const gchar *flags;
717     fcswils_elp elp;
718
719     /* Response i.e. SW_ACC for an ELP has the same format as the request */
720     /* We skip the initial 4 bytes as we don't care about the opcode */
721     tvb_memcpy (tvb, (guint8 *)&elp, 4, FC_SWILS_ELP_SIZE);
722
723     elp.r_a_tov = g_ntohl (elp.r_a_tov);
724     elp.e_d_tov = g_ntohl (elp.e_d_tov);
725     elp.isl_flwctrl_mode = g_ntohs (elp.isl_flwctrl_mode);
726     elp.flw_ctrl_parmlen = g_ntohs (elp.flw_ctrl_parmlen);
727
728     if (elp_tree) {
729         offset += 4;
730         proto_tree_add_item (elp_tree, hf_swils_elp_rev, tvb, offset++, 1, 0);
731         proto_tree_add_item (elp_tree, hf_swils_elp_flags, tvb, offset, 2, 0);
732         offset += 3;
733         proto_tree_add_uint_format (elp_tree, hf_swils_elp_r_a_tov, tvb, offset, 4,
734                                     elp.r_a_tov, "R_A_TOV: %d msecs", elp.r_a_tov);
735         offset += 4;
736         proto_tree_add_uint_format (elp_tree, hf_swils_elp_e_d_tov, tvb, offset, 4,
737                                     elp.e_d_tov, "E_D_TOV: %d msecs", elp.e_d_tov);
738         offset += 4;
739         proto_tree_add_string (elp_tree, hf_swils_elp_req_epn, tvb, offset, 8,
740                                fcwwn_to_str (elp.req_epname));
741         offset += 8;
742         proto_tree_add_string (elp_tree, hf_swils_elp_req_esn, tvb, offset, 8,
743                                fcwwn_to_str (elp.req_sname));
744         offset += 8;
745
746         flags="";
747         if (elp.clsf_svcparm[0] & 0x80) {
748             if (elp.clsf_svcparm[4] & 0x20) {
749                 flags="Class F Valid | X_ID Interlock";
750             } else {
751                 flags="Class F Valid | No X_ID Interlk";
752             }
753         } else {
754             flags="Class F Invld";
755         }
756         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_clsf_svcp, tvb, offset, 6,
757                                      &elp.clsf_svcparm[0], "Class F Svc Parameters: (%s)", flags);
758         offset += 6;
759
760         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_rcvsz, tvb, offset, 2, 0);
761         offset += 2;
762         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_conseq, tvb, offset, 2, 0);
763         offset += 2;
764         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_e2e, tvb, offset, 2, 0);
765         offset += 2;
766         proto_tree_add_item (elp_tree, hf_swils_elp_clsf_openseq, tvb, offset, 2, 0);
767         offset += 4;
768
769         flags="";
770         if (elp.cls1_svcparm[0] & 0x80) {
771 #define MAX_FLAGS_LEN 40
772             char *flagsbuf;
773             gint stroff, returned_length;
774
775             flagsbuf=ep_alloc(MAX_FLAGS_LEN);
776             stroff = 0;
777
778             returned_length = g_snprintf (flagsbuf+stroff, MAX_FLAGS_LEN-stroff,
779                                           "Class 1 Valid");
780             stroff += MIN(returned_length, MAX_FLAGS_LEN-stroff);
781             if (elp.cls1_svcparm[0] & 0x40) {
782                 returned_length = g_snprintf (flagsbuf+stroff, MAX_FLAGS_LEN-stroff, " | IMX");
783                 stroff += MIN(returned_length, MAX_FLAGS_LEN-stroff);
784             }
785             if (elp.cls1_svcparm[0] & 0x20) {
786                 returned_length = g_snprintf (flagsbuf+stroff, MAX_FLAGS_LEN-stroff, " | IPS");
787                 stroff += MIN(returned_length, MAX_FLAGS_LEN-stroff);
788             }
789             if (elp.cls1_svcparm[0] & 0x10) {
790                 returned_length = g_snprintf (flagsbuf+stroff, MAX_FLAGS_LEN-stroff, " | LKS");
791                 stroff += MIN(returned_length, MAX_FLAGS_LEN-stroff);
792             }
793             flags=flagsbuf;
794         }
795         else {
796             flags="Class 1 Invalid";
797         }
798
799         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls1_svcp, tvb, offset, 2,
800                                      tvb_get_ptr (tvb, offset, 2),
801                                      "Class 1 Svc Parameters: (%s)", flags);
802         offset += 2;
803         if (elp.cls1_svcparm[0] & 0x80) {
804             proto_tree_add_item (elp_tree, hf_swils_elp_cls1_rcvsz, tvb, offset, 2, 0);
805         }
806         offset += 2;
807
808         flags="";
809         if (elp.cls2_svcparm[0] & 0x80) {
810             if (elp.cls2_svcparm[0] & 0x08) {
811                 flags="Class 2 Valid | Seq Delivery";
812             }
813             else {
814                 flags="Class 2 Valid | No Seq Delivery";
815             }
816         }
817         else {
818             flags="Class 2 Invld";
819         }
820
821         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls2_svcp, tvb, offset, 2,
822                                      &elp.cls2_svcparm[0],
823                                      "Class 2 Svc Parameters: (%s)", flags);
824         offset += 2;
825
826         if (elp.cls2_svcparm[0] & 0x80) {
827             proto_tree_add_item (elp_tree, hf_swils_elp_cls2_rcvsz, tvb, offset, 2, 0);
828         }
829         offset += 2;
830
831         flags="";
832         if (elp.cls3_svcparm[0] & 0x80) {
833             if (elp.cls3_svcparm[0] & 0x08) {
834                 flags="Class 3 Valid | Seq Delivery";
835             }
836             else {
837                 flags="Class 3 Valid | No Seq Delivery";
838             }
839         }
840         else {
841             flags="Class 3 Invld";
842         }
843         proto_tree_add_bytes_format (elp_tree, hf_swils_elp_cls3_svcp, tvb, offset, 2,
844                                      &elp.cls3_svcparm[0],
845                                      "Class 3 Svc Parameters: (%s)", flags);
846         offset += 2;
847
848         if (elp.cls3_svcparm[0] & 0x80) {
849             proto_tree_add_item (elp_tree, hf_swils_elp_cls3_rcvsz, tvb, offset, 2, 0);
850         }
851         offset += 22;
852
853         proto_tree_add_string (elp_tree, hf_swils_elp_isl_fc_mode, tvb, offset, 2,
854                                val_to_str (elp.isl_flwctrl_mode, fcswils_elp_fc_val, "Vendor Unique"));
855         offset += 2;
856         proto_tree_add_item (elp_tree, hf_swils_elp_fcplen, tvb, offset, 2, 0);
857         offset += 2;
858         proto_tree_add_item (elp_tree, hf_swils_elp_b2bcredit, tvb, offset, 4, 0);
859         offset += 4;
860         proto_tree_add_item (elp_tree, hf_swils_elp_compat1, tvb, offset, 4, 0);
861         offset += 4;
862         proto_tree_add_item (elp_tree, hf_swils_elp_compat2, tvb, offset, 4, 0);
863         offset += 4;
864         proto_tree_add_item (elp_tree, hf_swils_elp_compat3, tvb, offset, 4, 0);
865         offset += 4;
866         proto_tree_add_item (elp_tree, hf_swils_elp_compat4, tvb, offset, 4, 0);
867     }
868
869 }
870
871 static void
872 dissect_swils_efp (tvbuff_t *tvb, proto_tree *efp_tree, guint8 isreq _U_)
873 {
874
875 /* Set up structures needed to add the protocol subtree and manage it */
876     proto_item *subti;
877     proto_tree *lrec_tree;
878     int num_listrec = 0,
879         offset = 0;
880     fcswils_efp efp;
881     guint8 rec_type;
882
883     offset += 1;
884     efp.reclen = tvb_get_guint8 (tvb, offset);
885     if (efp_tree)
886         proto_tree_add_uint (efp_tree, hf_swils_efp_record_len, tvb, offset, 1, efp.reclen);
887     offset += 1;
888     efp.payload_len = tvb_get_ntohs (tvb, offset);
889     if (efp.payload_len < FC_SWILS_EFP_SIZE) {
890         if (efp_tree)
891             proto_tree_add_uint_format (efp_tree, hf_swils_efp_payload_len,
892                                         tvb, offset, 2, efp.payload_len,
893                                         "Payload Len: %u (bogus, must be >= %u)",
894                                         efp.payload_len, FC_SWILS_EFP_SIZE);
895         return;
896     }
897     if (efp_tree)
898         proto_tree_add_item (efp_tree, hf_swils_efp_payload_len, tvb, offset, 2, 0);
899     offset += 5;       /* skip 3 reserved bytes, too */
900     if (efp_tree)
901         proto_tree_add_item (efp_tree, hf_swils_efp_pswitch_pri, tvb,
902                              offset, 1, FALSE);
903     offset++;
904     tvb_memcpy (tvb, efp.pswitch_name, offset, 8);
905     if (efp_tree)
906         proto_tree_add_string (efp_tree, hf_swils_efp_pswitch_name, tvb, offset,
907                                8, fcwwn_to_str (efp.pswitch_name));
908     offset += 8;
909
910     /* Add List Records now */
911     if (efp_tree) {
912         if (efp.reclen == 0) {
913             proto_tree_add_text (efp_tree, tvb, 0, 0, "Record length is zero");
914             return;
915         }
916         num_listrec = (efp.payload_len - FC_SWILS_EFP_SIZE)/efp.reclen;
917         while (num_listrec-- > 0) {
918             rec_type = tvb_get_guint8 (tvb, offset);
919             subti = proto_tree_add_text (efp_tree, tvb, offset, -1,
920                                          "%s",
921                                          val_to_str(rec_type,
922                                                     fcswils_rectype_val,
923                                                     "Unknown record type (0x%02x)"));
924             lrec_tree = proto_item_add_subtree (subti, ett_fcswils_efplist);
925             proto_tree_add_uint (lrec_tree, hf_swils_efp_rec_type, tvb, offset, 1,
926                                  rec_type);
927             switch (rec_type) {
928
929             case FC_SWILS_LRECTYPE_DOMAIN:
930                 proto_tree_add_item (lrec_tree, hf_swils_efp_dom_id, tvb, offset+1, 1, 0);
931                 proto_tree_add_string (lrec_tree, hf_swils_efp_switch_name, tvb, offset+8, 8,
932                                        tvb_fcwwn_to_str (tvb, offset+8));
933                 break;
934
935             case FC_SWILS_LRECTYPE_MCAST:
936                 proto_tree_add_item (lrec_tree, hf_swils_efp_mcast_grpno, tvb, offset+1, 1, 0);
937                 break;
938             }
939             offset += efp.reclen;
940         }
941     }
942 }
943
944 static void
945 dissect_swils_dia (tvbuff_t *tvb, proto_tree *dia_tree, guint8 isreq _U_)
946 {
947     /* Set up structures needed to add the protocol subtree and manage it */
948     int offset = 0;
949
950     if (dia_tree) {
951         proto_tree_add_string (dia_tree, hf_swils_dia_switch_name, tvb, offset+4,
952                                8, tvb_fcwwn_to_str (tvb, offset+4));
953     }
954 }
955
956 static void
957 dissect_swils_rdi (tvbuff_t *tvb, proto_tree *rdi_tree, guint8 isreq)
958 {
959     /* Set up structures needed to add the protocol subtree and manage it */
960     int offset = 0;
961     int i, plen, numrec;
962
963     if (rdi_tree) {
964         plen = tvb_get_ntohs (tvb, offset+2);
965
966         proto_tree_add_item (rdi_tree, hf_swils_rdi_payload_len, tvb, offset+2, 2, 0);
967         proto_tree_add_string (rdi_tree, hf_swils_rdi_req_sname, tvb, offset+4,
968                                8, tvb_fcwwn_to_str (tvb, offset+4));
969
970         /* 12 is the length of the initial header and 4 is the size of each
971          * domain request record.
972          */
973         numrec = (plen - 12)/4;
974         offset = 12;
975         for (i = 0; i < numrec; i++) {
976             if (isreq) {
977                 proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
978                                      "Requested Domain ID: %d",
979                                      tvb_get_guint8 (tvb, offset+3));
980             }
981             else {
982                 proto_tree_add_text (rdi_tree, tvb, offset+3, 1,
983                                      "Granted Domain ID: %d",
984                                      tvb_get_guint8 (tvb, offset+3));
985             }
986             offset += 4;
987         }
988     }
989 }
990
991 static void
992 dissect_swils_fspf_hdr (tvbuff_t *tvb, proto_tree *tree, int offset)
993 {
994     proto_item *subti;
995     proto_tree *fspfh_tree;
996
997     if (tree) {
998         /* 20 is the size of FSPF header */
999         subti = proto_tree_add_text (tree, tvb, offset, 20, "FSPF Header");
1000         fspfh_tree = proto_item_add_subtree (subti, ett_fcswils_fspfhdr);
1001
1002         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_rev, tvb, offset+4,
1003                              1, 0);
1004         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_ar_num, tvb,
1005                              offset+5, 1, 0);
1006         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth_type, tvb,
1007                              offset+6, 1, 0);
1008         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_dom_id, tvb, offset+11,
1009                              1, 0);
1010         proto_tree_add_item (fspfh_tree, hf_swils_fspfh_auth, tvb, offset+12,
1011                              8, 0);
1012     }
1013 }
1014
1015 static void
1016 dissect_swils_fspf_lsrechdr (tvbuff_t *tvb, proto_tree *tree, int offset)
1017 {
1018     proto_tree_add_item (tree, hf_swils_lsrh_lsr_type, tvb, offset, 1, 0);
1019     proto_tree_add_text (tree, tvb, offset+2, 2, "LSR Age: %d secs",
1020                          tvb_get_ntohs (tvb, offset+2));
1021     proto_tree_add_text (tree, tvb, offset+4, 4, "Options : 0x%x",
1022                          tvb_get_ntohl (tvb, offset+4));
1023     proto_tree_add_item (tree, hf_swils_lsrh_lsid, tvb, offset+11, 1, 0);
1024     proto_tree_add_item (tree, hf_swils_lsrh_adv_domid, tvb, offset+15, 1, 0);
1025     proto_tree_add_item (tree, hf_swils_lsrh_ls_incid, tvb, offset+16, 4, 0);
1026     proto_tree_add_text (tree, tvb, offset+20, 2, "Checksum: 0x%x",
1027                          tvb_get_ntohs (tvb, offset+20));
1028     proto_tree_add_text (tree, tvb, offset+22, 2, "LSR Length: %d",
1029                          tvb_get_ntohs (tvb, offset+22));
1030 }
1031
1032 static void
1033 dissect_swils_fspf_ldrec (tvbuff_t *tvb, proto_tree *tree, int offset)
1034 {
1035     proto_tree_add_string (tree, hf_swils_ldrec_linkid, tvb, offset, 4,
1036                            tvb_fc_to_str (tvb, offset+1));
1037     proto_tree_add_item (tree, hf_swils_ldrec_out_pidx, tvb, offset+5, 3, 0);
1038     proto_tree_add_item (tree, hf_swils_ldrec_nbr_pidx, tvb, offset+9, 3, 0);
1039     proto_tree_add_item (tree, hf_swils_ldrec_link_type, tvb, offset+12, 1, 0);
1040     proto_tree_add_item (tree, hf_swils_ldrec_link_cost, tvb, offset+14, 2, 0);
1041 }
1042
1043 static void
1044 dissect_swils_fspf_lsrec (tvbuff_t *tvb, proto_tree *tree, int offset,
1045                           int num_lsrec)
1046 {
1047     int i, j, num_ldrec;
1048     proto_item *subti1, *subti;
1049     proto_tree *lsrec_tree, *ldrec_tree, *lsrechdr_tree;
1050
1051     if (tree) {
1052         for (j = 0; j < num_lsrec; j++) {
1053             num_ldrec = tvb_get_ntohs (tvb, offset+26);
1054             subti = proto_tree_add_text (tree, tvb, offset, (28+num_ldrec*16),
1055                                          "Link State Record %d (Domain %d)", j,
1056                                          tvb_get_guint8 (tvb, offset+15));
1057             lsrec_tree = proto_item_add_subtree (subti, ett_fcswils_lsrec);
1058
1059             subti = proto_tree_add_text (lsrec_tree, tvb, offset, 24,
1060                                          "Link State Record Header");
1061             lsrechdr_tree = proto_item_add_subtree (subti,
1062                                                     ett_fcswils_lsrechdr);
1063
1064             dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
1065             proto_tree_add_text (tree, tvb, offset+26, 2, "Number of Links: %d",
1066                                  num_ldrec);
1067             offset += 28;
1068
1069             for (i = 0; i < num_ldrec; i++) {
1070                 subti1 = proto_tree_add_text (lsrec_tree, tvb, offset, 16,
1071                                               "Link Descriptor %d "
1072                                               "(Neighbor domain %d)", i,
1073                                               tvb_get_guint8 (tvb, offset+3));
1074                 ldrec_tree = proto_item_add_subtree (subti1, ett_fcswils_ldrec);
1075                 dissect_swils_fspf_ldrec (tvb, ldrec_tree, offset);
1076                 offset += 16;
1077             }
1078         }
1079     }
1080 }
1081
1082 static void
1083 dissect_swils_hello (tvbuff_t *tvb, proto_tree *hlo_tree, guint8 isreq _U_)
1084 {
1085     /* Set up structures needed to add the protocol subtree and manage it */
1086     int offset = 0;
1087
1088     if (hlo_tree) {
1089         dissect_swils_fspf_hdr (tvb, hlo_tree, offset);
1090
1091         proto_tree_add_item (hlo_tree, hf_swils_hlo_options, tvb, offset+20, 4, 0);
1092         proto_tree_add_item (hlo_tree, hf_swils_hlo_hloint, tvb, offset+24, 4, 0);
1093         proto_tree_add_item (hlo_tree, hf_swils_hlo_deadint, tvb, offset+28, 4, 0);
1094         proto_tree_add_item (hlo_tree, hf_swils_hlo_rcv_domid, tvb, offset+35, 1, 0);
1095         proto_tree_add_item (hlo_tree, hf_swils_hlo_orig_pidx, tvb, offset+37, 3, 0);
1096     }
1097 }
1098
1099 static void
1100 dissect_swils_lsupdate (tvbuff_t *tvb, proto_tree *lsu_tree, guint8 isreq _U_)
1101 {
1102     /* Set up structures needed to add the protocol subtree and manage it */
1103     int offset = 0;
1104     int num_lsrec;
1105
1106     if (lsu_tree) {
1107         dissect_swils_fspf_hdr (tvb, lsu_tree, offset);
1108
1109         proto_tree_add_text (lsu_tree, tvb, offset+23, 1, "Flags : %s",
1110                              val_to_str (tvb_get_guint8 (tvb, offset+23),
1111                                          fc_swils_fspf_lsrflags_val, "0x%x"));
1112         num_lsrec = tvb_get_ntohl (tvb, offset+24);
1113
1114         proto_tree_add_text (lsu_tree, tvb, offset+24, 4, "Num of LSRs: %d",
1115                              num_lsrec);
1116
1117         offset = 28;
1118         dissect_swils_fspf_lsrec (tvb, lsu_tree, offset, num_lsrec);
1119     }
1120 }
1121
1122 static void
1123 dissect_swils_lsack (tvbuff_t *tvb, proto_tree *lsa_tree, guint8 isreq _U_)
1124 {
1125     /* Set up structures needed to add the protocol subtree and manage it */
1126     int offset = 0;
1127     int num_lsrechdr, i;
1128     proto_item *subti;
1129     proto_tree *lsrechdr_tree;
1130
1131     if (lsa_tree) {
1132         dissect_swils_fspf_hdr (tvb, lsa_tree, offset);
1133
1134         proto_tree_add_text (lsa_tree, tvb, offset+23, 1, "Flags : %s",
1135                              val_to_str (tvb_get_guint8 (tvb, offset+23),
1136                                          fc_swils_fspf_lsrflags_val, "0x%x"));
1137         num_lsrechdr = tvb_get_ntohl (tvb, offset+24);
1138
1139         proto_tree_add_text (lsa_tree, tvb, offset+24, 4, "Num of LSR Headers: %d",
1140                              num_lsrechdr);
1141
1142         offset = 28;
1143
1144         for (i = 0; i < num_lsrechdr; i++) {
1145             subti = proto_tree_add_text (lsa_tree, tvb, offset, 24,
1146                                          "Link State Record Header (Domain %d)",
1147                                          tvb_get_guint8 (tvb, offset+15));
1148             lsrechdr_tree = proto_item_add_subtree (subti,
1149                                                     ett_fcswils_lsrechdr);
1150             dissect_swils_fspf_lsrechdr (tvb, lsrechdr_tree, offset);
1151             offset += 24;
1152         }
1153     }
1154 }
1155
1156 static void
1157 dissect_swils_rscn (tvbuff_t *tvb, proto_tree *rscn_tree, guint8 isreq)
1158 {
1159     /* Set up structures needed to add the protocol subtree and manage it */
1160     int offset = 0;
1161     proto_tree *dev_tree;
1162     int addrfmt, evtype;
1163     int numrec, i;
1164     proto_item *subti;
1165
1166     if (rscn_tree) {
1167         if (!isreq)
1168             return;
1169
1170         evtype = tvb_get_guint8 (tvb, offset+4);
1171         addrfmt = evtype & 0x0F;
1172         evtype = evtype >> 4;
1173
1174         proto_tree_add_item (rscn_tree, hf_swils_rscn_evtype, tvb, offset+4,
1175                              1, 0);
1176         proto_tree_add_item (rscn_tree, hf_swils_rscn_addrfmt, tvb, offset+4,
1177                              1, 0);
1178         proto_tree_add_string (rscn_tree, hf_swils_rscn_affectedport, tvb,
1179                                offset+5, 3, tvb_fc_to_str (tvb, offset+5));
1180         proto_tree_add_item (rscn_tree, hf_swils_rscn_detectfn, tvb,
1181                              offset+8, 4, 0);
1182         numrec = tvb_get_ntohl (tvb, offset+12);
1183
1184         if (!tvb_bytes_exist (tvb, offset+16, FC_SWILS_RSCN_DEVENTRY_SIZE*numrec)) {
1185             /* Some older devices do not include device entry information. */
1186             return;
1187         }
1188
1189         proto_tree_add_text (rscn_tree, tvb, offset+12, 4, "Num Entries: %d",
1190                              numrec);
1191
1192         offset = 16;
1193         for (i = 0; i < numrec; i++) {
1194             subti = proto_tree_add_text (rscn_tree, tvb, offset, 20,
1195                                          "Device Entry %d", i);
1196             dev_tree = proto_item_add_subtree (rscn_tree, ett_fcswils_rscn_dev);
1197
1198             proto_tree_add_item (dev_tree, hf_swils_rscn_portstate, tvb, offset, 1, 0);
1199             proto_tree_add_string (dev_tree, hf_swils_rscn_portid, tvb, offset+1, 3,
1200                                    tvb_fc_to_str (tvb, offset+1));
1201             proto_tree_add_string (dev_tree, hf_swils_rscn_pwwn, tvb, offset+4, 8,
1202                                    tvb_fcwwn_to_str (tvb, offset+4));
1203             proto_tree_add_string (dev_tree, hf_swils_rscn_nwwn, tvb, offset+12, 8,
1204                                    tvb_fcwwn_to_str (tvb, offset+12));
1205             offset += 20;
1206         }
1207     }
1208 }
1209
1210 /*
1211  * Merge Request contains zoning objects organized in the following format:
1212  *
1213  * Zone Set Object
1214  *      |
1215  *      +---------------- Zone Object
1216  *      |                      |
1217  *      +--                    +---------------- Zone Member
1218  *      |                      |                     |
1219  *      +--                    +----                 +-----
1220  *
1221  * So the decoding of the zone merge request is based on this structure
1222  */
1223
1224 static void
1225 dissect_swils_zone_mbr (tvbuff_t *tvb, proto_tree *zmbr_tree, int offset)
1226 {
1227     guint8 mbrtype;
1228     int idlen;
1229     char dpbuf[2+8+1];
1230     char *str;
1231
1232     mbrtype = tvb_get_guint8 (tvb, offset);
1233     proto_tree_add_uint (zmbr_tree, hf_swils_zone_mbrtype, tvb,
1234                          offset, 1, mbrtype);
1235     proto_tree_add_text (zmbr_tree, tvb, offset+2, 1, "Flags: 0x%x",
1236                          tvb_get_guint8 (tvb, offset+2));
1237     idlen = tvb_get_guint8 (tvb, offset+3);
1238     proto_tree_add_text (zmbr_tree, tvb, offset+3, 1,
1239                          "Identifier Length: %u", idlen);
1240     switch (mbrtype) {
1241     case FC_SWILS_ZONEMBR_WWN:
1242         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1243                                offset+4, 8,
1244                                tvb_fcwwn_to_str (tvb, offset+4));
1245         break;
1246     case FC_SWILS_ZONEMBR_DP:
1247         g_snprintf(dpbuf, sizeof(dpbuf), "0x%08x", tvb_get_ntohl (tvb, offset+4));
1248         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1249                                offset+4, 4, dpbuf);
1250         break;
1251     case FC_SWILS_ZONEMBR_FCID:
1252         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1253                                offset+4, 4,
1254                                tvb_fc_to_str (tvb, offset+5));
1255         break;
1256     case FC_SWILS_ZONEMBR_ALIAS:
1257         str = zonenm_to_str (tvb, offset+4);
1258         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1259                                offset+4, idlen, str);
1260         break;
1261     case FC_SWILS_ZONEMBR_WWN_LUN:
1262         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1263                                offset+4, 8,
1264                                tvb_fcwwn_to_str (tvb, offset+4));
1265         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
1266                              offset+12, 8, 0);
1267         break;
1268     case FC_SWILS_ZONEMBR_DP_LUN:
1269         g_snprintf(dpbuf, sizeof(dpbuf), "0x%08x", tvb_get_ntohl (tvb, offset+4));
1270         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1271                                offset+4, 4, dpbuf);
1272         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
1273                              offset+8, 8, FALSE);
1274         break;
1275     case FC_SWILS_ZONEMBR_FCID_LUN:
1276         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1277                                offset+4, 4,
1278                                tvb_fc_to_str (tvb, offset+5));
1279         proto_tree_add_item (zmbr_tree, hf_swils_zone_mbrid_lun, tvb,
1280                              offset+8, 8, 0);
1281         break;
1282     default:
1283         proto_tree_add_string (zmbr_tree, hf_swils_zone_mbrid, tvb,
1284                                offset+4, idlen,
1285                                "Unknown member type format");
1286
1287     }
1288 }
1289
1290 static void
1291 dissect_swils_zone_obj (tvbuff_t *tvb, proto_tree *zobj_tree, int offset)
1292 {
1293     proto_tree *zmbr_tree;
1294     int mbrlen, numrec, i, objtype;
1295     char *str;
1296     proto_item *subti;
1297
1298     objtype = tvb_get_guint8 (tvb, offset);
1299
1300     proto_tree_add_item (zobj_tree, hf_swils_zone_objtype, tvb, offset,
1301                          1, 0);
1302     proto_tree_add_item (zobj_tree, hf_swils_zone_protocol, tvb,
1303                          offset+1, 1, 0);
1304     str = zonenm_to_str (tvb, offset+4);
1305     proto_tree_add_string (zobj_tree, hf_swils_zone_objname, tvb,
1306                            offset+4, ZONENAME_LEN (tvb, offset+4), str);
1307
1308     numrec = tvb_get_ntohl (tvb, offset+4+ZONENAME_LEN (tvb, offset+4));
1309     proto_tree_add_text (zobj_tree, tvb,
1310                          offset+4+ZONENAME_LEN (tvb, offset+4), 4,
1311                          "Number of Zone Members: %d", numrec);
1312
1313     offset += 8 + ZONENAME_LEN (tvb, offset+4);
1314     for (i = 0; i < numrec; i++) {
1315         if (objtype == FC_SWILS_ZONEOBJ_ZONESET) {
1316             dissect_swils_zone_obj (tvb, zobj_tree, offset);
1317             offset += get_zoneobj_len (tvb, offset);
1318         }
1319         else {
1320             mbrlen = 4 + tvb_get_guint8 (tvb, offset+3);
1321             subti = proto_tree_add_text (zobj_tree, tvb, offset, mbrlen,
1322                                          "Zone Member %d", i);
1323             zmbr_tree = proto_item_add_subtree (zobj_tree,
1324                                                 ett_fcswils_zonembr);
1325             dissect_swils_zone_mbr (tvb, zmbr_tree, offset);
1326             offset += mbrlen;
1327         }
1328     }
1329 }
1330
1331 static void
1332 dissect_swils_mergereq (tvbuff_t *tvb, proto_tree *mr_tree, guint8 isreq)
1333 {
1334     /* Set up structures needed to add the protocol subtree and manage it */
1335     int offset = 0;
1336     proto_tree *zobjlist_tree, *zobj_tree;
1337     int numrec, i, zonesetlen, objlistlen, objlen;
1338     char *str;
1339     proto_item *subti;
1340
1341     if (mr_tree) {
1342         if (isreq) {
1343             /* zonesetlen is the size of the zoneset including the zone name */
1344             zonesetlen = tvb_get_ntohs (tvb, offset+2);
1345             proto_tree_add_text (mr_tree, tvb, offset+2, 2,
1346                                  "Active ZoneSet Length: %u", zonesetlen);
1347
1348             if (zonesetlen) {
1349                 str = zonenm_to_str (tvb, offset+4);
1350                 proto_tree_add_string (mr_tree, hf_swils_zone_activezonenm, tvb,
1351                                        offset+4, ZONENAME_LEN (tvb, offset+4),
1352                                        str);
1353
1354                 /* objlistlen gives the size of the active zoneset object list */
1355                 objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
1356                 /* Offset = start of the active zoneset zoning object list */
1357                 offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
1358                 numrec = tvb_get_ntohl (tvb, offset);
1359
1360                 subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
1361                                              "Active Zone Set");
1362                 zobjlist_tree = proto_item_add_subtree (subti,
1363                                                         ett_fcswils_zoneobjlist);
1364
1365                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1366                                      "Number of zoning objects: %d", numrec);
1367
1368                 offset += 4;
1369                 for (i = 0; i < numrec; i++) {
1370                     objlen = get_zoneobj_len (tvb, offset);
1371                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset+4,
1372                                                  objlen, "Zone Object %d", i);
1373                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1374                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1375                     offset += objlen;
1376                 }
1377             }
1378             else {
1379                 offset += 4;
1380             }
1381
1382             zonesetlen = tvb_get_ntohl (tvb, offset);
1383             proto_tree_add_text (mr_tree, tvb, offset, 4,
1384                                  "Full Zone Set Length: %d", zonesetlen);
1385
1386             if (zonesetlen) {
1387                 objlistlen = zonesetlen;
1388                 /* Offset = start of the active zoneset zoning object list */
1389                 offset += 4;
1390                 numrec = tvb_get_ntohl (tvb, offset);
1391
1392                 subti = proto_tree_add_text (mr_tree, tvb, offset, objlistlen,
1393                                              "Full Zone Set");
1394
1395                 zobjlist_tree = proto_item_add_subtree (subti,
1396                                                         ett_fcswils_zoneobjlist);
1397                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1398                                      "Number of zoning objects: %d", numrec);
1399                 offset += 4;
1400                 for (i = 0; i < numrec; i++) {
1401                     objlen = get_zoneobj_len (tvb, offset);
1402                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1403                                                  objlen, "Zone Object %d", i);
1404                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1405                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1406                     offset += objlen;
1407                 }
1408             }
1409         }
1410         else {
1411             proto_tree_add_item (mr_tree, hf_swils_zone_status, tvb,
1412                                  offset+5, 1, 0);
1413             proto_tree_add_item (mr_tree, hf_swils_zone_reason, tvb,
1414                                  offset+6, 1, 0);
1415             proto_tree_add_text (mr_tree, tvb, offset+7, 1,
1416                                  "Vendor Unique: 0x%x",
1417                                  tvb_get_guint8 (tvb, offset+7));
1418         }
1419     }
1420 }
1421
1422 static void
1423 dissect_swils_aca (tvbuff_t *tvb, proto_tree *aca_tree, guint8 isreq)
1424 {
1425     /* Set up structures needed to add the protocol subtree and manage it */
1426     int offset = 0;
1427     int numrec, plen, i;
1428
1429     if (aca_tree) {
1430         if (isreq) {
1431             plen = tvb_get_ntohs (tvb, offset+2);
1432             proto_tree_add_text (aca_tree, tvb, offset+2, 2,
1433                                  "Domain ID List Length: %d", plen);
1434             numrec = plen/4;
1435             offset = 4;
1436
1437             for (i = 0; i < numrec; i++) {
1438                 proto_tree_add_uint_format (aca_tree, hf_swils_aca_domainid,
1439                                             tvb, offset+3, 1,
1440                                             tvb_get_guint8 (tvb, offset+3),
1441                                             "Domain ID %d: %d", i,
1442                                             tvb_get_guint8 (tvb, offset+3));
1443                 offset += 4;
1444             }
1445         }
1446         else {
1447             proto_tree_add_item (aca_tree, hf_swils_zone_status, tvb,
1448                                  offset+5, 1, 0);
1449             proto_tree_add_item (aca_tree, hf_swils_zone_reason, tvb,
1450                                  offset+6, 1, 0);
1451             proto_tree_add_text (aca_tree, tvb, offset+7, 1,
1452                                  "Vendor Unique: 0x%x",
1453                                  tvb_get_guint8 (tvb, offset+7));
1454         }
1455     }
1456 }
1457
1458 static void
1459 dissect_swils_rca (tvbuff_t *tvb, proto_tree *rca_tree, guint8 isreq)
1460 {
1461     /* Set up structures needed to add the protocol subtree and manage it */
1462     int offset = 0;
1463
1464     if (rca_tree) {
1465         if (!isreq) {
1466             proto_tree_add_item (rca_tree, hf_swils_zone_status, tvb,
1467                                  offset+5, 1, 0);
1468             proto_tree_add_item (rca_tree, hf_swils_zone_reason, tvb,
1469                                  offset+6, 1, 0);
1470             proto_tree_add_text (rca_tree, tvb, offset+7, 1,
1471                                  "Vendor Unique: 0x%x",
1472                                  tvb_get_guint8 (tvb, offset+7));
1473         }
1474     }
1475 }
1476
1477 static void
1478 dissect_swils_sfc (tvbuff_t *tvb, proto_tree *sfc_tree, guint8 isreq)
1479 {
1480     /* Set up structures needed to add the protocol subtree and manage it */
1481     int offset = 0;
1482     proto_tree *zobjlist_tree, *zobj_tree;
1483     int numrec, i, zonesetlen, objlistlen, objlen;
1484     char *str;
1485     proto_item *subti;
1486
1487     if (sfc_tree) {
1488         if (isreq) {
1489             proto_tree_add_item (sfc_tree, hf_swils_sfc_opcode, tvb, offset+1, 1, 0);
1490
1491             zonesetlen = tvb_get_ntohs (tvb, offset+2);
1492             proto_tree_add_text (sfc_tree, tvb, offset+2, 2,
1493                                  "ZoneSet Length: %d", zonesetlen);
1494
1495             if (zonesetlen) {
1496                 str = zonenm_to_str (tvb, offset+4);
1497                 proto_tree_add_string (sfc_tree, hf_swils_sfc_zonenm, tvb,
1498                                        offset+4, ZONENAME_LEN (tvb, offset+4),
1499                                        str);
1500
1501                 /* objlistlen gives the size of the active zoneset object list */
1502                 objlistlen = zonesetlen - ZONENAME_LEN (tvb, offset+4);
1503                 /* Offset = start of the active zoneset zoning object list */
1504                 offset = offset + (4 + ZONENAME_LEN (tvb, offset+4));
1505                 numrec = tvb_get_ntohl (tvb, offset);
1506
1507                 subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
1508                                              "Zone Set");
1509                 zobjlist_tree = proto_item_add_subtree (subti,
1510                                                         ett_fcswils_zoneobjlist);
1511
1512                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1513                                      "Number of zoning objects: %d", numrec);
1514
1515                 offset += 4;
1516                 for (i = 0; i < numrec; i++) {
1517                     objlen = get_zoneobj_len (tvb, offset);
1518                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1519                                                  objlen, "Zone Object %d", i);
1520                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1521                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1522                     offset += objlen;
1523                 }
1524             }
1525             else {
1526                 offset += 4;
1527             }
1528
1529             zonesetlen = tvb_get_ntohl (tvb, offset);
1530             proto_tree_add_text (sfc_tree, tvb, offset, 4,
1531                                  "Full Zone Set Length: %d", zonesetlen);
1532
1533             if (zonesetlen) {
1534                 objlistlen = zonesetlen;
1535                 /* Offset = start of the active zoneset zoning object list */
1536                 offset += 4;
1537                 numrec = tvb_get_ntohl (tvb, offset);
1538
1539                 subti = proto_tree_add_text (sfc_tree, tvb, offset, objlistlen,
1540                                              "Full Zone Set");
1541
1542                 zobjlist_tree = proto_item_add_subtree (subti,
1543                                                         ett_fcswils_zoneobjlist);
1544                 proto_tree_add_text (zobjlist_tree, tvb, offset, 4,
1545                                      "Number of zoning objects: %d", numrec);
1546                 offset += 4;
1547                 for (i = 0; i < numrec; i++) {
1548                     objlen = get_zoneobj_len (tvb, offset);
1549                     subti = proto_tree_add_text (zobjlist_tree, tvb, offset,
1550                                                  objlen, "Zone Object %d", i);
1551                     zobj_tree = proto_item_add_subtree (subti, ett_fcswils_zoneobj);
1552                     dissect_swils_zone_obj (tvb, zobj_tree, offset);
1553                     offset += objlen;
1554                 }
1555             }
1556         }
1557         else {
1558             proto_tree_add_item (sfc_tree, hf_swils_zone_status, tvb,
1559                                  offset+5, 1, 0);
1560             proto_tree_add_item (sfc_tree, hf_swils_zone_reason, tvb,
1561                                  offset+6, 1, 0);
1562             proto_tree_add_text (sfc_tree, tvb, offset+7, 1,
1563                                  "Vendor Unique: 0x%x",
1564                                  tvb_get_guint8 (tvb, offset+7));
1565         }
1566     }
1567 }
1568
1569 static void
1570 dissect_swils_ufc (tvbuff_t *tvb, proto_tree *ufc_tree, guint8 isreq)
1571 {
1572     /* Set up structures needed to add the protocol subtree and manage it */
1573     int offset = 0;
1574
1575     if (ufc_tree) {
1576         if (!isreq) {
1577             proto_tree_add_item (ufc_tree, hf_swils_zone_status, tvb,
1578                                  offset+5, 1, 0);
1579             proto_tree_add_item (ufc_tree, hf_swils_zone_reason, tvb,
1580                                  offset+6, 1, 0);
1581             proto_tree_add_text (ufc_tree, tvb, offset+7, 1,
1582                                  "Vendor Unique: 0x%x",
1583                                  tvb_get_guint8 (tvb, offset+7));
1584         }
1585     }
1586 }
1587
1588 static void
1589 dissect_swils_esc (tvbuff_t *tvb, proto_tree *esc_tree, guint8 isreq)
1590 {
1591     /* Set up structures needed to add the protocol subtree and manage it */
1592     int offset = 0;
1593     int i, numrec, plen;
1594     proto_tree *pdesc_tree;
1595     proto_item *subti;
1596
1597     if (esc_tree) {
1598         if (isreq) {
1599             plen = tvb_get_ntohs (tvb, offset+2);
1600             proto_tree_add_text (esc_tree, tvb, offset+2, 2,
1601                                  "Payload Length: %d", plen);
1602             proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
1603                                  offset+4, 8, 0);
1604             numrec = (plen - 12)/12;
1605             offset = 12;
1606
1607             for (i = 0; i < numrec; i++) {
1608                 subti = proto_tree_add_text (esc_tree, tvb, offset, 12,
1609                                              "Protocol Descriptor %d", i);
1610                 pdesc_tree = proto_item_add_subtree (subti,
1611                                                      ett_fcswils_esc_pdesc);
1612                 proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
1613                                      offset, 8, 0);
1614                 proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
1615                                      tvb, offset+10, 2, 0);
1616                 offset += 12;
1617             }
1618         }
1619         else {
1620             proto_tree_add_item (esc_tree, hf_swils_esc_swvendorid, tvb,
1621                                  offset+4, 8, 0);
1622             subti = proto_tree_add_text (esc_tree, tvb, offset+12, 12,
1623                                          "Accepted Protocol Descriptor");
1624             pdesc_tree = proto_item_add_subtree (subti, ett_fcswils_esc_pdesc);
1625
1626             proto_tree_add_item (pdesc_tree, hf_swils_esc_pdesc_vendorid, tvb,
1627                                  offset+12, 8, 0);
1628             proto_tree_add_item (pdesc_tree, hf_swils_esc_protocolid,
1629                                  tvb, offset+22, 2, 0);
1630         }
1631     }
1632 }
1633
1634 static void
1635 dissect_swils_drlir (tvbuff_t *tvb _U_, proto_tree *drlir_tree _U_,
1636                      guint8 isreq _U_)
1637 {
1638     /* Set up structures needed to add the protocol subtree and manage it */
1639     return;
1640 }
1641
1642 static void
1643 dissect_swils_swrjt (tvbuff_t *tvb, proto_tree *swrjt_tree, guint8 isreq _U_)
1644 {
1645     /* Set up structures needed to add the protocol subtree and manage it */
1646     int offset = 0;
1647
1648     if (swrjt_tree) {
1649         proto_tree_add_item (swrjt_tree, hf_swils_rjt, tvb, offset+5, 1, 0);
1650         proto_tree_add_item (swrjt_tree, hf_swils_rjtdet, tvb, offset+6, 1, 0);
1651         proto_tree_add_item (swrjt_tree, hf_swils_rjtvendor, tvb, offset+7,
1652                              1, 0);
1653     }
1654 }
1655
1656 static void
1657 dissect_swils_ess (tvbuff_t *tvb, proto_tree *ess_tree, guint8 isreq _U_)
1658 {
1659     int offset = 0;
1660     gint16 numcapobj = 0;
1661     gint len = 0;
1662     gint capobjlen = 0;
1663     proto_item *ti = NULL;
1664     proto_tree *ieinfo_tree = NULL;
1665
1666     if (!ess_tree) {
1667         return;
1668     }
1669
1670     proto_tree_add_item (ess_tree, hf_swils_ess_rev, tvb, offset+4, 4, 0);
1671     proto_tree_add_item (ess_tree, hf_swils_ess_len, tvb, offset+8, 4, 0);
1672     len = tvb_get_ntohl (tvb, offset+8);
1673
1674     ti = proto_tree_add_text (ess_tree, tvb, offset+12,
1675                               MAX_INTERCONNECT_ELEMENT_INFO_LEN+4,
1676                               "Interconnect Element Info");
1677     ieinfo_tree = proto_item_add_subtree (ti, ett_fcswils_ieinfo);
1678     dissect_swils_interconnect_element_info (tvb, ieinfo_tree, offset+12);
1679     len -= 256;                /* the interconnect obj above is 256 bytes */
1680     offset += 268;
1681
1682     proto_tree_add_item (ess_tree, hf_swils_ess_numobj, tvb, offset, 2, 0);
1683     numcapobj = tvb_get_ntohs (tvb, offset);
1684
1685     len -= 4;                  /* 2B numcapobj + 2B rsvd */
1686     offset += 4;
1687
1688     while ((len > 0) && (numcapobj > 0)) {
1689         capobjlen = dissect_swils_ess_capability_obj (tvb, ess_tree, offset);
1690         numcapobj--;
1691         len -= capobjlen;
1692         offset += capobjlen;
1693     }
1694 }
1695
1696 static void
1697 dissect_swils_mrra (tvbuff_t *tvb, proto_tree *tree, guint8 isreq)
1698 {
1699
1700     int offset = 0;
1701
1702     if (!tree) {
1703         return;
1704     }
1705
1706     if (isreq) {
1707         proto_tree_add_item (tree, hf_swils_mrra_rev, tvb, offset+4, 4, 0);
1708         proto_tree_add_item (tree, hf_swils_mrra_size, tvb, offset+8, 4, 0);
1709         proto_tree_add_item (tree, hf_swils_mrra_vendorid, tvb, offset+12, 8, 0);
1710         proto_tree_add_item (tree, hf_swils_mrra_vendorinfo, tvb, offset+20,
1711                              8, 0);
1712     } else {
1713         proto_tree_add_item (tree, hf_swils_mrra_vendorid, tvb, offset+4,
1714                              8, 0);
1715         proto_tree_add_item (tree, hf_swils_mrra_reply, tvb, offset+12,
1716                              4, 0);
1717         proto_tree_add_item (tree, hf_swils_mrra_reply_size, tvb, offset+16,
1718                              4, 0);
1719         proto_tree_add_item (tree, hf_swils_mrra_waittime, tvb, offset+20,
1720                              4, 0);
1721     }
1722
1723
1724 }
1725
1726 static fcswils_func_table_t fcswils_func_table[FC_SWILS_MAXCODE] = {
1727     /* 0x00 */ {NULL},
1728     /* 0x01 */ {dissect_swils_swrjt},
1729     /* 0x02 */ {NULL},
1730     /* 0x03 */ {NULL},
1731     /* 0x04 */ {NULL},
1732     /* 0x05 */ {NULL},
1733     /* 0x06 */ {NULL},
1734     /* 0x07 */ {NULL},
1735     /* 0x08 */ {NULL},
1736     /* 0x09 */ {NULL},
1737     /* 0x0a */ {NULL},
1738     /* 0x0b */ {NULL},
1739     /* 0x0c */ {NULL},
1740     /* 0x0d */ {NULL},
1741     /* 0x0e */ {NULL},
1742     /* 0x0f */ {NULL},
1743     /* 0x10 */ {dissect_swils_elp},
1744     /* 0x11 */ {dissect_swils_efp},
1745     /* 0x12 */ {dissect_swils_dia},
1746     /* 0x13 */ {dissect_swils_rdi},
1747     /* 0x14 */ {dissect_swils_hello},
1748     /* 0x15 */ {dissect_swils_lsupdate},
1749     /* 0x16 */ {dissect_swils_lsack},
1750     /* 0x17 */ {dissect_swils_nullpayload},
1751     /* 0x18 */ {dissect_swils_nullpayload},
1752     /* 0x19 */ {NULL},
1753     /* 0x1a */ {NULL},
1754     /* 0x1b */ {dissect_swils_rscn},
1755     /* 0x1c */ {NULL},
1756     /* 0x1d */ {NULL},
1757     /* 0x1e */ {dissect_swils_drlir},
1758     /* 0x1f */ {NULL},
1759     /* 0x20 */ {NULL /*dissect_swils_dscn*/},
1760     /* 0x21 */ {NULL /*dissect_swils_loopd*/},
1761     /* 0x22 */ {dissect_swils_mergereq},
1762     /* 0x23 */ {dissect_swils_aca},
1763     /* 0x24 */ {dissect_swils_rca},
1764     /* 0x25 */ {dissect_swils_sfc},
1765     /* 0x26 */ {dissect_swils_ufc},
1766     /* 0x27 */ {NULL},
1767     /* 0x28 */ {NULL},
1768     /* 0x29 */ {NULL},
1769     /* 0x2a */ {NULL},
1770     /* 0x2b */ {NULL},
1771     /* 0x2c */ {NULL},
1772     /* 0x2d */ {NULL},
1773     /* 0x2e */ {NULL},
1774     /* 0x2f */ {NULL},
1775     /* 0x30 */ {dissect_swils_esc},
1776     /* 0x31 */ {dissect_swils_ess},
1777     /* 0x32 */ {NULL},
1778     /* 0x33 */ {NULL},
1779     /* 0x34 */ {dissect_swils_mrra}
1780 };
1781
1782 /* Code to actually dissect the packets */
1783 static void
1784 dissect_fcswils (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1785 {
1786     proto_item *ti = NULL;
1787     guint8 opcode,
1788         failed_opcode = 0;
1789     int offset = 0;
1790     conversation_t *conversation;
1791     fcswils_conv_data_t *cdata;
1792     fcswils_conv_key_t ckey, *req_key;
1793     proto_tree *swils_tree = NULL;
1794     guint8 isreq = FC_SWILS_REQ;
1795     tvbuff_t *next_tvb;
1796
1797     /* Make entries in Protocol column and Info column on summary display */
1798     col_set_str(pinfo->cinfo, COL_PROTOCOL, "SW_ILS");
1799
1800     /* decoding of this is done by each individual opcode handler */
1801     opcode = tvb_get_guint8 (tvb, 0);
1802
1803     if (tree) {
1804         ti = proto_tree_add_protocol_format (tree, proto_fcswils, tvb, 0,
1805                                              tvb_length (tvb), "SW_ILS");
1806         swils_tree = proto_item_add_subtree (ti, ett_fcswils);
1807     }
1808
1809     /* Register conversation if this is not a response */
1810     if ((opcode != FC_SWILS_SWACC) && (opcode != FC_SWILS_SWRJT)) {
1811         conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1812                                           pinfo->ptype, pinfo->oxid,
1813                                           pinfo->rxid, NO_PORT2);
1814         if (!conversation) {
1815             conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1816                                              pinfo->ptype, pinfo->oxid,
1817                                              pinfo->rxid, NO_PORT2);
1818         }
1819
1820         ckey.conv_idx = conversation->index;
1821
1822         cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash,
1823                                                             &ckey);
1824         if (cdata) {
1825             /* Since we never free the memory used by an exchange, this maybe a
1826              * case of another request using the same exchange as a previous
1827              * req.
1828              */
1829             cdata->opcode = opcode;
1830         }
1831         else {
1832             req_key = se_alloc (sizeof(fcswils_conv_key_t));
1833             req_key->conv_idx = conversation->index;
1834
1835             cdata = se_alloc (sizeof(fcswils_conv_data_t));
1836             cdata->opcode = opcode;
1837
1838             g_hash_table_insert (fcswils_req_hash, req_key, cdata);
1839         }
1840     }
1841     else {
1842         /* Opcode is ACC or RJT */
1843         conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
1844                                           pinfo->ptype, pinfo->oxid,
1845                                           pinfo->rxid, NO_PORT2);
1846         isreq = FC_SWILS_RPLY;
1847         if (!conversation) {
1848             if (tree && (opcode == FC_SWILS_SWACC)) {
1849                 /* No record of what this accept is for. Can't decode */
1850                 proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
1851                                      "No record of Exchg. Unable to decode SW_ACC");
1852                 return;
1853             }
1854         }
1855         else {
1856             ckey.conv_idx = conversation->index;
1857
1858             cdata = (fcswils_conv_data_t *)g_hash_table_lookup (fcswils_req_hash, &ckey);
1859
1860             if (cdata != NULL) {
1861                 if (opcode == FC_SWILS_SWACC)
1862                     opcode = cdata->opcode;
1863                 else
1864                     failed_opcode = cdata->opcode;
1865             }
1866
1867             if (tree) {
1868                 if ((cdata == NULL) && (opcode != FC_SWILS_SWRJT)) {
1869                     /* No record of what this accept is for. Can't decode */
1870                     proto_tree_add_text (swils_tree, tvb, 0, tvb_length (tvb),
1871                                          "No record of SW_ILS Req. Unable to decode SW_ACC");
1872                     return;
1873                 }
1874             }
1875         }
1876     }
1877
1878     if (check_col (pinfo->cinfo, COL_INFO)) {
1879         if (isreq == FC_SWILS_REQ) {
1880             col_add_str (pinfo->cinfo, COL_INFO,
1881                          val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
1882         }
1883         else if (opcode == FC_SWILS_SWRJT) {
1884             col_add_fstr (pinfo->cinfo, COL_INFO, "SW_RJT (%s)",
1885                           val_to_str (failed_opcode, fc_swils_opcode_key_val, "0x%x"));
1886         }
1887         else {
1888             col_add_fstr (pinfo->cinfo, COL_INFO, "SW_ACC (%s)",
1889                           val_to_str (opcode, fc_swils_opcode_key_val, "0x%x"));
1890         }
1891     }
1892
1893     if (tree) {
1894         proto_tree_add_item (swils_tree, hf_swils_opcode, tvb, offset, 1, 0);
1895     }
1896
1897     if ((opcode < FC_SWILS_MAXCODE) && fcswils_func_table[opcode].func) {
1898          fcswils_func_table[opcode].func (tvb, swils_tree, isreq);
1899     } else if (opcode == FC_SWILS_AUTH_ILS) {
1900          /* This is treated differently */
1901          if (isreq && fcsp_handle)
1902               call_dissector (fcsp_handle, tvb, pinfo, swils_tree);
1903     } else {
1904          /* data dissector */
1905          next_tvb = tvb_new_subset_remaining (tvb, offset+4);
1906          call_dissector (data_handle, next_tvb, pinfo, tree);
1907     }
1908
1909 }
1910
1911 /* Register the protocol with Wireshark */
1912
1913 void
1914 proto_register_fcswils (void)
1915 {
1916     static hf_register_info hf[] = {
1917         { &hf_swils_opcode,
1918           {"Cmd Code", "swils.opcode",
1919            FT_UINT8, BASE_HEX, VALS (fc_swils_opcode_key_val), 0x0, NULL, HFILL}},
1920         { &hf_swils_elp_rev,
1921           {"Revision", "swils.elp.rev",
1922            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1923         { &hf_swils_elp_flags,
1924           {"Flag", "swils.elp.flag",
1925            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1926         { &hf_swils_elp_r_a_tov,
1927           {"R_A_TOV", "swils.elp.ratov",
1928            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1929         { &hf_swils_elp_e_d_tov,
1930           {"E_D_TOV", "swils.elp.edtov",
1931            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1932         { &hf_swils_elp_req_epn,
1933           {"Req Eport Name", "swils.elp.reqepn",
1934            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1935         { &hf_swils_elp_req_esn,
1936           {"Req Switch Name", "swils.elp.reqesn",
1937            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1938         { &hf_swils_elp_clsf_svcp,
1939           {"Class F Svc Param", "swils.elp.clsfp",
1940            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1941         { &hf_swils_elp_clsf_rcvsz,
1942           {"Max Class F Frame Size", "swils.elp.clsfrsz",
1943            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1944         { &hf_swils_elp_clsf_conseq,
1945           {"Class F Max Concurrent Seq", "swils.elp.clsfcs",
1946            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1947         { &hf_swils_elp_clsf_e2e,
1948           {"Class F E2E Credit", "swils.elp.cfe2e",
1949            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1950         { &hf_swils_elp_clsf_openseq,
1951           {"Class F Max Open Seq", "swils.elp.oseq",
1952            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1953         { &hf_swils_elp_cls1_svcp,
1954           {"Class 1 Svc Param", "swils.elp.cls1p",
1955            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1956         { &hf_swils_elp_cls1_rcvsz,
1957           {"Class 1 Frame Size", "swils.elp.cls1rsz",
1958            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1959         { &hf_swils_elp_cls2_svcp,
1960           {"Class 2 Svc Param", "swils.elp.cls2p",
1961            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1962         { &hf_swils_elp_cls2_rcvsz,
1963           {"Class 2 Frame Size", "swils.elp.cls1rsz",
1964            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1965         { &hf_swils_elp_cls3_svcp,
1966           {"Class 3 Svc Param", "swils.elp.cls3p",
1967            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1968         { &hf_swils_elp_cls3_rcvsz,
1969           {"Class 3 Frame Size", "swils.elp.cls1rsz",
1970            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1971         { &hf_swils_elp_isl_fc_mode,
1972           {"ISL Flow Ctrl Mode", "swils.elp.fcmode",
1973            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1974         { &hf_swils_elp_fcplen,
1975           {"Flow Ctrl Param Len", "swils.elp.fcplen",
1976            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1977         { &hf_swils_elp_b2bcredit,
1978           {"B2B Credit", "swils.elp.b2b",
1979            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1980         { &hf_swils_elp_compat1,
1981           {"Compatibility Param 1", "swils.elp.compat1",
1982            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1983         { &hf_swils_elp_compat2,
1984           {"Compatibility Param 2", "swils.elp.compat2",
1985            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1986         { &hf_swils_elp_compat3,
1987           {"Compatibility Param 3", "swils.elp.compat3",
1988            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1989         { &hf_swils_elp_compat4,
1990           {"Compatibility Param 4", "swils.elp.compat4",
1991            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1992         { &hf_swils_efp_rec_type,
1993           {"Record Type", "swils.efp.rectype",
1994            FT_UINT8, BASE_HEX, VALS (fcswils_rectype_val), 0x0, NULL, HFILL}},
1995         { &hf_swils_efp_dom_id,
1996           {"Domain ID", "swils.efp.domid",
1997            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
1998         { &hf_swils_efp_switch_name,
1999           {"Switch Name", "swils.efp.sname",
2000            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2001         { &hf_swils_efp_mcast_grpno,
2002           {"Mcast Grp#", "swils.efp.mcastno",
2003            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2004         { &hf_swils_efp_alias_token,
2005           {"Alias Token", "swils.efp.aliastok",
2006            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2007         { &hf_swils_efp_record_len,
2008           {"Record Len", "swils.efp.recordlen",
2009            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2010         { &hf_swils_efp_payload_len,
2011           {"Payload Len", "swils.efp.payloadlen",
2012            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2013         { &hf_swils_efp_pswitch_pri,
2014           {"Principal Switch Priority", "swils.efp.psprio",
2015            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2016         { &hf_swils_efp_pswitch_name,
2017           {"Principal Switch Name", "swils.efp.psname",
2018            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2019         { &hf_swils_dia_switch_name,
2020           {"Switch Name", "swils.dia.sname",
2021            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2022         { &hf_swils_rdi_payload_len,
2023           {"Payload Len", "swils.rdi.len",
2024            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2025         { &hf_swils_rdi_req_sname,
2026           {"Req Switch Name", "swils.rdi.reqsn",
2027            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2028         { &hf_swils_fspfh_cmd,
2029           {"Command:", "swils.fspf.cmd",
2030            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2031         { &hf_swils_fspfh_rev,
2032           {"Version", "swils.fspf.ver",
2033            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2034         { &hf_swils_fspfh_ar_num,
2035           {"AR Number", "swils.fspf.arnum",
2036            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2037         { &hf_swils_fspfh_auth_type,
2038           {"Authentication Type", "swils.fspf.authtype",
2039            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2040         { &hf_swils_fspfh_dom_id,
2041           {"Originating Domain ID", "swils.fspf.origdomid",
2042            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2043         { &hf_swils_fspfh_auth,
2044           {"Authentication", "swils.fspf.auth",
2045            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2046         { &hf_swils_hlo_options,
2047           {"Options", "swils.hlo.options",
2048            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2049         { &hf_swils_hlo_hloint,
2050           {"Hello Interval (secs)", "swils.hlo.hloint",
2051            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2052         { &hf_swils_hlo_deadint,
2053           {"Dead Interval (secs)", "swils.hlo.deadint",
2054            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2055         { &hf_swils_hlo_rcv_domid,
2056           {"Recipient Domain ID", "swils.hlo.rcvdomid",
2057            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2058         { &hf_swils_hlo_orig_pidx,
2059           {"Originating Port Idx", "swils.hlo.origpidx",
2060            FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2061         { &hf_swils_lsrh_lsr_type,
2062           {"LSR Type", "swils.lsr.type",
2063            FT_UINT8, BASE_HEX, VALS (fc_swils_fspf_linkrec_val), 0x0, NULL, HFILL}},
2064         { &hf_swils_lsrh_lsid,
2065           {"Link State Id", "swils.ls.id",
2066            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2067         { &hf_swils_lsrh_adv_domid,
2068           {"Advertising Domain Id", "swils.lsr.advdomid",
2069            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2070         { &hf_swils_lsrh_ls_incid,
2071           {"LS Incarnation Number", "swils.lsr.incid",
2072            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2073         { &hf_swils_ldrec_linkid,
2074           {"Link ID", "swils.ldr.linkid",
2075            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2076         { &hf_swils_ldrec_out_pidx,
2077           {"Output Port Idx", "swils.ldr.out_portidx",
2078            FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2079         { &hf_swils_ldrec_nbr_pidx,
2080           {"Neighbor Port Idx", "swils.ldr.nbr_portidx",
2081            FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2082         { &hf_swils_ldrec_link_type,
2083           {"Link Type", "swils.ldr.linktype",
2084            FT_UINT8, BASE_HEX, VALS (fc_swils_link_type_val), 0x0, NULL, HFILL}},
2085         { &hf_swils_ldrec_link_cost,
2086           {"Link Cost", "swils.ldr.linkcost",
2087            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2088         { &hf_swils_rscn_evtype,
2089           {"Event Type", "swils.rscn.evtype",
2090            FT_UINT8, BASE_DEC, VALS (fc_swils_rscn_portstate_val), 0xF0, NULL, HFILL}},
2091         { &hf_swils_rscn_addrfmt,
2092           {"Address Format", "swils.rscn.addrfmt",
2093            FT_UINT8, BASE_DEC, VALS (fc_swils_rscn_addrfmt_val), 0x0F, NULL, HFILL}},
2094         { &hf_swils_rscn_affectedport,
2095           {"Affected Port ID", "swils.rscn.affectedport",
2096            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2097         { &hf_swils_rscn_detectfn,
2098           {"Detection Function", "swils.rscn.detectfn",
2099            FT_UINT32, BASE_HEX, VALS (fc_swils_rscn_detectfn_val), 0x0, NULL, HFILL}},
2100         { &hf_swils_rscn_portstate,
2101           {"Port State", "swils.rscn.portstate",
2102            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2103         { &hf_swils_rscn_portid,
2104           {"Port Id", "swils.rscn.portid",
2105            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2106         { &hf_swils_rscn_pwwn,
2107           {"Port WWN", "swils.rscn.pwwn",
2108            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2109         { &hf_swils_rscn_nwwn,
2110           {"Node WWN", "swils.rscn.nwwn",
2111            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2112         { &hf_swils_esc_swvendorid,
2113           {"Switch Vendor ID", "swils.esc.swvendor",
2114            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2115         { &hf_swils_esc_pdesc_vendorid,
2116           {"Vendor ID", "swils.esc.vendorid",
2117            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2118         { &hf_swils_esc_protocolid,
2119           {"Protocol ID", "swils.esc.protocol",
2120            FT_UINT16, BASE_HEX, VALS (fc_swils_esc_protocol_val), 0x0, NULL, HFILL}},
2121         { &hf_swils_zone_activezonenm,
2122           {"Active Zoneset Name", "swils.mr.activezonesetname",
2123            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2124         { &hf_swils_zone_objname,
2125           {"Zone Object Name", "swils.zone.zoneobjname",
2126            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2127         { &hf_swils_zone_objtype,
2128           {"Zone Object Type", "swils.zone.zoneobjtype",
2129            FT_UINT8, BASE_HEX, VALS (fc_swils_zoneobj_type_val), 0x0, NULL, HFILL}},
2130         { &hf_swils_zone_mbrtype,
2131           {"Zone Member Type", "swils.zone.mbrtype",
2132            FT_UINT8, BASE_HEX, VALS (fc_swils_zonembr_type_val), 0x0, NULL, HFILL}},
2133         { &hf_swils_zone_protocol,
2134           {"Zone Protocol", "swils.zone.protocol",
2135            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2136         { &hf_swils_zone_mbrid,
2137           {"Member Identifier", "swils.zone.mbrid",
2138            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2139         { &hf_swils_zone_status,
2140           {"Zone Command Status", "swils.zone.status",
2141            FT_UINT8, BASE_HEX, VALS (fc_swils_mr_rsp_val), 0x0,
2142            "Applies to MR, ACA, RCA, SFC, UFC", HFILL}},
2143         { &hf_swils_zone_reason,
2144           {"Zone Command Reason Code", "swils.zone.reason",
2145            FT_UINT8, BASE_HEX, VALS (fc_swils_mr_reason_val), 0x0,
2146            "Applies to MR, ACA, RCA, SFC, UFC", HFILL}},
2147         { &hf_swils_aca_domainid,
2148           {"Known Domain ID", "swils.aca.domainid",
2149            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2150         { &hf_swils_sfc_opcode,
2151           {"Operation Request", "swils.sfc.opcode",
2152            FT_UINT8, BASE_HEX, VALS (fc_swils_sfc_op_val), 0x0, NULL, HFILL}},
2153         { &hf_swils_sfc_zonenm,
2154           {"Zone Set Name", "swils.sfc.zonename",
2155            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2156         { &hf_swils_rjt,
2157           {"Reason Code", "swils.rjt.reason",
2158            FT_UINT8, BASE_HEX, VALS (fc_swils_rjt_val), 0x0, NULL, HFILL}},
2159         { &hf_swils_rjtdet,
2160           {"Reason Code Explanantion", "swils.rjt.reasonexpl",
2161            FT_UINT8, BASE_HEX, VALS (fc_swils_deterr_val), 0x0, NULL, HFILL}},
2162         { &hf_swils_rjtvendor,
2163           {"Vendor Unique Error Code", "swils.rjt.vendor",
2164            FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2165         { &hf_swils_zone_mbrid_lun,
2166           {"LUN", "swils.zone.lun",
2167            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2168         { &hf_swils_ess_rev,
2169           {"Revision", "swils.ess.revision",
2170            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2171         { &hf_swils_ess_len,
2172           {"Payload Length", "swils.ess.leb",
2173            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2174         { &hf_swils_ess_numobj,
2175           {"Number of Capability Objects", "swils.ess.numobj",
2176            FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2177         { &hf_swils_interconnect_list_len,
2178           {"List Length", "swils.ess.listlen",
2179            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2180         { &hf_swils_ess_vendorname,
2181           {"Vendor Name", "swils.ess.vendorname",
2182            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2183         { &hf_swils_ess_modelname,
2184           {"Model Name", "swils.ess.modelname",
2185            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2186         { &hf_swils_ess_relcode,
2187           {"Release Code", "swils.ess.relcode",
2188            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2189         { &hf_swils_ess_vendorspecific,
2190           {"Vendor Specific", "swils.ess.vendorspecific",
2191            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2192         { &hf_swils_ess_cap_type,
2193           {"Type", "swils.ess.capability.type",
2194            FT_UINT8, BASE_DEC, VALS (fc_ct_gstype_vals), 0x0, NULL, HFILL}},
2195         { &hf_swils_ess_cap_subtype,
2196           {"Subtype", "swils.ess.capability.subtype",
2197            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2198         { &hf_swils_ess_cap_numentries,
2199           {"Number of Entries", "swils.ess.capability.numentries",
2200            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2201         { &hf_swils_ess_cap_svc,
2202           {"Service Name", "swils.ess.capability.service",
2203            FT_UINT8, BASE_DEC, VALS (fc_ct_gsserver_vals), 0x0, NULL, HFILL}},
2204         { &hf_swils_ess_dns_obj0h,
2205           {"Name Server Entry Object 00h Support", "swils.ess.capability.dns.obj0h",
2206            FT_BOOLEAN, 8, NULL, 0x1, NULL, HFILL}},
2207         { &hf_swils_ess_dns_obj1h,
2208           {"Name Server Entry Object 01h Support", "swils.ess.capability.dns.obj1h",
2209            FT_BOOLEAN, 8, NULL, 0x2, NULL, HFILL}},
2210         { &hf_swils_ess_dns_obj2h,
2211           {"Name Server Entry Object 02h Support", "swils.ess.capability.dns.obj2h",
2212            FT_BOOLEAN, 8, NULL, 0x4, NULL, HFILL}},
2213         { &hf_swils_ess_dns_obj3h,
2214           {"Name Server Entry Object 03h Support", "swils.ess.capability.dns.obj3h",
2215            FT_BOOLEAN, 8, NULL, 0x8, NULL, HFILL}},
2216         { &hf_swils_ess_dns_zlacc,
2217           {"GE_PT Zero Length Accepted", "swils.ess.capability.dns.zlacc",
2218            FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL}},
2219         { &hf_swils_ess_dns_vendor,
2220           {"Vendor Specific Flags", "swils.ess.capability.dns.vendor",
2221            FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2222         { &hf_swils_ess_fctlr_rscn,
2223           {"SW_RSCN Supported", "swils.ess.capability.fctlr.rscn",
2224            FT_BOOLEAN, 8, NULL, 0x1, NULL, HFILL}},
2225         { &hf_swils_ess_fctlr_vendor,
2226           {"Vendor Specific Flags", "swils.ess.capability.fctlr.vendor",
2227            FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
2228         { &hf_swils_ess_fcs_basic,
2229           {"Basic Configuration Services", "swils.ess.capability.fcs.basic",
2230            FT_BOOLEAN, 8, NULL, 0x1, NULL, HFILL}},
2231         { &hf_swils_ess_fcs_platform,
2232           {"Platform Configuration Services", "swils.ess.capability.fcs.platform",
2233            FT_BOOLEAN, 8, NULL, 0x2, NULL, HFILL}},
2234         { &hf_swils_ess_fcs_topology,
2235           {"Topology Discovery Services", "swils.ess.capability.fcs.topology",
2236            FT_BOOLEAN, 8, NULL, 0x4, NULL, HFILL}},
2237         { &hf_swils_ess_fcs_enhanced,
2238           {"Enhanced Configuration Services", "swils.ess.capability.fcs.enhanced",
2239            FT_BOOLEAN, 8, NULL, 0x8, NULL, HFILL}},
2240         { &hf_swils_ess_fzs_enh_supp,
2241           {"Enhanced Zoning Supported", "swils.ess.capability.fzs.ezonesupp",
2242            FT_BOOLEAN, 8, NULL, 0x1, NULL, HFILL}},
2243         { &hf_swils_ess_fzs_enh_ena,
2244           {"Enhanced Zoning Enabled", "swils.ess.capability.fzs.ezoneena",
2245            FT_BOOLEAN, 8, NULL, 0x2, NULL, HFILL}},
2246         { &hf_swils_ess_fzs_mr,
2247           {"Merge Control Setting", "swils.ess.capability.fzs.mr",
2248            FT_BOOLEAN, 8, NULL, 0x4, NULL, HFILL}},
2249         { &hf_swils_ess_fzs_defzone,
2250           {"Default Zone Setting", "swils.ess.capability.fzs.defzone",
2251            FT_BOOLEAN, 8, NULL, 0x8, NULL, HFILL}},
2252         { &hf_swils_ess_fzs_zsdb_supp,
2253           {"Zoneset Database Supported", "swils.ess.capability.fzs.zsdbsupp",
2254            FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL}},
2255         { &hf_swils_ess_fzs_zsdb_ena,
2256           {"Zoneset Database Enabled", "swils.ess.capability.fzs.zsdbena",
2257            FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL}},
2258         { &hf_swils_ess_fzs_adc_supp,
2259           {"Active Direct Command Supported", "swils.ess.capability.fzs.adcsupp",
2260            FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL}},
2261         { &hf_swils_ess_fzs_hardzone,
2262           {"Hard Zoning Supported", "swils.ess.capability.fzs.hardzone",
2263            FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}},
2264         { &hf_swils_ess_cap_len,
2265           {"Length", "swils.ess.capability.length",
2266            FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2267         { &hf_swils_ess_cap_t10,
2268           {"T10 Vendor ID", "swils.ess.capability.t10id",
2269            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2270         { &hf_swils_ess_cap_vendorobj,
2271           {"Vendor-Specific Info", "swils.ess.capability.vendorobj",
2272            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2273         { &hf_swils_mrra_rev,
2274           {"Revision", "swils.mrra.revision",
2275            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2276         { &hf_swils_mrra_size,
2277           {"Merge Request Size", "swils.mrra.size",
2278            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2279         { &hf_swils_mrra_vendorid,
2280           {"Vendor ID", "swils.mrra.vendorid",
2281            FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2282         { &hf_swils_mrra_vendorinfo,
2283           {"Vendor-Specific Info", "swils.mrra.vendorinfo",
2284            FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
2285         { &hf_swils_mrra_reply,
2286           {"MRRA Response", "swils.mrra.reply",
2287            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2288         { &hf_swils_mrra_reply_size,
2289           {"Maximum Resources Available", "swils.mrra.replysize",
2290            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2291         { &hf_swils_mrra_waittime,
2292           {"Waiting Period (secs)", "swils.mrra.waittime",
2293            FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
2294     };
2295
2296     static gint *ett[] = {
2297         &ett_fcswils,
2298         &ett_fcswils_swacc,
2299         &ett_fcswils_swrjt,
2300         &ett_fcswils_elp,
2301         &ett_fcswils_efp,
2302         &ett_fcswils_efplist,
2303         &ett_fcswils_dia,
2304         &ett_fcswils_rdi,
2305         &ett_fcswils_fspfhdr,
2306         &ett_fcswils_hlo,
2307         &ett_fcswils_lsrec,
2308         &ett_fcswils_lsrechdr,
2309         &ett_fcswils_ldrec,
2310         &ett_fcswils_lsu,
2311         &ett_fcswils_lsa,
2312         &ett_fcswils_bf,
2313         &ett_fcswils_rcf,
2314         &ett_fcswils_rscn,
2315         &ett_fcswils_rscn_dev,
2316         &ett_fcswils_drlir,
2317         &ett_fcswils_mr,
2318         &ett_fcswils_zoneobjlist,
2319         &ett_fcswils_zoneobj,
2320         &ett_fcswils_zonembr,
2321         &ett_fcswils_aca,
2322         &ett_fcswils_rca,
2323         &ett_fcswils_sfc,
2324         &ett_fcswils_ufc,
2325         &ett_fcswils_esc,
2326         &ett_fcswils_esc_pdesc,
2327         &ett_fcswils_ieinfo,
2328         &ett_fcswils_capinfo
2329     };
2330
2331     proto_fcswils = proto_register_protocol("Fibre Channel SW_ILS", "FC-SWILS", "swils");
2332
2333     proto_register_field_array(proto_fcswils, hf, array_length(hf));
2334     proto_register_subtree_array(ett, array_length(ett));
2335     register_init_routine(&fcswils_init_protocol);
2336 }
2337
2338 void
2339 proto_reg_handoff_fcswils (void)
2340 {
2341     dissector_handle_t swils_handle;
2342
2343     swils_handle = create_dissector_handle (dissect_fcswils, proto_fcswils);
2344     dissector_add_uint("fc.ftype", FC_FTYPE_SWILS, swils_handle);
2345
2346     data_handle = find_dissector ("data");
2347     fcsp_handle = find_dissector ("fcsp");
2348 }