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