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