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