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