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